diff --git a/.vscode/example/tasks.json b/.vscode/example/tasks.json index 28e67d45..3c01506a 100644 --- a/.vscode/example/tasks.json +++ b/.vscode/example/tasks.json @@ -4,13 +4,13 @@ "version": "2.0.0", "tasks": [ { - "label": "[Release] Build", + "label": "[Release] Build Firmware", "group": "build", "type": "shell", "command": "./fbt COMPACT=1 DEBUG=0" }, { - "label": "[Debug] Build", + "label": "[Debug] Build Firmware", "group": "build", "type": "shell", "command": "./fbt" @@ -123,17 +123,29 @@ "type": "shell", "command": "./fbt COMPACT=1 DEBUG=0 fap_dist" }, + { + "label": "[Debug] Build App", + "group": "build", + "type": "shell", + "command": "./fbt build APPSRC=${relativeFileDirname}" + }, + { + "label": "[Release] Build App", + "group": "build", + "type": "shell", + "command": "./fbt COMPACT=1 DEBUG=0 build APPSRC=${relativeFileDirname}" + }, { "label": "[Debug] Launch App on Flipper", "group": "build", "type": "shell", - "command": "./fbt launch_app APPSRC=${relativeFileDirname}" + "command": "./fbt launch APPSRC=${relativeFileDirname}" }, { "label": "[Release] Launch App on Flipper", "group": "build", "type": "shell", - "command": "./fbt COMPACT=1 DEBUG=0 launch_app APPSRC=${relativeFileDirname}" + "command": "./fbt COMPACT=1 DEBUG=0 launch APPSRC=${relativeFileDirname}" }, { "label": "[Debug] Launch App on Flipper with Serial Console", diff --git a/applications/debug/subghz_test/application.fam b/applications/debug/subghz_test/application.fam new file mode 100644 index 00000000..1b3e19d7 --- /dev/null +++ b/applications/debug/subghz_test/application.fam @@ -0,0 +1,14 @@ +App( + appid="subghz_test", + name="Sub-Ghz test", + apptype=FlipperAppType.DEBUG, + targets=["f7"], + entry_point="subghz_test_app", + requires=["gui"], + stack_size=4 * 1024, + order=50, + fap_icon="subghz_test_10px.png", + fap_category="Debug", + fap_icon_assets="images", + fap_version="0.1", +) diff --git a/applications/debug/subghz_test/helpers/subghz_test_event.h b/applications/debug/subghz_test/helpers/subghz_test_event.h new file mode 100644 index 00000000..a0a85197 --- /dev/null +++ b/applications/debug/subghz_test/helpers/subghz_test_event.h @@ -0,0 +1,7 @@ +#pragma once + +typedef enum { + //SubGhzTestCustomEvent + SubGhzTestCustomEventStartId = 100, + SubGhzTestCustomEventSceneShowOnlyRX, +} SubGhzTestCustomEvent; diff --git a/applications/main/subghz/helpers/subghz_testing.c b/applications/debug/subghz_test/helpers/subghz_test_frequency.c similarity index 95% rename from applications/main/subghz/helpers/subghz_testing.c rename to applications/debug/subghz_test/helpers/subghz_test_frequency.c index 8afa868e..ed1ba704 100644 --- a/applications/main/subghz/helpers/subghz_testing.c +++ b/applications/debug/subghz_test/helpers/subghz_test_frequency.c @@ -1,4 +1,4 @@ -#include "subghz_testing.h" +#include "subghz_test_frequency.h" const uint32_t subghz_frequencies_testing[] = { /* 300 - 348 */ diff --git a/applications/main/subghz/helpers/subghz_testing.h b/applications/debug/subghz_test/helpers/subghz_test_frequency.h similarity index 84% rename from applications/main/subghz/helpers/subghz_testing.h rename to applications/debug/subghz_test/helpers/subghz_test_frequency.h index 29ce578a..7dd1423f 100644 --- a/applications/main/subghz/helpers/subghz_testing.h +++ b/applications/debug/subghz_test/helpers/subghz_test_frequency.h @@ -1,5 +1,5 @@ #pragma once -#include "../subghz_i.h" +#include "../subghz_test_app_i.h" extern const uint32_t subghz_frequencies_testing[]; extern const uint32_t subghz_frequencies_count_testing; diff --git a/applications/debug/subghz_test/helpers/subghz_test_types.h b/applications/debug/subghz_test/helpers/subghz_test_types.h new file mode 100644 index 00000000..03be6459 --- /dev/null +++ b/applications/debug/subghz_test/helpers/subghz_test_types.h @@ -0,0 +1,18 @@ +#pragma once + +#include +#include + +#define SUBGHZ_TEST_VERSION_APP "0.1" +#define SUBGHZ_TEST_DEVELOPED "SkorP" +#define SUBGHZ_TEST_GITHUB "https://github.com/flipperdevices/flipperzero-firmware" + +typedef enum { + SubGhzTestViewVariableItemList, + SubGhzTestViewSubmenu, + SubGhzTestViewStatic, + SubGhzTestViewCarrier, + SubGhzTestViewPacket, + SubGhzTestViewWidget, + SubGhzTestViewPopup, +} SubGhzTestView; diff --git a/applications/debug/subghz_test/images/DolphinCommon_56x48.png b/applications/debug/subghz_test/images/DolphinCommon_56x48.png new file mode 100644 index 00000000..089aaed8 Binary files /dev/null and b/applications/debug/subghz_test/images/DolphinCommon_56x48.png differ diff --git a/applications/debug/subghz_test/protocol/math.c b/applications/debug/subghz_test/protocol/math.c new file mode 100644 index 00000000..24202ad1 --- /dev/null +++ b/applications/debug/subghz_test/protocol/math.c @@ -0,0 +1,244 @@ +#include "math.h" + +uint64_t subghz_protocol_blocks_reverse_key(uint64_t key, uint8_t bit_count) { + uint64_t reverse_key = 0; + for(uint8_t i = 0; i < bit_count; i++) { + reverse_key = reverse_key << 1 | bit_read(key, i); + } + return reverse_key; +} + +uint8_t subghz_protocol_blocks_get_parity(uint64_t key, uint8_t bit_count) { + uint8_t parity = 0; + for(uint8_t i = 0; i < bit_count; i++) { + parity += bit_read(key, i); + } + return parity & 0x01; +} + +uint8_t subghz_protocol_blocks_crc4( + uint8_t const message[], + size_t size, + uint8_t polynomial, + uint8_t init) { + uint8_t remainder = init << 4; // LSBs are unused + uint8_t poly = polynomial << 4; + uint8_t bit; + + while(size--) { + remainder ^= *message++; + for(bit = 0; bit < 8; bit++) { + if(remainder & 0x80) { + remainder = (remainder << 1) ^ poly; + } else { + remainder = (remainder << 1); + } + } + } + return remainder >> 4 & 0x0f; // discard the LSBs +} + +uint8_t subghz_protocol_blocks_crc7( + uint8_t const message[], + size_t size, + uint8_t polynomial, + uint8_t init) { + uint8_t remainder = init << 1; // LSB is unused + uint8_t poly = polynomial << 1; + + for(size_t byte = 0; byte < size; ++byte) { + remainder ^= message[byte]; + for(uint8_t bit = 0; bit < 8; ++bit) { + if(remainder & 0x80) { + remainder = (remainder << 1) ^ poly; + } else { + remainder = (remainder << 1); + } + } + } + return remainder >> 1 & 0x7f; // discard the LSB +} + +uint8_t subghz_protocol_blocks_crc8( + uint8_t const message[], + size_t size, + uint8_t polynomial, + uint8_t init) { + uint8_t remainder = init; + + for(size_t byte = 0; byte < size; ++byte) { + remainder ^= message[byte]; + for(uint8_t bit = 0; bit < 8; ++bit) { + if(remainder & 0x80) { + remainder = (remainder << 1) ^ polynomial; + } else { + remainder = (remainder << 1); + } + } + } + return remainder; +} + +uint8_t subghz_protocol_blocks_crc8le( + uint8_t const message[], + size_t size, + uint8_t polynomial, + uint8_t init) { + uint8_t remainder = subghz_protocol_blocks_reverse_key(init, 8); + polynomial = subghz_protocol_blocks_reverse_key(polynomial, 8); + + for(size_t byte = 0; byte < size; ++byte) { + remainder ^= message[byte]; + for(uint8_t bit = 0; bit < 8; ++bit) { + if(remainder & 1) { + remainder = (remainder >> 1) ^ polynomial; + } else { + remainder = (remainder >> 1); + } + } + } + return remainder; +} + +uint16_t subghz_protocol_blocks_crc16lsb( + uint8_t const message[], + size_t size, + uint16_t polynomial, + uint16_t init) { + uint16_t remainder = init; + + for(size_t byte = 0; byte < size; ++byte) { + remainder ^= message[byte]; + for(uint8_t bit = 0; bit < 8; ++bit) { + if(remainder & 1) { + remainder = (remainder >> 1) ^ polynomial; + } else { + remainder = (remainder >> 1); + } + } + } + return remainder; +} + +uint16_t subghz_protocol_blocks_crc16( + uint8_t const message[], + size_t size, + uint16_t polynomial, + uint16_t init) { + uint16_t remainder = init; + + for(size_t byte = 0; byte < size; ++byte) { + remainder ^= message[byte] << 8; + for(uint8_t bit = 0; bit < 8; ++bit) { + if(remainder & 0x8000) { + remainder = (remainder << 1) ^ polynomial; + } else { + remainder = (remainder << 1); + } + } + } + return remainder; +} + +uint8_t subghz_protocol_blocks_lfsr_digest8( + uint8_t const message[], + size_t size, + uint8_t gen, + uint8_t key) { + uint8_t sum = 0; + for(size_t byte = 0; byte < size; ++byte) { + uint8_t data = message[byte]; + for(int i = 7; i >= 0; --i) { + // XOR key into sum if data bit is set + if((data >> i) & 1) sum ^= key; + + // roll the key right (actually the LSB is dropped here) + // and apply the gen (needs to include the dropped LSB as MSB) + if(key & 1) + key = (key >> 1) ^ gen; + else + key = (key >> 1); + } + } + return sum; +} + +uint8_t subghz_protocol_blocks_lfsr_digest8_reflect( + uint8_t const message[], + size_t size, + uint8_t gen, + uint8_t key) { + uint8_t sum = 0; + // Process message from last byte to first byte (reflected) + for(int byte = size - 1; byte >= 0; --byte) { + uint8_t data = message[byte]; + // Process individual bits of each byte (reflected) + for(uint8_t i = 0; i < 8; ++i) { + // XOR key into sum if data bit is set + if((data >> i) & 1) { + sum ^= key; + } + + // roll the key left (actually the LSB is dropped here) + // and apply the gen (needs to include the dropped lsb as MSB) + if(key & 0x80) + key = (key << 1) ^ gen; + else + key = (key << 1); + } + } + return sum; +} + +uint16_t subghz_protocol_blocks_lfsr_digest16( + uint8_t const message[], + size_t size, + uint16_t gen, + uint16_t key) { + uint16_t sum = 0; + for(size_t byte = 0; byte < size; ++byte) { + uint8_t data = message[byte]; + for(int8_t i = 7; i >= 0; --i) { + // if data bit is set then xor with key + if((data >> i) & 1) sum ^= key; + + // roll the key right (actually the LSB is dropped here) + // and apply the gen (needs to include the dropped LSB as MSB) + if(key & 1) + key = (key >> 1) ^ gen; + else + key = (key >> 1); + } + } + return sum; +} + +uint8_t subghz_protocol_blocks_add_bytes(uint8_t const message[], size_t size) { + uint32_t result = 0; + for(size_t i = 0; i < size; ++i) { + result += message[i]; + } + return (uint8_t)result; +} + +uint8_t subghz_protocol_blocks_parity8(uint8_t byte) { + byte ^= byte >> 4; + byte &= 0xf; + return (0x6996 >> byte) & 1; +} + +uint8_t subghz_protocol_blocks_parity_bytes(uint8_t const message[], size_t size) { + uint8_t result = 0; + for(size_t i = 0; i < size; ++i) { + result ^= subghz_protocol_blocks_parity8(message[i]); + } + return result; +} + +uint8_t subghz_protocol_blocks_xor_bytes(uint8_t const message[], size_t size) { + uint8_t result = 0; + for(size_t i = 0; i < size; ++i) { + result ^= message[i]; + } + return result; +} \ No newline at end of file diff --git a/applications/debug/subghz_test/protocol/math.h b/applications/debug/subghz_test/protocol/math.h new file mode 100644 index 00000000..dcea3da5 --- /dev/null +++ b/applications/debug/subghz_test/protocol/math.h @@ -0,0 +1,222 @@ +#pragma once + +#include +#include +#include + +#define bit_read(value, bit) (((value) >> (bit)) & 0x01) +#define bit_set(value, bit) \ + ({ \ + __typeof__(value) _one = (1); \ + (value) |= (_one << (bit)); \ + }) +#define bit_clear(value, bit) \ + ({ \ + __typeof__(value) _one = (1); \ + (value) &= ~(_one << (bit)); \ + }) +#define bit_write(value, bit, bitvalue) (bitvalue ? bit_set(value, bit) : bit_clear(value, bit)) +#define DURATION_DIFF(x, y) (((x) < (y)) ? ((y) - (x)) : ((x) - (y))) + +#ifdef __cplusplus +extern "C" { +#endif + +/** Flip the data bitwise + * + * @param key In data + * @param bit_count number of data bits + * + * @return Reverse data + */ +uint64_t subghz_protocol_blocks_reverse_key(uint64_t key, uint8_t bit_count); + +/** Get parity the data bitwise + * + * @param key In data + * @param bit_count number of data bits + * + * @return parity + */ +uint8_t subghz_protocol_blocks_get_parity(uint64_t key, uint8_t bit_count); + +/** CRC-4 + * + * @param message array of bytes to check + * @param size number of bytes in message + * @param polynomial CRC polynomial + * @param init starting crc value + * + * @return CRC value + */ +uint8_t subghz_protocol_blocks_crc4( + uint8_t const message[], + size_t size, + uint8_t polynomial, + uint8_t init); + +/** CRC-7 + * + * @param message array of bytes to check + * @param size number of bytes in message + * @param polynomial CRC polynomial + * @param init starting crc value + * + * @return CRC value + */ +uint8_t subghz_protocol_blocks_crc7( + uint8_t const message[], + size_t size, + uint8_t polynomial, + uint8_t init); + +/** Generic Cyclic Redundancy Check CRC-8. Example polynomial: 0x31 = x8 + x5 + + * x4 + 1 (x8 is implicit) Example polynomial: 0x80 = x8 + x7 (a normal + * bit-by-bit parity XOR) + * + * @param message array of bytes to check + * @param size number of bytes in message + * @param polynomial byte is from x^7 to x^0 (x^8 is implicitly one) + * @param init starting crc value + * + * @return CRC value + */ +uint8_t subghz_protocol_blocks_crc8( + uint8_t const message[], + size_t size, + uint8_t polynomial, + uint8_t init); + +/** "Little-endian" Cyclic Redundancy Check CRC-8 LE Input and output are + * reflected, i.e. least significant bit is shifted in first + * + * @param message array of bytes to check + * @param size number of bytes in message + * @param polynomial CRC polynomial + * @param init starting crc value + * + * @return CRC value + */ +uint8_t subghz_protocol_blocks_crc8le( + uint8_t const message[], + size_t size, + uint8_t polynomial, + uint8_t init); + +/** CRC-16 LSB. Input and output are reflected, i.e. least significant bit is + * shifted in first. Note that poly and init already need to be reflected + * + * @param message array of bytes to check + * @param size number of bytes in message + * @param polynomial CRC polynomial + * @param init starting crc value + * + * @return CRC value + */ +uint16_t subghz_protocol_blocks_crc16lsb( + uint8_t const message[], + size_t size, + uint16_t polynomial, + uint16_t init); + +/** CRC-16 + * + * @param message array of bytes to check + * @param size number of bytes in message + * @param polynomial CRC polynomial + * @param init starting crc value + * + * @return CRC value + */ +uint16_t subghz_protocol_blocks_crc16( + uint8_t const message[], + size_t size, + uint16_t polynomial, + uint16_t init); + +/** Digest-8 by "LFSR-based Toeplitz hash" + * + * @param message bytes of message data + * @param size number of bytes to digest + * @param gen key stream generator, needs to includes the MSB if the + * LFSR is rolling + * @param key initial key + * + * @return digest value + */ +uint8_t subghz_protocol_blocks_lfsr_digest8( + uint8_t const message[], + size_t size, + uint8_t gen, + uint8_t key); + +/** Digest-8 by "LFSR-based Toeplitz hash", byte reflect, bit reflect + * + * @param message bytes of message data + * @param size number of bytes to digest + * @param gen key stream generator, needs to includes the MSB if the + * LFSR is rolling + * @param key initial key + * + * @return digest value + */ +uint8_t subghz_protocol_blocks_lfsr_digest8_reflect( + uint8_t const message[], + size_t size, + uint8_t gen, + uint8_t key); + +/** Digest-16 by "LFSR-based Toeplitz hash" + * + * @param message bytes of message data + * @param size number of bytes to digest + * @param gen key stream generator, needs to includes the MSB if the + * LFSR is rolling + * @param key initial key + * + * @return digest value + */ +uint16_t subghz_protocol_blocks_lfsr_digest16( + uint8_t const message[], + size_t size, + uint16_t gen, + uint16_t key); + +/** Compute Addition of a number of bytes + * + * @param message bytes of message data + * @param size number of bytes to sum + * + * @return summation value + */ +uint8_t subghz_protocol_blocks_add_bytes(uint8_t const message[], size_t size); + +/** Compute bit parity of a single byte (8 bits) + * + * @param byte single byte to check + * + * @return 1 odd parity, 0 even parity + */ +uint8_t subghz_protocol_blocks_parity8(uint8_t byte); + +/** Compute bit parity of a number of bytes + * + * @param message bytes of message data + * @param size number of bytes to sum + * + * @return 1 odd parity, 0 even parity + */ +uint8_t subghz_protocol_blocks_parity_bytes(uint8_t const message[], size_t size); + +/** Compute XOR (byte-wide parity) of a number of bytes + * + * @param message bytes of message data + * @param size number of bytes to sum + * + * @return summation value, per bit-position 1 odd parity, 0 even parity + */ +uint8_t subghz_protocol_blocks_xor_bytes(uint8_t const message[], size_t size); + +#ifdef __cplusplus +} +#endif diff --git a/lib/subghz/protocols/princeton_for_testing.c b/applications/debug/subghz_test/protocol/princeton_for_testing.c similarity index 99% rename from lib/subghz/protocols/princeton_for_testing.c rename to applications/debug/subghz_test/protocol/princeton_for_testing.c index 478d14cd..334a8241 100644 --- a/lib/subghz/protocols/princeton_for_testing.c +++ b/applications/debug/subghz_test/protocol/princeton_for_testing.c @@ -1,7 +1,7 @@ #include "princeton_for_testing.h" #include -#include "../blocks/math.h" +#include "math.h" /* * Help diff --git a/lib/subghz/protocols/princeton_for_testing.h b/applications/debug/subghz_test/protocol/princeton_for_testing.h similarity index 97% rename from lib/subghz/protocols/princeton_for_testing.h rename to applications/debug/subghz_test/protocol/princeton_for_testing.h index 07a37ec5..7b4201d3 100644 --- a/lib/subghz/protocols/princeton_for_testing.h +++ b/applications/debug/subghz_test/protocol/princeton_for_testing.h @@ -1,6 +1,8 @@ #pragma once -#include "base.h" +//#include "base.h" +#include +#include /** SubGhzDecoderPrinceton anonymous type */ typedef struct SubGhzDecoderPrinceton SubGhzDecoderPrinceton; diff --git a/applications/debug/subghz_test/scenes/subghz_test_scene.c b/applications/debug/subghz_test/scenes/subghz_test_scene.c new file mode 100644 index 00000000..ff439ef0 --- /dev/null +++ b/applications/debug/subghz_test/scenes/subghz_test_scene.c @@ -0,0 +1,30 @@ +#include "../subghz_test_app_i.h" + +// Generate scene on_enter handlers array +#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter, +void (*const subghz_test_scene_on_enter_handlers[])(void*) = { +#include "subghz_test_scene_config.h" +}; +#undef ADD_SCENE + +// Generate scene on_event handlers array +#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event, +bool (*const subghz_test_scene_on_event_handlers[])(void* context, SceneManagerEvent event) = { +#include "subghz_test_scene_config.h" +}; +#undef ADD_SCENE + +// Generate scene on_exit handlers array +#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit, +void (*const subghz_test_scene_on_exit_handlers[])(void* context) = { +#include "subghz_test_scene_config.h" +}; +#undef ADD_SCENE + +// Initialize scene handlers configuration structure +const SceneManagerHandlers subghz_test_scene_handlers = { + .on_enter_handlers = subghz_test_scene_on_enter_handlers, + .on_event_handlers = subghz_test_scene_on_event_handlers, + .on_exit_handlers = subghz_test_scene_on_exit_handlers, + .scene_num = SubGhzTestSceneNum, +}; diff --git a/applications/debug/subghz_test/scenes/subghz_test_scene.h b/applications/debug/subghz_test/scenes/subghz_test_scene.h new file mode 100644 index 00000000..0e6e0648 --- /dev/null +++ b/applications/debug/subghz_test/scenes/subghz_test_scene.h @@ -0,0 +1,29 @@ +#pragma once + +#include + +// Generate scene id and total number +#define ADD_SCENE(prefix, name, id) SubGhzTestScene##id, +typedef enum { +#include "subghz_test_scene_config.h" + SubGhzTestSceneNum, +} SubGhzTestScene; +#undef ADD_SCENE + +extern const SceneManagerHandlers subghz_test_scene_handlers; + +// Generate scene on_enter handlers declaration +#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*); +#include "subghz_test_scene_config.h" +#undef ADD_SCENE + +// Generate scene on_event handlers declaration +#define ADD_SCENE(prefix, name, id) \ + bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event); +#include "subghz_test_scene_config.h" +#undef ADD_SCENE + +// Generate scene on_exit handlers declaration +#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context); +#include "subghz_test_scene_config.h" +#undef ADD_SCENE diff --git a/applications/debug/subghz_test/scenes/subghz_test_scene_about.c b/applications/debug/subghz_test/scenes/subghz_test_scene_about.c new file mode 100644 index 00000000..64263d73 --- /dev/null +++ b/applications/debug/subghz_test/scenes/subghz_test_scene_about.c @@ -0,0 +1,66 @@ +#include "../subghz_test_app_i.h" + +void subghz_test_scene_about_widget_callback(GuiButtonType result, InputType type, void* context) { + SubGhzTestApp* app = context; + if(type == InputTypeShort) { + view_dispatcher_send_custom_event(app->view_dispatcher, result); + } +} + +void subghz_test_scene_about_on_enter(void* context) { + SubGhzTestApp* app = context; + + FuriString* temp_str; + temp_str = furi_string_alloc(); + furi_string_printf(temp_str, "\e#%s\n", "Information"); + + furi_string_cat_printf(temp_str, "Version: %s\n", SUBGHZ_TEST_VERSION_APP); + furi_string_cat_printf(temp_str, "Developed by: %s\n", SUBGHZ_TEST_DEVELOPED); + furi_string_cat_printf(temp_str, "Github: %s\n\n", SUBGHZ_TEST_GITHUB); + + furi_string_cat_printf(temp_str, "\e#%s\n", "Description"); + furi_string_cat_printf( + temp_str, + "This application is designed\nto test the functionality of the\nbuilt-in CC1101 module.\n\n"); + + widget_add_text_box_element( + app->widget, + 0, + 0, + 128, + 14, + AlignCenter, + AlignBottom, + "\e#\e! \e!\n", + false); + widget_add_text_box_element( + app->widget, + 0, + 2, + 128, + 14, + AlignCenter, + AlignBottom, + "\e#\e! Sub-Ghz Test \e!\n", + false); + widget_add_text_scroll_element(app->widget, 0, 16, 128, 50, furi_string_get_cstr(temp_str)); + furi_string_free(temp_str); + + view_dispatcher_switch_to_view(app->view_dispatcher, SubGhzTestViewWidget); +} + +bool subghz_test_scene_about_on_event(void* context, SceneManagerEvent event) { + SubGhzTestApp* app = context; + bool consumed = false; + UNUSED(app); + UNUSED(event); + + return consumed; +} + +void subghz_test_scene_about_on_exit(void* context) { + SubGhzTestApp* app = context; + + // Clear views + widget_reset(app->widget); +} diff --git a/applications/debug/subghz_test/scenes/subghz_test_scene_carrier.c b/applications/debug/subghz_test/scenes/subghz_test_scene_carrier.c new file mode 100644 index 00000000..41ff5c8c --- /dev/null +++ b/applications/debug/subghz_test/scenes/subghz_test_scene_carrier.c @@ -0,0 +1,29 @@ +#include "../subghz_test_app_i.h" + +void subghz_test_scene_carrier_callback(SubGhzTestCarrierEvent event, void* context) { + furi_assert(context); + SubGhzTestApp* app = context; + view_dispatcher_send_custom_event(app->view_dispatcher, event); +} + +void subghz_test_scene_carrier_on_enter(void* context) { + SubGhzTestApp* app = context; + subghz_test_carrier_set_callback( + app->subghz_test_carrier, subghz_test_scene_carrier_callback, app); + view_dispatcher_switch_to_view(app->view_dispatcher, SubGhzTestViewCarrier); +} + +bool subghz_test_scene_carrier_on_event(void* context, SceneManagerEvent event) { + SubGhzTestApp* app = context; + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == SubGhzTestCarrierEventOnlyRx) { + scene_manager_next_scene(app->scene_manager, SubGhzTestSceneShowOnlyRx); + return true; + } + } + return false; +} + +void subghz_test_scene_carrier_on_exit(void* context) { + UNUSED(context); +} diff --git a/applications/debug/subghz_test/scenes/subghz_test_scene_config.h b/applications/debug/subghz_test/scenes/subghz_test_scene_config.h new file mode 100644 index 00000000..80a42c37 --- /dev/null +++ b/applications/debug/subghz_test/scenes/subghz_test_scene_config.h @@ -0,0 +1,6 @@ +ADD_SCENE(subghz_test, start, Start) +ADD_SCENE(subghz_test, about, About) +ADD_SCENE(subghz_test, carrier, Carrier) +ADD_SCENE(subghz_test, packet, Packet) +ADD_SCENE(subghz_test, static, Static) +ADD_SCENE(subghz_test, show_only_rx, ShowOnlyRx) diff --git a/applications/debug/subghz_test/scenes/subghz_test_scene_packet.c b/applications/debug/subghz_test/scenes/subghz_test_scene_packet.c new file mode 100644 index 00000000..b43a4d0c --- /dev/null +++ b/applications/debug/subghz_test/scenes/subghz_test_scene_packet.c @@ -0,0 +1,29 @@ +#include "../subghz_test_app_i.h" + +void subghz_test_scene_packet_callback(SubGhzTestPacketEvent event, void* context) { + furi_assert(context); + SubGhzTestApp* app = context; + view_dispatcher_send_custom_event(app->view_dispatcher, event); +} + +void subghz_test_scene_packet_on_enter(void* context) { + SubGhzTestApp* app = context; + subghz_test_packet_set_callback( + app->subghz_test_packet, subghz_test_scene_packet_callback, app); + view_dispatcher_switch_to_view(app->view_dispatcher, SubGhzTestViewPacket); +} + +bool subghz_test_scene_packet_on_event(void* context, SceneManagerEvent event) { + SubGhzTestApp* app = context; + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == SubGhzTestPacketEventOnlyRx) { + scene_manager_next_scene(app->scene_manager, SubGhzTestSceneShowOnlyRx); + return true; + } + } + return false; +} + +void subghz_test_scene_packet_on_exit(void* context) { + UNUSED(context); +} diff --git a/applications/debug/subghz_test/scenes/subghz_test_scene_show_only_rx.c b/applications/debug/subghz_test/scenes/subghz_test_scene_show_only_rx.c new file mode 100644 index 00000000..3d5a5435 --- /dev/null +++ b/applications/debug/subghz_test/scenes/subghz_test_scene_show_only_rx.c @@ -0,0 +1,49 @@ +#include "../subghz_test_app_i.h" +#include + +void subghz_test_scene_show_only_rx_popup_callback(void* context) { + SubGhzTestApp* app = context; + view_dispatcher_send_custom_event(app->view_dispatcher, SubGhzTestCustomEventSceneShowOnlyRX); +} + +void subghz_test_scene_show_only_rx_on_enter(void* context) { + SubGhzTestApp* app = context; + + // Setup view + Popup* popup = app->popup; + + const char* header_text = "Transmission is blocked"; + const char* message_text = "Transmission on\nthis frequency is\nrestricted in\nyour region"; + if(!furi_hal_region_is_provisioned()) { + header_text = "Firmware update needed"; + message_text = "Please update\nfirmware before\nusing this feature\nflipp.dev/upd"; + } + + popup_set_header(popup, header_text, 63, 3, AlignCenter, AlignTop); + popup_set_text(popup, message_text, 0, 17, AlignLeft, AlignTop); + popup_set_icon(popup, 72, 17, &I_DolphinCommon_56x48); + + popup_set_timeout(popup, 1500); + popup_set_context(popup, app); + popup_set_callback(popup, subghz_test_scene_show_only_rx_popup_callback); + popup_enable_timeout(popup); + view_dispatcher_switch_to_view(app->view_dispatcher, SubGhzTestViewPopup); +} + +bool subghz_test_scene_show_only_rx_on_event(void* context, SceneManagerEvent event) { + SubGhzTestApp* app = context; + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == SubGhzTestCustomEventSceneShowOnlyRX) { + scene_manager_previous_scene(app->scene_manager); + return true; + } + } + return false; +} + +void subghz_test_scene_show_only_rx_on_exit(void* context) { + SubGhzTestApp* app = context; + Popup* popup = app->popup; + + popup_reset(popup); +} diff --git a/applications/debug/subghz_test/scenes/subghz_test_scene_start.c b/applications/debug/subghz_test/scenes/subghz_test_scene_start.c new file mode 100644 index 00000000..cf3b0816 --- /dev/null +++ b/applications/debug/subghz_test/scenes/subghz_test_scene_start.c @@ -0,0 +1,77 @@ +#include "../subghz_test_app_i.h" + +typedef enum { + SubmenuIndexSubGhzTestCarrier, + SubmenuIndexSubGhzTestPacket, + SubmenuIndexSubGhzTestStatic, + SubmenuIndexSubGhzTestAbout, +} SubmenuIndex; + +void subghz_test_scene_start_submenu_callback(void* context, uint32_t index) { + SubGhzTestApp* app = context; + view_dispatcher_send_custom_event(app->view_dispatcher, index); +} + +void subghz_test_scene_start_on_enter(void* context) { + SubGhzTestApp* app = context; + Submenu* submenu = app->submenu; + + submenu_add_item( + submenu, + "Carrier", + SubmenuIndexSubGhzTestCarrier, + subghz_test_scene_start_submenu_callback, + app); + submenu_add_item( + submenu, + "Packet", + SubmenuIndexSubGhzTestPacket, + subghz_test_scene_start_submenu_callback, + app); + submenu_add_item( + submenu, + "Static", + SubmenuIndexSubGhzTestStatic, + subghz_test_scene_start_submenu_callback, + app); + submenu_add_item( + submenu, + "About", + SubmenuIndexSubGhzTestAbout, + subghz_test_scene_start_submenu_callback, + app); + + submenu_set_selected_item( + submenu, scene_manager_get_scene_state(app->scene_manager, SubGhzTestSceneStart)); + + view_dispatcher_switch_to_view(app->view_dispatcher, SubGhzTestViewSubmenu); +} + +bool subghz_test_scene_start_on_event(void* context, SceneManagerEvent event) { + SubGhzTestApp* app = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == SubmenuIndexSubGhzTestAbout) { + scene_manager_next_scene(app->scene_manager, SubGhzTestSceneAbout); + consumed = true; + } else if(event.event == SubmenuIndexSubGhzTestCarrier) { + scene_manager_next_scene(app->scene_manager, SubGhzTestSceneCarrier); + consumed = true; + } else if(event.event == SubmenuIndexSubGhzTestPacket) { + scene_manager_next_scene(app->scene_manager, SubGhzTestScenePacket); + consumed = true; + } else if(event.event == SubmenuIndexSubGhzTestStatic) { + scene_manager_next_scene(app->scene_manager, SubGhzTestSceneStatic); + consumed = true; + } + scene_manager_set_scene_state(app->scene_manager, SubGhzTestSceneStart, event.event); + } + + return consumed; +} + +void subghz_test_scene_start_on_exit(void* context) { + SubGhzTestApp* app = context; + submenu_reset(app->submenu); +} diff --git a/applications/debug/subghz_test/scenes/subghz_test_scene_static.c b/applications/debug/subghz_test/scenes/subghz_test_scene_static.c new file mode 100644 index 00000000..a008d243 --- /dev/null +++ b/applications/debug/subghz_test/scenes/subghz_test_scene_static.c @@ -0,0 +1,29 @@ +#include "../subghz_test_app_i.h" + +void subghz_test_scene_static_callback(SubGhzTestStaticEvent event, void* context) { + furi_assert(context); + SubGhzTestApp* app = context; + view_dispatcher_send_custom_event(app->view_dispatcher, event); +} + +void subghz_test_scene_static_on_enter(void* context) { + SubGhzTestApp* app = context; + subghz_test_static_set_callback( + app->subghz_test_static, subghz_test_scene_static_callback, app); + view_dispatcher_switch_to_view(app->view_dispatcher, SubGhzTestViewStatic); +} + +bool subghz_test_scene_static_on_event(void* context, SceneManagerEvent event) { + SubGhzTestApp* app = context; + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == SubGhzTestStaticEventOnlyRx) { + scene_manager_next_scene(app->scene_manager, SubGhzTestSceneShowOnlyRx); + return true; + } + } + return false; +} + +void subghz_test_scene_static_on_exit(void* context) { + UNUSED(context); +} diff --git a/applications/debug/subghz_test/subghz_test_10px.png b/applications/debug/subghz_test/subghz_test_10px.png new file mode 100644 index 00000000..10dac0ec Binary files /dev/null and b/applications/debug/subghz_test/subghz_test_10px.png differ diff --git a/applications/debug/subghz_test/subghz_test_app.c b/applications/debug/subghz_test/subghz_test_app.c new file mode 100644 index 00000000..704941fb --- /dev/null +++ b/applications/debug/subghz_test/subghz_test_app.c @@ -0,0 +1,139 @@ +#include "subghz_test_app_i.h" + +#include +#include + +static bool subghz_test_app_custom_event_callback(void* context, uint32_t event) { + furi_assert(context); + SubGhzTestApp* app = context; + return scene_manager_handle_custom_event(app->scene_manager, event); +} + +static bool subghz_test_app_back_event_callback(void* context) { + furi_assert(context); + SubGhzTestApp* app = context; + return scene_manager_handle_back_event(app->scene_manager); +} + +static void subghz_test_app_tick_event_callback(void* context) { + furi_assert(context); + SubGhzTestApp* app = context; + scene_manager_handle_tick_event(app->scene_manager); +} + +SubGhzTestApp* subghz_test_app_alloc() { + SubGhzTestApp* app = malloc(sizeof(SubGhzTestApp)); + + // GUI + app->gui = furi_record_open(RECORD_GUI); + + // View Dispatcher + app->view_dispatcher = view_dispatcher_alloc(); + app->scene_manager = scene_manager_alloc(&subghz_test_scene_handlers, app); + view_dispatcher_enable_queue(app->view_dispatcher); + + view_dispatcher_set_event_callback_context(app->view_dispatcher, app); + view_dispatcher_set_custom_event_callback( + app->view_dispatcher, subghz_test_app_custom_event_callback); + view_dispatcher_set_navigation_event_callback( + app->view_dispatcher, subghz_test_app_back_event_callback); + view_dispatcher_set_tick_event_callback( + app->view_dispatcher, subghz_test_app_tick_event_callback, 100); + + view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); + + // Open Notification record + app->notifications = furi_record_open(RECORD_NOTIFICATION); + + // SubMenu + app->submenu = submenu_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, SubGhzTestViewSubmenu, submenu_get_view(app->submenu)); + + // Widget + app->widget = widget_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, SubGhzTestViewWidget, widget_get_view(app->widget)); + + // Popup + app->popup = popup_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, SubGhzTestViewPopup, popup_get_view(app->popup)); + + // Carrier Test Module + app->subghz_test_carrier = subghz_test_carrier_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, + SubGhzTestViewCarrier, + subghz_test_carrier_get_view(app->subghz_test_carrier)); + + // Packet Test + app->subghz_test_packet = subghz_test_packet_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, + SubGhzTestViewPacket, + subghz_test_packet_get_view(app->subghz_test_packet)); + + // Static send + app->subghz_test_static = subghz_test_static_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, + SubGhzTestViewStatic, + subghz_test_static_get_view(app->subghz_test_static)); + + scene_manager_next_scene(app->scene_manager, SubGhzTestSceneStart); + + return app; +} + +void subghz_test_app_free(SubGhzTestApp* app) { + furi_assert(app); + + // Submenu + view_dispatcher_remove_view(app->view_dispatcher, SubGhzTestViewSubmenu); + submenu_free(app->submenu); + + // Widget + view_dispatcher_remove_view(app->view_dispatcher, SubGhzTestViewWidget); + widget_free(app->widget); + + // Popup + view_dispatcher_remove_view(app->view_dispatcher, SubGhzTestViewPopup); + popup_free(app->popup); + + // Carrier Test + view_dispatcher_remove_view(app->view_dispatcher, SubGhzTestViewCarrier); + subghz_test_carrier_free(app->subghz_test_carrier); + + // Packet Test + view_dispatcher_remove_view(app->view_dispatcher, SubGhzTestViewPacket); + subghz_test_packet_free(app->subghz_test_packet); + + // Static + view_dispatcher_remove_view(app->view_dispatcher, SubGhzTestViewStatic); + subghz_test_static_free(app->subghz_test_static); + + // View dispatcher + view_dispatcher_free(app->view_dispatcher); + scene_manager_free(app->scene_manager); + + // Notifications + furi_record_close(RECORD_NOTIFICATION); + app->notifications = NULL; + + // Close records + furi_record_close(RECORD_GUI); + + free(app); +} + +int32_t subghz_test_app(void* p) { + UNUSED(p); + SubGhzTestApp* subghz_test_app = subghz_test_app_alloc(); + + view_dispatcher_run(subghz_test_app->view_dispatcher); + + subghz_test_app_free(subghz_test_app); + + return 0; +} diff --git a/applications/debug/subghz_test/subghz_test_app_i.c b/applications/debug/subghz_test/subghz_test_app_i.c new file mode 100644 index 00000000..0ec6635a --- /dev/null +++ b/applications/debug/subghz_test/subghz_test_app_i.c @@ -0,0 +1,5 @@ +#include "subghz_test_app_i.h" + +#include + +#define TAG "SubGhzTest" diff --git a/applications/debug/subghz_test/subghz_test_app_i.h b/applications/debug/subghz_test/subghz_test_app_i.h new file mode 100644 index 00000000..c96f9c4e --- /dev/null +++ b/applications/debug/subghz_test/subghz_test_app_i.h @@ -0,0 +1,32 @@ +#pragma once + +#include "helpers/subghz_test_types.h" +#include "helpers/subghz_test_event.h" + +#include "scenes/subghz_test_scene.h" +#include +#include +#include +#include +#include +#include +#include + +#include "views/subghz_test_static.h" +#include "views/subghz_test_carrier.h" +#include "views/subghz_test_packet.h" + +typedef struct SubGhzTestApp SubGhzTestApp; + +struct SubGhzTestApp { + Gui* gui; + ViewDispatcher* view_dispatcher; + SceneManager* scene_manager; + NotificationApp* notifications; + Submenu* submenu; + Widget* widget; + Popup* popup; + SubGhzTestStatic* subghz_test_static; + SubGhzTestCarrier* subghz_test_carrier; + SubGhzTestPacket* subghz_test_packet; +}; diff --git a/applications/main/subghz/views/subghz_test_carrier.c b/applications/debug/subghz_test/views/subghz_test_carrier.c similarity index 98% rename from applications/main/subghz/views/subghz_test_carrier.c rename to applications/debug/subghz_test/views/subghz_test_carrier.c index 254a4127..53e309b7 100644 --- a/applications/main/subghz/views/subghz_test_carrier.c +++ b/applications/debug/subghz_test/views/subghz_test_carrier.c @@ -1,6 +1,6 @@ #include "subghz_test_carrier.h" -#include "../subghz_i.h" -#include "../helpers/subghz_testing.h" +#include "../subghz_test_app_i.h" +#include "../helpers/subghz_test_frequency.h" #include #include diff --git a/applications/main/subghz/views/subghz_test_carrier.h b/applications/debug/subghz_test/views/subghz_test_carrier.h similarity index 100% rename from applications/main/subghz/views/subghz_test_carrier.h rename to applications/debug/subghz_test/views/subghz_test_carrier.h diff --git a/applications/main/subghz/views/subghz_test_packet.c b/applications/debug/subghz_test/views/subghz_test_packet.c similarity index 98% rename from applications/main/subghz/views/subghz_test_packet.c rename to applications/debug/subghz_test/views/subghz_test_packet.c index bc2c474b..bab83ab5 100644 --- a/applications/main/subghz/views/subghz_test_packet.c +++ b/applications/debug/subghz_test/views/subghz_test_packet.c @@ -1,6 +1,6 @@ #include "subghz_test_packet.h" -#include "../subghz_i.h" -#include "../helpers/subghz_testing.h" +#include "../subghz_test_app_i.h" +#include "../helpers/subghz_test_frequency.h" #include #include @@ -8,7 +8,7 @@ #include #include #include -#include +#include "../protocol/princeton_for_testing.h" #define SUBGHZ_TEST_PACKET_COUNT 500 diff --git a/applications/main/subghz/views/subghz_test_packet.h b/applications/debug/subghz_test/views/subghz_test_packet.h similarity index 100% rename from applications/main/subghz/views/subghz_test_packet.h rename to applications/debug/subghz_test/views/subghz_test_packet.h diff --git a/applications/main/subghz/views/subghz_test_static.c b/applications/debug/subghz_test/views/subghz_test_static.c similarity index 98% rename from applications/main/subghz/views/subghz_test_static.c rename to applications/debug/subghz_test/views/subghz_test_static.c index 197af21f..6764fd5c 100644 --- a/applications/main/subghz/views/subghz_test_static.c +++ b/applications/debug/subghz_test/views/subghz_test_static.c @@ -1,6 +1,6 @@ #include "subghz_test_static.h" -#include "../subghz_i.h" -#include "../helpers/subghz_testing.h" +#include "../subghz_test_app_i.h" +#include "../helpers/subghz_test_frequency.h" #include #include @@ -8,7 +8,7 @@ #include #include #include -#include +#include "../protocol/princeton_for_testing.h" #define TAG "SubGhzTestStatic" diff --git a/applications/main/subghz/views/subghz_test_static.h b/applications/debug/subghz_test/views/subghz_test_static.h similarity index 100% rename from applications/main/subghz/views/subghz_test_static.h rename to applications/debug/subghz_test/views/subghz_test_static.h diff --git a/applications/debug/unit_tests/infrared/infrared_test.c b/applications/debug/unit_tests/infrared/infrared_test.c index 2bcb95da..b2acad47 100644 --- a/applications/debug/unit_tests/infrared/infrared_test.c +++ b/applications/debug/unit_tests/infrared/infrared_test.c @@ -425,6 +425,7 @@ MU_TEST(infrared_test_decoder_mixed) { infrared_test_run_decoder(InfraredProtocolSamsung32, 1); infrared_test_run_decoder(InfraredProtocolSIRC, 3); infrared_test_run_decoder(InfraredProtocolKaseikyo, 1); + infrared_test_run_decoder(InfraredProtocolRCA, 1); } MU_TEST(infrared_test_decoder_nec) { @@ -499,6 +500,15 @@ MU_TEST(infrared_test_decoder_kaseikyo) { infrared_test_run_decoder(InfraredProtocolKaseikyo, 6); } +MU_TEST(infrared_test_decoder_rca) { + infrared_test_run_decoder(InfraredProtocolRCA, 1); + infrared_test_run_decoder(InfraredProtocolRCA, 2); + infrared_test_run_decoder(InfraredProtocolRCA, 3); + infrared_test_run_decoder(InfraredProtocolRCA, 4); + infrared_test_run_decoder(InfraredProtocolRCA, 5); + infrared_test_run_decoder(InfraredProtocolRCA, 6); +} + MU_TEST(infrared_test_encoder_decoder_all) { infrared_test_run_encoder_decoder(InfraredProtocolNEC, 1); infrared_test_run_encoder_decoder(InfraredProtocolNECext, 1); @@ -509,6 +519,7 @@ MU_TEST(infrared_test_encoder_decoder_all) { infrared_test_run_encoder_decoder(InfraredProtocolRC5, 1); infrared_test_run_encoder_decoder(InfraredProtocolSIRC, 1); infrared_test_run_encoder_decoder(InfraredProtocolKaseikyo, 1); + infrared_test_run_encoder_decoder(InfraredProtocolRCA, 1); } MU_TEST_SUITE(infrared_test) { @@ -527,6 +538,7 @@ MU_TEST_SUITE(infrared_test) { MU_RUN_TEST(infrared_test_decoder_samsung32); MU_RUN_TEST(infrared_test_decoder_necext1); MU_RUN_TEST(infrared_test_decoder_kaseikyo); + MU_RUN_TEST(infrared_test_decoder_rca); MU_RUN_TEST(infrared_test_decoder_mixed); MU_RUN_TEST(infrared_test_encoder_decoder_all); } diff --git a/applications/drivers/subghz/application.fam b/applications/drivers/subghz/application.fam index aaf0e1bd..2ee11483 100644 --- a/applications/drivers/subghz/application.fam +++ b/applications/drivers/subghz/application.fam @@ -4,5 +4,6 @@ App( targets=["f7"], entry_point="subghz_device_cc1101_ext_ep", requires=["subghz"], + sdk_headers=["cc1101_ext/cc1101_ext_interconnect.h"], fap_libs=["hwdrivers"], ) diff --git a/applications/examples/example_thermo/README.md b/applications/examples/example_thermo/README.md index 08240a1f..d298de64 100644 --- a/applications/examples/example_thermo/README.md +++ b/applications/examples/example_thermo/README.md @@ -18,7 +18,7 @@ Before launching the application, connect the sensor to Flipper's external GPIO In order to launch this demo, follow the steps below: 1. Make sure your Flipper has an SD card installed. 2. Connect your Flipper to the computer via a USB cable. -3. Run `./fbt launch_app APPSRC=example_thermo` in your terminal emulator of choice. +3. Run `./fbt launch APPSRC=example_thermo` in your terminal emulator of choice. ## Changing the data pin It is possible to use other GPIO pin as a 1-Wire data pin. In order to change it, set the `THERMO_GPIO_PIN` macro to any of the options listed below: diff --git a/applications/external/weather_station/protocols/oregon3.c b/applications/external/weather_station/protocols/oregon3.c index a211c5ad..bd35c2fd 100644 --- a/applications/external/weather_station/protocols/oregon3.c +++ b/applications/external/weather_station/protocols/oregon3.c @@ -116,9 +116,11 @@ static ManchesterEvent level_and_duration_to_event(bool level, uint32_t duration static uint8_t oregon3_sensor_id_var_bits(uint16_t sensor_id) { switch(sensor_id) { case ID_THGR221: - default: // nibbles: temp + hum + '0' return (4 + 2 + 1) * 4; + default: + FURI_LOG_D(TAG, "Unsupported sensor id 0x%x", sensor_id); + return 0; } } @@ -198,10 +200,8 @@ void ws_protocol_decoder_oregon3_feed(void* context, bool level, uint32_t durati oregon3_sensor_id_var_bits(OREGON3_SENSOR_ID(instance->generic.data)); if(!instance->var_bits) { - // sensor is not supported, stop decoding, but showing the decoded fixed part + // sensor is not supported, stop decoding instance->decoder.parser_step = Oregon3DecoderStepReset; - if(instance->base.callback) - instance->base.callback(&instance->base, instance->base.context); } else { instance->decoder.parser_step = Oregon3DecoderStepVarData; } diff --git a/applications/main/application.fam b/applications/main/application.fam index 75d55af9..0a90ee22 100644 --- a/applications/main/application.fam +++ b/applications/main/application.fam @@ -4,7 +4,6 @@ App( apptype=FlipperAppType.METAPACKAGE, provides=[ "gpio", - "onewire", "ibutton", "infrared", "lfrfid", @@ -13,5 +12,20 @@ App( "bad_usb", "u2f", "archive", + "main_apps_on_start", + ], +) + +App( + appid="main_apps_on_start", + name="On start hooks", + apptype=FlipperAppType.METAPACKAGE, + provides=[ + "ibutton_start", + "onewire_start", + "subghz_start", + "infrared_start", + "lfrfid_start", + "nfc_start", ], ) diff --git a/applications/main/archive/helpers/archive_browser.c b/applications/main/archive/helpers/archive_browser.c index 70137d69..51457fe8 100644 --- a/applications/main/archive/helpers/archive_browser.c +++ b/applications/main/archive/helpers/archive_browser.c @@ -64,8 +64,20 @@ static void if(!is_last) { archive_add_file_item(browser, is_folder, furi_string_get_cstr(item_path)); } else { + bool load_again = false; with_view_model( - browser->view, ArchiveBrowserViewModel * model, { model->list_loading = false; }, true); + browser->view, + ArchiveBrowserViewModel * model, + { + model->list_loading = false; + if(archive_is_file_list_load_required(model)) { + load_again = true; + } + }, + true); + if(load_again) { + archive_file_array_load(browser, 0); + } } } @@ -111,6 +123,26 @@ bool archive_is_item_in_array(ArchiveBrowserViewModel* model, uint32_t idx) { return true; } +bool archive_is_file_list_load_required(ArchiveBrowserViewModel* model) { + size_t array_size = files_array_size(model->files); + + if((model->list_loading) || (array_size >= model->item_cnt)) { + return false; + } + + if((model->array_offset > 0) && + (model->item_idx < (model->array_offset + FILE_LIST_BUF_LEN / 4))) { + return true; + } + + if(((model->array_offset + array_size) < model->item_cnt) && + (model->item_idx > (int32_t)(model->array_offset + array_size - FILE_LIST_BUF_LEN / 4))) { + return true; + } + + return false; +} + void archive_update_offset(ArchiveBrowserView* browser) { furi_assert(browser); diff --git a/applications/main/archive/helpers/archive_browser.h b/applications/main/archive/helpers/archive_browser.h index 09ffea1f..5e66a3db 100644 --- a/applications/main/archive/helpers/archive_browser.h +++ b/applications/main/archive/helpers/archive_browser.h @@ -64,6 +64,7 @@ inline bool archive_is_known_app(ArchiveFileTypeEnum type) { } bool archive_is_item_in_array(ArchiveBrowserViewModel* model, uint32_t idx); +bool archive_is_file_list_load_required(ArchiveBrowserViewModel* model); void archive_update_offset(ArchiveBrowserView* browser); void archive_update_focus(ArchiveBrowserView* browser, const char* target); diff --git a/applications/main/archive/scenes/archive_scene_browser.c b/applications/main/archive/scenes/archive_scene_browser.c index e02f7622..370830a0 100644 --- a/applications/main/archive/scenes/archive_scene_browser.c +++ b/applications/main/archive/scenes/archive_scene_browser.c @@ -5,13 +5,14 @@ #include "../helpers/archive_browser.h" #include "../views/archive_browser_view.h" #include "archive/scenes/archive_scene.h" +#include #define TAG "ArchiveSceneBrowser" #define SCENE_STATE_DEFAULT (0) #define SCENE_STATE_NEED_REFRESH (1) -const char* archive_get_flipper_app_name(ArchiveFileTypeEnum file_type) { +static const char* archive_get_flipper_app_name(ArchiveFileTypeEnum file_type) { switch(file_type) { case ArchiveFileTypeIButton: return "iButton"; diff --git a/applications/main/archive/views/archive_browser_view.c b/applications/main/archive/views/archive_browser_view.c index 3c2f1321..ba147f74 100644 --- a/applications/main/archive/views/archive_browser_view.c +++ b/applications/main/archive/views/archive_browser_view.c @@ -248,24 +248,10 @@ View* archive_browser_get_view(ArchiveBrowserView* browser) { return browser->view; } -static bool is_file_list_load_required(ArchiveBrowserViewModel* model) { - size_t array_size = files_array_size(model->files); - - if((model->list_loading) || (array_size >= model->item_cnt)) { - return false; +static void file_list_rollover(ArchiveBrowserViewModel* model) { + if(!model->list_loading && files_array_size(model->files) < model->item_cnt) { + files_array_reset(model->files); } - - if((model->array_offset > 0) && - (model->item_idx < (model->array_offset + FILE_LIST_BUF_LEN / 4))) { - return true; - } - - if(((model->array_offset + array_size) < model->item_cnt) && - (model->item_idx > (int32_t)(model->array_offset + array_size - FILE_LIST_BUF_LEN / 4))) { - return true; - } - - return false; } static bool archive_view_input(InputEvent* event, void* context) { @@ -347,12 +333,13 @@ static bool archive_view_input(InputEvent* event, void* context) { if(model->item_idx < scroll_speed) { model->button_held_for_ticks = 0; model->item_idx = model->item_cnt - 1; + file_list_rollover(model); } else { model->item_idx = ((model->item_idx - scroll_speed) + model->item_cnt) % model->item_cnt; } - if(is_file_list_load_required(model)) { + if(archive_is_file_list_load_required(model)) { model->list_loading = true; browser->callback(ArchiveBrowserEventLoadPrevItems, browser->context); } @@ -366,10 +353,11 @@ static bool archive_view_input(InputEvent* event, void* context) { if(model->item_idx + scroll_speed >= count) { model->button_held_for_ticks = 0; model->item_idx = 0; + file_list_rollover(model); } else { model->item_idx = (model->item_idx + scroll_speed) % model->item_cnt; } - if(is_file_list_load_required(model)) { + if(archive_is_file_list_load_required(model)) { model->list_loading = true; browser->callback(ArchiveBrowserEventLoadNextItems, browser->context); } diff --git a/applications/main/bad_usb/application.fam b/applications/main/bad_usb/application.fam index 2442dd3a..5c42c9fa 100644 --- a/applications/main/bad_usb/application.fam +++ b/applications/main/bad_usb/application.fam @@ -1,15 +1,12 @@ App( appid="bad_usb", name="Bad USB", - apptype=FlipperAppType.APP, + apptype=FlipperAppType.MENUEXTERNAL, entry_point="bad_usb_app", - cdefines=["APP_BAD_USB"], - requires=[ - "gui", - "dialogs", - ], stack_size=2 * 1024, icon="A_BadUsb_14", order=70, fap_libs=["assets"], + fap_icon="icon.png", + fap_category="USB", ) diff --git a/applications/main/bad_usb/icon.png b/applications/main/bad_usb/icon.png new file mode 100644 index 00000000..037474aa Binary files /dev/null and b/applications/main/bad_usb/icon.png differ diff --git a/applications/main/gpio/application.fam b/applications/main/gpio/application.fam index efeb8b6f..76391992 100644 --- a/applications/main/gpio/application.fam +++ b/applications/main/gpio/application.fam @@ -1,12 +1,12 @@ App( appid="gpio", name="GPIO", - apptype=FlipperAppType.APP, + apptype=FlipperAppType.MENUEXTERNAL, entry_point="gpio_app", - cdefines=["APP_GPIO"], - requires=["gui"], stack_size=1 * 1024, icon="A_GPIO_14", order=50, fap_libs=["assets"], + fap_icon="icon.png", + fap_category="GPIO", ) diff --git a/applications/main/gpio/icon.png b/applications/main/gpio/icon.png new file mode 100644 index 00000000..4a6eccf0 Binary files /dev/null and b/applications/main/gpio/icon.png differ diff --git a/applications/main/ibutton/application.fam b/applications/main/ibutton/application.fam index 06968bba..a8faa629 100644 --- a/applications/main/ibutton/application.fam +++ b/applications/main/ibutton/application.fam @@ -1,25 +1,21 @@ App( appid="ibutton", name="iButton", - apptype=FlipperAppType.APP, + apptype=FlipperAppType.MENUEXTERNAL, targets=["f7"], entry_point="ibutton_app", - cdefines=["APP_IBUTTON"], - requires=[ - "gui", - "dialogs", - ], - provides=["ibutton_start"], icon="A_iButton_14", stack_size=2 * 1024, order=60, fap_libs=["assets"], + fap_icon="icon.png", + fap_category="iButton", ) App( appid="ibutton_start", apptype=FlipperAppType.STARTUP, + targets=["f7"], entry_point="ibutton_on_system_start", - requires=["ibutton"], order=60, ) diff --git a/applications/main/ibutton/icon.png b/applications/main/ibutton/icon.png new file mode 100644 index 00000000..2fdaf123 Binary files /dev/null and b/applications/main/ibutton/icon.png differ diff --git a/applications/main/ibutton/scenes/ibutton_scene_delete_confirm.c b/applications/main/ibutton/scenes/ibutton_scene_delete_confirm.c index 587cb748..b293af95 100644 --- a/applications/main/ibutton/scenes/ibutton_scene_delete_confirm.c +++ b/applications/main/ibutton/scenes/ibutton_scene_delete_confirm.c @@ -12,15 +12,15 @@ void ibutton_scene_delete_confirm_on_enter(void* context) { widget_add_button_element( widget, GuiButtonTypeRight, "Delete", ibutton_widget_callback, context); - furi_string_printf(tmp, "Delete %s?", ibutton->key_name); - widget_add_string_element( - widget, 128 / 2, 0, AlignCenter, AlignTop, FontPrimary, furi_string_get_cstr(tmp)); + furi_string_printf(tmp, "\e#Delete %s?\e#", ibutton->key_name); + widget_add_text_box_element( + widget, 0, 0, 128, 23, AlignCenter, AlignCenter, furi_string_get_cstr(tmp), false); furi_string_reset(tmp); ibutton_protocols_render_brief_data(ibutton->protocols, key, tmp); widget_add_string_multiline_element( - widget, 128 / 2, 16, AlignCenter, AlignTop, FontSecondary, furi_string_get_cstr(tmp)); + widget, 128 / 2, 24, AlignCenter, AlignTop, FontSecondary, furi_string_get_cstr(tmp)); view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewWidget); furi_string_free(tmp); diff --git a/applications/main/infrared/application.fam b/applications/main/infrared/application.fam index e5483e9f..b78b088a 100644 --- a/applications/main/infrared/application.fam +++ b/applications/main/infrared/application.fam @@ -1,25 +1,21 @@ App( appid="infrared", name="Infrared", - apptype=FlipperAppType.APP, + apptype=FlipperAppType.MENUEXTERNAL, entry_point="infrared_app", targets=["f7"], - cdefines=["APP_INFRARED"], - requires=[ - "gui", - "dialogs", - ], - provides=["infrared_start"], icon="A_Infrared_14", stack_size=3 * 1024, order=40, fap_libs=["assets"], + fap_icon="icon.png", + fap_category="Infrared", ) App( appid="infrared_start", apptype=FlipperAppType.STARTUP, + targets=["f7"], entry_point="infrared_on_system_start", - requires=["infrared"], order=20, ) diff --git a/applications/main/infrared/icon.png b/applications/main/infrared/icon.png new file mode 100644 index 00000000..22c98618 Binary files /dev/null and b/applications/main/infrared/icon.png differ diff --git a/applications/main/lfrfid/application.fam b/applications/main/lfrfid/application.fam index 8fe1bac4..cad07fbf 100644 --- a/applications/main/lfrfid/application.fam +++ b/applications/main/lfrfid/application.fam @@ -1,27 +1,21 @@ App( appid="lfrfid", name="125 kHz RFID", - apptype=FlipperAppType.APP, + apptype=FlipperAppType.MENUEXTERNAL, targets=["f7"], entry_point="lfrfid_app", - cdefines=["APP_LF_RFID"], - requires=[ - "gui", - "dialogs", - ], - provides=[ - "lfrfid_start", - ], icon="A_125khz_14", stack_size=2 * 1024, order=20, fap_libs=["assets"], + fap_icon="icon.png", + fap_category="RFID", ) App( appid="lfrfid_start", + targets=["f7"], apptype=FlipperAppType.STARTUP, entry_point="lfrfid_on_system_start", - requires=["lfrfid"], order=50, ) diff --git a/applications/main/lfrfid/icon.png b/applications/main/lfrfid/icon.png new file mode 100644 index 00000000..ce01284a Binary files /dev/null and b/applications/main/lfrfid/icon.png differ diff --git a/applications/main/nfc/application.fam b/applications/main/nfc/application.fam index f0912704..bc34d4e6 100644 --- a/applications/main/nfc/application.fam +++ b/applications/main/nfc/application.fam @@ -1,24 +1,21 @@ App( appid="nfc", name="NFC", - apptype=FlipperAppType.APP, + apptype=FlipperAppType.MENUEXTERNAL, targets=["f7"], entry_point="nfc_app", - cdefines=["APP_NFC"], - requires=[ - "gui", - "dialogs", - ], - provides=["nfc_start"], icon="A_NFC_14", stack_size=5 * 1024, order=30, + fap_libs=["assets"], + fap_icon="icon.png", + fap_category="NFC", ) App( appid="nfc_start", + targets=["f7"], apptype=FlipperAppType.STARTUP, entry_point="nfc_on_system_start", - requires=["nfc"], order=30, ) diff --git a/applications/main/nfc/icon.png b/applications/main/nfc/icon.png new file mode 100644 index 00000000..6bc02711 Binary files /dev/null and b/applications/main/nfc/icon.png differ diff --git a/applications/main/onewire/application.fam b/applications/main/onewire/application.fam index 68d4f671..3d35abce 100644 --- a/applications/main/onewire/application.fam +++ b/applications/main/onewire/application.fam @@ -1,14 +1,6 @@ -App( - appid="onewire", - name="1-Wire", - apptype=FlipperAppType.METAPACKAGE, - provides=["onewire_start"], -) - App( appid="onewire_start", apptype=FlipperAppType.STARTUP, entry_point="onewire_on_system_start", - requires=["onewire"], order=60, ) diff --git a/applications/main/subghz/application.fam b/applications/main/subghz/application.fam index f0dc66e8..4f21cb6c 100644 --- a/applications/main/subghz/application.fam +++ b/applications/main/subghz/application.fam @@ -1,25 +1,21 @@ App( appid="subghz", name="Sub-GHz", - apptype=FlipperAppType.APP, + apptype=FlipperAppType.MENUEXTERNAL, targets=["f7"], entry_point="subghz_app", - cdefines=["APP_SUBGHZ"], - requires=[ - "gui", - "cli", - "dialogs", - ], - provides=["subghz_start"], icon="A_Sub1ghz_14", stack_size=3 * 1024, order=10, + fap_libs=["assets", "hwdrivers"], + fap_icon="icon.png", + fap_category="Sub-GHz", ) App( appid="subghz_start", + targets=["f7"], apptype=FlipperAppType.STARTUP, entry_point="subghz_on_system_start", - requires=["subghz"], order=40, ) diff --git a/applications/main/subghz/helpers/subghz_types.h b/applications/main/subghz/helpers/subghz_types.h index 8beb7b9e..e71c22dd 100644 --- a/applications/main/subghz/helpers/subghz_types.h +++ b/applications/main/subghz/helpers/subghz_types.h @@ -80,9 +80,6 @@ typedef enum { SubGhzViewIdFrequencyAnalyzer, SubGhzViewIdReadRAW, - SubGhzViewIdStatic, - SubGhzViewIdTestCarrier, - SubGhzViewIdTestPacket, } SubGhzViewId; /** SubGhz load type file */ diff --git a/applications/main/subghz/icon.png b/applications/main/subghz/icon.png new file mode 100644 index 00000000..5a25fdf4 Binary files /dev/null and b/applications/main/subghz/icon.png differ diff --git a/applications/main/subghz/scenes/subghz_scene_config.h b/applications/main/subghz/scenes/subghz_scene_config.h index 97aa946e..47655958 100644 --- a/applications/main/subghz/scenes/subghz_scene_config.h +++ b/applications/main/subghz/scenes/subghz_scene_config.h @@ -12,10 +12,6 @@ ADD_SCENE(subghz, show_only_rx, ShowOnlyRx) ADD_SCENE(subghz, saved_menu, SavedMenu) ADD_SCENE(subghz, delete, Delete) ADD_SCENE(subghz, delete_success, DeleteSuccess) -ADD_SCENE(subghz, test, Test) -ADD_SCENE(subghz, test_static, TestStatic) -ADD_SCENE(subghz, test_carrier, TestCarrier) -ADD_SCENE(subghz, test_packet, TestPacket) ADD_SCENE(subghz, set_type, SetType) ADD_SCENE(subghz, frequency_analyzer, FrequencyAnalyzer) ADD_SCENE(subghz, read_raw, ReadRAW) diff --git a/applications/main/subghz/scenes/subghz_scene_start.c b/applications/main/subghz/scenes/subghz_scene_start.c index ce631b39..951c756d 100644 --- a/applications/main/subghz/scenes/subghz_scene_start.c +++ b/applications/main/subghz/scenes/subghz_scene_start.c @@ -4,7 +4,6 @@ enum SubmenuIndex { SubmenuIndexRead = 10, SubmenuIndexSaved, - SubmenuIndexTest, SubmenuIndexAddManually, SubmenuIndexFrequencyAnalyzer, SubmenuIndexReadRAW, @@ -56,10 +55,6 @@ void subghz_scene_start_on_enter(void* context) { SubmenuIndexRadioSetting, subghz_scene_start_submenu_callback, subghz); - if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { - submenu_add_item( - subghz->submenu, "Test", SubmenuIndexTest, subghz_scene_start_submenu_callback, subghz); - } submenu_set_selected_item( subghz->submenu, scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneStart)); @@ -101,11 +96,6 @@ bool subghz_scene_start_on_event(void* context, SceneManagerEvent event) { scene_manager_next_scene(subghz->scene_manager, SubGhzSceneFrequencyAnalyzer); dolphin_deed(DolphinDeedSubGhzFrequencyAnalyzer); return true; - } else if(event.event == SubmenuIndexTest) { - scene_manager_set_scene_state( - subghz->scene_manager, SubGhzSceneStart, SubmenuIndexTest); - scene_manager_next_scene(subghz->scene_manager, SubGhzSceneTest); - return true; } else if(event.event == SubmenuIndexShowRegionInfo) { scene_manager_set_scene_state( subghz->scene_manager, SubGhzSceneStart, SubmenuIndexShowRegionInfo); diff --git a/applications/main/subghz/scenes/subghz_scene_test.c b/applications/main/subghz/scenes/subghz_scene_test.c deleted file mode 100644 index 65f9bbde..00000000 --- a/applications/main/subghz/scenes/subghz_scene_test.c +++ /dev/null @@ -1,61 +0,0 @@ -#include "../subghz_i.h" - -enum SubmenuIndex { - SubmenuIndexCarrier, - SubmenuIndexPacket, - SubmenuIndexStatic, -}; - -void subghz_scene_test_submenu_callback(void* context, uint32_t index) { - SubGhz* subghz = context; - view_dispatcher_send_custom_event(subghz->view_dispatcher, index); -} - -void subghz_scene_test_on_enter(void* context) { - SubGhz* subghz = context; - - submenu_add_item( - subghz->submenu, - "Carrier", - SubmenuIndexCarrier, - subghz_scene_test_submenu_callback, - subghz); - submenu_add_item( - subghz->submenu, "Packet", SubmenuIndexPacket, subghz_scene_test_submenu_callback, subghz); - submenu_add_item( - subghz->submenu, "Static", SubmenuIndexStatic, subghz_scene_test_submenu_callback, subghz); - - submenu_set_selected_item( - subghz->submenu, scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneTest)); - - view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdMenu); -} - -bool subghz_scene_test_on_event(void* context, SceneManagerEvent event) { - SubGhz* subghz = context; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == SubmenuIndexCarrier) { - scene_manager_set_scene_state( - subghz->scene_manager, SubGhzSceneTest, SubmenuIndexCarrier); - scene_manager_next_scene(subghz->scene_manager, SubGhzSceneTestCarrier); - return true; - } else if(event.event == SubmenuIndexPacket) { - scene_manager_set_scene_state( - subghz->scene_manager, SubGhzSceneTest, SubmenuIndexPacket); - scene_manager_next_scene(subghz->scene_manager, SubGhzSceneTestPacket); - return true; - } else if(event.event == SubmenuIndexStatic) { - scene_manager_set_scene_state( - subghz->scene_manager, SubGhzSceneTest, SubmenuIndexStatic); - scene_manager_next_scene(subghz->scene_manager, SubGhzSceneTestStatic); - return true; - } - } - return false; -} - -void subghz_scene_test_on_exit(void* context) { - SubGhz* subghz = context; - submenu_reset(subghz->submenu); -} diff --git a/applications/main/subghz/scenes/subghz_scene_test_carrier.c b/applications/main/subghz/scenes/subghz_scene_test_carrier.c deleted file mode 100644 index 9677792b..00000000 --- a/applications/main/subghz/scenes/subghz_scene_test_carrier.c +++ /dev/null @@ -1,30 +0,0 @@ -#include "../subghz_i.h" -#include "../views/subghz_test_carrier.h" - -void subghz_scene_test_carrier_callback(SubGhzTestCarrierEvent event, void* context) { - furi_assert(context); - SubGhz* subghz = context; - view_dispatcher_send_custom_event(subghz->view_dispatcher, event); -} - -void subghz_scene_test_carrier_on_enter(void* context) { - SubGhz* subghz = context; - subghz_test_carrier_set_callback( - subghz->subghz_test_carrier, subghz_scene_test_carrier_callback, subghz); - view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdTestCarrier); -} - -bool subghz_scene_test_carrier_on_event(void* context, SceneManagerEvent event) { - SubGhz* subghz = context; - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == SubGhzTestCarrierEventOnlyRx) { - scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowOnlyRx); - return true; - } - } - return false; -} - -void subghz_scene_test_carrier_on_exit(void* context) { - UNUSED(context); -} diff --git a/applications/main/subghz/scenes/subghz_scene_test_packet.c b/applications/main/subghz/scenes/subghz_scene_test_packet.c deleted file mode 100644 index 99f0ab17..00000000 --- a/applications/main/subghz/scenes/subghz_scene_test_packet.c +++ /dev/null @@ -1,30 +0,0 @@ -#include "../subghz_i.h" -#include "../views/subghz_test_packet.h" - -void subghz_scene_test_packet_callback(SubGhzTestPacketEvent event, void* context) { - furi_assert(context); - SubGhz* subghz = context; - view_dispatcher_send_custom_event(subghz->view_dispatcher, event); -} - -void subghz_scene_test_packet_on_enter(void* context) { - SubGhz* subghz = context; - subghz_test_packet_set_callback( - subghz->subghz_test_packet, subghz_scene_test_packet_callback, subghz); - view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdTestPacket); -} - -bool subghz_scene_test_packet_on_event(void* context, SceneManagerEvent event) { - SubGhz* subghz = context; - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == SubGhzTestPacketEventOnlyRx) { - scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowOnlyRx); - return true; - } - } - return false; -} - -void subghz_scene_test_packet_on_exit(void* context) { - UNUSED(context); -} diff --git a/applications/main/subghz/scenes/subghz_scene_test_static.c b/applications/main/subghz/scenes/subghz_scene_test_static.c deleted file mode 100644 index 10e6d02a..00000000 --- a/applications/main/subghz/scenes/subghz_scene_test_static.c +++ /dev/null @@ -1,30 +0,0 @@ -#include "../subghz_i.h" -#include "../views/subghz_test_static.h" - -void subghz_scene_test_static_callback(SubGhzTestStaticEvent event, void* context) { - furi_assert(context); - SubGhz* subghz = context; - view_dispatcher_send_custom_event(subghz->view_dispatcher, event); -} - -void subghz_scene_test_static_on_enter(void* context) { - SubGhz* subghz = context; - subghz_test_static_set_callback( - subghz->subghz_test_static, subghz_scene_test_static_callback, subghz); - view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdStatic); -} - -bool subghz_scene_test_static_on_event(void* context, SceneManagerEvent event) { - SubGhz* subghz = context; - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == SubGhzTestStaticEventOnlyRx) { - scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowOnlyRx); - return true; - } - } - return false; -} - -void subghz_scene_test_static_on_exit(void* context) { - UNUSED(context); -} diff --git a/applications/main/subghz/subghz.c b/applications/main/subghz/subghz.c index 09963584..e8148798 100644 --- a/applications/main/subghz/subghz.c +++ b/applications/main/subghz/subghz.c @@ -129,27 +129,6 @@ SubGhz* subghz_alloc() { SubGhzViewIdReadRAW, subghz_read_raw_get_view(subghz->subghz_read_raw)); - // Carrier Test Module - subghz->subghz_test_carrier = subghz_test_carrier_alloc(); - view_dispatcher_add_view( - subghz->view_dispatcher, - SubGhzViewIdTestCarrier, - subghz_test_carrier_get_view(subghz->subghz_test_carrier)); - - // Packet Test - subghz->subghz_test_packet = subghz_test_packet_alloc(); - view_dispatcher_add_view( - subghz->view_dispatcher, - SubGhzViewIdTestPacket, - subghz_test_packet_get_view(subghz->subghz_test_packet)); - - // Static send - subghz->subghz_test_static = subghz_test_static_alloc(); - view_dispatcher_add_view( - subghz->view_dispatcher, - SubGhzViewIdStatic, - subghz_test_static_get_view(subghz->subghz_test_static)); - //init threshold rssi subghz->threshold_rssi = subghz_threshold_rssi_alloc(); @@ -183,18 +162,6 @@ void subghz_free(SubGhz* subghz) { subghz_txrx_stop(subghz->txrx); subghz_txrx_sleep(subghz->txrx); - // Packet Test - view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewIdTestPacket); - subghz_test_packet_free(subghz->subghz_test_packet); - - // Carrier Test - view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewIdTestCarrier); - subghz_test_carrier_free(subghz->subghz_test_carrier); - - // Static - view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewIdStatic); - subghz_test_static_free(subghz->subghz_test_static); - // Receiver view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewIdReceiver); subghz_view_receiver_free(subghz->subghz_receiver); diff --git a/applications/main/subghz/subghz_i.h b/applications/main/subghz/subghz_i.h index fc3404c0..9e58f394 100644 --- a/applications/main/subghz/subghz_i.h +++ b/applications/main/subghz/subghz_i.h @@ -9,10 +9,6 @@ #include "views/subghz_frequency_analyzer.h" #include "views/subghz_read_raw.h" -#include "views/subghz_test_static.h" -#include "views/subghz_test_carrier.h" -#include "views/subghz_test_packet.h" - #include #include #include @@ -64,9 +60,6 @@ struct SubGhz { SubGhzFrequencyAnalyzer* subghz_frequency_analyzer; SubGhzReadRAW* subghz_read_raw; - SubGhzTestStatic* subghz_test_static; - SubGhzTestCarrier* subghz_test_carrier; - SubGhzTestPacket* subghz_test_packet; SubGhzProtocolFlag filter; FuriString* error_str; diff --git a/applications/main/u2f/application.fam b/applications/main/u2f/application.fam index 82010ffb..8167e627 100644 --- a/applications/main/u2f/application.fam +++ b/applications/main/u2f/application.fam @@ -1,15 +1,12 @@ App( appid="u2f", name="U2F", - apptype=FlipperAppType.APP, + apptype=FlipperAppType.MENUEXTERNAL, entry_point="u2f_app", - cdefines=["APP_U2F"], - requires=[ - "gui", - "dialogs", - ], stack_size=2 * 1024, icon="A_U2F_14", order=80, fap_libs=["assets"], + fap_category="USB", + fap_icon="icon.png", ) diff --git a/applications/main/u2f/icon.png b/applications/main/u2f/icon.png new file mode 100644 index 00000000..fcd87a2e Binary files /dev/null and b/applications/main/u2f/icon.png differ diff --git a/applications/services/applications.h b/applications/services/applications.h index 45b050a0..426d6d2d 100644 --- a/applications/services/applications.h +++ b/applications/services/applications.h @@ -17,6 +17,12 @@ typedef struct { const FlipperInternalApplicationFlag flags; } FlipperInternalApplication; +typedef struct { + const char* name; + const Icon* icon; + const char* path; +} FlipperExternalApplication; + typedef void (*FlipperInternalOnStartHook)(void); extern const char* FLIPPER_AUTORUN_APP_NAME; @@ -52,3 +58,9 @@ extern const FlipperInternalApplication FLIPPER_ARCHIVE; */ extern const FlipperInternalApplication FLIPPER_SETTINGS_APPS[]; extern const size_t FLIPPER_SETTINGS_APPS_COUNT; + +/* External Menu Apps list + * Spawned by loader + */ +extern const FlipperExternalApplication FLIPPER_EXTERNAL_APPS[]; +extern const size_t FLIPPER_EXTERNAL_APPS_COUNT; diff --git a/applications/services/cli/cli_commands.c b/applications/services/cli/cli_commands.c index 3f94deeb..467e7c53 100644 --- a/applications/services/cli/cli_commands.c +++ b/applications/services/cli/cli_commands.c @@ -89,6 +89,14 @@ void cli_command_help(Cli* cli, FuriString* args, void* context) { } } +void cli_command_uptime(Cli* cli, FuriString* args, void* context) { + UNUSED(cli); + UNUSED(args); + UNUSED(context); + uint32_t uptime = furi_get_tick() / furi_kernel_get_tick_frequency(); + printf("Uptime: %luh%lum%lus", uptime / 60 / 60, uptime / 60 % 60, uptime % 60); +} + void cli_command_date(Cli* cli, FuriString* args, void* context) { UNUSED(cli); UNUSED(context); @@ -165,24 +173,23 @@ void cli_command_log_tx_callback(const uint8_t* buffer, size_t size, void* conte furi_stream_buffer_send(context, buffer, size, 0); } -void cli_command_log_level_set_from_string(FuriString* level) { - if(furi_string_cmpi_str(level, "default") == 0) { - furi_log_set_level(FuriLogLevelDefault); - } else if(furi_string_cmpi_str(level, "none") == 0) { - furi_log_set_level(FuriLogLevelNone); - } else if(furi_string_cmpi_str(level, "error") == 0) { - furi_log_set_level(FuriLogLevelError); - } else if(furi_string_cmpi_str(level, "warn") == 0) { - furi_log_set_level(FuriLogLevelWarn); - } else if(furi_string_cmpi_str(level, "info") == 0) { - furi_log_set_level(FuriLogLevelInfo); - } else if(furi_string_cmpi_str(level, "debug") == 0) { - furi_log_set_level(FuriLogLevelDebug); - } else if(furi_string_cmpi_str(level, "trace") == 0) { - furi_log_set_level(FuriLogLevelTrace); +bool cli_command_log_level_set_from_string(FuriString* level) { + FuriLogLevel log_level; + if(furi_log_level_from_string(furi_string_get_cstr(level), &log_level)) { + furi_log_set_level(log_level); + return true; } else { - printf("Unknown log level\r\n"); + printf(" — start logging using the current level from the system settings\r\n"); + printf(" — only critical errors and other important messages\r\n"); + printf(" — non-critical errors and warnings including \r\n"); + printf(" — non-critical information including \r\n"); + printf(" — the default system log level (equivalent to )\r\n"); + printf( + " — debug information including (may impact system performance)\r\n"); + printf( + " — system traces including (may impact system performance)\r\n"); } + return false; } void cli_command_log(Cli* cli, FuriString* args, void* context) { @@ -193,12 +200,20 @@ void cli_command_log(Cli* cli, FuriString* args, void* context) { bool restore_log_level = false; if(furi_string_size(args) > 0) { - cli_command_log_level_set_from_string(args); + if(!cli_command_log_level_set_from_string(args)) { + furi_stream_buffer_free(ring); + return; + } restore_log_level = true; } + const char* current_level; + furi_log_level_to_string(furi_log_get_level(), ¤t_level); + printf("Current log level: %s\r\n", current_level); + furi_hal_console_set_tx_callback(cli_command_log_tx_callback, ring); + printf("Use to list available log levels\r\n"); printf("Press CTRL+C to stop...\r\n"); while(!cli_cmd_interrupt_received(cli)) { size_t ret = furi_stream_buffer_receive(ring, buffer, CLI_COMMAND_LOG_BUFFER_SIZE, 50); @@ -444,6 +459,7 @@ void cli_commands_init(Cli* cli) { cli_add_command(cli, "?", CliCommandFlagParallelSafe, cli_command_help, NULL); cli_add_command(cli, "help", CliCommandFlagParallelSafe, cli_command_help, NULL); + cli_add_command(cli, "uptime", CliCommandFlagDefault, cli_command_uptime, NULL); cli_add_command(cli, "date", CliCommandFlagParallelSafe, cli_command_date, NULL); cli_add_command(cli, "log", CliCommandFlagParallelSafe, cli_command_log, NULL); cli_add_command(cli, "sysctl", CliCommandFlagDefault, cli_command_sysctl, NULL); diff --git a/applications/services/desktop/desktop_settings.h b/applications/services/desktop/desktop_settings.h index 7ab39094..9b88868a 100644 --- a/applications/services/desktop/desktop_settings.h +++ b/applications/services/desktop/desktop_settings.h @@ -8,7 +8,7 @@ #include #include -#define DESKTOP_SETTINGS_VER (7) +#define DESKTOP_SETTINGS_VER (8) #define DESKTOP_SETTINGS_PATH INT_PATH(DESKTOP_SETTINGS_FILE_NAME) #define DESKTOP_SETTINGS_MAGIC (0x17) @@ -42,7 +42,6 @@ typedef struct { } PinCode; typedef struct { - bool is_external; char name_or_path[MAX_APP_LENGTH]; } FavoriteApp; diff --git a/applications/services/desktop/scenes/desktop_scene_debug.c b/applications/services/desktop/scenes/desktop_scene_debug.c index a5bd3a6b..866c736a 100644 --- a/applications/services/desktop/scenes/desktop_scene_debug.c +++ b/applications/services/desktop/scenes/desktop_scene_debug.c @@ -14,8 +14,6 @@ void desktop_scene_debug_callback(DesktopEvent event, void* context) { void desktop_scene_debug_on_enter(void* context) { Desktop* desktop = (Desktop*)context; - desktop_debug_get_dolphin_data(desktop->debug_view); - desktop_debug_set_callback(desktop->debug_view, desktop_scene_debug_callback, desktop); view_dispatcher_switch_to_view(desktop->view_dispatcher, DesktopViewIdDebug); } @@ -32,24 +30,6 @@ bool desktop_scene_debug_on_event(void* context, SceneManagerEvent event) { dolphin_flush(dolphin); consumed = true; break; - - case DesktopDebugEventDeed: - dolphin_deed(DolphinDeedTestRight); - desktop_debug_get_dolphin_data(desktop->debug_view); - consumed = true; - break; - - case DesktopDebugEventWrongDeed: - dolphin_deed(DolphinDeedTestLeft); - desktop_debug_get_dolphin_data(desktop->debug_view); - consumed = true; - break; - - case DesktopDebugEventSaveState: - dolphin_flush(dolphin); - consumed = true; - break; - default: break; } @@ -60,6 +40,5 @@ bool desktop_scene_debug_on_event(void* context, SceneManagerEvent event) { } void desktop_scene_debug_on_exit(void* context) { - Desktop* desktop = (Desktop*)context; - desktop_debug_reset_screen_idx(desktop->debug_view); + UNUSED(context); } diff --git a/applications/services/desktop/views/desktop_view_debug.c b/applications/services/desktop/views/desktop_view_debug.c index 7a16c084..35c7dc03 100644 --- a/applications/services/desktop/views/desktop_view_debug.c +++ b/applications/services/desktop/views/desktop_view_debug.c @@ -18,96 +18,71 @@ void desktop_debug_set_callback( } void desktop_debug_render(Canvas* canvas, void* model) { + UNUSED(model); canvas_clear(canvas); - DesktopDebugViewModel* m = model; const Version* ver; char buffer[64]; - static const char* headers[] = {"Device Info:", "Dolphin Info:"}; - canvas_set_color(canvas, ColorBlack); canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned( - canvas, 64, 1 + STATUS_BAR_Y_SHIFT, AlignCenter, AlignTop, headers[m->screen]); + + uint32_t uptime = furi_get_tick() / furi_kernel_get_tick_frequency(); + snprintf( + buffer, + sizeof(buffer), + "Uptime: %luh%lum%lus", + uptime / 60 / 60, + uptime / 60 % 60, + uptime % 60); + canvas_draw_str_aligned(canvas, 64, 1 + STATUS_BAR_Y_SHIFT, AlignCenter, AlignTop, buffer); + canvas_set_font(canvas, FontSecondary); - if(m->screen != DesktopViewStatsMeta) { - // Hardware version - const char* my_name = furi_hal_version_get_name_ptr(); - snprintf( - buffer, - sizeof(buffer), - "%d.F%dB%dC%d %s:%s %s", - furi_hal_version_get_hw_version(), - furi_hal_version_get_hw_target(), - furi_hal_version_get_hw_body(), - furi_hal_version_get_hw_connect(), - furi_hal_version_get_hw_region_name(), - furi_hal_region_get_name(), - my_name ? my_name : "Unknown"); - canvas_draw_str(canvas, 0, 19 + STATUS_BAR_Y_SHIFT, buffer); + // Hardware version + const char* my_name = furi_hal_version_get_name_ptr(); + snprintf( + buffer, + sizeof(buffer), + "%d.F%dB%dC%d %s:%s %s", + furi_hal_version_get_hw_version(), + furi_hal_version_get_hw_target(), + furi_hal_version_get_hw_body(), + furi_hal_version_get_hw_connect(), + furi_hal_version_get_hw_region_name(), + furi_hal_region_get_name(), + my_name ? my_name : "Unknown"); + canvas_draw_str(canvas, 0, 19 + STATUS_BAR_Y_SHIFT, buffer); - ver = furi_hal_version_get_firmware_version(); - const BleGlueC2Info* c2_ver = NULL; + ver = furi_hal_version_get_firmware_version(); + const BleGlueC2Info* c2_ver = NULL; #ifdef SRV_BT - c2_ver = ble_glue_get_c2_info(); + c2_ver = ble_glue_get_c2_info(); #endif - if(!ver) { //-V1051 - canvas_draw_str(canvas, 0, 30 + STATUS_BAR_Y_SHIFT, "No info"); - return; - } - - snprintf( - buffer, - sizeof(buffer), - "%s [%s]", - version_get_version(ver), - version_get_builddate(ver)); - canvas_draw_str(canvas, 0, 30 + STATUS_BAR_Y_SHIFT, buffer); - - uint16_t api_major, api_minor; - furi_hal_info_get_api_version(&api_major, &api_minor); - snprintf( - buffer, - sizeof(buffer), - "%s%s [%d.%d] %s", - version_get_dirty_flag(ver) ? "[!] " : "", - version_get_githash(ver), - api_major, - api_minor, - c2_ver ? c2_ver->StackTypeString : ""); - canvas_draw_str(canvas, 0, 40 + STATUS_BAR_Y_SHIFT, buffer); - - snprintf( - buffer, sizeof(buffer), "[%d] %s", version_get_target(ver), version_get_gitbranch(ver)); - canvas_draw_str(canvas, 0, 50 + STATUS_BAR_Y_SHIFT, buffer); - - } else { - Dolphin* dolphin = furi_record_open(RECORD_DOLPHIN); - DolphinStats stats = dolphin_stats(dolphin); - furi_record_close(RECORD_DOLPHIN); - - uint32_t current_lvl = stats.level; - uint32_t remaining = dolphin_state_xp_to_levelup(m->icounter); - - canvas_set_font(canvas, FontSecondary); - snprintf(buffer, sizeof(buffer), "Icounter: %lu Butthurt %lu", m->icounter, m->butthurt); - canvas_draw_str(canvas, 5, 19 + STATUS_BAR_Y_SHIFT, buffer); - - snprintf( - buffer, - sizeof(buffer), - "Level: %lu To level up: %lu", - current_lvl, - (remaining == (uint32_t)(-1) ? remaining : 0)); - canvas_draw_str(canvas, 5, 29 + STATUS_BAR_Y_SHIFT, buffer); - - // even if timestamp is uint64_t, it's safe to cast it to uint32_t, because furi_hal_rtc_datetime_to_timestamp only returns uint32_t - snprintf(buffer, sizeof(buffer), "%lu", (uint32_t)m->timestamp); - - canvas_draw_str(canvas, 5, 39 + STATUS_BAR_Y_SHIFT, buffer); - canvas_draw_str(canvas, 0, 49 + STATUS_BAR_Y_SHIFT, "[< >] icounter value [ok] save"); + if(!ver) { //-V1051 + canvas_draw_str(canvas, 0, 30 + STATUS_BAR_Y_SHIFT, "No info"); + return; } + + snprintf( + buffer, sizeof(buffer), "%s [%s]", version_get_version(ver), version_get_builddate(ver)); + canvas_draw_str(canvas, 0, 30 + STATUS_BAR_Y_SHIFT, buffer); + + uint16_t api_major, api_minor; + furi_hal_info_get_api_version(&api_major, &api_minor); + snprintf( + buffer, + sizeof(buffer), + "%s%s [%d.%d] %s", + version_get_dirty_flag(ver) ? "[!] " : "", + version_get_githash(ver), + api_major, + api_minor, + c2_ver ? c2_ver->StackTypeString : ""); + canvas_draw_str(canvas, 0, 40 + STATUS_BAR_Y_SHIFT, buffer); + + snprintf( + buffer, sizeof(buffer), "[%d] %s", version_get_target(ver), version_get_gitbranch(ver)); + canvas_draw_str(canvas, 0, 50 + STATUS_BAR_Y_SHIFT, buffer); } View* desktop_debug_get_view(DesktopDebugView* debug_view) { @@ -115,61 +90,43 @@ View* desktop_debug_get_view(DesktopDebugView* debug_view) { return debug_view->view; } -bool desktop_debug_input(InputEvent* event, void* context) { +static bool desktop_debug_input(InputEvent* event, void* context) { furi_assert(event); furi_assert(context); DesktopDebugView* debug_view = context; - if(event->type != InputTypeShort && event->type != InputTypeRepeat) { - return false; - } - - DesktopViewStatsScreens current = 0; - with_view_model( - debug_view->view, - DesktopDebugViewModel * model, - { -#ifdef SRV_DOLPHIN_STATE_DEBUG - if((event->key == InputKeyDown) || (event->key == InputKeyUp)) { - model->screen = !model->screen; - } -#endif - current = model->screen; - }, - true); - - size_t count = (event->type == InputTypeRepeat) ? 10 : 1; - if(current == DesktopViewStatsMeta) { - if(event->key == InputKeyLeft) { - while(count-- > 0) { - debug_view->callback(DesktopDebugEventWrongDeed, debug_view->context); - } - } else if(event->key == InputKeyRight) { - while(count-- > 0) { - debug_view->callback(DesktopDebugEventDeed, debug_view->context); - } - } else if(event->key == InputKeyOk) { - debug_view->callback(DesktopDebugEventSaveState, debug_view->context); - } else { - return false; - } - } - - if(event->key == InputKeyBack) { + if(event->key == InputKeyBack && event->type == InputTypeShort) { debug_view->callback(DesktopDebugEventExit, debug_view->context); } return true; } +static void desktop_debug_enter(void* context) { + DesktopDebugView* debug_view = context; + furi_timer_start(debug_view->timer, furi_ms_to_ticks(1000)); +} + +static void desktop_debug_exit(void* context) { + DesktopDebugView* debug_view = context; + furi_timer_stop(debug_view->timer); +} +void desktop_debug_timer(void* context) { + DesktopDebugView* debug_view = context; + view_get_model(debug_view->view); + view_commit_model(debug_view->view, true); +} + DesktopDebugView* desktop_debug_alloc() { DesktopDebugView* debug_view = malloc(sizeof(DesktopDebugView)); debug_view->view = view_alloc(); - view_allocate_model(debug_view->view, ViewModelTypeLocking, sizeof(DesktopDebugViewModel)); + debug_view->timer = furi_timer_alloc(desktop_debug_timer, FuriTimerTypePeriodic, debug_view); view_set_context(debug_view->view, debug_view); view_set_draw_callback(debug_view->view, (ViewDrawCallback)desktop_debug_render); view_set_input_callback(debug_view->view, desktop_debug_input); + view_set_enter_callback(debug_view->view, desktop_debug_enter); + view_set_exit_callback(debug_view->view, desktop_debug_exit); return debug_view; } @@ -177,27 +134,7 @@ DesktopDebugView* desktop_debug_alloc() { void desktop_debug_free(DesktopDebugView* debug_view) { furi_assert(debug_view); + furi_timer_free(debug_view->timer); view_free(debug_view->view); free(debug_view); } - -void desktop_debug_get_dolphin_data(DesktopDebugView* debug_view) { - Dolphin* dolphin = furi_record_open(RECORD_DOLPHIN); - DolphinStats stats = dolphin_stats(dolphin); - with_view_model( - debug_view->view, - DesktopDebugViewModel * model, - { - model->icounter = stats.icounter; - model->butthurt = stats.butthurt; - model->timestamp = stats.timestamp; - }, - true); - - furi_record_close(RECORD_DOLPHIN); -} - -void desktop_debug_reset_screen_idx(DesktopDebugView* debug_view) { - with_view_model( - debug_view->view, DesktopDebugViewModel * model, { model->screen = 0; }, true); -} diff --git a/applications/services/desktop/views/desktop_view_debug.h b/applications/services/desktop/views/desktop_view_debug.h index f6af16b2..fea0c22a 100644 --- a/applications/services/desktop/views/desktop_view_debug.h +++ b/applications/services/desktop/views/desktop_view_debug.h @@ -8,26 +8,13 @@ typedef struct DesktopDebugView DesktopDebugView; typedef void (*DesktopDebugViewCallback)(DesktopEvent event, void* context); -// Debug info -typedef enum { - DesktopViewStatsFw, - DesktopViewStatsMeta, - DesktopViewStatsTotalCount, -} DesktopViewStatsScreens; - struct DesktopDebugView { View* view; + FuriTimer* timer; DesktopDebugViewCallback callback; void* context; }; -typedef struct { - uint32_t icounter; - uint32_t butthurt; - uint64_t timestamp; - DesktopViewStatsScreens screen; -} DesktopDebugViewModel; - void desktop_debug_set_callback( DesktopDebugView* debug_view, DesktopDebugViewCallback callback, @@ -36,7 +23,5 @@ void desktop_debug_set_callback( View* desktop_debug_get_view(DesktopDebugView* debug_view); DesktopDebugView* desktop_debug_alloc(); -void desktop_debug_free(DesktopDebugView* debug_view); -void desktop_debug_get_dolphin_data(DesktopDebugView* debug_view); -void desktop_debug_reset_screen_idx(DesktopDebugView* debug_view); +void desktop_debug_free(DesktopDebugView* debug_view); diff --git a/applications/services/gui/modules/file_browser.c b/applications/services/gui/modules/file_browser.c index c764a1cf..91b03ec8 100644 --- a/applications/services/gui/modules/file_browser.c +++ b/applications/services/gui/modules/file_browser.c @@ -303,6 +303,12 @@ static bool browser_is_list_load_required(FileBrowserModel* model) { return false; } +static void browser_list_rollover(FileBrowserModel* model) { + if(!model->list_loading && items_array_size(model->items) < model->item_cnt) { + items_array_reset(model->items); + } +} + static void browser_update_offset(FileBrowser* browser) { furi_assert(browser); @@ -385,7 +391,7 @@ static void browser_list_load_cb(void* context, uint32_t list_load_offset) { } } }, - true); + false); BrowserItem_t_clear(&back_item); } @@ -425,14 +431,15 @@ static void (browser->hide_ext) && (item.type == BrowserItemTypeFile)); } + // We shouldn't update screen on each item if custom callback is not set + // Otherwise it will cause screen flickering + bool instant_update = (browser->item_callback != NULL); with_view_model( browser->view, FileBrowserModel * model, - { - items_array_push_back(model->items, item); - // TODO: calculate if element is visible - }, - true); + { items_array_push_back(model->items, item); }, + instant_update); + furi_string_free(item.display_name); furi_string_free(item.path); if(item.custom_icon_data) { @@ -440,7 +447,18 @@ static void } } else { with_view_model( - browser->view, FileBrowserModel * model, { model->list_loading = false; }, true); + browser->view, + FileBrowserModel * model, + { + model->list_loading = false; + if(browser_is_list_load_required(model)) { + model->list_loading = true; + int32_t load_offset = CLAMP( + model->item_idx - ITEM_LIST_LEN_MAX / 2, (int32_t)model->item_cnt, 0); + file_browser_worker_load(browser->worker, load_offset, ITEM_LIST_LEN_MAX); + } + }, + true); } } @@ -604,11 +622,13 @@ static bool file_browser_view_input_callback(InputEvent* event, void* context) { if(model->item_idx < scroll_speed) { model->button_held_for_ticks = 0; model->item_idx = model->item_cnt - 1; + browser_list_rollover(model); } else { model->item_idx = ((model->item_idx - scroll_speed) + model->item_cnt) % model->item_cnt; } + if(browser_is_list_load_required(model)) { model->list_loading = true; int32_t load_offset = CLAMP( @@ -622,13 +642,14 @@ static bool file_browser_view_input_callback(InputEvent* event, void* context) { model->button_held_for_ticks += 1; } else if(event->key == InputKeyDown) { - int32_t count = model->item_cnt; - if(model->item_idx + scroll_speed >= count) { + if(model->item_idx + scroll_speed >= (int32_t)model->item_cnt) { model->button_held_for_ticks = 0; model->item_idx = 0; + browser_list_rollover(model); } else { model->item_idx = (model->item_idx + scroll_speed) % model->item_cnt; } + if(browser_is_list_load_required(model)) { model->list_loading = true; int32_t load_offset = CLAMP( diff --git a/applications/services/loader/loader.c b/applications/services/loader/loader.c index ab7876a0..41c0f95d 100644 --- a/applications/services/loader/loader.c +++ b/applications/services/loader/loader.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -11,7 +12,20 @@ #define TAG "Loader" #define LOADER_MAGIC_THREAD_VALUE 0xDEADBEEF -// api + +// helpers + +static const char* loader_find_external_application_by_name(const char* app_name) { + for(size_t i = 0; i < FLIPPER_EXTERNAL_APPS_COUNT; i++) { + if(strcmp(FLIPPER_EXTERNAL_APPS[i].name, app_name) == 0) { + return FLIPPER_EXTERNAL_APPS[i].path; + } + } + + return NULL; +} + +// API LoaderStatus loader_start(Loader* loader, const char* name, const char* args, FuriString* error_message) { @@ -33,17 +47,33 @@ LoaderStatus loader_start_with_gui_error(Loader* loader, const char* name, const FuriString* error_message = furi_string_alloc(); LoaderStatus status = loader_start(loader, name, args, error_message); - // TODO: we have many places where we can emit a double start, ex: desktop, menu - // so i prefer to not show LoaderStatusErrorAppStarted error message for now - if(status == LoaderStatusErrorUnknownApp || status == LoaderStatusErrorInternal) { + if(status == LoaderStatusErrorUnknownApp && + loader_find_external_application_by_name(name) != NULL) { + // Special case for external apps + DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS); + DialogMessage* message = dialog_message_alloc(); + dialog_message_set_header(message, "Update needed", 64, 3, AlignCenter, AlignTop); + dialog_message_set_buttons(message, NULL, NULL, NULL); + dialog_message_set_icon(message, &I_DolphinCommon_56x48, 72, 17); + dialog_message_set_text( + message, "Update firmware\nto run this app", 3, 26, AlignLeft, AlignTop); + dialog_message_show(dialogs, message); + dialog_message_free(message); + furi_record_close(RECORD_DIALOGS); + } else if(status == LoaderStatusErrorUnknownApp || status == LoaderStatusErrorInternal) { + // TODO: we have many places where we can emit a double start, ex: desktop, menu + // so i prefer to not show LoaderStatusErrorAppStarted error message for now DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS); DialogMessage* message = dialog_message_alloc(); dialog_message_set_header(message, "Error", 64, 0, AlignCenter, AlignTop); dialog_message_set_buttons(message, NULL, NULL, NULL); - furi_string_replace(error_message, ":", "\n"); + furi_string_replace(error_message, "/ext/apps/", ""); + furi_string_replace(error_message, ", ", "\n"); + furi_string_replace(error_message, ": ", "\n"); + dialog_message_set_text( - message, furi_string_get_cstr(error_message), 64, 32, AlignCenter, AlignCenter); + message, furi_string_get_cstr(error_message), 64, 35, AlignCenter, AlignCenter); dialog_message_show(dialogs, message); dialog_message_free(message); @@ -268,22 +298,20 @@ static LoaderStatus loader_start_external_app( if(preload_res != FlipperApplicationPreloadStatusSuccess) { const char* err_msg = flipper_application_preload_status_to_string(preload_res); status = loader_make_status_error( - LoaderStatusErrorInternal, error_message, "Preload failed %s: %s", path, err_msg); + LoaderStatusErrorInternal, error_message, "Preload failed, %s: %s", path, err_msg); break; } - FURI_LOG_I(TAG, "Mapping"); FlipperApplicationLoadStatus load_status = flipper_application_map_to_memory(loader->app.fap); if(load_status != FlipperApplicationLoadStatusSuccess) { const char* err_msg = flipper_application_load_status_to_string(load_status); status = loader_make_status_error( - LoaderStatusErrorInternal, error_message, "Load failed %s: %s", path, err_msg); + LoaderStatusErrorInternal, error_message, "Load failed, %s: %s", path, err_msg); break; } FURI_LOG_I(TAG, "Loaded in %zums", (size_t)(furi_get_tick() - start)); - FURI_LOG_I(TAG, "Starting app"); loader->app.thread = flipper_application_alloc_thread(loader->app.fap, args); FuriString* app_name = furi_string_alloc(); @@ -379,7 +407,15 @@ static LoaderStatus loader_do_start_by_name( break; } - // check external apps + // check External Applications + { + const char* path = loader_find_external_application_by_name(name); + if(path) { + name = path; + } + } + + // check Faps { Storage* storage = furi_record_open(RECORD_STORAGE); if(storage_file_exists(storage, name)) { diff --git a/applications/services/loader/loader_applications.c b/applications/services/loader/loader_applications.c index 1801edef..8ae91d76 100644 --- a/applications/services/loader/loader_applications.c +++ b/applications/services/loader/loader_applications.c @@ -20,7 +20,7 @@ static int32_t loader_applications_thread(void* p); LoaderApplications* loader_applications_alloc(void (*closed_cb)(void*), void* context) { LoaderApplications* loader_applications = malloc(sizeof(LoaderApplications)); loader_applications->thread = - furi_thread_alloc_ex(TAG, 512, loader_applications_thread, (void*)loader_applications); + furi_thread_alloc_ex(TAG, 768, loader_applications_thread, (void*)loader_applications); loader_applications->closed_cb = closed_cb; loader_applications->context = context; furi_thread_start(loader_applications->thread); @@ -38,6 +38,11 @@ typedef struct { FuriString* fap_path; DialogsApp* dialogs; Storage* storage; + Loader* loader; + + Gui* gui; + ViewHolder* view_holder; + Loading* loading; } LoaderApplicationsApp; static LoaderApplicationsApp* loader_applications_app_alloc() { @@ -45,15 +50,30 @@ static LoaderApplicationsApp* loader_applications_app_alloc() { app->fap_path = furi_string_alloc_set(EXT_PATH("apps")); app->dialogs = furi_record_open(RECORD_DIALOGS); app->storage = furi_record_open(RECORD_STORAGE); + app->loader = furi_record_open(RECORD_LOADER); + + app->gui = furi_record_open(RECORD_GUI); + app->view_holder = view_holder_alloc(); + app->loading = loading_alloc(); + + view_holder_attach_to_gui(app->view_holder, app->gui); + view_holder_set_view(app->view_holder, loading_get_view(app->loading)); + return app; } //-V773 -static void loader_applications_app_free(LoaderApplicationsApp* loader_applications_app) { - furi_assert(loader_applications_app); +static void loader_applications_app_free(LoaderApplicationsApp* app) { + furi_assert(app); + + view_holder_free(app->view_holder); + loading_free(app->loading); + furi_record_close(RECORD_GUI); + + furi_record_close(RECORD_LOADER); furi_record_close(RECORD_DIALOGS); furi_record_close(RECORD_STORAGE); - furi_string_free(loader_applications_app->fap_path); - free(loader_applications_app); + furi_string_free(app->fap_path); + free(app); } static bool loader_applications_item_callback( @@ -96,47 +116,38 @@ static void loader_pubsub_callback(const void* message, void* context) { } } -static void loader_applications_start_app(const char* name) { - // start loading animation - Gui* gui = furi_record_open(RECORD_GUI); - ViewHolder* view_holder = view_holder_alloc(); - Loading* loading = loading_alloc(); - - view_holder_attach_to_gui(view_holder, gui); - view_holder_set_view(view_holder, loading_get_view(loading)); - view_holder_start(view_holder); +static void loader_applications_start_app(LoaderApplicationsApp* app) { + const char* name = furi_string_get_cstr(app->fap_path); // load app FuriThreadId thread_id = furi_thread_get_current_id(); - Loader* loader = furi_record_open(RECORD_LOADER); FuriPubSubSubscription* subscription = - furi_pubsub_subscribe(loader_get_pubsub(loader), loader_pubsub_callback, thread_id); + furi_pubsub_subscribe(loader_get_pubsub(app->loader), loader_pubsub_callback, thread_id); - LoaderStatus status = loader_start_with_gui_error(loader, name, NULL); + LoaderStatus status = loader_start_with_gui_error(app->loader, name, NULL); if(status == LoaderStatusOk) { furi_thread_flags_wait(APPLICATION_STOP_EVENT, FuriFlagWaitAny, FuriWaitForever); } - furi_pubsub_unsubscribe(loader_get_pubsub(loader), subscription); - furi_record_close(RECORD_LOADER); - - // stop loading animation - view_holder_stop(view_holder); - view_holder_free(view_holder); - loading_free(loading); - furi_record_close(RECORD_GUI); + furi_pubsub_unsubscribe(loader_get_pubsub(app->loader), subscription); } static int32_t loader_applications_thread(void* p) { LoaderApplications* loader_applications = p; - LoaderApplicationsApp* loader_applications_app = loader_applications_app_alloc(); + LoaderApplicationsApp* app = loader_applications_app_alloc(); - while(loader_applications_select_app(loader_applications_app)) { - loader_applications_start_app(furi_string_get_cstr(loader_applications_app->fap_path)); + // start loading animation + view_holder_start(app->view_holder); + + while(loader_applications_select_app(app)) { + loader_applications_start_app(app); } - loader_applications_app_free(loader_applications_app); + // stop loading animation + view_holder_stop(app->view_holder); + + loader_applications_app_free(app); if(loader_applications->closed_cb) { loader_applications->closed_cb(loader_applications->context); diff --git a/applications/services/loader/loader_menu.c b/applications/services/loader/loader_menu.c index 28283f85..149fea72 100644 --- a/applications/services/loader/loader_menu.c +++ b/applications/services/loader/loader_menu.c @@ -52,12 +52,18 @@ static void loader_menu_start(const char* name) { furi_record_close(RECORD_LOADER); } -static void loader_menu_callback(void* context, uint32_t index) { +static void loader_menu_apps_callback(void* context, uint32_t index) { UNUSED(context); const char* name = FLIPPER_APPS[index].name; loader_menu_start(name); } +static void loader_menu_external_apps_callback(void* context, uint32_t index) { + UNUSED(context); + const char* path = FLIPPER_EXTERNAL_APPS[index].name; + loader_menu_start(path); +} + static void loader_menu_applications_callback(void* context, uint32_t index) { UNUSED(index); UNUSED(context); @@ -89,13 +95,24 @@ static uint32_t loader_menu_exit(void* context) { static void loader_menu_build_menu(LoaderMenuApp* app, LoaderMenu* menu) { size_t i; + + for(i = 0; i < FLIPPER_EXTERNAL_APPS_COUNT; i++) { + menu_add_item( + app->primary_menu, + FLIPPER_EXTERNAL_APPS[i].name, + FLIPPER_EXTERNAL_APPS[i].icon, + i, + loader_menu_external_apps_callback, + (void*)menu); + } + for(i = 0; i < FLIPPER_APPS_COUNT; i++) { menu_add_item( app->primary_menu, FLIPPER_APPS[i].name, FLIPPER_APPS[i].icon, i, - loader_menu_callback, + loader_menu_apps_callback, (void*)menu); } menu_add_item( diff --git a/applications/services/power/power_service/power.c b/applications/services/power/power_service/power.c index 72dc8f3f..aadb5f46 100644 --- a/applications/services/power/power_service/power.c +++ b/applications/services/power/power_service/power.c @@ -117,6 +117,7 @@ static bool power_update_info(Power* power) { info.is_charging = furi_hal_power_is_charging(); info.gauge_is_ok = furi_hal_power_gauge_is_ok(); + info.is_shutdown_requested = furi_hal_power_is_shutdown_requested(); info.charge = furi_hal_power_get_pct(); info.health = furi_hal_power_get_bat_health_pct(); info.capacity_remaining = furi_hal_power_get_battery_remaining_capacity(); @@ -145,7 +146,7 @@ static void power_check_low_battery(Power* power) { } // Check battery charge and vbus voltage - if((power->info.charge == 0) && (power->info.voltage_vbus < 4.0f) && + if((power->info.is_shutdown_requested) && (power->info.voltage_vbus < 4.0f) && power->show_low_bat_level_message) { if(!power->battery_low) { view_dispatcher_send_to_front(power->view_dispatcher); diff --git a/applications/services/power/power_service/power.h b/applications/services/power/power_service/power.h index c7f5d7e3..fdc5b527 100644 --- a/applications/services/power/power_service/power.h +++ b/applications/services/power/power_service/power.h @@ -37,6 +37,7 @@ typedef struct { typedef struct { bool gauge_is_ok; bool is_charging; + bool is_shutdown_requested; float current_charger; float current_gauge; diff --git a/applications/services/storage/storage_external_api.c b/applications/services/storage/storage_external_api.c index 5fcaa592..585ded41 100644 --- a/applications/services/storage/storage_external_api.c +++ b/applications/services/storage/storage_external_api.c @@ -430,6 +430,20 @@ FS_Error storage_common_rename(Storage* storage, const char* old_path, const cha break; } + if(storage_dir_exists(storage, old_path)) { + FuriString* dir_path = furi_string_alloc_set_str(old_path); + if(!furi_string_end_with_str(dir_path, "/")) { + furi_string_cat_str(dir_path, "/"); + } + const char* dir_path_s = furi_string_get_cstr(dir_path); + if(strncmp(new_path, dir_path_s, strlen(dir_path_s)) == 0) { + error = FSE_INVALID_NAME; + furi_string_free(dir_path); + break; + } + furi_string_free(dir_path); + } + if(storage_file_exists(storage, new_path)) { storage_common_remove(storage, new_path); } diff --git a/applications/settings/about/about.c b/applications/settings/about/about.c index 68810330..55bd43e5 100644 --- a/applications/settings/about/about.c +++ b/applications/settings/about/about.c @@ -82,7 +82,9 @@ static DialogMessageButton icon1_screen(DialogsApp* dialogs, DialogMessage* mess static DialogMessageButton icon2_screen(DialogsApp* dialogs, DialogMessage* message) { DialogMessageButton result; - dialog_message_set_icon(message, &I_Certification2_98x33, 15, 10); + dialog_message_set_icon(message, &I_Certification2_46x33, 15, 10); + dialog_message_set_text( + message, furi_hal_version_get_mic_id(), 63, 27, AlignLeft, AlignCenter); result = dialog_message_show(dialogs, message); dialog_message_set_icon(message, NULL, 0, 0); diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_favorite.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_favorite.c index c35a1056..26e7bc58 100644 --- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_favorite.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_favorite.c @@ -5,11 +5,26 @@ #include #include +#define APPS_COUNT (FLIPPER_APPS_COUNT + FLIPPER_EXTERNAL_APPS_COUNT) + #define EXTERNAL_BROWSER_NAME ("Applications") -#define EXTERNAL_BROWSER_INDEX (FLIPPER_APPS_COUNT + 1) +#define EXTERNAL_BROWSER_INDEX (APPS_COUNT + 1) #define EXTERNAL_APPLICATION_NAME ("[External Application]") -#define EXTERNAL_APPLICATION_INDEX (FLIPPER_APPS_COUNT + 2) +#define EXTERNAL_APPLICATION_INDEX (APPS_COUNT + 2) + +#define PRESELECTED_SPECIAL 0xffffffff + +static const char* favorite_fap_get_app_name(size_t i) { + const char* name; + if(i < FLIPPER_APPS_COUNT) { + name = FLIPPER_APPS[i].name; + } else { + name = FLIPPER_EXTERNAL_APPS[i - FLIPPER_APPS_COUNT].name; + } + + return name; +} static bool favorite_fap_selector_item_callback( FuriString* file_path, @@ -42,21 +57,17 @@ 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; + uint32_t pre_select_item = PRESELECTED_SPECIAL; 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( - submenu, - FLIPPER_APPS[i].name, - i, - desktop_settings_scene_favorite_submenu_callback, - app); + for(size_t i = 0; i < APPS_COUNT; i++) { + const char* name = favorite_fap_get_app_name(i); + + submenu_add_item(submenu, name, i, desktop_settings_scene_favorite_submenu_callback, app); // Select favorite item in submenu - if(!curr_favorite_app->is_external && - !strcmp(FLIPPER_APPS[i].name, curr_favorite_app->name_or_path)) { + if(!strcmp(name, curr_favorite_app->name_or_path)) { pre_select_item = i; } } @@ -77,7 +88,7 @@ void desktop_settings_scene_favorite_on_enter(void* context) { desktop_settings_scene_favorite_submenu_callback, app); - if(curr_favorite_app->is_external) { + if(pre_select_item == PRESELECTED_SPECIAL) { if(curr_favorite_app->name_or_path[0] == '\0') { pre_select_item = EXTERNAL_BROWSER_INDEX; } else { @@ -104,7 +115,6 @@ bool desktop_settings_scene_favorite_on_event(void* context, SceneManagerEvent e if(event.type == SceneManagerEventTypeCustom) { if(event.event == EXTERNAL_BROWSER_INDEX) { - curr_favorite_app->is_external = true; curr_favorite_app->name_or_path[0] = '\0'; consumed = true; } else if(event.event == EXTERNAL_APPLICATION_INDEX) { @@ -125,7 +135,6 @@ bool desktop_settings_scene_favorite_on_event(void* context, SceneManagerEvent e if(dialog_file_browser_show(app->dialogs, temp_path, temp_path, &browser_options)) { 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), @@ -133,9 +142,8 @@ bool desktop_settings_scene_favorite_on_event(void* context, SceneManagerEvent e consumed = true; } } else { - curr_favorite_app->is_external = false; - strncpy( - curr_favorite_app->name_or_path, FLIPPER_APPS[event.event].name, MAX_APP_LENGTH); + const char* name = favorite_fap_get_app_name(event.event); + if(name) strncpy(curr_favorite_app->name_or_path, name, MAX_APP_LENGTH); consumed = true; } if(consumed) { diff --git a/applications/settings/power_settings_app/views/battery_info.c b/applications/settings/power_settings_app/views/battery_info.c index d56dfc62..8add60db 100644 --- a/applications/settings/power_settings_app/views/battery_info.c +++ b/applications/settings/power_settings_app/views/battery_info.c @@ -54,8 +54,7 @@ static void draw_battery(Canvas* canvas, BatteryInfoModel* data, int x, int y) { (uint32_t)(data->vbus_voltage * 10) % 10, current); } else if(current < -5) { - // Often gauge reports anything in the range 1~5ma as 5ma - // That brings confusion, so we'll treat it as Napping + // 0-5ma deadband snprintf( emote, sizeof(emote), diff --git a/applications/system/updater/util/update_task.c b/applications/system/updater/util/update_task.c index 708d10ce..74d752b4 100644 --- a/applications/system/updater/util/update_task.c +++ b/applications/system/updater/util/update_task.c @@ -19,7 +19,7 @@ static const char* update_task_stage_descr[] = { [UpdateTaskStageRadioErase] = "Uninstalling radio FW", [UpdateTaskStageRadioWrite] = "Writing radio FW", [UpdateTaskStageRadioInstall] = "Installing radio FW", - [UpdateTaskStageRadioBusy] = "Radio is updating", + [UpdateTaskStageRadioBusy] = "Core 2 busy", [UpdateTaskStageOBValidation] = "Validating opt. bytes", [UpdateTaskStageLfsBackup] = "Backing up LFS", [UpdateTaskStageLfsRestore] = "Restoring LFS", @@ -30,6 +30,191 @@ static const char* update_task_stage_descr[] = { [UpdateTaskStageOBError] = "OB, report", }; +static const struct { + UpdateTaskStage stage; + uint8_t percent_min, percent_max; + const char* descr; +} update_task_error_detail[] = { + { + .stage = UpdateTaskStageReadManifest, + .percent_min = 0, + .percent_max = 13, + .descr = "Wrong Updater HW", + }, + { + .stage = UpdateTaskStageReadManifest, + .percent_min = 14, + .percent_max = 20, + .descr = "Manifest pointer error", + }, + { + .stage = UpdateTaskStageReadManifest, + .percent_min = 21, + .percent_max = 30, + .descr = "Manifest load error", + }, + { + .stage = UpdateTaskStageReadManifest, + .percent_min = 31, + .percent_max = 40, + .descr = "Wrong package version", + }, + { + .stage = UpdateTaskStageReadManifest, + .percent_min = 41, + .percent_max = 50, + .descr = "HW Target mismatch", + }, + { + .stage = UpdateTaskStageReadManifest, + .percent_min = 51, + .percent_max = 60, + .descr = "No DFU file", + }, + { + .stage = UpdateTaskStageReadManifest, + .percent_min = 61, + .percent_max = 80, + .descr = "No Radio file", + }, +#ifndef FURI_RAM_EXEC + { + .stage = UpdateTaskStageLfsBackup, + .percent_min = 0, + .percent_max = 100, + .descr = "FS R/W error", + }, +#else + { + .stage = UpdateTaskStageRadioImageValidate, + .percent_min = 0, + .percent_max = 98, + .descr = "FS Read error", + }, + { + .stage = UpdateTaskStageRadioImageValidate, + .percent_min = 99, + .percent_max = 100, + .descr = "CRC mismatch", + }, + { + .stage = UpdateTaskStageRadioErase, + .percent_min = 0, + .percent_max = 30, + .descr = "Stack remove: cmd error", + }, + { + .stage = UpdateTaskStageRadioErase, + .percent_min = 31, + .percent_max = 100, + .descr = "Stack remove: wait failed", + }, + { + .stage = UpdateTaskStageRadioWrite, + .percent_min = 0, + .percent_max = 100, + .descr = "Stack write: error", + }, + { + .stage = UpdateTaskStageRadioInstall, + .percent_min = 0, + .percent_max = 10, + .descr = "Stack install: cmd error", + }, + { + .stage = UpdateTaskStageRadioInstall, + .percent_min = 11, + .percent_max = 100, + .descr = "Stack install: wait failed", + }, + { + .stage = UpdateTaskStageRadioBusy, + .percent_min = 0, + .percent_max = 10, + .descr = "Failed to start C2", + }, + { + .stage = UpdateTaskStageRadioBusy, + .percent_min = 11, + .percent_max = 20, + .descr = "C2 FUS swich failed", + }, + { + .stage = UpdateTaskStageRadioBusy, + .percent_min = 21, + .percent_max = 30, + .descr = "FUS operation failed", + }, + { + .stage = UpdateTaskStageRadioBusy, + .percent_min = 31, + .percent_max = 100, + .descr = "C2 Stach switch failed", + }, + { + .stage = UpdateTaskStageOBValidation, + .percent_min = 0, + .percent_max = 100, + .descr = "Uncorr. value mismatch", + }, + { + .stage = UpdateTaskStageValidateDFUImage, + .percent_min = 0, + .percent_max = 1, + .descr = "Failed to open DFU file", + }, + { + .stage = UpdateTaskStageValidateDFUImage, + .percent_min = 1, + .percent_max = 97, + .descr = "DFU file read error", + }, + { + .stage = UpdateTaskStageValidateDFUImage, + .percent_min = 98, + .percent_max = 100, + .descr = "DFU file CRC mismatch", + }, + { + .stage = UpdateTaskStageFlashWrite, + .percent_min = 0, + .percent_max = 100, + .descr = "Flash write error", + }, + { + .stage = UpdateTaskStageFlashValidate, + .percent_min = 0, + .percent_max = 100, + .descr = "Flash compare error", + }, +#endif +#ifndef FURI_RAM_EXEC + { + .stage = UpdateTaskStageLfsRestore, + .percent_min = 0, + .percent_max = 100, + .descr = "LFS I/O error", + }, + { + .stage = UpdateTaskStageResourcesUpdate, + .percent_min = 0, + .percent_max = 100, + .descr = "SD card I/O error", + }, +#endif +}; + +static const char* update_task_get_error_message(UpdateTaskStage stage, uint8_t percent) { + for(size_t i = 0; i < COUNT_OF(update_task_error_detail); i++) { + if(update_task_error_detail[i].stage == stage && + percent >= update_task_error_detail[i].percent_min && + percent <= update_task_error_detail[i].percent_max) { + return update_task_error_detail[i].descr; + } + } + return "Unknown error"; +} + typedef struct { UpdateTaskStageGroup group; uint8_t weight; @@ -111,8 +296,9 @@ void update_task_set_progress(UpdateTask* update_task, UpdateTaskStage stage, ui if(stage >= UpdateTaskStageError) { furi_string_printf( update_task->state.status, - "%s #[%d-%d]", - update_task_stage_descr[stage], + "%s\n#[%d-%d]", + update_task_get_error_message( + update_task->state.stage, update_task->state.stage_progress), update_task->state.stage, update_task->state.stage_progress); } else { diff --git a/applications/system/updater/util/update_task_i.h b/applications/system/updater/util/update_task_i.h index 0dbeca5f..1b664e57 100644 --- a/applications/system/updater/util/update_task_i.h +++ b/applications/system/updater/util/update_task_i.h @@ -24,3 +24,8 @@ bool update_task_open_file(UpdateTask* update_task, FuriString* filename); int32_t update_task_worker_flash_writer(void* context); int32_t update_task_worker_backup_restore(void* context); + +#define CHECK_RESULT(x) \ + if(!(x)) { \ + break; \ + } diff --git a/applications/system/updater/util/update_task_worker_backup.c b/applications/system/updater/util/update_task_worker_backup.c index f2c33c2e..ef4276fa 100644 --- a/applications/system/updater/util/update_task_worker_backup.c +++ b/applications/system/updater/util/update_task_worker_backup.c @@ -15,11 +15,6 @@ #define TAG "UpdWorkerBackup" -#define CHECK_RESULT(x) \ - if(!(x)) { \ - break; \ - } - static bool update_task_pre_update(UpdateTask* update_task) { bool success = false; FuriString* backup_file_path; diff --git a/applications/system/updater/util/update_task_worker_flasher.c b/applications/system/updater/util/update_task_worker_flasher.c index 5d247746..d6dc13e3 100644 --- a/applications/system/updater/util/update_task_worker_flasher.c +++ b/applications/system/updater/util/update_task_worker_flasher.c @@ -13,11 +13,6 @@ #define TAG "UpdWorkerRAM" -#define CHECK_RESULT(x) \ - if(!(x)) { \ - break; \ - } - #define STM_DFU_VENDOR_ID 0x0483 #define STM_DFU_PRODUCT_ID 0xDF11 /* Written into DFU file by build pipeline */ @@ -137,7 +132,7 @@ static bool update_task_write_stack_data(UpdateTask* update_task) { } static void update_task_wait_for_restart(UpdateTask* update_task) { - update_task_set_progress(update_task, UpdateTaskStageRadioBusy, 10); + update_task_set_progress(update_task, UpdateTaskStageRadioBusy, 70); furi_delay_ms(C2_MODE_SWITCH_TIMEOUT); furi_crash("C2 timeout"); } @@ -153,12 +148,12 @@ static bool update_task_write_stack(UpdateTask* update_task) { manifest->radio_crc); CHECK_RESULT(update_task_write_stack_data(update_task)); - update_task_set_progress(update_task, UpdateTaskStageRadioInstall, 0); + update_task_set_progress(update_task, UpdateTaskStageRadioInstall, 10); CHECK_RESULT( ble_glue_fus_stack_install(manifest->radio_address, 0) != BleGlueCommandResultError); - update_task_set_progress(update_task, UpdateTaskStageRadioInstall, 80); + update_task_set_progress(update_task, UpdateTaskStageProgress, 80); CHECK_RESULT(ble_glue_fus_wait_operation() == BleGlueCommandResultOK); - update_task_set_progress(update_task, UpdateTaskStageRadioInstall, 100); + update_task_set_progress(update_task, UpdateTaskStageProgress, 100); /* ...system will restart here. */ update_task_wait_for_restart(update_task); } while(false); @@ -170,9 +165,9 @@ static bool update_task_remove_stack(UpdateTask* update_task) { FURI_LOG_W(TAG, "Removing stack"); update_task_set_progress(update_task, UpdateTaskStageRadioErase, 30); CHECK_RESULT(ble_glue_fus_stack_delete() != BleGlueCommandResultError); - update_task_set_progress(update_task, UpdateTaskStageRadioErase, 80); + update_task_set_progress(update_task, UpdateTaskStageProgress, 80); CHECK_RESULT(ble_glue_fus_wait_operation() == BleGlueCommandResultOK); - update_task_set_progress(update_task, UpdateTaskStageRadioErase, 100); + update_task_set_progress(update_task, UpdateTaskStageProgress, 100); /* ...system will restart here. */ update_task_wait_for_restart(update_task); } while(false); @@ -180,6 +175,7 @@ static bool update_task_remove_stack(UpdateTask* update_task) { } static bool update_task_manage_radiostack(UpdateTask* update_task) { + update_task_set_progress(update_task, UpdateTaskStageRadioBusy, 10); bool success = false; do { CHECK_RESULT(ble_glue_wait_for_c2_start(FURI_HAL_BT_C2_START_TIMEOUT)); @@ -208,15 +204,17 @@ static bool update_task_manage_radiostack(UpdateTask* update_task) { /* Version or type mismatch. Let's boot to FUS and start updating. */ FURI_LOG_W(TAG, "Restarting to FUS"); furi_hal_rtc_set_flag(FuriHalRtcFlagC2Update); + update_task_set_progress(update_task, UpdateTaskStageProgress, 20); + CHECK_RESULT(furi_hal_bt_ensure_c2_mode(BleGlueC2ModeFUS)); /* ...system will restart here. */ update_task_wait_for_restart(update_task); } } else if(c2_state->mode == BleGlueC2ModeFUS) { /* OK, we're in FUS mode. */ - update_task_set_progress(update_task, UpdateTaskStageRadioBusy, 10); FURI_LOG_W(TAG, "Waiting for FUS to settle"); - ble_glue_fus_wait_operation(); + update_task_set_progress(update_task, UpdateTaskStageProgress, 30); + CHECK_RESULT(ble_glue_fus_wait_operation() == BleGlueCommandResultOK); if(stack_version_match) { /* We can't check StackType with FUS, but partial version matches */ if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagC2Update)) { @@ -230,7 +228,7 @@ static bool update_task_manage_radiostack(UpdateTask* update_task) { /* We might just had the stack installed. * Let's start it up to check its version */ FURI_LOG_W(TAG, "Starting stack to check full version"); - update_task_set_progress(update_task, UpdateTaskStageRadioBusy, 40); + update_task_set_progress(update_task, UpdateTaskStageProgress, 50); CHECK_RESULT(furi_hal_bt_ensure_c2_mode(BleGlueC2ModeStack)); /* ...system will restart here. */ update_task_wait_for_restart(update_task); diff --git a/applications/system/updater/views/updater_main.c b/applications/system/updater/views/updater_main.c index 1199cc88..d32d51b7 100644 --- a/applications/system/updater/views/updater_main.c +++ b/applications/system/updater/views/updater_main.c @@ -81,16 +81,17 @@ static void updater_main_draw_callback(Canvas* canvas, void* _model) { canvas_set_font(canvas, FontPrimary); if(model->failed) { - canvas_draw_str_aligned(canvas, 42, 16, AlignLeft, AlignTop, "Update Failed!"); + canvas_draw_icon(canvas, 2, 22, &I_Warning_30x23); + canvas_draw_str_aligned(canvas, 40, 9, AlignLeft, AlignTop, "Update Failed!"); canvas_set_font(canvas, FontSecondary); - canvas_draw_str_aligned( - canvas, 42, 32, AlignLeft, AlignTop, furi_string_get_cstr(model->status)); - canvas_draw_icon(canvas, 7, 16, &I_Warning_30x23); + elements_multiline_text_aligned( + canvas, 75, 26, AlignCenter, AlignTop, furi_string_get_cstr(model->status)); + canvas_draw_str_aligned( - canvas, 18, 51, AlignLeft, AlignTop, "to retry, hold to abort"); - canvas_draw_icon(canvas, 7, 50, &I_Ok_btn_9x9); - canvas_draw_icon(canvas, 75, 51, &I_Pin_back_arrow_10x8); + canvas, 18, 55, AlignLeft, AlignTop, "to retry, hold to abort"); + canvas_draw_icon(canvas, 7, 54, &I_Ok_btn_9x9); + canvas_draw_icon(canvas, 75, 55, &I_Pin_back_arrow_10x8); } else { canvas_draw_str_aligned(canvas, 55, 14, AlignLeft, AlignTop, "UPDATING"); canvas_set_font(canvas, FontSecondary); diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_0.png b/assets/dolphin/external/L1_My_dude_128x64/frame_0.png new file mode 100644 index 00000000..bf07d03d Binary files /dev/null and b/assets/dolphin/external/L1_My_dude_128x64/frame_0.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_1.png b/assets/dolphin/external/L1_My_dude_128x64/frame_1.png new file mode 100644 index 00000000..4402654c Binary files /dev/null and b/assets/dolphin/external/L1_My_dude_128x64/frame_1.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_10.png b/assets/dolphin/external/L1_My_dude_128x64/frame_10.png new file mode 100644 index 00000000..10dabe4c Binary files /dev/null and b/assets/dolphin/external/L1_My_dude_128x64/frame_10.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_11.png b/assets/dolphin/external/L1_My_dude_128x64/frame_11.png new file mode 100644 index 00000000..878712fe Binary files /dev/null and b/assets/dolphin/external/L1_My_dude_128x64/frame_11.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_12.png b/assets/dolphin/external/L1_My_dude_128x64/frame_12.png new file mode 100644 index 00000000..19fc985a Binary files /dev/null and b/assets/dolphin/external/L1_My_dude_128x64/frame_12.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_13.png b/assets/dolphin/external/L1_My_dude_128x64/frame_13.png new file mode 100644 index 00000000..39172f26 Binary files /dev/null and b/assets/dolphin/external/L1_My_dude_128x64/frame_13.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_14.png b/assets/dolphin/external/L1_My_dude_128x64/frame_14.png new file mode 100644 index 00000000..9a3a84ff Binary files /dev/null and b/assets/dolphin/external/L1_My_dude_128x64/frame_14.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_15.png b/assets/dolphin/external/L1_My_dude_128x64/frame_15.png new file mode 100644 index 00000000..2472c272 Binary files /dev/null and b/assets/dolphin/external/L1_My_dude_128x64/frame_15.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_16.png b/assets/dolphin/external/L1_My_dude_128x64/frame_16.png new file mode 100644 index 00000000..4940aef6 Binary files /dev/null and b/assets/dolphin/external/L1_My_dude_128x64/frame_16.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_17.png b/assets/dolphin/external/L1_My_dude_128x64/frame_17.png new file mode 100644 index 00000000..fd910ce5 Binary files /dev/null and b/assets/dolphin/external/L1_My_dude_128x64/frame_17.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_18.png b/assets/dolphin/external/L1_My_dude_128x64/frame_18.png new file mode 100644 index 00000000..ed33f18a Binary files /dev/null and b/assets/dolphin/external/L1_My_dude_128x64/frame_18.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_19.png b/assets/dolphin/external/L1_My_dude_128x64/frame_19.png new file mode 100644 index 00000000..d602a01d Binary files /dev/null and b/assets/dolphin/external/L1_My_dude_128x64/frame_19.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_2.png b/assets/dolphin/external/L1_My_dude_128x64/frame_2.png new file mode 100644 index 00000000..b680b4ae Binary files /dev/null and b/assets/dolphin/external/L1_My_dude_128x64/frame_2.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_20.png b/assets/dolphin/external/L1_My_dude_128x64/frame_20.png new file mode 100644 index 00000000..2dfa931f Binary files /dev/null and b/assets/dolphin/external/L1_My_dude_128x64/frame_20.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_21.png b/assets/dolphin/external/L1_My_dude_128x64/frame_21.png new file mode 100644 index 00000000..272064d9 Binary files /dev/null and b/assets/dolphin/external/L1_My_dude_128x64/frame_21.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_22.png b/assets/dolphin/external/L1_My_dude_128x64/frame_22.png new file mode 100644 index 00000000..35d0149a Binary files /dev/null and b/assets/dolphin/external/L1_My_dude_128x64/frame_22.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_23.png b/assets/dolphin/external/L1_My_dude_128x64/frame_23.png new file mode 100644 index 00000000..83d02ef8 Binary files /dev/null and b/assets/dolphin/external/L1_My_dude_128x64/frame_23.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_24.png b/assets/dolphin/external/L1_My_dude_128x64/frame_24.png new file mode 100644 index 00000000..f3ac4417 Binary files /dev/null and b/assets/dolphin/external/L1_My_dude_128x64/frame_24.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_25.png b/assets/dolphin/external/L1_My_dude_128x64/frame_25.png new file mode 100644 index 00000000..832c2bde Binary files /dev/null and b/assets/dolphin/external/L1_My_dude_128x64/frame_25.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_26.png b/assets/dolphin/external/L1_My_dude_128x64/frame_26.png new file mode 100644 index 00000000..3836a3b0 Binary files /dev/null and b/assets/dolphin/external/L1_My_dude_128x64/frame_26.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_27.png b/assets/dolphin/external/L1_My_dude_128x64/frame_27.png new file mode 100644 index 00000000..ff621b73 Binary files /dev/null and b/assets/dolphin/external/L1_My_dude_128x64/frame_27.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_28.png b/assets/dolphin/external/L1_My_dude_128x64/frame_28.png new file mode 100644 index 00000000..94e05f94 Binary files /dev/null and b/assets/dolphin/external/L1_My_dude_128x64/frame_28.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_29.png b/assets/dolphin/external/L1_My_dude_128x64/frame_29.png new file mode 100644 index 00000000..1ce384b1 Binary files /dev/null and b/assets/dolphin/external/L1_My_dude_128x64/frame_29.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_3.png b/assets/dolphin/external/L1_My_dude_128x64/frame_3.png new file mode 100644 index 00000000..a5056eb4 Binary files /dev/null and b/assets/dolphin/external/L1_My_dude_128x64/frame_3.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_30.png b/assets/dolphin/external/L1_My_dude_128x64/frame_30.png new file mode 100644 index 00000000..8d42b8b4 Binary files /dev/null and b/assets/dolphin/external/L1_My_dude_128x64/frame_30.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_31.png b/assets/dolphin/external/L1_My_dude_128x64/frame_31.png new file mode 100644 index 00000000..ac926d7b Binary files /dev/null and b/assets/dolphin/external/L1_My_dude_128x64/frame_31.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_32.png b/assets/dolphin/external/L1_My_dude_128x64/frame_32.png new file mode 100644 index 00000000..35070eb6 Binary files /dev/null and b/assets/dolphin/external/L1_My_dude_128x64/frame_32.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_33.png b/assets/dolphin/external/L1_My_dude_128x64/frame_33.png new file mode 100644 index 00000000..a6c973f6 Binary files /dev/null and b/assets/dolphin/external/L1_My_dude_128x64/frame_33.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_34.png b/assets/dolphin/external/L1_My_dude_128x64/frame_34.png new file mode 100644 index 00000000..3f9407f3 Binary files /dev/null and b/assets/dolphin/external/L1_My_dude_128x64/frame_34.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_35.png b/assets/dolphin/external/L1_My_dude_128x64/frame_35.png new file mode 100644 index 00000000..6059e00d Binary files /dev/null and b/assets/dolphin/external/L1_My_dude_128x64/frame_35.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_36.png b/assets/dolphin/external/L1_My_dude_128x64/frame_36.png new file mode 100644 index 00000000..d2cd0c97 Binary files /dev/null and b/assets/dolphin/external/L1_My_dude_128x64/frame_36.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_37.png b/assets/dolphin/external/L1_My_dude_128x64/frame_37.png new file mode 100644 index 00000000..e60fd08d Binary files /dev/null and b/assets/dolphin/external/L1_My_dude_128x64/frame_37.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_38.png b/assets/dolphin/external/L1_My_dude_128x64/frame_38.png new file mode 100644 index 00000000..70e56b16 Binary files /dev/null and b/assets/dolphin/external/L1_My_dude_128x64/frame_38.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_39.png b/assets/dolphin/external/L1_My_dude_128x64/frame_39.png new file mode 100644 index 00000000..450b4d4f Binary files /dev/null and b/assets/dolphin/external/L1_My_dude_128x64/frame_39.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_4.png b/assets/dolphin/external/L1_My_dude_128x64/frame_4.png new file mode 100644 index 00000000..2d9f4e96 Binary files /dev/null and b/assets/dolphin/external/L1_My_dude_128x64/frame_4.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_40.png b/assets/dolphin/external/L1_My_dude_128x64/frame_40.png new file mode 100644 index 00000000..36920034 Binary files /dev/null and b/assets/dolphin/external/L1_My_dude_128x64/frame_40.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_41.png b/assets/dolphin/external/L1_My_dude_128x64/frame_41.png new file mode 100644 index 00000000..e0f88226 Binary files /dev/null and b/assets/dolphin/external/L1_My_dude_128x64/frame_41.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_42.png b/assets/dolphin/external/L1_My_dude_128x64/frame_42.png new file mode 100644 index 00000000..a8a23536 Binary files /dev/null and b/assets/dolphin/external/L1_My_dude_128x64/frame_42.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_43.png b/assets/dolphin/external/L1_My_dude_128x64/frame_43.png new file mode 100644 index 00000000..6a402b35 Binary files /dev/null and b/assets/dolphin/external/L1_My_dude_128x64/frame_43.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_44.png b/assets/dolphin/external/L1_My_dude_128x64/frame_44.png new file mode 100644 index 00000000..f425bcc1 Binary files /dev/null and b/assets/dolphin/external/L1_My_dude_128x64/frame_44.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_45.png b/assets/dolphin/external/L1_My_dude_128x64/frame_45.png new file mode 100644 index 00000000..b0ea1a7e Binary files /dev/null and b/assets/dolphin/external/L1_My_dude_128x64/frame_45.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_46.png b/assets/dolphin/external/L1_My_dude_128x64/frame_46.png new file mode 100644 index 00000000..3113ff2e Binary files /dev/null and b/assets/dolphin/external/L1_My_dude_128x64/frame_46.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_47.png b/assets/dolphin/external/L1_My_dude_128x64/frame_47.png new file mode 100644 index 00000000..87403c61 Binary files /dev/null and b/assets/dolphin/external/L1_My_dude_128x64/frame_47.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_48.png b/assets/dolphin/external/L1_My_dude_128x64/frame_48.png new file mode 100644 index 00000000..2734e2fc Binary files /dev/null and b/assets/dolphin/external/L1_My_dude_128x64/frame_48.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_5.png b/assets/dolphin/external/L1_My_dude_128x64/frame_5.png new file mode 100644 index 00000000..df225594 Binary files /dev/null and b/assets/dolphin/external/L1_My_dude_128x64/frame_5.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_6.png b/assets/dolphin/external/L1_My_dude_128x64/frame_6.png new file mode 100644 index 00000000..4c00552e Binary files /dev/null and b/assets/dolphin/external/L1_My_dude_128x64/frame_6.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_7.png b/assets/dolphin/external/L1_My_dude_128x64/frame_7.png new file mode 100644 index 00000000..97038094 Binary files /dev/null and b/assets/dolphin/external/L1_My_dude_128x64/frame_7.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_8.png b/assets/dolphin/external/L1_My_dude_128x64/frame_8.png new file mode 100644 index 00000000..86e41e91 Binary files /dev/null and b/assets/dolphin/external/L1_My_dude_128x64/frame_8.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/frame_9.png b/assets/dolphin/external/L1_My_dude_128x64/frame_9.png new file mode 100644 index 00000000..4334eefa Binary files /dev/null and b/assets/dolphin/external/L1_My_dude_128x64/frame_9.png differ diff --git a/assets/dolphin/external/L1_My_dude_128x64/meta.txt b/assets/dolphin/external/L1_My_dude_128x64/meta.txt new file mode 100644 index 00000000..8c326cf4 --- /dev/null +++ b/assets/dolphin/external/L1_My_dude_128x64/meta.txt @@ -0,0 +1,32 @@ +Filetype: Flipper Animation +Version: 1 + +Width: 128 +Height: 64 +Passive frames: 19 +Active frames: 51 +Frames order: 0 1 2 3 4 5 6 0 1 2 7 8 9 10 11 12 7 8 9 13 14 15 14 13 14 15 7 8 9 16 17 18 13 14 19 20 21 22 23 24 21 25 26 27 28 29 30 31 32 33 32 34 35 36 35 34 37 38 39 40 41 42 43 44 45 46 17 47 48 7 +Active cycles: 1 +Frame rate: 2 +Duration: 3600 +Active cooldown: 7 + +Bubble slots: 1 + +Slot: 0 +X: 41 +Y: 43 +Text: My dude +AlignH: Right +AlignV: Top +StartFrame: 50 +EndFrame: 50 + +Slot: 0 +X: 59 +Y: 43 +Text: My dude +AlignH: Left +AlignV: Top +StartFrame: 54 +EndFrame: 54 \ No newline at end of file diff --git a/assets/dolphin/external/manifest.txt b/assets/dolphin/external/manifest.txt index 55abe0ce..4e3dbbf1 100644 --- a/assets/dolphin/external/manifest.txt +++ b/assets/dolphin/external/manifest.txt @@ -97,6 +97,13 @@ Min butthurt: 0 Max butthurt: 10 Min level: 1 Max level: 3 +Weight: 3 + +Name: L1_My_dude_128x64 +Min butthurt: 0 +Max butthurt: 8 +Min level: 1 +Max level: 3 Weight: 4 Name: L2_Wake_up_128x64 diff --git a/assets/icons/About/Certification2_46x33.png b/assets/icons/About/Certification2_46x33.png new file mode 100644 index 00000000..d421b829 Binary files /dev/null and b/assets/icons/About/Certification2_46x33.png differ diff --git a/assets/icons/About/Certification2_98x33.png b/assets/icons/About/Certification2_98x33.png deleted file mode 100644 index 49c5581c..00000000 Binary files a/assets/icons/About/Certification2_98x33.png and /dev/null differ diff --git a/assets/resources/badusb/Install_qFlipper_windows.txt b/assets/resources/badusb/Install_qFlipper_windows.txt new file mode 100644 index 00000000..94282321 --- /dev/null +++ b/assets/resources/badusb/Install_qFlipper_windows.txt @@ -0,0 +1,42 @@ +REM Written by @dexv +DELAY 2000 +GUI r +DELAY 500 +STRING powershell +ENTER +DELAY 1000 +STRING $url = "https://update.flipperzero.one/qFlipper/release/windows-amd64/portable" +ENTER +STRING $output = "$env:USERPROFILE\Documents\qFlipper.zip" +ENTER +STRING $destination = "$env:USERPROFILE\Documents\qFlipper" +ENTER +STRING $shortcutPath = "$env:USERPROFILE\Desktop\qFlipper.lnk" +ENTER +STRING $scriptPath = "$env:USERPROFILE\Documents\qFlipperInstall.ps1" +ENTER +STRING $driverPath = "$destination\STM32 Driver" +ENTER +STRING $installBat = "$driverPath\install.bat" +ENTER +STRING (New-Object System.Net.WebClient).DownloadFile($url, $output) +ENTER +STRING Expand-Archive -Path $output -DestinationPath $destination -Force +ENTER +STRING Set-Location -Path $destination +ENTER +STRING Start-Process -FilePath ".\qFlipper.exe" +ENTER +STRING Start-Process -Wait -FilePath "cmd.exe" -ArgumentList "/c $installBat" +ENTER +STRING $shell = New-Object -ComObject WScript.Shell +ENTER +STRING $shortcut = $shell.CreateShortcut($shortcutPath) +ENTER +STRING $shortcut.TargetPath = "$destination\qFlipper.exe" +ENTER +STRING $shortcut.Save() +ENTER +DELAY 500 +STRING "powershell -ExecutionPolicy Bypass -File $scriptPath" +ENTER diff --git a/assets/resources/infrared/assets/ac.ir b/assets/resources/infrared/assets/ac.ir index c7b1aaf7..6ec6fc82 100644 --- a/assets/resources/infrared/assets/ac.ir +++ b/assets/resources/infrared/assets/ac.ir @@ -507,3 +507,77 @@ type: raw frequency: 38000 duty_cycle: 0.330000 data: 3539 1637 533 1225 502 1193 534 375 501 376 501 376 500 1226 501 376 501 376 500 1226 500 1227 501 376 529 1197 558 320 557 319 555 1169 531 1195 531 346 529 1196 530 1198 528 349 526 352 524 1229 497 379 497 379 497 1230 497 380 497 380 497 379 498 380 497 380 497 380 497 380 497 380 497 380 497 380 497 380 497 380 497 380 497 380 497 380 497 9042 3535 1674 496 1230 497 1230 497 380 497 380 497 380 497 1230 497 380 497 380 496 1230 497 1230 497 380 497 1230 497 380 497 380 497 1231 496 1230 497 380 497 1231 496 1231 496 380 496 380 497 1231 496 380 497 380 496 1231 496 380 497 380 497 380 497 380 497 380 497 380 497 380 497 380 497 380 497 380 496 380 497 380 497 380 497 380 497 380 496 381 496 380 497 380 497 380 497 381 496 1231 496 381 496 380 497 380 497 381 496 381 496 1231 496 381 496 381 496 380 497 381 495 1231 496 1231 496 1231 496 380 497 381 496 381 496 380 496 381 496 381 496 381 496 381 496 381 496 1231 496 1231 496 381 496 381 496 381 496 381 496 381 496 381 496 381 496 381 496 1231 496 381 496 381 496 1232 495 381 495 1232 495 381 496 1231 496 1231 496 381 496 381 496 381 496 381 496 381 496 381 496 381 496 381 496 381 496 381 496 381 496 381 496 381 496 381 496 381 496 381 496 381 496 381 496 381 496 381 496 381 495 381 496 381 496 381 496 381 496 1232 495 381 496 381 496 381 496 381 496 381 495 381 496 381 495 382 495 381 496 382 495 381 495 382 495 381 495 382 495 382 495 382 495 382 495 382 495 382 495 382 495 382 495 382 495 381 495 1232 495 1232 495 1232 495 1232 495 1232 495 382 495 382 495 382 495 +# +# Model: Hitachi RAK-50PEB +name: Off +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 30683 50966 3411 1600 493 1186 493 347 492 348 491 348 491 349 490 349 490 350 489 351 488 351 488 352 487 352 488 351 488 1192 487 352 487 351 488 352 487 352 487 352 488 352 488 351 488 1192 487 1191 488 352 487 352 487 352 487 352 487 352 487 352 487 352 487 352 487 1192 487 352 487 1192 487 1192 487 1192 487 1192 488 1192 487 1192 488 352 487 1192 487 1192 487 352 487 352 487 352 487 352 488 352 487 352 488 352 487 352 487 1192 487 1192 487 1192 487 1192 487 1192 487 1192 487 1192 487 1192 487 352 487 352 488 352 487 1192 487 352 487 352 487 352 487 352 487 1192 487 352 487 353 486 1192 487 353 486 353 486 353 486 353 486 1193 486 353 487 353 486 353 486 353 486 353 486 353 486 1193 486 1193 486 353 487 353 486 353 486 353 486 353 487 353 486 353 486 353 486 1193 486 353 486 353 486 1193 486 353 487 353 486 353 487 353 486 353 486 353 486 353 486 353 487 353 486 353 486 1193 486 1193 486 353 487 353 486 353 486 353 486 354 485 353 486 354 485 353 486 354 486 353 486 353 486 354 486 353 486 353 487 1193 486 1194 485 353 487 353 486 354 485 354 485 354 486 354 485 354 485 354 485 354 485 354 485 354 485 354 485 354 485 354 485 354 486 354 485 354 485 354 485 354 485 354 485 354 485 354 485 354 485 354 485 354 486 354 485 354 485 354 485 354 485 354 485 354 485 354 485 354 485 354 485 354 485 354 485 354 485 355 484 355 484 355 484 354 485 354 485 355 484 355 484 355 484 355 484 354 486 355 484 378 461 356 484 378 461 355 485 355 484 355 484 355 485 355 484 378 461 378 461 355 484 356 483 355 484 378 461 378 462 355 485 378 461 378 462 378 461 379 461 356 483 378 461 1195 484 378 461 379 461 356 484 378 461 379 460 379 461 378 461 378 462 378 461 379 461 378 461 378 461 379 460 379 460 379 461 378 461 378 461 378 461 378 461 378 461 379 460 379 460 379 460 379 461 379 460 1219 460 1219 460 379 461 1219 460 379 461 1219 460 +# +name: Dh +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 30684 50965 3412 1599 494 1185 494 346 493 346 493 347 492 348 491 349 490 349 490 350 489 351 489 350 489 350 489 351 489 1191 488 351 488 351 488 351 489 351 488 351 488 351 488 351 488 1191 488 1191 488 351 488 351 488 351 488 351 488 351 488 351 489 351 488 351 488 1191 488 351 489 1191 488 1191 488 1191 488 1191 488 1191 488 1191 488 351 488 1191 488 1192 487 351 488 352 487 351 488 351 488 352 487 352 487 352 487 352 488 1192 487 1192 487 1216 463 1192 487 1192 488 1192 487 1193 486 1192 488 352 487 352 487 352 487 1193 486 376 463 376 463 376 464 352 487 1216 463 376 463 376 463 1216 464 376 463 376 463 376 463 1216 463 376 463 376 463 353 486 353 487 376 463 376 463 376 463 1216 463 376 463 1216 463 376 464 376 463 376 463 376 464 376 463 376 463 376 463 376 463 1216 463 376 463 1216 463 376 463 376 463 376 463 376 463 376 463 376 463 376 463 376 463 376 464 376 463 1216 463 1217 463 376 463 377 462 377 462 377 463 376 463 376 463 377 462 376 463 377 462 377 462 377 463 376 463 377 462 377 462 1217 462 1216 463 377 463 377 462 377 462 377 462 377 463 376 463 377 462 377 463 377 462 377 462 377 462 377 462 377 462 377 462 377 462 377 462 377 463 377 462 377 463 377 462 377 462 1217 462 377 462 377 462 377 463 377 462 377 463 377 462 377 462 377 462 377 462 377 463 377 462 377 462 377 462 377 462 377 462 377 463 377 462 377 462 377 462 377 462 377 462 377 462 377 463 377 462 377 462 377 462 377 462 377 462 377 462 377 462 377 462 377 462 377 462 377 462 377 463 377 462 377 463 377 462 377 462 377 462 377 462 377 462 377 462 377 462 377 462 377 462 377 462 377 462 1217 462 377 462 377 462 377 462 377 462 378 461 377 462 377 462 378 462 377 462 377 462 377 463 377 462 378 461 378 462 377 462 378 461 377 462 378 461 378 461 378 461 378 462 377 462 378 462 1217 462 1218 461 1218 461 378 461 378 461 1218 462 377 462 378 462 +# +name: Cool_hi +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 30747 50897 3484 1554 543 1137 542 310 529 309 530 309 530 309 530 310 529 309 530 310 529 309 530 309 530 309 530 309 530 1138 541 309 531 309 530 309 530 309 530 309 530 309 530 309 530 1138 541 1138 541 310 529 309 530 309 531 309 530 309 530 309 530 309 530 310 529 1139 541 309 530 1138 541 1138 541 1138 541 1138 542 1138 541 1138 541 310 529 1138 541 1138 541 309 530 309 530 309 531 310 529 309 530 309 530 309 530 309 530 1139 541 1139 540 1139 541 1138 541 1139 540 1139 540 1138 541 1139 540 310 529 310 529 309 530 1139 541 310 529 309 530 309 530 309 530 1139 540 309 530 309 530 1139 541 309 530 309 530 309 530 1139 540 309 531 309 530 1139 541 309 530 309 530 309 530 309 530 309 530 309 530 1139 540 309 531 309 530 309 530 309 530 309 530 309 530 309 531 309 530 309 531 309 530 1139 540 310 529 309 530 309 530 309 530 309 530 309 531 310 529 310 529 309 531 310 529 1140 540 309 530 309 531 309 530 309 530 309 530 309 531 309 530 309 530 309 530 309 530 309 531 309 530 309 531 309 530 310 529 1140 539 1140 539 309 530 309 530 309 530 309 530 310 529 309 530 309 530 309 530 309 530 309 531 309 530 309 530 309 530 309 530 309 530 309 531 309 530 309 530 309 530 309 530 309 530 1140 540 309 530 309 530 309 530 309 530 309 531 309 530 309 531 309 530 309 530 310 530 309 530 309 531 309 530 309 530 309 530 309 530 309 530 309 531 309 530 309 530 309 531 309 530 309 530 309 531 309 531 309 530 309 530 309 530 309 530 309 531 309 531 309 530 309 530 309 530 309 530 309 530 309 531 309 530 309 531 309 530 309 531 309 530 309 530 309 531 309 530 309 530 309 530 309 530 1141 538 309 531 309 530 309 530 309 530 309 531 309 530 309 530 309 530 309 531 309 530 309 530 309 530 309 530 309 530 309 530 309 530 310 530 309 531 309 530 309 530 309 530 309 530 309 530 309 531 1142 537 309 530 1142 538 309 530 1141 538 309 530 309 530 +# +name: Cool_lo +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 30694 50951 3483 1555 542 1137 542 308 531 309 530 308 531 308 531 308 531 308 531 308 531 308 531 308 532 308 531 308 532 1139 541 308 531 308 531 308 531 308 531 308 531 309 531 308 531 1139 541 1139 540 308 531 308 531 308 531 308 531 309 530 308 531 308 531 308 532 1139 541 308 532 1139 540 1139 541 1139 540 1139 540 1139 540 1139 541 309 530 1139 540 1139 540 308 531 308 531 308 531 308 532 308 531 308 531 308 531 308 531 1140 540 1139 541 1139 540 1139 540 1139 540 1139 541 1139 540 1139 540 308 531 308 531 308 531 1140 540 309 530 308 531 308 532 308 531 1140 540 308 531 308 532 1140 539 308 531 308 531 308 531 308 532 308 531 308 531 1140 540 308 531 308 531 308 531 308 531 308 532 308 531 1140 540 308 531 308 531 308 531 308 531 308 531 308 531 1140 540 1140 540 1140 539 308 531 1140 539 308 531 308 531 308 532 308 531 306 533 308 531 306 533 308 531 307 533 308 531 1141 539 308 532 308 531 308 531 306 534 306 533 306 534 306 533 306 533 306 533 306 533 306 534 307 532 307 533 306 533 308 532 1141 539 1141 539 308 531 308 532 308 531 307 533 307 481 352 538 307 533 307 532 307 533 307 481 352 539 307 532 307 533 306 482 352 487 352 537 306 534 307 482 352 538 307 482 352 487 1192 539 309 530 307 531 306 483 352 487 352 538 307 482 352 538 306 483 352 487 352 487 352 487 353 486 352 488 353 486 352 487 352 487 353 487 353 486 353 486 353 487 352 487 353 486 353 486 353 486 353 486 353 487 353 487 353 486 353 486 353 487 353 486 353 486 353 486 353 487 353 486 353 487 352 487 353 486 353 486 353 487 353 486 353 486 353 487 353 486 353 487 353 486 353 487 353 486 1193 537 306 483 353 486 353 487 353 486 353 487 353 486 353 486 353 487 353 486 353 486 353 487 353 486 353 486 353 486 353 486 353 487 353 486 353 486 353 486 353 486 353 486 353 486 353 486 1194 485 353 487 1193 538 1142 486 1193 486 353 486 353 486 353 568 +# +name: Heat_hi +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 30703 50953 3432 1606 490 1189 490 349 490 349 490 349 490 350 489 350 489 350 489 350 490 350 489 350 489 350 490 350 489 1190 490 350 489 350 489 350 489 350 489 350 490 350 489 350 490 1190 490 1190 489 350 489 350 489 350 489 350 490 350 490 350 489 350 490 350 490 1190 489 350 490 1190 489 1190 490 1190 489 1190 490 1190 489 1190 489 350 490 1190 489 1190 489 350 490 350 489 350 490 350 489 350 489 350 490 350 489 350 490 1190 489 1190 489 1190 490 1190 489 1190 490 1190 489 1190 489 1191 489 350 489 350 489 350 490 1190 490 350 489 350 490 350 489 350 490 1190 489 350 490 350 489 1190 490 350 489 350 490 350 490 350 489 350 489 350 489 1191 489 350 489 350 490 350 489 350 489 1191 489 1190 489 350 489 350 490 350 489 350 490 350 489 351 489 350 489 350 489 350 489 350 490 350 489 350 489 1191 489 350 489 351 489 351 488 351 489 351 488 351 489 350 489 351 489 351 489 1191 488 351 488 351 488 351 489 350 489 351 488 350 490 350 489 351 488 351 488 351 489 350 489 350 489 351 489 351 489 350 489 1191 488 1191 489 350 489 351 488 351 489 351 488 351 489 351 488 351 488 351 489 351 489 351 489 350 489 351 489 351 488 351 488 351 488 351 489 351 488 351 488 351 488 351 489 351 489 1191 488 351 489 351 488 351 489 351 488 351 489 351 489 351 488 351 488 351 489 351 489 351 488 351 488 351 488 351 489 351 488 351 488 351 489 351 488 351 488 351 489 351 489 351 488 351 488 351 489 351 489 351 488 351 489 351 488 351 489 351 488 351 489 351 488 351 489 351 488 351 489 351 488 351 488 351 489 351 488 351 489 351 489 351 489 351 488 351 489 351 488 351 488 351 489 351 488 1192 488 351 488 351 488 351 489 351 488 351 488 351 489 351 489 351 489 351 488 351 488 351 489 351 488 351 489 351 488 351 489 351 488 351 488 351 489 351 488 351 489 351 488 351 489 351 488 351 489 351 489 1191 488 1191 488 352 488 351 488 352 488 351 489 +# +name: Heat_lo +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 30675 50953 3432 1606 490 1190 489 350 489 350 489 350 489 350 489 351 488 350 489 351 489 351 488 351 489 351 488 351 489 1191 488 351 488 351 489 351 488 351 488 351 488 351 489 351 488 1191 489 1191 489 351 488 351 488 351 488 351 488 351 489 351 489 351 488 351 489 1191 488 351 488 1191 489 1191 488 1191 488 1191 488 1191 488 1191 488 351 489 1191 488 1191 489 351 488 351 489 351 488 351 489 351 488 351 488 351 488 351 488 1191 488 1191 488 1191 488 1191 489 1191 488 1191 488 1191 489 1191 488 351 488 351 489 351 488 1191 488 351 489 351 488 351 488 351 489 1191 488 351 489 351 488 1191 488 351 488 351 488 351 489 351 489 351 488 351 489 1191 488 351 488 351 489 351 488 351 488 1191 488 1191 488 351 488 351 489 351 488 351 489 351 488 351 489 351 489 1191 488 1192 488 1191 488 351 489 1191 489 351 488 351 488 351 489 351 489 351 488 351 488 351 489 351 488 351 488 351 488 1192 488 351 489 351 488 351 488 351 489 351 489 351 488 351 488 351 488 352 487 352 488 351 488 352 488 351 488 351 488 351 488 1192 488 1192 487 352 488 352 487 352 487 352 488 352 487 352 488 351 488 352 488 352 488 352 487 352 488 351 488 351 488 352 488 352 487 352 488 352 487 352 488 352 488 352 488 352 487 1192 487 352 487 352 488 352 488 352 488 352 487 352 487 352 488 352 487 352 487 352 487 352 488 352 488 352 487 352 487 352 488 352 487 352 488 352 487 352 487 352 487 352 487 352 487 352 488 352 487 352 487 352 487 352 488 352 487 352 488 352 487 352 488 352 487 352 487 352 488 352 487 352 488 352 487 352 488 352 488 352 487 352 487 352 487 352 487 352 487 352 488 352 487 352 487 352 487 1193 486 352 487 352 488 352 487 352 487 352 488 352 487 352 488 352 488 352 487 352 488 352 487 353 486 353 487 352 487 352 488 352 488 352 487 352 487 352 487 352 487 353 487 352 488 352 488 352 487 1193 486 1193 486 1193 486 1193 487 353 487 352 487 353 486 +# +# Model: LG PC07SQR +name: Off +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 3169 9836 535 1553 511 551 491 543 491 544 490 1586 490 532 510 530 511 543 491 1579 489 1577 490 543 490 543 491 543 491 544 490 544 489 544 490 543 491 544 490 550 492 544 490 543 491 1586 489 542 492 1583 492 552 490 532 510 537 512 1585 491 +# +name: Dh +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 3385 9888 512 1544 512 544 489 544 489 544 490 1586 489 545 489 544 489 545 489 531 511 541 508 533 508 542 507 544 489 546 487 544 490 1587 489 1573 510 543 490 543 491 1578 490 545 489 1574 509 545 488 1587 489 1573 510 1586 490 1579 489 1568 507 +# +name: Cool_hi +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 3288 9816 598 1504 574 472 569 463 571 463 571 1515 568 472 569 461 573 471 571 459 590 462 571 463 571 447 594 462 572 462 571 464 570 459 590 463 570 464 570 1496 571 1497 570 463 571 1514 569 464 570 1504 572 1514 569 471 571 473 568 462 572 +# +name: Cool_lo +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 3205 9865 616 1473 536 518 516 517 517 517 517 1575 517 527 568 464 515 517 571 463 570 462 572 462 572 469 573 461 573 463 570 462 572 469 573 1504 572 451 590 451 591 472 569 463 571 1494 573 461 573 1497 570 1505 570 1503 572 471 571 1491 592 +# +name: Heat_hi +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 3363 9846 596 1495 514 518 515 517 517 515 518 1552 516 502 539 517 517 516 518 516 518 517 517 517 571 462 517 518 516 1554 568 461 589 462 572 1505 571 1507 568 1514 514 1568 570 461 573 1504 572 472 570 1507 592 1490 593 460 574 462 572 447 594 +# +name: Heat_lo +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 3204 9889 537 1587 491 529 512 544 489 545 489 1573 510 530 511 543 491 552 490 538 511 543 491 543 491 532 509 543 491 1587 489 537 512 543 491 1577 490 543 491 543 491 544 489 543 491 1586 489 544 490 1587 489 539 510 543 491 543 491 1586 490 diff --git a/assets/resources/infrared/assets/tv.ir b/assets/resources/infrared/assets/tv.ir index ba880712..c4b6f0c4 100644 --- a/assets/resources/infrared/assets/tv.ir +++ b/assets/resources/infrared/assets/tv.ir @@ -1681,3 +1681,39 @@ type: raw frequency: 38000 duty_cycle: 0.330000 data: 3462 1592 490 332 513 1200 489 331 514 1201 489 355 490 1201 489 356 512 1178 489 356 512 1178 512 334 487 1202 488 1202 488 357 512 1178 512 334 486 1203 487 1202 488 1203 487 1204 486 383 461 1228 488 357 488 357 487 357 487 1203 486 1204 486 359 485 1205 485 360 485 361 484 360 485 360 485 361 484 361 484 361 484 1206 484 360 484 361 484 361 484 1206 484 361 484 361 484 361 484 1206 484 361 484 1206 484 361 484 71543 3434 1620 486 359 485 1205 485 360 485 1206 484 360 485 1206 484 360 485 1206 484 360 485 1206 484 360 485 1205 485 1206 484 360 485 1206 484 360 485 1206 484 1206 484 1206 484 1206 484 361 484 1206 484 360 485 360 485 361 484 1206 484 1206 484 360 484 1206 484 360 485 361 484 361 484 360 485 361 484 361 484 361 484 1206 484 361 484 361 484 361 484 1206 484 361 484 361 484 361 484 1207 483 361 484 1206 484 361 484 71543 3435 1619 486 358 486 1204 486 359 486 1205 485 360 485 1205 485 360 485 1205 485 360 485 1205 485 360 484 1205 485 1205 485 360 485 1205 485 360 485 1205 485 1205 485 1205 485 1206 484 360 485 1205 485 360 485 360 485 360 485 1205 485 1206 484 360 485 1206 484 360 485 360 485 360 485 360 485 360 485 360 485 360 485 1206 484 360 485 360 485 360 485 1206 484 360 485 360 485 360 485 1205 485 360 485 1206 484 360 485 71542 3436 1619 486 358 487 1204 486 359 485 1205 485 360 485 1205 485 360 485 1205 485 360 485 1205 485 360 485 1205 485 1205 485 360 485 1205 485 360 485 1206 484 1206 484 1206 484 1206 484 360 485 1206 484 360 485 360 485 361 484 1206 484 1206 484 361 484 1206 484 361 484 361 484 361 484 361 484 361 484 361 484 360 485 1206 484 361 484 361 484 361 484 1206 484 361 484 361 484 360 485 1206 484 361 484 1206 484 361 484 71542 3437 1618 487 358 486 1204 486 359 486 1205 485 360 485 1205 485 360 485 1205 485 360 485 1205 485 360 485 1205 485 1206 484 360 485 1205 485 360 485 1206 484 1205 485 1206 484 1205 485 360 485 1205 485 360 485 360 485 360 485 1205 485 1205 485 360 485 1205 485 360 485 360 485 360 485 360 485 360 485 360 485 360 485 1205 485 360 485 360 485 360 485 1205 485 360 485 360 485 360 485 1205 485 360 485 1205 485 360 485 +# Model: TCL +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 3977 3993 494 1994 495 1995 496 1997 494 1996 495 1004 496 1004 496 1995 496 1004 496 1997 494 1005 495 1995 495 1007 493 1006 494 1006 494 1005 495 1007 493 1997 494 1995 496 1004 496 1995 496 1005 495 1995 496 1003 497 1995 496 8467 3980 3993 494 1994 495 1996 495 1997 494 1995 496 1004 496 1006 494 1995 496 1004 496 1996 495 1004 496 1996 495 1005 495 1005 495 1004 496 1005 495 1005 495 1996 495 1995 496 1005 495 1996 495 1004 496 1995 496 1006 569 1920 571 8393 3980 3993 571 1918 572 1922 569 1920 571 1920 571 929 572 929 571 1920 571 929 571 1920 571 929 571 1921 570 930 570 929 571 929 571 929 571 928 572 1920 571 1921 570 930 571 1920 572 930 571 1921 571 929 571 1923 569 8396 3980 3994 570 1921 569 1923 569 1921 571 1920 572 929 572 930 571 1921 570 930 571 1922 570 930 571 1921 570 930 570 930 571 929 571 929 571 929 572 1922 570 1921 570 931 570 1922 570 930 571 1922 569 931 570 1921 570 +# +name: Vol_up +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 3979 3995 493 1994 496 1997 495 1999 492 1999 492 1006 495 1008 493 1998 493 1006 494 1997 495 1999 493 1997 494 1998 493 1006 495 1007 493 1005 495 1006 495 2025 467 1998 494 1006 494 1996 495 1006 494 1005 495 1006 494 1007 493 8468 3979 3995 492 1995 495 1999 492 1997 494 1997 494 1007 493 1006 494 1997 494 1006 494 1997 494 1996 571 1923 569 1921 570 930 570 929 571 931 569 931 575 1916 570 1920 571 930 570 1922 570 930 571 930 570 930 576 924 576 +# +name: Vol_dn +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 3951 3994 494 1997 493 1998 494 1998 493 1998 493 1005 496 1005 496 1996 495 1005 495 1997 495 1996 495 1996 495 1006 494 1005 495 1006 494 1005 495 1006 494 1996 495 1998 493 1005 495 1997 494 1008 492 1006 494 1006 494 1997 494 8471 3977 3996 493 1996 493 1997 494 1998 493 1997 494 1006 494 1007 493 1997 494 1009 492 1996 495 1996 495 1997 494 1006 494 1006 494 1006 494 1006 494 1006 494 1997 493 1997 494 1006 494 1996 494 1005 495 1004 495 1006 494 1996 494 +# +name: Ch_next +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 3978 3994 494 1995 495 1996 495 1996 495 1996 495 1006 494 1004 497 1997 494 1005 495 1997 520 1970 577 923 578 1914 577 924 576 924 576 925 575 924 576 1914 577 1915 576 924 576 1914 577 924 576 923 577 1915 576 926 574 8388 3978 3993 576 1913 576 1915 576 1915 576 1917 574 923 577 923 577 1943 548 925 575 1916 576 1915 575 924 576 1915 576 925 575 927 573 925 575 926 574 1916 574 1918 573 927 573 1918 573 928 572 927 573 1918 573 926 574 8389 4006 3966 572 1918 571 1919 572 1918 573 1920 570 929 571 929 571 1922 569 928 571 1920 571 1921 570 928 572 1919 572 929 571 929 571 929 571 929 571 1921 570 1921 521 980 569 1921 521 981 519 979 521 1971 520 979 521 +# +name: Ch_prev +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 3979 3994 494 1995 495 1997 494 1996 495 1998 493 1005 495 1006 494 1997 494 1005 495 1996 495 1995 496 1005 495 1005 495 1006 494 1005 495 1004 496 1005 495 1997 494 1997 494 1004 496 1996 495 1005 495 1005 495 1997 494 1996 495 8467 3976 3991 496 1995 495 1996 494 1994 496 1996 494 1005 495 1005 495 1996 495 1005 495 1995 495 1995 496 1006 494 1005 495 1006 494 1005 495 1004 496 1006 494 1994 496 1996 494 1005 495 1995 495 1004 496 1004 496 1995 495 1996 494 +# +name: Mute +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 3981 3992 495 1994 495 1995 496 1996 494 1996 495 1005 495 1006 494 1995 495 1997 494 1996 495 1996 494 1997 494 1996 495 1006 494 1005 495 1004 496 1005 495 1995 496 1994 496 1005 495 1004 496 1005 495 1006 494 1004 496 1006 494 8466 3978 3991 495 1994 495 1997 493 1994 496 1995 495 1004 496 1004 496 1996 494 1997 493 1996 494 1995 495 1995 495 1997 493 1004 495 1004 495 1006 494 1005 494 1998 491 1996 494 1006 494 1004 496 1006 494 1006 493 1005 495 1005 571 diff --git a/assets/unit_tests/infrared/test_rca.irtest b/assets/unit_tests/infrared/test_rca.irtest new file mode 100644 index 00000000..bfe34e8e --- /dev/null +++ b/assets/unit_tests/infrared/test_rca.irtest @@ -0,0 +1,105 @@ +Filetype: IR tests file +Version: 1 +# +name: decoder_input1 +type: raw +data: 1000000 3994 3969 552 1945 551 1945 552 1945 551 1945 552 946 551 947 550 1947 548 951 546 1953 542 979 518 1979 517 981 492 1006 491 1006 492 1006 492 1006 492 2005 492 2005 492 1006 492 2005 492 1006 492 2005 492 1006 492 2006 491 +# +name: decoder_expected1 +type: parsed_array +count: 1 +# +protocol: RCA +address: 0F 00 00 00 +command: 54 00 00 00 +repeat: false +# +name: decoder_input2 +type: raw +data: 1000000 4055 3941 605 1891 551 1947 550 1946 551 1946 551 947 551 947 550 1947 549 949 548 1951 545 1977 519 1978 519 1979 518 980 518 980 518 980 518 980 518 1979 518 1979 518 981 517 1979 518 980 518 980 518 980 518 980 518 +# +name: decoder_expected2 +type: parsed_array +count: 1 +# +protocol: RCA +address: 0F 00 00 00 +command: F4 00 00 00 +repeat: false +# +name: decoder_input3 +type: raw +data: 1000000 4027 3970 551 1946 550 1946 551 1946 551 1946 551 946 551 947 550 1947 549 949 547 1951 545 1978 518 1979 492 1006 492 1007 491 1006 492 1006 492 1006 492 2006 491 2006 491 1006 492 2006 491 1007 491 1007 491 1006 492 2006 491 +# +name: decoder_expected3 +type: parsed_array +count: 1 +# +protocol: RCA +address: 0F 00 00 00 +command: 74 00 00 00 +repeat: false +# +name: decoder_input4 +type: raw +data: 1000000 4021 3941 551 1946 550 1946 551 1946 551 1945 552 946 551 947 550 1947 549 950 547 1952 544 1977 519 979 519 1979 518 980 518 980 518 980 518 980 518 1979 518 1979 518 980 518 1979 518 980 518 980 518 1979 518 980 518 +# +name: decoder_expected4 +type: parsed_array +count: 1 +# +protocol: RCA +address: 0F 00 00 00 +command: B4 00 00 00 +repeat: false +# +name: decoder_input5 +type: raw +data: 1000000 4022 3941 551 1946 551 1946 577 1919 578 1919 578 920 552 946 551 1946 550 947 550 1949 547 1952 544 978 520 979 519 980 518 980 518 980 518 980 518 1979 518 1979 518 980 518 1979 518 980 518 980 518 1979 518 1980 517 +# +name: decoder_expected5 +type: parsed_array +count: 1 +# +protocol: RCA +address: 0F 00 00 00 +command: 34 00 00 00 +repeat: false +# +name: decoder_input6 +type: raw +data: 1000000 3995 3968 552 1944 552 1946 550 1946 550 1946 551 947 550 948 549 1947 549 1949 547 1952 544 1978 518 1979 492 2005 492 1006 492 1006 492 1006 492 1006 492 2005 492 2005 492 1006 492 1006 492 1006 492 1006 492 1006 492 1006 492 +# +name: decoder_expected6 +type: parsed_array +count: 1 +# +protocol: RCA +address: 0F 00 00 00 +command: FC 00 00 00 +repeat: false +# +name: encoder_decoder_input1 +type: parsed_array +count: 4 +# +protocol: RCA +address: 0F 00 00 00 +command: 74 00 00 00 +repeat: false +# +protocol: RCA +address: 0F 00 00 00 +command: B4 00 00 00 +repeat: false +# +protocol: RCA +address: 0F 00 00 00 +command: 34 00 00 00 +repeat: false +# +protocol: RCA +address: 0F 00 00 00 +command: FC 00 00 00 +repeat: false +# diff --git a/documentation/AppsOnSDCard.md b/documentation/AppsOnSDCard.md index 212df5b1..051fbb84 100644 --- a/documentation/AppsOnSDCard.md +++ b/documentation/AppsOnSDCard.md @@ -13,7 +13,8 @@ FAPs are created and developed the same way as internal applications that are pa To build your application as a FAP, create a folder with your app's source code in `applications_user`, then write its code the way you'd do when creating a regular built-in application. Then configure its `application.fam` manifest, and set its _apptype_ to FlipperAppType.EXTERNAL. See [Application Manifests](./AppManifests.md#application-definition) for more details. - To build your application, run `./fbt fap_{APPID}`, where APPID is your application's ID in its manifest. -- To build your app and upload it over USB to run on Flipper, use `./fbt launch_app APPSRC=applications_user/path/to/app`. This command is configured in the default [VS Code profile](../.vscode/ReadMe.md) as a "Launch App on Flipper" build action (Ctrl+Shift+B menu). +- To build your app and upload it over USB to run on Flipper, use `./fbt launch APPSRC=applications_user/path/to/app`. This command is configured in the default [VS Code profile](../.vscode/ReadMe.md) as a "Launch App on Flipper" build action (Ctrl+Shift+B menu). +- To build an app without uploading it to Flipper, use `./fbt build APPSRC=applications_user/path/to/app`. This command is also availabe in VSCode configuration as "Build App". - To build all FAPs, run `./fbt faps` or `./fbt fap_dist`. ## FAP assets diff --git a/documentation/OTA.md b/documentation/OTA.md index 799548f4..ed75560c 100644 --- a/documentation/OTA.md +++ b/documentation/OTA.md @@ -87,9 +87,12 @@ Even if something goes wrong, updater allows you to retry failed operations and | Uninstalling radio FW | **4** | **0** | SHCI Delete command error | | | | **80** | Error awaiting command status | | Writing radio FW | **5** | **0-100** | Block read/write error | -| Installing radio FW | **6** | **0** | SHCI Install command error | +| Installing radio FW | **6** | **10** | SHCI Install command error | | | | **80** | Error awaiting command status | -| Radio is updating | **7** | **10** | Error waiting for operation completion | +| Core2 is busy | **7** | **10** | Couldn't start C2 | +| | | **20** | Failed to switch C2 to FUS mode | +| | | **30** | Error in FUS operation | +| | | **50** | Failed to switch C2 to stack mode | | Validating opt. bytes | **8** | **yy** | Option byte code | | Checking DFU file | **9** | **0** | Error opening DFU file | | | | **1-98** | Error reading DFU file | diff --git a/documentation/file_formats/InfraredFileFormats.md b/documentation/file_formats/InfraredFileFormats.md index 3c0acdcb..c9b6a953 100644 --- a/documentation/file_formats/InfraredFileFormats.md +++ b/documentation/file_formats/InfraredFileFormats.md @@ -1,5 +1,22 @@ # Infrared Flipper File Formats + +## Supported protocols list for `type: parsed` +``` + NEC + NECext + NEC42 + NEC42ext + Samsung32 + RC6 + RC5 + RC5X + SIRC + SIRC15 + SIRC20 + Kaseikyo + RCA +``` ## Infrared Remote File Format ### Example diff --git a/firmware/targets/f18/api_symbols.csv b/firmware/targets/f18/api_symbols.csv index 46099799..8b04f441 100644 --- a/firmware/targets/f18/api_symbols.csv +++ b/firmware/targets/f18/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,33.0,, +Version,+,34.3,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -36,7 +36,6 @@ 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/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,, @@ -56,6 +55,7 @@ Header,+,firmware/targets/f7/furi_hal/furi_hal_spi_types.h,, Header,+,firmware/targets/f7/furi_hal/furi_hal_uart.h,, Header,+,firmware/targets/f7/furi_hal/furi_hal_usb_cdc.h,, Header,+,firmware/targets/f7/platform_specific/intrinsic_export.h,, +Header,+,firmware/targets/f7/platform_specific/math_wrapper.h,, Header,+,firmware/targets/furi_hal_include/furi_hal.h,, Header,+,firmware/targets/furi_hal_include/furi_hal_bt.h,, Header,+,firmware/targets/furi_hal_include/furi_hal_bt_hid.h,, @@ -81,6 +81,7 @@ Header,+,firmware/targets/furi_hal_include/furi_hal_usb_hid_u2f.h,, Header,+,firmware/targets/furi_hal_include/furi_hal_version.h,, Header,+,firmware/targets/furi_hal_include/furi_hal_vibro.h,, Header,+,lib/digital_signal/digital_signal.h,, +Header,+,lib/drivers/cc1101_regs.h,, Header,+,lib/flipper_application/api_hashtable/api_hashtable.h,, Header,+,lib/flipper_application/api_hashtable/compilesort.hpp,, Header,+,lib/flipper_application/flipper_application.h,, @@ -289,12 +290,18 @@ Function,+,__assert_func,void,"const char*, int, const char*, const char*" Function,+,__clear_cache,void,"void*, void*" Function,-,__eprintf,void,"const char*, const char*, unsigned int, const char*" Function,+,__errno,int*, +Function,-,__fpclassifyd,int,double +Function,-,__fpclassifyf,int,float Function,+,__furi_crash,void, Function,+,__furi_critical_enter,__FuriCriticalInfo, Function,+,__furi_critical_exit,void,__FuriCriticalInfo Function,+,__furi_halt,void, Function,-,__getdelim,ssize_t,"char**, size_t*, int, FILE*" Function,-,__getline,ssize_t,"char**, size_t*, FILE*" +Function,-,__isinfd,int,double +Function,-,__isinff,int,float +Function,-,__isnand,int,double +Function,-,__isnanf,int,float Function,-,__itoa,char*,"int, char*, int" Function,-,__locale_mb_cur_max,int, Function,+,__retarget_lock_acquire,void,_LOCK_T @@ -307,6 +314,9 @@ Function,+,__retarget_lock_release,void,_LOCK_T Function,+,__retarget_lock_release_recursive,void,_LOCK_T Function,-,__retarget_lock_try_acquire,int,_LOCK_T Function,-,__retarget_lock_try_acquire_recursive,int,_LOCK_T +Function,-,__signbitd,int,double +Function,-,__signbitf,int,float +Function,-,__signgam,int*, Function,-,__srget_r,int,"_reent*, FILE*" Function,-,__swbuf_r,int,"_reent*, int, FILE*" Function,-,__utoa,char*,"unsigned, char*, int" @@ -459,6 +469,12 @@ Function,-,_wctomb_r,int,"_reent*, char*, wchar_t, _mbstate_t*" Function,-,a64l,long,const char* Function,+,abort,void, Function,-,abs,int,int +Function,-,acos,double,double +Function,-,acosf,float,float +Function,-,acosh,double,double +Function,-,acoshf,float,float +Function,-,acoshl,long double,long double +Function,-,acosl,long double,long double Function,-,aligned_alloc,void*,"size_t, size_t" Function,+,aligned_free,void,void* Function,+,aligned_malloc,void*,"size_t, size_t" @@ -474,11 +490,26 @@ Function,+,args_read_probably_quoted_string_and_trim,_Bool,"FuriString*, FuriStr Function,+,args_read_string_and_trim,_Bool,"FuriString*, FuriString*" Function,-,asctime,char*,const tm* Function,-,asctime_r,char*,"const tm*, char*" +Function,-,asin,double,double +Function,-,asinf,float,float +Function,-,asinh,double,double +Function,-,asinhf,float,float +Function,-,asinhl,long double,long double +Function,-,asinl,long double,long double Function,-,asiprintf,int,"char**, const char*, ..." Function,-,asniprintf,char*,"char*, size_t*, const char*, ..." Function,-,asnprintf,char*,"char*, size_t*, const char*, ..." Function,-,asprintf,int,"char**, const char*, ..." Function,-,at_quick_exit,int,void (*)() +Function,-,atan,double,double +Function,-,atan2,double,"double, double" +Function,-,atan2f,float,"float, float" +Function,-,atan2l,long double,"long double, long double" +Function,-,atanf,float,float +Function,-,atanh,double,double +Function,-,atanhf,float,float +Function,-,atanhl,long double,long double +Function,-,atanl,long double,long double Function,-,atexit,int,void (*)() Function,-,atof,double,const char* Function,-,atoff,float,const char* @@ -571,6 +602,12 @@ Function,+,canvas_set_font,void,"Canvas*, Font" Function,+,canvas_set_font_direction,void,"Canvas*, CanvasDirection" Function,+,canvas_string_width,uint16_t,"Canvas*, const char*" Function,+,canvas_width,uint8_t,const Canvas* +Function,-,cbrt,double,double +Function,-,cbrtf,float,float +Function,-,cbrtl,long double,long double +Function,-,ceil,double,double +Function,-,ceilf,float,float +Function,-,ceill,long double,long double Function,-,cfree,void,void* Function,-,clearerr,void,FILE* Function,-,clearerr_unlocked,void,FILE* @@ -591,6 +628,15 @@ Function,+,composite_api_resolver_add,void,"CompositeApiResolver*, const ElfApiI Function,+,composite_api_resolver_alloc,CompositeApiResolver*, Function,+,composite_api_resolver_free,void,CompositeApiResolver* Function,+,composite_api_resolver_get,const ElfApiInterface*,CompositeApiResolver* +Function,-,copysign,double,"double, double" +Function,-,copysignf,float,"float, float" +Function,-,copysignl,long double,"long double, long double" +Function,-,cos,double,double +Function,-,cosf,float,float +Function,-,cosh,double,double +Function,-,coshf,float,float +Function,-,coshl,long double,long double +Function,-,cosl,long double,long double Function,+,crc32_calc_buffer,uint32_t,"uint32_t, const void*, size_t" Function,+,crc32_calc_file,uint32_t,"File*, const FileCrcProgressCb, void*" Function,-,ctermid,char*,char* @@ -660,6 +706,8 @@ Function,+,dolphin_stats,DolphinStats,Dolphin* Function,+,dolphin_upgrade_level,void,Dolphin* Function,-,dprintf,int,"int, const char*, ..." Function,-,drand48,double, +Function,-,drem,double,"double, double" +Function,-,dremf,float,"float, float" Function,-,eTaskConfirmSleepModeStatus,eSleepModeStatus, Function,-,eTaskGetState,eTaskState,TaskHandle_t Function,+,elements_bold_rounded_frame,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t" @@ -687,10 +735,33 @@ Function,+,empty_screen_alloc,EmptyScreen*, Function,+,empty_screen_free,void,EmptyScreen* Function,+,empty_screen_get_view,View*,EmptyScreen* Function,-,erand48,double,unsigned short[3] +Function,-,erf,double,double +Function,-,erfc,double,double +Function,-,erfcf,float,float +Function,-,erfcl,long double,long double +Function,-,erff,float,float +Function,-,erfl,long double,long double Function,-,exit,void,int +Function,-,exp,double,double +Function,-,exp10,double,double +Function,-,exp10f,float,float +Function,-,exp2,double,double +Function,-,exp2f,float,float +Function,-,exp2l,long double,long double +Function,-,expf,float,float +Function,-,expl,long double,long double Function,-,explicit_bzero,void,"void*, size_t" +Function,-,expm1,double,double +Function,-,expm1f,float,float +Function,-,expm1l,long double,long double +Function,-,fabs,double,double +Function,-,fabsf,float,float +Function,-,fabsl,long double,long double Function,-,fclose,int,FILE* Function,-,fcloseall,int, +Function,-,fdim,double,"double, double" +Function,-,fdimf,float,"float, float" +Function,-,fdiml,long double,"long double, long double" Function,-,fdopen,FILE*,"int, const char*" Function,-,feof,int,FILE* Function,-,feof_unlocked,int,FILE* @@ -735,6 +806,9 @@ Function,+,file_stream_open,_Bool,"Stream*, const char*, FS_AccessMode, FS_OpenM Function,-,fileno,int,FILE* Function,-,fileno_unlocked,int,FILE* Function,+,filesystem_api_error_get_desc,const char*,FS_Error +Function,-,finite,int,double +Function,-,finitef,int,float +Function,-,finitel,int,long double Function,-,fiprintf,int,"FILE*, const char*, ..." Function,-,fiscanf,int,"FILE*, const char*, ..." Function,+,flipper_application_alloc,FlipperApplication*,"Storage*, const ElfApiInterface*" @@ -812,10 +886,25 @@ Function,+,flipper_format_write_string_cstr,_Bool,"FlipperFormat*, const char*, Function,+,flipper_format_write_uint32,_Bool,"FlipperFormat*, const char*, const uint32_t*, const uint16_t" Function,+,float_is_equal,_Bool,"float, float" Function,-,flockfile,void,FILE* +Function,-,floor,double,double +Function,-,floorf,float,float +Function,-,floorl,long double,long double Function,-,fls,int,int Function,-,flsl,int,long Function,-,flsll,int,long long +Function,-,fma,double,"double, double, double" +Function,-,fmaf,float,"float, float, float" +Function,-,fmal,long double,"long double, long double, long double" +Function,-,fmax,double,"double, double" +Function,-,fmaxf,float,"float, float" +Function,-,fmaxl,long double,"long double, long double" Function,-,fmemopen,FILE*,"void*, size_t, const char*" +Function,-,fmin,double,"double, double" +Function,-,fminf,float,"float, float" +Function,-,fminl,long double,"long double, long double" +Function,-,fmod,double,"double, double" +Function,-,fmodf,float,"float, float" +Function,-,fmodl,long double,"long double, long double" Function,-,fopen,FILE*,"const char*, const char*" Function,-,fopencookie,FILE*,"void*, const char*, cookie_io_functions_t" Function,-,fprintf,int,"FILE*, const char*, ..." @@ -828,6 +917,9 @@ Function,-,fread,size_t,"void*, size_t, size_t, FILE*" Function,-,fread_unlocked,size_t,"void*, size_t, size_t, FILE*" Function,+,free,void,void* Function,-,freopen,FILE*,"const char*, const char*, FILE*" +Function,-,frexp,double,"double, int*" +Function,-,frexpf,float,"float, int*" +Function,-,frexpl,long double,"long double, int*" Function,-,fscanf,int,"FILE*, const char*, ..." Function,-,fseek,int,"FILE*, long, int" Function,-,fseeko,int,"FILE*, off_t, int" @@ -1056,6 +1148,7 @@ Function,-,furi_hal_power_insomnia_level,uint16_t, Function,+,furi_hal_power_is_charging,_Bool, Function,+,furi_hal_power_is_charging_done,_Bool, Function,+,furi_hal_power_is_otg_enabled,_Bool, +Function,+,furi_hal_power_is_shutdown_requested,_Bool, Function,+,furi_hal_power_off,void, Function,+,furi_hal_power_reset,void, Function,+,furi_hal_power_set_battery_charge_voltage_limit,void,float @@ -1171,6 +1264,7 @@ Function,+,furi_hal_version_get_hw_target,uint8_t, Function,+,furi_hal_version_get_hw_timestamp,uint32_t, Function,+,furi_hal_version_get_hw_version,uint8_t, Function,+,furi_hal_version_get_ic_id,const char*, +Function,+,furi_hal_version_get_mic_id,const char*, Function,+,furi_hal_version_get_model_code,const char*, Function,+,furi_hal_version_get_model_name,const char*, Function,+,furi_hal_version_get_name_ptr,const char*, @@ -1188,6 +1282,8 @@ Function,+,furi_kernel_restore_lock,int32_t,int32_t Function,+,furi_kernel_unlock,int32_t, Function,+,furi_log_get_level,FuriLogLevel, Function,-,furi_log_init,void, +Function,+,furi_log_level_from_string,_Bool,"const char*, FuriLogLevel*" +Function,+,furi_log_level_to_string,_Bool,"FuriLogLevel, const char**" Function,+,furi_log_print_format,void,"FuriLogLevel, const char*, const char*, ..." Function,+,furi_log_print_raw_format,void,"FuriLogLevel, const char*, ..." Function,+,furi_log_set_level,void,FuriLogLevel @@ -1338,6 +1434,10 @@ Function,+,furi_timer_start,FuriStatus,"FuriTimer*, uint32_t" Function,+,furi_timer_stop,FuriStatus,FuriTimer* Function,-,fwrite,size_t,"const void*, size_t, size_t, FILE*" Function,-,fwrite_unlocked,size_t,"const void*, size_t, size_t, FILE*" +Function,-,gamma,double,double +Function,-,gamma_r,double,"double, int*" +Function,-,gammaf,float,float +Function,-,gammaf_r,float,"float, int*" Function,-,gap_get_state,GapState, Function,-,gap_init,_Bool,"GapConfig*, GapEventCallback, void*" Function,-,gap_start_advertising,void, @@ -1370,6 +1470,9 @@ Function,+,hex_char_to_hex_nibble,_Bool,"char, uint8_t*" Function,+,hex_char_to_uint8,_Bool,"char, char, uint8_t*" Function,+,hex_chars_to_uint64,_Bool,"const char*, uint64_t*" Function,+,hex_chars_to_uint8,_Bool,"const char*, uint8_t*" +Function,-,hypot,double,"double, double" +Function,-,hypotf,float,"float, float" +Function,-,hypotl,long double,"long double, long double" Function,+,icon_animation_alloc,IconAnimation*,const Icon* Function,+,icon_animation_free,void,IconAnimation* Function,+,icon_animation_get_height,uint8_t,const IconAnimation* @@ -1381,7 +1484,12 @@ Function,+,icon_animation_stop,void,IconAnimation* Function,+,icon_get_data,const uint8_t*,const Icon* Function,+,icon_get_height,uint8_t,const Icon* Function,+,icon_get_width,uint8_t,const Icon* +Function,-,ilogb,int,double +Function,-,ilogbf,int,float +Function,-,ilogbl,int,long double Function,-,index,char*,"const char*, int" +Function,-,infinity,double, +Function,-,infinityf,float, Function,-,initstate,char*,"unsigned, char*, size_t" Function,+,input_get_key_name,const char*,InputKey Function,+,input_get_type_name,const char*,InputType @@ -1401,8 +1509,12 @@ Function,-,isdigit,int,int Function,-,isdigit_l,int,"int, locale_t" Function,-,isgraph,int,int Function,-,isgraph_l,int,"int, locale_t" +Function,-,isinf,int,double +Function,-,isinff,int,float Function,-,islower,int,int Function,-,islower_l,int,"int, locale_t" +Function,-,isnan,int,double +Function,-,isnanf,int,float Function,-,isprint,int,int Function,-,isprint_l,int,"int, locale_t" Function,-,ispunct,int,int @@ -1414,13 +1526,33 @@ Function,-,isupper_l,int,"int, locale_t" Function,-,isxdigit,int,int Function,-,isxdigit_l,int,"int, locale_t" Function,-,itoa,char*,"int, char*, int" +Function,-,j0,double,double +Function,-,j0f,float,float +Function,-,j1,double,double +Function,-,j1f,float,float +Function,-,jn,double,"int, double" +Function,-,jnf,float,"int, float" Function,-,jrand48,long,unsigned short[3] Function,-,l64a,char*,long Function,-,labs,long,long Function,-,lcong48,void,unsigned short[7] +Function,-,ldexp,double,"double, int" +Function,-,ldexpf,float,"float, int" +Function,-,ldexpl,long double,"long double, int" Function,-,ldiv,ldiv_t,"long, long" +Function,-,lgamma,double,double +Function,-,lgamma_r,double,"double, int*" +Function,-,lgammaf,float,float +Function,-,lgammaf_r,float,"float, int*" +Function,-,lgammal,long double,long double Function,-,llabs,long long,long long Function,-,lldiv,lldiv_t,"long long, long long" +Function,-,llrint,long long int,double +Function,-,llrintf,long long int,float +Function,-,llrintl,long long int,long double +Function,-,llround,long long int,double +Function,-,llroundf,long long int,float +Function,-,llroundl,long long int,long double Function,+,loader_get_pubsub,FuriPubSub*,Loader* Function,+,loader_is_locked,_Bool,Loader* Function,+,loader_lock,_Bool,Loader* @@ -1443,7 +1575,28 @@ Function,+,locale_set_measurement_unit,void,LocaleMeasurementUnits Function,+,locale_set_time_format,void,LocaleTimeFormat Function,-,localtime,tm*,const time_t* Function,-,localtime_r,tm*,"const time_t*, tm*" +Function,-,log,double,double +Function,-,log10,double,double +Function,-,log10f,float,float +Function,-,log10l,long double,long double +Function,-,log1p,double,double +Function,-,log1pf,float,float +Function,-,log1pl,long double,long double +Function,-,log2,double,double +Function,-,log2f,float,float +Function,-,log2l,long double,long double +Function,-,logb,double,double +Function,-,logbf,float,float +Function,-,logbl,long double,long double +Function,-,logf,float,float +Function,-,logl,long double,long double Function,-,lrand48,long, +Function,-,lrint,long int,double +Function,-,lrintf,long int,float +Function,-,lrintl,long int,long double +Function,-,lround,long int,double +Function,-,lroundf,long int,float +Function,-,lroundl,long,long double Function,+,malloc,void*,size_t Function,+,manchester_advance,_Bool,"ManchesterState, ManchesterEvent, ManchesterState*, _Bool*" Function,+,manchester_encoder_advance,_Bool,"ManchesterEncoderState*, const _Bool, ManchesterEncoderResult*" @@ -1521,6 +1674,9 @@ Function,-,mkstemp,int,char* Function,-,mkstemps,int,"char*, int" Function,-,mktemp,char*,char* Function,-,mktime,time_t,tm* +Function,-,modf,double,"double, double*" +Function,-,modff,float,"float, float*" +Function,-,modfl,long double,"long double, long double*" Function,-,mrand48,long, Function,-,music_worker_alloc,MusicWorker*, Function,-,music_worker_clear,void,MusicWorker* @@ -1534,6 +1690,18 @@ Function,-,music_worker_set_callback,void,"MusicWorker*, MusicWorkerCallback, vo Function,-,music_worker_set_volume,void,"MusicWorker*, float" Function,-,music_worker_start,void,MusicWorker* Function,-,music_worker_stop,void,MusicWorker* +Function,-,nan,double,const char* +Function,-,nanf,float,const char* +Function,-,nanl,long double,const char* +Function,-,nearbyint,double,double +Function,-,nearbyintf,float,float +Function,-,nearbyintl,long double,long double +Function,-,nextafter,double,"double, double" +Function,-,nextafterf,float,"float, float" +Function,-,nextafterl,long double,"long double, long double" +Function,-,nexttoward,double,"double, long double" +Function,-,nexttowardf,float,"float, long double" +Function,-,nexttowardl,long double,"long double, long double" Function,+,notification_internal_message,void,"NotificationApp*, const NotificationSequence*" Function,+,notification_internal_message_block,void,"NotificationApp*, const NotificationSequence*" Function,+,notification_message,void,"NotificationApp*, const NotificationSequence*" @@ -1601,12 +1769,17 @@ Function,+,popup_set_icon,void,"Popup*, uint8_t, uint8_t, const Icon*" Function,+,popup_set_text,void,"Popup*, const char*, uint8_t, uint8_t, Align, Align" Function,+,popup_set_timeout,void,"Popup*, uint32_t" Function,-,posix_memalign,int,"void**, size_t, size_t" +Function,-,pow,double,"double, double" +Function,-,pow10,double,double +Function,-,pow10f,float,float Function,+,power_enable_low_battery_level_notification,void,"Power*, _Bool" Function,+,power_get_info,void,"Power*, PowerInfo*" Function,+,power_get_pubsub,FuriPubSub*,Power* Function,+,power_is_battery_healthy,_Bool,Power* Function,+,power_off,void,Power* Function,+,power_reboot,void,PowerBootMode +Function,+,powf,float,"float, float" +Function,-,powl,long double,"long double, long double" Function,+,pretty_format_bytes_hex_canonical,void,"FuriString*, size_t, const char*, const uint8_t*, size_t" Function,-,printf,int,"const char*, ..." Function,+,property_value_out,void,"PropertyValueContext*, const char*, unsigned int, ..." @@ -1664,11 +1837,23 @@ Function,+,realloc,void*,"void*, size_t" Function,-,reallocarray,void*,"void*, size_t, size_t" Function,-,reallocf,void*,"void*, size_t" Function,-,realpath,char*,"const char*, char*" +Function,-,remainder,double,"double, double" +Function,-,remainderf,float,"float, float" +Function,-,remainderl,long double,"long double, long double" Function,-,remove,int,const char* +Function,-,remquo,double,"double, double, int*" +Function,-,remquof,float,"float, float, int*" +Function,-,remquol,long double,"long double, long double, int*" Function,-,rename,int,"const char*, const char*" Function,-,renameat,int,"int, const char*, int, const char*" Function,-,rewind,void,FILE* Function,-,rindex,char*,"const char*, int" +Function,-,rint,double,double +Function,-,rintf,float,float +Function,-,rintl,long double,long double +Function,-,round,double,double +Function,+,roundf,float,float +Function,-,roundl,long double,long double Function,+,rpc_session_close,void,RpcSession* Function,+,rpc_session_feed,size_t,"RpcSession*, uint8_t*, size_t, TickType_t" Function,+,rpc_session_get_available_size,size_t,RpcSession* @@ -1693,6 +1878,12 @@ Function,-,rpmatch,int,const char* Function,+,saved_struct_get_payload_size,_Bool,"const char*, uint8_t, uint8_t, size_t*" Function,+,saved_struct_load,_Bool,"const char*, void*, size_t, uint8_t, uint8_t" Function,+,saved_struct_save,_Bool,"const char*, void*, size_t, uint8_t, uint8_t" +Function,-,scalbln,double,"double, long int" +Function,-,scalblnf,float,"float, long int" +Function,-,scalblnl,long double,"long double, long" +Function,-,scalbn,double,"double, int" +Function,+,scalbnf,float,"float, int" +Function,-,scalbnl,long double,"long double, int" Function,-,scanf,int,"const char*, ..." Function,+,scene_manager_alloc,SceneManager*,"const SceneManagerHandlers*, void*" Function,+,scene_manager_free,void,SceneManager* @@ -1732,11 +1923,22 @@ Function,+,sha256_finish,void,"sha256_context*, unsigned char[32]" Function,+,sha256_process,void,sha256_context* Function,+,sha256_start,void,sha256_context* Function,+,sha256_update,void,"sha256_context*, const unsigned char*, unsigned int" +Function,-,sin,double,double +Function,-,sincos,void,"double, double*, double*" +Function,-,sincosf,void,"float, float*, float*" +Function,-,sinf,float,float +Function,-,sinh,double,double +Function,-,sinhf,float,float +Function,-,sinhl,long double,long double +Function,-,sinl,long double,long double Function,-,siprintf,int,"char*, const char*, ..." Function,-,siscanf,int,"const char*, const char*, ..." Function,-,sniprintf,int,"char*, size_t, const char*, ..." Function,+,snprintf,int,"char*, size_t, const char*, ..." Function,-,sprintf,int,"char*, const char*, ..." +Function,-,sqrt,double,double +Function,-,sqrtf,float,float +Function,-,sqrtl,long double,long double Function,+,srand,void,unsigned Function,-,srand48,void,long Function,-,srandom,void,unsigned @@ -1891,6 +2093,12 @@ Function,+,submenu_reset,void,Submenu* Function,+,submenu_set_header,void,"Submenu*, const char*" Function,+,submenu_set_selected_item,void,"Submenu*, uint32_t" Function,-,system,int,const char* +Function,-,tan,double,double +Function,-,tanf,float,float +Function,-,tanh,double,double +Function,-,tanhf,float,float +Function,-,tanhl,long double,long double +Function,-,tanl,long double,long double Function,+,tar_archive_add_dir,_Bool,"TarArchive*, const char*, const char*" Function,+,tar_archive_add_file,_Bool,"TarArchive*, const char*, const char*, const int32_t" Function,+,tar_archive_alloc,TarArchive*,Storage* @@ -1923,6 +2131,9 @@ Function,+,text_input_reset,void,TextInput* Function,+,text_input_set_header_text,void,"TextInput*, const char*" Function,+,text_input_set_result_callback,void,"TextInput*, TextInputCallback, void*, char*, size_t, _Bool" Function,+,text_input_set_validator,void,"TextInput*, TextInputValidatorCallback, void*" +Function,-,tgamma,double,double +Function,-,tgammaf,float,float +Function,-,tgammal,long double,long double Function,-,time,time_t,time_t* Function,-,timingsafe_bcmp,int,"const void*, const void*, size_t" Function,-,timingsafe_memcmp,int,"const void*, const void*, size_t" @@ -1934,6 +2145,9 @@ Function,-,tolower,int,int Function,-,tolower_l,int,"int, locale_t" Function,-,toupper,int,int Function,-,toupper_l,int,"int, locale_t" +Function,-,trunc,double,double +Function,-,truncf,float,float +Function,-,truncl,long double,long double Function,-,tzset,void, Function,-,uECC_compress,void,"const uint8_t*, uint8_t*, uECC_Curve" Function,+,uECC_compute_public_key,int,"const uint8_t*, uint8_t*, uECC_Curve" @@ -2166,6 +2380,12 @@ Function,-,xTimerGetTimerDaemonTaskHandle,TaskHandle_t, Function,-,xTimerIsTimerActive,BaseType_t,TimerHandle_t Function,-,xTimerPendFunctionCall,BaseType_t,"PendedFunction_t, void*, uint32_t, TickType_t" Function,-,xTimerPendFunctionCallFromISR,BaseType_t,"PendedFunction_t, void*, uint32_t, BaseType_t*" +Function,-,y0,double,double +Function,-,y0f,float,float +Function,-,y1,double,double +Function,-,y1f,float,float +Function,-,yn,double,"int, double" +Function,-,ynf,float,"int, float" Variable,-,AHBPrescTable,const uint32_t[16], Variable,-,APBPrescTable,const uint32_t[8], Variable,-,ITM_RxBuffer,volatile int32_t, diff --git a/firmware/targets/f18/furi_hal/furi_hal_power_calibration.h b/firmware/targets/f18/furi_hal/furi_hal_power_calibration.h deleted file mode 100644 index e97e1657..00000000 --- a/firmware/targets/f18/furi_hal/furi_hal_power_calibration.h +++ /dev/null @@ -1,37 +0,0 @@ -const ParamCEDV cedv = { - .cedv_conf.gauge_conf = - { - .CCT = 1, - .CSYNC = 0, - .EDV_CMP = 0, - .SC = 1, - .FIXED_EDV0 = 1, - .FCC_LIM = 1, - .FC_FOR_VDQ = 1, - .IGNORE_SD = 1, - .SME0 = 0, - }, - .full_charge_cap = 1300, - .design_cap = 1300, - .EDV0 = 3300, - .EDV1 = 3321, - .EDV2 = 3355, - .EMF = 3679, - .C0 = 430, - .C1 = 0, - .R1 = 408, - .R0 = 334, - .T0 = 4626, - .TC = 11, - .DOD0 = 4044, - .DOD10 = 3905, - .DOD20 = 3807, - .DOD30 = 3718, - .DOD40 = 3642, - .DOD50 = 3585, - .DOD60 = 3546, - .DOD70 = 3514, - .DOD80 = 3477, - .DOD90 = 3411, - .DOD100 = 3299, -}; diff --git a/firmware/targets/f18/furi_hal/furi_hal_power_config.c b/firmware/targets/f18/furi_hal/furi_hal_power_config.c new file mode 100644 index 00000000..50efceb7 --- /dev/null +++ b/firmware/targets/f18/furi_hal/furi_hal_power_config.c @@ -0,0 +1,149 @@ +#include + +const BQ27220DMGaugingConfig furi_hal_power_gauge_data_memory_gauging_config = { + .CCT = 1, + .CSYNC = 0, + .EDV_CMP = 0, + .SC = 1, + .FIXED_EDV0 = 1, + .FCC_LIM = 1, + .FC_FOR_VDQ = 1, + .IGNORE_SD = 1, + .SME0 = 0, +}; + +const BQ27220DMData furi_hal_power_gauge_data_memory[] = { + { + .address = BQ27220DMAddressGasGaugingCEDVProfile1GaugingConfig, + .type = BQ27220DMTypePtr16, + .value.u32 = (uint32_t)&furi_hal_power_gauge_data_memory_gauging_config, + }, + { + .address = BQ27220DMAddressGasGaugingCEDVProfile1FullChargeCapacity, + .type = BQ27220DMTypeU16, + .value.u16 = 1300, + }, + { + .address = BQ27220DMAddressGasGaugingCEDVProfile1DesignCapacity, + .type = BQ27220DMTypeU16, + .value.u16 = 1300, + }, + { + .address = BQ27220DMAddressGasGaugingCEDVProfile1EMF, + .type = BQ27220DMTypeU16, + .value.u16 = 3679, + }, + { + .address = BQ27220DMAddressGasGaugingCEDVProfile1C0, + .type = BQ27220DMTypeU16, + .value.u16 = 430, + }, + { + .address = BQ27220DMAddressGasGaugingCEDVProfile1R0, + .type = BQ27220DMTypeU16, + .value.u16 = 334, + }, + { + .address = BQ27220DMAddressGasGaugingCEDVProfile1T0, + .type = BQ27220DMTypeU16, + .value.u16 = 4626, + }, + { + .address = BQ27220DMAddressGasGaugingCEDVProfile1R1, + .type = BQ27220DMTypeU16, + .value.u16 = 408, + }, + { + .address = BQ27220DMAddressGasGaugingCEDVProfile1TC, + .type = BQ27220DMTypeU8, + .value.u8 = 11, + }, + { + .address = BQ27220DMAddressGasGaugingCEDVProfile1C1, + .type = BQ27220DMTypeU8, + .value.u8 = 0, + }, + { + .address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD0, + .type = BQ27220DMTypeU16, + .value.u16 = 4044, + }, + { + .address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD10, + .type = BQ27220DMTypeU16, + .value.u16 = 3905, + }, + { + .address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD20, + .type = BQ27220DMTypeU16, + .value.u16 = 3807, + }, + { + .address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD30, + .type = BQ27220DMTypeU16, + .value.u16 = 3718, + }, + { + .address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD40, + .type = BQ27220DMTypeU16, + .value.u16 = 3642, + }, + { + .address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD50, + .type = BQ27220DMTypeU16, + .value.u16 = 3585, + }, + { + .address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD60, + .type = BQ27220DMTypeU16, + .value.u16 = 3546, + }, + { + .address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD70, + .type = BQ27220DMTypeU16, + .value.u16 = 3514, + }, + { + .address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD80, + .type = BQ27220DMTypeU16, + .value.u16 = 3477, + }, + { + .address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD90, + .type = BQ27220DMTypeU16, + .value.u16 = 3411, + }, + { + .address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD100, + .type = BQ27220DMTypeU16, + .value.u16 = 3299, + }, + { + .address = BQ27220DMAddressGasGaugingCEDVProfile1EDV0, + .type = BQ27220DMTypeU16, + .value.u16 = 3300, + }, + { + .address = BQ27220DMAddressGasGaugingCEDVProfile1EDV1, + .type = BQ27220DMTypeU16, + .value.u16 = 3321, + }, + { + .address = BQ27220DMAddressGasGaugingCEDVProfile1EDV2, + .type = BQ27220DMTypeU16, + .value.u16 = 3355, + }, + { + .address = BQ27220DMAddressCalibrationCurrentDeadband, + .type = BQ27220DMTypeU8, + .value.u8 = 1, + }, + { + .address = BQ27220DMAddressConfigurationPowerSleepCurrent, + .type = BQ27220DMTypeI16, + .value.i16 = 1, + }, + { + .type = BQ27220DMTypeEnd, + }, +}; diff --git a/firmware/targets/f18/furi_hal/furi_hal_version_device.c b/firmware/targets/f18/furi_hal/furi_hal_version_device.c index 1b5090b9..e038b98d 100644 --- a/firmware/targets/f18/furi_hal/furi_hal_version_device.c +++ b/firmware/targets/f18/furi_hal/furi_hal_version_device.c @@ -5,17 +5,21 @@ bool furi_hal_version_do_i_belong_here() { } const char* furi_hal_version_get_model_name() { - return "Komi"; + return "Flipper Nano"; } const char* furi_hal_version_get_model_code() { - return "N/A"; + return "FN.1"; } const char* furi_hal_version_get_fcc_id() { - return "N/A"; + return "Pending"; } const char* furi_hal_version_get_ic_id() { - return "N/A"; + return "Pending"; +} + +const char* furi_hal_version_get_mic_id() { + return "Pending"; } diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index dbaeb8e4..dc0720ee 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1,5 +1,6 @@ entry,status,name,type,params -Version,+,33.0,, +Version,+,34.3,, +Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -49,7 +50,6 @@ Header,+,firmware/targets/f7/furi_hal/furi_hal_idle_timer.h,, Header,+,firmware/targets/f7/furi_hal/furi_hal_interrupt.h,, Header,+,firmware/targets/f7/furi_hal/furi_hal_nfc.h,, Header,+,firmware/targets/f7/furi_hal/furi_hal_os.h,, -Header,-,firmware/targets/f7/furi_hal/furi_hal_power_calibration.h,, Header,+,firmware/targets/f7/furi_hal/furi_hal_pwm.h,, Header,+,firmware/targets/f7/furi_hal/furi_hal_resources.h,, Header,+,firmware/targets/f7/furi_hal/furi_hal_rfid.h,, @@ -60,6 +60,7 @@ Header,+,firmware/targets/f7/furi_hal/furi_hal_target_hw.h,, Header,+,firmware/targets/f7/furi_hal/furi_hal_uart.h,, Header,+,firmware/targets/f7/furi_hal/furi_hal_usb_cdc.h,, Header,+,firmware/targets/f7/platform_specific/intrinsic_export.h,, +Header,+,firmware/targets/f7/platform_specific/math_wrapper.h,, Header,+,firmware/targets/furi_hal_include/furi_hal.h,, Header,+,firmware/targets/furi_hal_include/furi_hal_bt.h,, Header,+,firmware/targets/furi_hal_include/furi_hal_bt_hid.h,, @@ -86,6 +87,7 @@ Header,+,firmware/targets/furi_hal_include/furi_hal_usb_hid_u2f.h,, Header,+,firmware/targets/furi_hal_include/furi_hal_version.h,, Header,+,firmware/targets/furi_hal_include/furi_hal_vibro.h,, Header,+,lib/digital_signal/digital_signal.h,, +Header,+,lib/drivers/cc1101_regs.h,, Header,+,lib/flipper_application/api_hashtable/api_hashtable.h,, Header,+,lib/flipper_application/api_hashtable/compilesort.hpp,, Header,+,lib/flipper_application/flipper_application.h,, @@ -146,7 +148,12 @@ Header,+,lib/mlib/m-rbtree.h,, Header,+,lib/mlib/m-tuple.h,, Header,+,lib/mlib/m-variant.h,, Header,+,lib/music_worker/music_worker.h,, +Header,+,lib/nfc/helpers/mfkey32.h,, +Header,+,lib/nfc/helpers/nfc_generators.h,, Header,+,lib/nfc/nfc_device.h,, +Header,+,lib/nfc/nfc_types.h,, +Header,+,lib/nfc/nfc_worker.h,, +Header,+,lib/nfc/parsers/nfc_supported_card.h,, Header,+,lib/nfc/protocols/nfc_util.h,, Header,+,lib/one_wire/maxim_crc.h,, Header,+,lib/one_wire/one_wire_host.h,, @@ -186,6 +193,7 @@ Header,+,lib/subghz/blocks/encoder.h,, Header,+,lib/subghz/blocks/generic.h,, Header,+,lib/subghz/blocks/math.h,, Header,+,lib/subghz/devices/cc1101_configs.h,, +Header,+,lib/subghz/devices/cc1101_int/cc1101_int_interconnect.h,, Header,+,lib/subghz/environment.h,, Header,+,lib/subghz/protocols/raw.h,, Header,+,lib/subghz/receiver.h,, @@ -1261,6 +1269,7 @@ Function,-,furi_hal_power_insomnia_level,uint16_t, Function,+,furi_hal_power_is_charging,_Bool, Function,+,furi_hal_power_is_charging_done,_Bool, Function,+,furi_hal_power_is_otg_enabled,_Bool, +Function,+,furi_hal_power_is_shutdown_requested,_Bool, Function,+,furi_hal_power_off,void, Function,+,furi_hal_power_reset,void, Function,+,furi_hal_power_set_battery_charge_voltage_limit,void,float @@ -1383,8 +1392,8 @@ Function,+,furi_hal_subghz_rx_pipe_not_empty,_Bool, Function,+,furi_hal_subghz_set_async_mirror_pin,void,const GpioPin* Function,+,furi_hal_subghz_set_frequency,uint32_t,uint32_t Function,+,furi_hal_subghz_set_frequency_and_path,uint32_t,uint32_t -Function,-,furi_hal_subghz_set_path,void,FuriHalSubGhzPath -Function,-,furi_hal_subghz_shutdown,void, +Function,+,furi_hal_subghz_set_path,void,FuriHalSubGhzPath +Function,+,furi_hal_subghz_shutdown,void, Function,+,furi_hal_subghz_sleep,void, Function,+,furi_hal_subghz_start_async_rx,void,"FuriHalSubGhzCaptureCallback, void*" Function,+,furi_hal_subghz_start_async_tx,_Bool,"FuriHalSubGhzAsyncTxCallback, void*" @@ -1426,6 +1435,7 @@ Function,+,furi_hal_version_get_hw_target,uint8_t, Function,+,furi_hal_version_get_hw_timestamp,uint32_t, Function,+,furi_hal_version_get_hw_version,uint8_t, Function,+,furi_hal_version_get_ic_id,const char*, +Function,+,furi_hal_version_get_mic_id,const char*, Function,+,furi_hal_version_get_model_code,const char*, Function,+,furi_hal_version_get_model_name,const char*, Function,+,furi_hal_version_get_name_ptr,const char*, @@ -1443,6 +1453,8 @@ Function,+,furi_kernel_restore_lock,int32_t,int32_t Function,+,furi_kernel_unlock,int32_t, Function,+,furi_log_get_level,FuriLogLevel, Function,-,furi_log_init,void, +Function,+,furi_log_level_from_string,_Bool,"const char*, FuriLogLevel*" +Function,+,furi_log_level_to_string,_Bool,"FuriLogLevel, const char**" Function,+,furi_log_print_format,void,"FuriLogLevel, const char*, const char*, ..." Function,+,furi_log_print_raw_format,void,"FuriLogLevel, const char*, ..." Function,+,furi_log_set_level,void,FuriLogLevel @@ -1933,40 +1945,40 @@ Function,-,mf_classic_authenticate,_Bool,"FuriHalNfcTxRxContext*, uint8_t, uint6 Function,-,mf_classic_authenticate_skip_activate,_Bool,"FuriHalNfcTxRxContext*, uint8_t, uint64_t, MfClassicKey, _Bool, uint32_t" Function,-,mf_classic_block_to_value,_Bool,"const uint8_t*, int32_t*, uint8_t*" Function,-,mf_classic_check_card_type,_Bool,"uint8_t, uint8_t, uint8_t" -Function,-,mf_classic_dict_add_key,_Bool,"MfClassicDict*, uint8_t*" +Function,+,mf_classic_dict_add_key,_Bool,"MfClassicDict*, uint8_t*" Function,-,mf_classic_dict_add_key_str,_Bool,"MfClassicDict*, FuriString*" -Function,-,mf_classic_dict_alloc,MfClassicDict*,MfClassicDictType -Function,-,mf_classic_dict_check_presence,_Bool,MfClassicDictType -Function,-,mf_classic_dict_delete_index,_Bool,"MfClassicDict*, uint32_t" +Function,+,mf_classic_dict_alloc,MfClassicDict*,MfClassicDictType +Function,+,mf_classic_dict_check_presence,_Bool,MfClassicDictType +Function,+,mf_classic_dict_delete_index,_Bool,"MfClassicDict*, uint32_t" Function,-,mf_classic_dict_find_index,_Bool,"MfClassicDict*, uint8_t*, uint32_t*" Function,-,mf_classic_dict_find_index_str,_Bool,"MfClassicDict*, FuriString*, uint32_t*" -Function,-,mf_classic_dict_free,void,MfClassicDict* +Function,+,mf_classic_dict_free,void,MfClassicDict* Function,-,mf_classic_dict_get_key_at_index,_Bool,"MfClassicDict*, uint64_t*, uint32_t" -Function,-,mf_classic_dict_get_key_at_index_str,_Bool,"MfClassicDict*, FuriString*, uint32_t" +Function,+,mf_classic_dict_get_key_at_index_str,_Bool,"MfClassicDict*, FuriString*, uint32_t" Function,-,mf_classic_dict_get_next_key,_Bool,"MfClassicDict*, uint64_t*" -Function,-,mf_classic_dict_get_next_key_str,_Bool,"MfClassicDict*, FuriString*" -Function,-,mf_classic_dict_get_total_keys,uint32_t,MfClassicDict* -Function,-,mf_classic_dict_is_key_present,_Bool,"MfClassicDict*, uint8_t*" +Function,+,mf_classic_dict_get_next_key_str,_Bool,"MfClassicDict*, FuriString*" +Function,+,mf_classic_dict_get_total_keys,uint32_t,MfClassicDict* +Function,+,mf_classic_dict_is_key_present,_Bool,"MfClassicDict*, uint8_t*" Function,-,mf_classic_dict_is_key_present_str,_Bool,"MfClassicDict*, FuriString*" Function,-,mf_classic_dict_rewind,_Bool,MfClassicDict* Function,-,mf_classic_emulator,_Bool,"MfClassicEmulator*, FuriHalNfcTxRxContext*, _Bool" Function,-,mf_classic_get_classic_type,MfClassicType,"uint8_t, uint8_t, uint8_t" -Function,-,mf_classic_get_read_sectors_and_keys,void,"MfClassicData*, uint8_t*, uint8_t*" -Function,-,mf_classic_get_sector_by_block,uint8_t,uint8_t +Function,+,mf_classic_get_read_sectors_and_keys,void,"MfClassicData*, uint8_t*, uint8_t*" +Function,+,mf_classic_get_sector_by_block,uint8_t,uint8_t Function,-,mf_classic_get_sector_trailer_block_num_by_sector,uint8_t,uint8_t -Function,-,mf_classic_get_sector_trailer_by_sector,MfClassicSectorTrailer*,"MfClassicData*, uint8_t" +Function,+,mf_classic_get_sector_trailer_by_sector,MfClassicSectorTrailer*,"MfClassicData*, uint8_t" Function,-,mf_classic_get_total_block_num,uint16_t,MfClassicType -Function,-,mf_classic_get_total_sectors_num,uint8_t,MfClassicType +Function,+,mf_classic_get_total_sectors_num,uint8_t,MfClassicType Function,-,mf_classic_get_type_str,const char*,MfClassicType Function,-,mf_classic_halt,void,"FuriHalNfcTxRxContext*, Crypto1*" Function,-,mf_classic_is_allowed_access_data_block,_Bool,"MfClassicData*, uint8_t, MfClassicKey, MfClassicAction" Function,-,mf_classic_is_allowed_access_sector_trailer,_Bool,"MfClassicData*, uint8_t, MfClassicKey, MfClassicAction" -Function,-,mf_classic_is_block_read,_Bool,"MfClassicData*, uint8_t" -Function,-,mf_classic_is_card_read,_Bool,MfClassicData* -Function,-,mf_classic_is_key_found,_Bool,"MfClassicData*, uint8_t, MfClassicKey" +Function,+,mf_classic_is_block_read,_Bool,"MfClassicData*, uint8_t" +Function,+,mf_classic_is_card_read,_Bool,MfClassicData* +Function,+,mf_classic_is_key_found,_Bool,"MfClassicData*, uint8_t, MfClassicKey" Function,-,mf_classic_is_sector_data_read,_Bool,"MfClassicData*, uint8_t" Function,-,mf_classic_is_sector_read,_Bool,"MfClassicData*, uint8_t" -Function,-,mf_classic_is_sector_trailer,_Bool,uint8_t +Function,+,mf_classic_is_sector_trailer,_Bool,uint8_t Function,-,mf_classic_is_value_block,_Bool,"MfClassicData*, uint8_t" Function,-,mf_classic_read_block,_Bool,"FuriHalNfcTxRxContext*, Crypto1*, uint8_t, MfClassicBlock*" Function,-,mf_classic_read_card,uint8_t,"FuriHalNfcTxRxContext*, MfClassicReader*, MfClassicData*" @@ -1984,10 +1996,10 @@ Function,-,mf_classic_value_to_block,void,"int32_t, uint8_t, uint8_t*" Function,-,mf_classic_write_block,_Bool,"FuriHalNfcTxRxContext*, Crypto1*, uint8_t, MfClassicBlock*" Function,-,mf_classic_write_sector,_Bool,"FuriHalNfcTxRxContext*, MfClassicData*, MfClassicData*, uint8_t" Function,-,mf_df_cat_application,void,"MifareDesfireApplication*, FuriString*" -Function,-,mf_df_cat_application_info,void,"MifareDesfireApplication*, FuriString*" -Function,-,mf_df_cat_card_info,void,"MifareDesfireData*, FuriString*" +Function,+,mf_df_cat_application_info,void,"MifareDesfireApplication*, FuriString*" +Function,+,mf_df_cat_card_info,void,"MifareDesfireData*, FuriString*" Function,-,mf_df_cat_data,void,"MifareDesfireData*, FuriString*" -Function,-,mf_df_cat_file,void,"MifareDesfireFile*, FuriString*" +Function,+,mf_df_cat_file,void,"MifareDesfireFile*, FuriString*" Function,-,mf_df_cat_free_mem,void,"MifareDesfireFreeMemory*, FuriString*" Function,-,mf_df_cat_key_settings,void,"MifareDesfireKeySettings*, FuriString*" Function,-,mf_df_cat_version,void,"MifareDesfireVersion*, FuriString*" @@ -2017,8 +2029,8 @@ 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_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*" Function,-,mf_ul_pwdgen_amiibo,uint32_t,FuriHalNfcDevData* @@ -2028,13 +2040,18 @@ Function,-,mf_ul_reset,void,MfUltralightData* Function,-,mf_ul_reset_emulation,void,"MfUltralightEmulator*, _Bool" Function,-,mf_ultralight_authenticate,_Bool,"FuriHalNfcTxRxContext*, uint32_t, uint16_t*" Function,-,mf_ultralight_fast_read_pages,_Bool,"FuriHalNfcTxRxContext*, MfUltralightReader*, MfUltralightData*" -Function,-,mf_ultralight_get_config_pages,MfUltralightConfigPages*,MfUltralightData* +Function,+,mf_ultralight_get_config_pages,MfUltralightConfigPages*,MfUltralightData* Function,-,mf_ultralight_read_counters,_Bool,"FuriHalNfcTxRxContext*, MfUltralightData*" Function,-,mf_ultralight_read_pages,_Bool,"FuriHalNfcTxRxContext*, MfUltralightReader*, MfUltralightData*" Function,-,mf_ultralight_read_pages_direct,_Bool,"FuriHalNfcTxRxContext*, uint8_t, uint8_t*" Function,-,mf_ultralight_read_signature,_Bool,"FuriHalNfcTxRxContext*, MfUltralightData*" Function,-,mf_ultralight_read_tearing_flags,_Bool,"FuriHalNfcTxRxContext*, MfUltralightData*" Function,-,mf_ultralight_read_version,_Bool,"FuriHalNfcTxRxContext*, MfUltralightReader*, MfUltralightData*" +Function,-,mfkey32_alloc,Mfkey32*,uint32_t +Function,-,mfkey32_free,void,Mfkey32* +Function,+,mfkey32_get_auth_sectors,uint16_t,FuriString* +Function,-,mfkey32_process_data,void,"Mfkey32*, uint8_t*, uint16_t, _Bool, _Bool" +Function,-,mfkey32_set_callback,void,"Mfkey32*, Mfkey32ParseDataCallback, void*" Function,-,mkdtemp,char*,char* Function,-,mkostemp,int,"char*, int" Function,-,mkostemps,int,"char*, int, int" @@ -2083,11 +2100,25 @@ Function,+,nfc_device_save_shadow,_Bool,"NfcDevice*, const char*" Function,+,nfc_device_set_loading_callback,void,"NfcDevice*, NfcLoadingCallback, void*" Function,+,nfc_device_set_name,void,"NfcDevice*, const char*" Function,+,nfc_file_select,_Bool,NfcDevice* +Function,-,nfc_generate_mf_classic,void,"NfcDeviceData*, uint8_t, MfClassicType" +Function,+,nfc_get_dev_type,const char*,FuriHalNfcType +Function,-,nfc_guess_protocol,const char*,NfcProtocol +Function,+,nfc_mf_classic_type,const char*,MfClassicType +Function,+,nfc_mf_ul_type,const char*,"MfUltralightType, _Bool" +Function,+,nfc_supported_card_verify_and_parse,_Bool,NfcDeviceData* Function,+,nfc_util_bytes2num,uint64_t,"const uint8_t*, uint8_t" Function,+,nfc_util_even_parity32,uint8_t,uint32_t Function,+,nfc_util_num2bytes,void,"uint64_t, uint8_t, uint8_t*" Function,+,nfc_util_odd_parity,void,"const uint8_t*, uint8_t*, uint8_t" Function,+,nfc_util_odd_parity8,uint8_t,uint8_t +Function,+,nfc_worker_alloc,NfcWorker*, +Function,+,nfc_worker_free,void,NfcWorker* +Function,+,nfc_worker_get_state,NfcWorkerState,NfcWorker* +Function,-,nfc_worker_nfcv_emulate,void,NfcWorker* +Function,-,nfc_worker_nfcv_sniff,void,NfcWorker* +Function,-,nfc_worker_nfcv_unlock,void,NfcWorker* +Function,+,nfc_worker_start,void,"NfcWorker*, NfcWorkerState, NfcDeviceData*, NfcWorkerCallback, void*" +Function,+,nfc_worker_stop,void,NfcWorker* Function,-,nfca_append_crc16,void,"uint8_t*, uint16_t" Function,-,nfca_emulation_handler,_Bool,"uint8_t*, uint16_t, uint8_t*, uint16_t*" Function,-,nfca_get_crc16,uint16_t,"uint8_t*, uint16_t" @@ -2664,10 +2695,12 @@ Function,-,strupr,char*,char* Function,-,strverscmp,int,"const char*, const char*" Function,-,strxfrm,size_t,"char*, const char*, size_t" Function,-,strxfrm_l,size_t,"char*, const char*, size_t, locale_t" +Function,-,stub_parser_verify_read,_Bool,"NfcWorker*, FuriHalNfcTxRxContext*" Function,+,subghz_block_generic_deserialize,SubGhzProtocolStatus,"SubGhzBlockGeneric*, FlipperFormat*" Function,+,subghz_block_generic_deserialize_check_count_bit,SubGhzProtocolStatus,"SubGhzBlockGeneric*, FlipperFormat*, uint16_t" Function,+,subghz_block_generic_get_preset_name,void,"const char*, FuriString*" Function,+,subghz_block_generic_serialize,SubGhzProtocolStatus,"SubGhzBlockGeneric*, FlipperFormat*, SubGhzRadioPreset*" +Function,-,subghz_device_cc1101_ext_ep,const FlipperAppPluginDescriptor*, Function,+,subghz_devices_begin,_Bool,const SubGhzDevice* Function,+,subghz_devices_deinit,void, Function,+,subghz_devices_end,void,const SubGhzDevice* @@ -2744,6 +2777,7 @@ Function,+,subghz_protocol_decoder_base_get_hash_data,uint8_t,SubGhzProtocolDeco Function,+,subghz_protocol_decoder_base_get_string,_Bool,"SubGhzProtocolDecoderBase*, FuriString*" Function,+,subghz_protocol_decoder_base_serialize,SubGhzProtocolStatus,"SubGhzProtocolDecoderBase*, FlipperFormat*, SubGhzRadioPreset*" Function,-,subghz_protocol_decoder_base_set_decoder_callback,void,"SubGhzProtocolDecoderBase*, SubGhzProtocolDecoderBaseRxCallback, void*" +Function,+,subghz_protocol_decoder_bin_raw_data_input_rssi,void,"SubGhzProtocolDecoderBinRAW*, float" Function,+,subghz_protocol_decoder_raw_alloc,void*,SubGhzEnvironment* Function,+,subghz_protocol_decoder_raw_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,+,subghz_protocol_decoder_raw_feed,void,"void*, _Bool, uint32_t" @@ -2755,6 +2789,7 @@ Function,+,subghz_protocol_encoder_raw_deserialize,SubGhzProtocolStatus,"void*, Function,+,subghz_protocol_encoder_raw_free,void,void* Function,+,subghz_protocol_encoder_raw_stop,void,void* Function,+,subghz_protocol_encoder_raw_yield,LevelDuration,void* +Function,+,subghz_protocol_keeloq_create_data,_Bool,"void*, FlipperFormat*, uint32_t, uint8_t, uint16_t, const char*, SubGhzRadioPreset*" Function,+,subghz_protocol_raw_file_encoder_worker_set_callback_end,void,"SubGhzProtocolEncoderRAW*, SubGhzProtocolEncoderRAWCallbackEnd, void*" Function,+,subghz_protocol_raw_gen_fff_data,void,"FlipperFormat*, const char*, const char*" Function,+,subghz_protocol_raw_get_sample_write,size_t,SubGhzProtocolDecoderRAW* @@ -2764,6 +2799,8 @@ Function,+,subghz_protocol_raw_save_to_file_stop,void,SubGhzProtocolDecoderRAW* Function,+,subghz_protocol_registry_count,size_t,const SubGhzProtocolRegistry* Function,+,subghz_protocol_registry_get_by_index,const SubGhzProtocol*,"const SubGhzProtocolRegistry*, size_t" Function,+,subghz_protocol_registry_get_by_name,const SubGhzProtocol*,"const SubGhzProtocolRegistry*, const char*" +Function,+,subghz_protocol_secplus_v1_check_fixed,_Bool,uint32_t +Function,+,subghz_protocol_secplus_v2_create_data,_Bool,"void*, FlipperFormat*, uint32_t, uint8_t, uint32_t, SubGhzRadioPreset*" Function,+,subghz_receiver_alloc_init,SubGhzReceiver*,SubGhzEnvironment* Function,+,subghz_receiver_decode,void,"SubGhzReceiver*, _Bool, uint32_t" Function,+,subghz_receiver_free,void,SubGhzReceiver* @@ -3352,6 +3389,8 @@ Variable,+,message_red_255,const NotificationMessage, Variable,+,message_sound_off,const NotificationMessage, Variable,+,message_vibro_off,const NotificationMessage, Variable,+,message_vibro_on,const NotificationMessage, +Variable,+,nfc_generators,const NfcGenerator*[], +Variable,-,nfc_supported_card,NfcSupportedCard[NfcSupportedCardTypeEnd], Variable,+,sequence_audiovisual_alert,const NotificationSequence, Variable,+,sequence_blink_blue_10,const NotificationSequence, Variable,+,sequence_blink_blue_100,const NotificationSequence, @@ -3401,6 +3440,7 @@ Variable,+,sequence_set_vibro_on,const NotificationSequence, Variable,+,sequence_single_vibro,const NotificationSequence, Variable,+,sequence_solid_yellow,const NotificationSequence, Variable,+,sequence_success,const NotificationSequence, +Variable,-,subghz_device_cc1101_int,const SubGhzDevice, Variable,+,subghz_device_cc1101_preset_2fsk_dev2_38khz_async_regs,const uint8_t[], Variable,+,subghz_device_cc1101_preset_2fsk_dev47_6khz_async_regs,const uint8_t[], Variable,+,subghz_device_cc1101_preset_gfsk_9_99kb_async_regs,const uint8_t[], diff --git a/firmware/targets/f7/furi_hal/furi_hal_power.c b/firmware/targets/f7/furi_hal/furi_hal_power.c index 5edde86e..035919d7 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_power.c +++ b/firmware/targets/f7/furi_hal/furi_hal_power.c @@ -15,6 +15,7 @@ #include #include +#include #include #include @@ -37,16 +38,18 @@ typedef struct { volatile uint8_t insomnia; volatile uint8_t suppress_charge; - uint8_t gauge_initialized; - uint8_t charger_initialized; + bool gauge_ok; + bool charger_ok; } FuriHalPower; static volatile FuriHalPower furi_hal_power = { .insomnia = 0, .suppress_charge = 0, + .gauge_ok = false, + .charger_ok = false, }; -#include +extern const BQ27220DMData furi_hal_power_gauge_data_memory[]; void furi_hal_power_init() { #ifdef FURI_HAL_POWER_DEBUG @@ -63,8 +66,13 @@ void furi_hal_power_init() { LL_C2_PWR_SetPowerMode(FURI_HAL_POWER_STOP_MODE); furi_hal_i2c_acquire(&furi_hal_i2c_handle_power); - bq27220_init(&furi_hal_i2c_handle_power, &cedv); - bq25896_init(&furi_hal_i2c_handle_power); + // Find and init gauge + if(bq27220_init(&furi_hal_i2c_handle_power)) { + furi_hal_power.gauge_ok = bq27220_apply_data_memory( + &furi_hal_i2c_handle_power, furi_hal_power_gauge_data_memory); + } + // Find and init charger + furi_hal_power.charger_ok = bq25896_init(&furi_hal_i2c_handle_power); furi_hal_i2c_release(&furi_hal_i2c_handle_power); FURI_LOG_I(TAG, "Init OK"); @@ -78,14 +86,29 @@ bool furi_hal_power_gauge_is_ok() { furi_hal_i2c_acquire(&furi_hal_i2c_handle_power); - if(bq27220_get_battery_status(&furi_hal_i2c_handle_power, &battery_status) == BQ27220_ERROR || - bq27220_get_operation_status(&furi_hal_i2c_handle_power, &operation_status) == - BQ27220_ERROR) { + if(!bq27220_get_battery_status(&furi_hal_i2c_handle_power, &battery_status) || + !bq27220_get_operation_status(&furi_hal_i2c_handle_power, &operation_status)) { ret = false; } else { ret &= battery_status.BATTPRES; ret &= operation_status.INITCOMP; - ret &= (cedv.design_cap == bq27220_get_design_capacity(&furi_hal_i2c_handle_power)); + ret &= furi_hal_power.gauge_ok; + } + + furi_hal_i2c_release(&furi_hal_i2c_handle_power); + + return ret; +} + +bool furi_hal_power_is_shutdown_requested() { + bool ret = false; + + BatteryStatus battery_status; + + furi_hal_i2c_acquire(&furi_hal_i2c_handle_power); + + if(bq27220_get_battery_status(&furi_hal_i2c_handle_power, &battery_status) != BQ27220_ERROR) { + ret = battery_status.SYSDWN; } furi_hal_i2c_release(&furi_hal_i2c_handle_power); @@ -576,9 +599,8 @@ void furi_hal_power_debug_get(PropertyValueCallback out, void* context) { const uint32_t ntc_mpct = bq25896_get_ntc_mpct(&furi_hal_i2c_handle_power); - if(bq27220_get_battery_status(&furi_hal_i2c_handle_power, &battery_status) != BQ27220_ERROR && - bq27220_get_operation_status(&furi_hal_i2c_handle_power, &operation_status) != - BQ27220_ERROR) { + if(bq27220_get_battery_status(&furi_hal_i2c_handle_power, &battery_status) && + bq27220_get_operation_status(&furi_hal_i2c_handle_power, &operation_status)) { property_value_out(&property_context, "%lu", 2, "charger", "ntc", ntc_mpct); property_value_out(&property_context, "%d", 2, "gauge", "calmd", operation_status.CALMD); property_value_out(&property_context, "%d", 2, "gauge", "sec", operation_status.SEC); diff --git a/firmware/targets/f7/furi_hal/furi_hal_power_calibration.h b/firmware/targets/f7/furi_hal/furi_hal_power_calibration.h deleted file mode 100644 index 5eb0f938..00000000 --- a/firmware/targets/f7/furi_hal/furi_hal_power_calibration.h +++ /dev/null @@ -1,37 +0,0 @@ -const ParamCEDV cedv = { - .cedv_conf.gauge_conf = - { - .CCT = 1, - .CSYNC = 0, - .EDV_CMP = 0, - .SC = 1, - .FIXED_EDV0 = 1, - .FCC_LIM = 1, - .FC_FOR_VDQ = 1, - .IGNORE_SD = 1, - .SME0 = 0, - }, - .full_charge_cap = 2101, - .design_cap = 2101, - .EDV0 = 3300, - .EDV1 = 3321, - .EDV2 = 3355, - .EMF = 3679, - .C0 = 430, - .C1 = 0, - .R1 = 408, - .R0 = 334, - .T0 = 4626, - .TC = 11, - .DOD0 = 4044, - .DOD10 = 3905, - .DOD20 = 3807, - .DOD30 = 3718, - .DOD40 = 3642, - .DOD50 = 3585, - .DOD60 = 3546, - .DOD70 = 3514, - .DOD80 = 3477, - .DOD90 = 3411, - .DOD100 = 3299, -}; diff --git a/firmware/targets/f7/furi_hal/furi_hal_power_config.c b/firmware/targets/f7/furi_hal/furi_hal_power_config.c new file mode 100644 index 00000000..488edce9 --- /dev/null +++ b/firmware/targets/f7/furi_hal/furi_hal_power_config.c @@ -0,0 +1,149 @@ +#include + +const BQ27220DMGaugingConfig furi_hal_power_gauge_data_memory_gauging_config = { + .CCT = 1, + .CSYNC = 0, + .EDV_CMP = 0, + .SC = 1, + .FIXED_EDV0 = 1, + .FCC_LIM = 1, + .FC_FOR_VDQ = 1, + .IGNORE_SD = 1, + .SME0 = 0, +}; + +const BQ27220DMData furi_hal_power_gauge_data_memory[] = { + { + .address = BQ27220DMAddressGasGaugingCEDVProfile1GaugingConfig, + .type = BQ27220DMTypePtr16, + .value.u32 = (uint32_t)&furi_hal_power_gauge_data_memory_gauging_config, + }, + { + .address = BQ27220DMAddressGasGaugingCEDVProfile1FullChargeCapacity, + .type = BQ27220DMTypeU16, + .value.u16 = 2100, + }, + { + .address = BQ27220DMAddressGasGaugingCEDVProfile1DesignCapacity, + .type = BQ27220DMTypeU16, + .value.u16 = 2100, + }, + { + .address = BQ27220DMAddressGasGaugingCEDVProfile1EMF, + .type = BQ27220DMTypeU16, + .value.u16 = 3679, + }, + { + .address = BQ27220DMAddressGasGaugingCEDVProfile1C0, + .type = BQ27220DMTypeU16, + .value.u16 = 430, + }, + { + .address = BQ27220DMAddressGasGaugingCEDVProfile1R0, + .type = BQ27220DMTypeU16, + .value.u16 = 334, + }, + { + .address = BQ27220DMAddressGasGaugingCEDVProfile1T0, + .type = BQ27220DMTypeU16, + .value.u16 = 4626, + }, + { + .address = BQ27220DMAddressGasGaugingCEDVProfile1R1, + .type = BQ27220DMTypeU16, + .value.u16 = 408, + }, + { + .address = BQ27220DMAddressGasGaugingCEDVProfile1TC, + .type = BQ27220DMTypeU8, + .value.u8 = 11, + }, + { + .address = BQ27220DMAddressGasGaugingCEDVProfile1C1, + .type = BQ27220DMTypeU8, + .value.u8 = 0, + }, + { + .address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD0, + .type = BQ27220DMTypeU16, + .value.u16 = 4044, + }, + { + .address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD10, + .type = BQ27220DMTypeU16, + .value.u16 = 3905, + }, + { + .address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD20, + .type = BQ27220DMTypeU16, + .value.u16 = 3807, + }, + { + .address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD30, + .type = BQ27220DMTypeU16, + .value.u16 = 3718, + }, + { + .address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD40, + .type = BQ27220DMTypeU16, + .value.u16 = 3642, + }, + { + .address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD50, + .type = BQ27220DMTypeU16, + .value.u16 = 3585, + }, + { + .address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD60, + .type = BQ27220DMTypeU16, + .value.u16 = 3546, + }, + { + .address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD70, + .type = BQ27220DMTypeU16, + .value.u16 = 3514, + }, + { + .address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD80, + .type = BQ27220DMTypeU16, + .value.u16 = 3477, + }, + { + .address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD90, + .type = BQ27220DMTypeU16, + .value.u16 = 3411, + }, + { + .address = BQ27220DMAddressGasGaugingCEDVProfile1StartDOD100, + .type = BQ27220DMTypeU16, + .value.u16 = 3299, + }, + { + .address = BQ27220DMAddressGasGaugingCEDVProfile1EDV0, + .type = BQ27220DMTypeU16, + .value.u16 = 3300, + }, + { + .address = BQ27220DMAddressGasGaugingCEDVProfile1EDV1, + .type = BQ27220DMTypeU16, + .value.u16 = 3321, + }, + { + .address = BQ27220DMAddressGasGaugingCEDVProfile1EDV2, + .type = BQ27220DMTypeU16, + .value.u16 = 3355, + }, + { + .address = BQ27220DMAddressCalibrationCurrentDeadband, + .type = BQ27220DMTypeU8, + .value.u8 = 1, + }, + { + .address = BQ27220DMAddressConfigurationPowerSleepCurrent, + .type = BQ27220DMTypeI16, + .value.i16 = 1, + }, + { + .type = BQ27220DMTypeEnd, + }, +}; diff --git a/firmware/targets/f7/furi_hal/furi_hal_version_device.c b/firmware/targets/f7/furi_hal/furi_hal_version_device.c index c059c2cb..be3f4bf3 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_version_device.c +++ b/firmware/targets/f7/furi_hal/furi_hal_version_device.c @@ -19,3 +19,7 @@ const char* furi_hal_version_get_fcc_id() { const char* furi_hal_version_get_ic_id() { return "27624-FZ"; } + +const char* furi_hal_version_get_mic_id() { + return "210-175991"; +} diff --git a/firmware/targets/f7/platform_specific/intrinsic_export.h b/firmware/targets/f7/platform_specific/intrinsic_export.h index ca343a12..d3c7be5e 100644 --- a/firmware/targets/f7/platform_specific/intrinsic_export.h +++ b/firmware/targets/f7/platform_specific/intrinsic_export.h @@ -1,3 +1,4 @@ +#pragma once #include #include diff --git a/firmware/targets/f7/platform_specific/math_wrapper.h b/firmware/targets/f7/platform_specific/math_wrapper.h new file mode 100644 index 00000000..83f5a8b7 --- /dev/null +++ b/firmware/targets/f7/platform_specific/math_wrapper.h @@ -0,0 +1,2 @@ +#pragma once +#include \ No newline at end of file diff --git a/firmware/targets/furi_hal_include/furi_hal_power.h b/firmware/targets/furi_hal_include/furi_hal_power.h index 6b4b6cd8..5edda6ba 100644 --- a/firmware/targets/furi_hal_include/furi_hal_power.h +++ b/firmware/targets/furi_hal_include/furi_hal_power.h @@ -34,6 +34,12 @@ void furi_hal_power_init(); */ bool furi_hal_power_gauge_is_ok(); +/** Check if gauge requests system shutdown + * + * @return true if system shutdown requested + */ +bool furi_hal_power_is_shutdown_requested(); + /** Get current insomnia level * * @return insomnia level: 0 - no insomnia, >0 - insomnia, bearer count. diff --git a/firmware/targets/furi_hal_include/furi_hal_version.h b/firmware/targets/furi_hal_include/furi_hal_version.h index aec4fc78..a9339a6c 100644 --- a/firmware/targets/furi_hal_include/furi_hal_version.h +++ b/firmware/targets/furi_hal_include/furi_hal_version.h @@ -85,6 +85,12 @@ const char* furi_hal_version_get_fcc_id(); */ const char* furi_hal_version_get_ic_id(); +/** Get MIC id + * + * @return MIC id as C-string + */ +const char* furi_hal_version_get_mic_id(); + /** Get OTP version * * @return OTP Version diff --git a/furi/core/log.c b/furi/core/log.c index d910ecf2..53467ecd 100644 --- a/furi/core/log.c +++ b/furi/core/log.c @@ -14,6 +14,21 @@ typedef struct { static FuriLogParams furi_log; +typedef struct { + const char* str; + FuriLogLevel level; +} FuriLogLevelDescription; + +static const FuriLogLevelDescription FURI_LOG_LEVEL_DESCRIPTIONS[] = { + {"default", FuriLogLevelDefault}, + {"none", FuriLogLevelNone}, + {"error", FuriLogLevelError}, + {"warn", FuriLogLevelWarn}, + {"info", FuriLogLevelInfo}, + {"debug", FuriLogLevelDebug}, + {"trace", FuriLogLevelTrace}, +}; + void furi_log_init() { // Set default logging parameters furi_log.log_level = FURI_LOG_LEVEL_DEFAULT; @@ -117,3 +132,23 @@ void furi_log_set_timestamp(FuriLogTimestamp timestamp) { furi_assert(timestamp); furi_log.timestamp = timestamp; } + +bool furi_log_level_to_string(FuriLogLevel level, const char** str) { + for(size_t i = 0; i < COUNT_OF(FURI_LOG_LEVEL_DESCRIPTIONS); i++) { + if(level == FURI_LOG_LEVEL_DESCRIPTIONS[i].level) { + *str = FURI_LOG_LEVEL_DESCRIPTIONS[i].str; + return true; + } + } + return false; +} + +bool furi_log_level_from_string(const char* str, FuriLogLevel* level) { + for(size_t i = 0; i < COUNT_OF(FURI_LOG_LEVEL_DESCRIPTIONS); i++) { + if(strcmp(str, FURI_LOG_LEVEL_DESCRIPTIONS[i].str) == 0) { + *level = FURI_LOG_LEVEL_DESCRIPTIONS[i].level; + return true; + } + } + return false; +} \ No newline at end of file diff --git a/furi/core/log.h b/furi/core/log.h index 46ae7f00..5d11add9 100644 --- a/furi/core/log.h +++ b/furi/core/log.h @@ -7,6 +7,7 @@ #include #include #include +#include #ifdef __cplusplus extern "C" { @@ -87,6 +88,23 @@ void furi_log_set_puts(FuriLogPuts puts); */ void furi_log_set_timestamp(FuriLogTimestamp timestamp); +/** Log level to string + * + * @param[in] level The level + * + * @return The string + */ +bool furi_log_level_to_string(FuriLogLevel level, const char** str); + +/** Log level from string + * + * @param[in] str The string + * @param level The level + * + * @return True if success, False otherwise + */ +bool furi_log_level_from_string(const char* str, FuriLogLevel* level); + /** Log methods * * @param tag The application tag diff --git a/lib/drivers/SConscript b/lib/drivers/SConscript index 3b7ee240..103472cc 100644 --- a/lib/drivers/SConscript +++ b/lib/drivers/SConscript @@ -4,6 +4,9 @@ env.Append( CPPPATH=[ "#/lib/drivers", ], + SDK_HEADERS=[ + File("cc1101_regs.h"), + ], ) diff --git a/lib/drivers/bq25896.c b/lib/drivers/bq25896.c index f675233b..76aae5e8 100644 --- a/lib/drivers/bq25896.c +++ b/lib/drivers/bq25896.c @@ -35,13 +35,15 @@ typedef struct { static bq25896_regs_t bq25896_regs; -void bq25896_init(FuriHalI2cBusHandle* handle) { +bool bq25896_init(FuriHalI2cBusHandle* handle) { + bool result = true; + bq25896_regs.r14.REG_RST = 1; - furi_hal_i2c_write_reg_8( + result &= furi_hal_i2c_write_reg_8( handle, BQ25896_ADDRESS, 0x14, *(uint8_t*)&bq25896_regs.r14, BQ25896_I2C_TIMEOUT); // Readout all registers - furi_hal_i2c_read_mem( + result &= furi_hal_i2c_read_mem( handle, BQ25896_ADDRESS, 0x00, @@ -52,26 +54,28 @@ void bq25896_init(FuriHalI2cBusHandle* handle) { // Poll ADC forever bq25896_regs.r02.CONV_START = 1; bq25896_regs.r02.CONV_RATE = 1; - furi_hal_i2c_write_reg_8( + result &= furi_hal_i2c_write_reg_8( handle, BQ25896_ADDRESS, 0x02, *(uint8_t*)&bq25896_regs.r02, BQ25896_I2C_TIMEOUT); bq25896_regs.r07.WATCHDOG = WatchdogDisable; - furi_hal_i2c_write_reg_8( + result &= furi_hal_i2c_write_reg_8( handle, BQ25896_ADDRESS, 0x07, *(uint8_t*)&bq25896_regs.r07, BQ25896_I2C_TIMEOUT); // OTG power configuration bq25896_regs.r0A.BOOSTV = 0x8; // BOOST Voltage: 5.062V bq25896_regs.r0A.BOOST_LIM = BoostLim_1400; // BOOST Current limit: 1.4A - furi_hal_i2c_write_reg_8( + result &= furi_hal_i2c_write_reg_8( handle, BQ25896_ADDRESS, 0x0A, *(uint8_t*)&bq25896_regs.r0A, BQ25896_I2C_TIMEOUT); - furi_hal_i2c_read_mem( + result &= furi_hal_i2c_read_mem( handle, BQ25896_ADDRESS, 0x00, (uint8_t*)&bq25896_regs, sizeof(bq25896_regs), BQ25896_I2C_TIMEOUT); + + return result; } void bq25896_set_boost_lim(FuriHalI2cBusHandle* handle, BoostLim boost_lim) { diff --git a/lib/drivers/bq25896.h b/lib/drivers/bq25896.h index ce729396..d35625ab 100644 --- a/lib/drivers/bq25896.h +++ b/lib/drivers/bq25896.h @@ -7,7 +7,7 @@ #include /** Initialize Driver */ -void bq25896_init(FuriHalI2cBusHandle* handle); +bool bq25896_init(FuriHalI2cBusHandle* handle); /** Set boost lim*/ void bq25896_set_boost_lim(FuriHalI2cBusHandle* handle, BoostLim boost_lim); diff --git a/lib/drivers/bq27220.c b/lib/drivers/bq27220.c index f64120fa..92dbfcd6 100644 --- a/lib/drivers/bq27220.c +++ b/lib/drivers/bq27220.c @@ -1,12 +1,16 @@ + #include "bq27220.h" #include "bq27220_reg.h" +#include "bq27220_data_memory.h" + +_Static_assert(sizeof(BQ27220DMGaugingConfig) == 2, "Incorrect structure size"); #include #include #define TAG "Gauge" -uint16_t bq27220_read_word(FuriHalI2cBusHandle* handle, uint8_t address) { +static uint16_t bq27220_read_word(FuriHalI2cBusHandle* handle, uint8_t address) { uint16_t buf = 0; furi_hal_i2c_read_mem( @@ -15,14 +19,14 @@ uint16_t bq27220_read_word(FuriHalI2cBusHandle* handle, uint8_t address) { return buf; } -bool bq27220_control(FuriHalI2cBusHandle* handle, uint16_t control) { +static bool bq27220_control(FuriHalI2cBusHandle* handle, uint16_t control) { bool ret = furi_hal_i2c_write_mem( handle, BQ27220_ADDRESS, CommandControl, (uint8_t*)&control, 2, BQ27220_I2C_TIMEOUT); return ret; } -uint8_t bq27220_get_checksum(uint8_t* data, uint16_t len) { +static uint8_t bq27220_get_checksum(uint8_t* data, uint16_t len) { uint8_t ret = 0; for(uint16_t i = 0; i < len; i++) { ret += data[i]; @@ -30,80 +34,181 @@ uint8_t bq27220_get_checksum(uint8_t* data, uint16_t len) { return 0xFF - ret; } -bool bq27220_set_parameter_u16(FuriHalI2cBusHandle* handle, uint16_t address, uint16_t value) { - bool ret; - uint8_t buffer[4]; +static bool bq27220_parameter_check( + FuriHalI2cBusHandle* handle, + uint16_t address, + uint32_t value, + size_t size, + bool update) { + furi_assert(size == 1 || size == 2 || size == 4); + bool ret = false; + uint8_t buffer[6] = {0}; + uint8_t old_data[4] = {0}; - buffer[0] = address & 0xFF; - buffer[1] = (address >> 8) & 0xFF; - buffer[2] = (value >> 8) & 0xFF; - buffer[3] = value & 0xFF; - ret = furi_hal_i2c_write_mem( - handle, BQ27220_ADDRESS, CommandSelectSubclass, buffer, 4, BQ27220_I2C_TIMEOUT); + do { + buffer[0] = address & 0xFF; + buffer[1] = (address >> 8) & 0xFF; - furi_delay_us(10000); + for(size_t i = 0; i < size; i++) { + buffer[1 + size - i] = (value >> (i * 8)) & 0xFF; + } - uint8_t checksum = bq27220_get_checksum(buffer, 4); - buffer[0] = checksum; - buffer[1] = 6; - ret &= furi_hal_i2c_write_mem( - handle, BQ27220_ADDRESS, CommandMACDataSum, buffer, 2, BQ27220_I2C_TIMEOUT); + if(update) { + if(!furi_hal_i2c_write_mem( + handle, + BQ27220_ADDRESS, + CommandSelectSubclass, + buffer, + size + 2, + BQ27220_I2C_TIMEOUT)) { + FURI_LOG_I(TAG, "DM write failed"); + break; + } + + furi_delay_us(10000); + + uint8_t checksum = bq27220_get_checksum(buffer, size + 2); + buffer[0] = checksum; + buffer[1] = 4 + size; // TODO: why 4? + if(!furi_hal_i2c_write_mem( + handle, BQ27220_ADDRESS, CommandMACDataSum, buffer, 2, BQ27220_I2C_TIMEOUT)) { + FURI_LOG_I(TAG, "CRC write failed"); + break; + } + + furi_delay_us(10000); + ret = true; + } else { + if(!furi_hal_i2c_write_mem( + handle, BQ27220_ADDRESS, CommandSelectSubclass, buffer, 2, BQ27220_I2C_TIMEOUT)) { + FURI_LOG_I(TAG, "DM SelectSubclass for read failed"); + break; + } + + if(!furi_hal_i2c_rx(handle, BQ27220_ADDRESS, old_data, size, BQ27220_I2C_TIMEOUT)) { + FURI_LOG_I(TAG, "DM read failed"); + break; + } + + if(*(uint32_t*)&(old_data[0]) != *(uint32_t*)&(buffer[2])) { + FURI_LOG_W( //-V641 + TAG, + "Data at 0x%04x(%zu): 0x%08lx!=0x%08lx", + address, + size, + *(uint32_t*)&(old_data[0]), + *(uint32_t*)&(buffer[2])); + } else { + ret = true; + } + } + } while(0); - furi_delay_us(10000); return ret; } -bool bq27220_init(FuriHalI2cBusHandle* handle, const ParamCEDV* cedv) { - uint32_t timeout = 100; - uint16_t design_cap = bq27220_get_design_capacity(handle); - if(cedv->design_cap == design_cap) { - FURI_LOG_I(TAG, "Skip battery profile update"); - return true; +static bool bq27220_data_memory_check( + FuriHalI2cBusHandle* handle, + const BQ27220DMData* data_memory, + bool update) { + if(update) { + if(!bq27220_control(handle, Control_ENTER_CFG_UPDATE)) { + FURI_LOG_E(TAG, "ENTER_CFG_UPDATE command failed"); + return false; + }; + + // Wait for enter CFG update mode + uint32_t timeout = 100; + OperationStatus status = {0}; + while((status.CFGUPDATE != true) && (timeout-- > 0)) { + bq27220_get_operation_status(handle, &status); + } + + if(timeout == 0) { + FURI_LOG_E(TAG, "CFGUPDATE mode failed"); + return false; + } } - FURI_LOG_I(TAG, "Start updating battery profile"); - OperationStatus status = {0}; - if(!bq27220_control(handle, Control_ENTER_CFG_UPDATE)) { - FURI_LOG_E(TAG, "Can't configure update"); + + // Process data memory records + bool result = true; + while(data_memory->type != BQ27220DMTypeEnd) { + if(data_memory->type == BQ27220DMTypeWait) { + furi_delay_us(data_memory->value.u32); + } else if(data_memory->type == BQ27220DMTypeU8) { + result &= bq27220_parameter_check( + handle, data_memory->address, data_memory->value.u8, 1, update); + } else if(data_memory->type == BQ27220DMTypeU16) { + result &= bq27220_parameter_check( + handle, data_memory->address, data_memory->value.u16, 2, update); + } else if(data_memory->type == BQ27220DMTypeU32) { + result &= bq27220_parameter_check( + handle, data_memory->address, data_memory->value.u32, 4, update); + } else if(data_memory->type == BQ27220DMTypeI8) { + result &= bq27220_parameter_check( + handle, data_memory->address, data_memory->value.i8, 1, update); + } else if(data_memory->type == BQ27220DMTypeI16) { + result &= bq27220_parameter_check( + handle, data_memory->address, data_memory->value.i16, 2, update); + } else if(data_memory->type == BQ27220DMTypeI32) { + result &= bq27220_parameter_check( + handle, data_memory->address, data_memory->value.i32, 4, update); + } else if(data_memory->type == BQ27220DMTypeF32) { + result &= bq27220_parameter_check( + handle, data_memory->address, data_memory->value.u32, 4, update); + } else if(data_memory->type == BQ27220DMTypePtr8) { + result &= bq27220_parameter_check( + handle, data_memory->address, *(uint8_t*)data_memory->value.u32, 1, update); + } else if(data_memory->type == BQ27220DMTypePtr16) { + result &= bq27220_parameter_check( + handle, data_memory->address, *(uint16_t*)data_memory->value.u32, 2, update); + } else if(data_memory->type == BQ27220DMTypePtr32) { + result &= bq27220_parameter_check( + handle, data_memory->address, *(uint32_t*)data_memory->value.u32, 4, update); + } else { + furi_crash("Invalid DM Type"); + } + data_memory++; + } + + // Finalize configuration update + if(update) { + bq27220_control(handle, Control_EXIT_CFG_UPDATE_REINIT); + furi_delay_us(10000); + } + + return result; +} + +bool bq27220_init(FuriHalI2cBusHandle* handle) { + // Request device number(chip PN) + if(!bq27220_control(handle, Control_DEVICE_NUMBER)) { + FURI_LOG_E(TAG, "Device is not present"); + return false; + }; + // Check control response + uint16_t data = 0; + data = bq27220_read_word(handle, CommandControl); + if(data != 0xFF00) { + FURI_LOG_E(TAG, "Invalid control response: %x", data); return false; }; - while((status.CFGUPDATE != true) && (timeout-- > 0)) { - bq27220_get_operation_status(handle, &status); - } - bq27220_set_parameter_u16(handle, AddressGaugingConfig, cedv->cedv_conf.gauge_conf_raw); - bq27220_set_parameter_u16(handle, AddressFullChargeCapacity, cedv->full_charge_cap); - bq27220_set_parameter_u16(handle, AddressDesignCapacity, cedv->design_cap); - bq27220_set_parameter_u16(handle, AddressEMF, cedv->EMF); - bq27220_set_parameter_u16(handle, AddressC0, cedv->C0); - bq27220_set_parameter_u16(handle, AddressR0, cedv->R0); - bq27220_set_parameter_u16(handle, AddressT0, cedv->T0); - bq27220_set_parameter_u16(handle, AddressR1, cedv->R1); - bq27220_set_parameter_u16(handle, AddressTC, (cedv->TC) << 8 | cedv->C1); - bq27220_set_parameter_u16(handle, AddressStartDOD0, cedv->DOD0); - bq27220_set_parameter_u16(handle, AddressStartDOD10, cedv->DOD10); - bq27220_set_parameter_u16(handle, AddressStartDOD20, cedv->DOD20); - bq27220_set_parameter_u16(handle, AddressStartDOD30, cedv->DOD30); - bq27220_set_parameter_u16(handle, AddressStartDOD40, cedv->DOD40); - bq27220_set_parameter_u16(handle, AddressStartDOD50, cedv->DOD40); - bq27220_set_parameter_u16(handle, AddressStartDOD60, cedv->DOD60); - bq27220_set_parameter_u16(handle, AddressStartDOD70, cedv->DOD70); - bq27220_set_parameter_u16(handle, AddressStartDOD80, cedv->DOD80); - bq27220_set_parameter_u16(handle, AddressStartDOD90, cedv->DOD90); - bq27220_set_parameter_u16(handle, AddressStartDOD100, cedv->DOD100); - bq27220_set_parameter_u16(handle, AddressEDV0, cedv->EDV0); - bq27220_set_parameter_u16(handle, AddressEDV1, cedv->EDV1); - bq27220_set_parameter_u16(handle, AddressEDV2, cedv->EDV2); + data = bq27220_read_word(handle, CommandMACData); + FURI_LOG_I(TAG, "Device Number %04x", data); - bq27220_control(handle, Control_EXIT_CFG_UPDATE_REINIT); - furi_delay_us(10000); - design_cap = bq27220_get_design_capacity(handle); - if(cedv->design_cap == design_cap) { - FURI_LOG_I(TAG, "Battery profile update success"); - return true; - } else { - FURI_LOG_E(TAG, "Battery profile update failed"); - return false; + return data == 0x0220; +} + +bool bq27220_apply_data_memory(FuriHalI2cBusHandle* handle, const BQ27220DMData* data_memory) { + FURI_LOG_I(TAG, "Verifying data memory"); + if(!bq27220_data_memory_check(handle, data_memory, false)) { + FURI_LOG_I(TAG, "Updating data memory"); + bq27220_data_memory_check(handle, data_memory, true); } + FURI_LOG_I(TAG, "Data memory verification complete"); + + return true; } uint16_t bq27220_get_voltage(FuriHalI2cBusHandle* handle) { @@ -114,24 +219,23 @@ int16_t bq27220_get_current(FuriHalI2cBusHandle* handle) { return bq27220_read_word(handle, CommandCurrent); } -uint8_t bq27220_get_battery_status(FuriHalI2cBusHandle* handle, BatteryStatus* battery_status) { +bool bq27220_get_battery_status(FuriHalI2cBusHandle* handle, BatteryStatus* battery_status) { uint16_t data = bq27220_read_word(handle, CommandBatteryStatus); if(data == BQ27220_ERROR) { - return BQ27220_ERROR; + return false; } else { *(uint16_t*)battery_status = data; - return BQ27220_SUCCESS; + return true; } } -uint8_t - bq27220_get_operation_status(FuriHalI2cBusHandle* handle, OperationStatus* operation_status) { +bool bq27220_get_operation_status(FuriHalI2cBusHandle* handle, OperationStatus* operation_status) { uint16_t data = bq27220_read_word(handle, CommandOperationStatus); if(data == BQ27220_ERROR) { - return BQ27220_ERROR; + return false; } else { *(uint16_t*)operation_status = data; - return BQ27220_SUCCESS; + return true; } } diff --git a/lib/drivers/bq27220.h b/lib/drivers/bq27220.h index c822301a..ca9e0312 100644 --- a/lib/drivers/bq27220.h +++ b/lib/drivers/bq27220.h @@ -47,60 +47,17 @@ typedef struct { _Static_assert(sizeof(OperationStatus) == 2, "Incorrect structure size"); -typedef struct { - // Low byte, Low bit first - bool CCT : 1; - bool CSYNC : 1; - bool RSVD0 : 1; - bool EDV_CMP : 1; - bool SC : 1; - bool FIXED_EDV0 : 1; - uint8_t RSVD1 : 2; - // High byte, Low bit first - bool FCC_LIM : 1; - bool RSVD2 : 1; - bool FC_FOR_VDQ : 1; - bool IGNORE_SD : 1; - bool SME0 : 1; - uint8_t RSVD3 : 3; -} GaugingConfig; - -_Static_assert(sizeof(GaugingConfig) == 2, "Incorrect structure size"); - -typedef struct { - union { - GaugingConfig gauge_conf; - uint16_t gauge_conf_raw; - } cedv_conf; - uint16_t full_charge_cap; - uint16_t design_cap; - uint16_t EDV0; - uint16_t EDV1; - uint16_t EDV2; - uint16_t EMF; - uint16_t C0; - uint16_t R0; - uint16_t T0; - uint16_t R1; - uint8_t TC; - uint8_t C1; - uint16_t DOD0; - uint16_t DOD10; - uint16_t DOD20; - uint16_t DOD30; - uint16_t DOD40; - uint16_t DOD50; - uint16_t DOD60; - uint16_t DOD70; - uint16_t DOD80; - uint16_t DOD90; - uint16_t DOD100; -} ParamCEDV; +typedef struct BQ27220DMData BQ27220DMData; /** Initialize Driver * @return true on success, false otherwise */ -bool bq27220_init(FuriHalI2cBusHandle* handle, const ParamCEDV* cedv); +bool bq27220_init(FuriHalI2cBusHandle* handle); + +/** Initialize Driver + * @return true on success, false otherwise + */ +bool bq27220_apply_data_memory(FuriHalI2cBusHandle* handle, const BQ27220DMData* data_memory); /** Get battery voltage in mV or error */ uint16_t bq27220_get_voltage(FuriHalI2cBusHandle* handle); @@ -109,11 +66,10 @@ uint16_t bq27220_get_voltage(FuriHalI2cBusHandle* handle); int16_t bq27220_get_current(FuriHalI2cBusHandle* handle); /** Get battery status */ -uint8_t bq27220_get_battery_status(FuriHalI2cBusHandle* handle, BatteryStatus* battery_status); +bool bq27220_get_battery_status(FuriHalI2cBusHandle* handle, BatteryStatus* battery_status); /** Get operation status */ -uint8_t - bq27220_get_operation_status(FuriHalI2cBusHandle* handle, OperationStatus* operation_status); +bool bq27220_get_operation_status(FuriHalI2cBusHandle* handle, OperationStatus* operation_status); /** Get temperature in units of 0.1°K */ uint16_t bq27220_get_temperature(FuriHalI2cBusHandle* handle); diff --git a/lib/drivers/bq27220_data_memory.h b/lib/drivers/bq27220_data_memory.h new file mode 100644 index 00000000..ae00be88 --- /dev/null +++ b/lib/drivers/bq27220_data_memory.h @@ -0,0 +1,84 @@ +#pragma once + +#include +#include + +typedef enum { + BQ27220DMTypeEnd, + BQ27220DMTypeWait, + BQ27220DMTypeU8, + BQ27220DMTypeU16, + BQ27220DMTypeU32, + BQ27220DMTypeI8, + BQ27220DMTypeI16, + BQ27220DMTypeI32, + BQ27220DMTypeF32, + BQ27220DMTypePtr8, + BQ27220DMTypePtr16, + BQ27220DMTypePtr32, +} BQ27220DMType; + +typedef enum { + BQ27220DMAddressGasGaugingCEDVProfile1GaugingConfig = 0x929B, + BQ27220DMAddressGasGaugingCEDVProfile1FullChargeCapacity = 0x929D, + BQ27220DMAddressGasGaugingCEDVProfile1DesignCapacity = 0x929F, + BQ27220DMAddressGasGaugingCEDVProfile1EMF = 0x92A3, + BQ27220DMAddressGasGaugingCEDVProfile1C0 = 0x92A9, + BQ27220DMAddressGasGaugingCEDVProfile1R0 = 0x92AB, + BQ27220DMAddressGasGaugingCEDVProfile1T0 = 0x92AD, + BQ27220DMAddressGasGaugingCEDVProfile1R1 = 0x92AF, + BQ27220DMAddressGasGaugingCEDVProfile1TC = 0x92B1, + BQ27220DMAddressGasGaugingCEDVProfile1C1 = 0x92B2, + BQ27220DMAddressGasGaugingCEDVProfile1EDV0 = 0x92B4, + BQ27220DMAddressGasGaugingCEDVProfile1EDV1 = 0x92B7, + BQ27220DMAddressGasGaugingCEDVProfile1EDV2 = 0x92BA, + BQ27220DMAddressGasGaugingCEDVProfile1StartDOD0 = 0x92BD, + BQ27220DMAddressGasGaugingCEDVProfile1StartDOD10 = 0x92BF, + BQ27220DMAddressGasGaugingCEDVProfile1StartDOD20 = 0x92C1, + BQ27220DMAddressGasGaugingCEDVProfile1StartDOD30 = 0x92C3, + BQ27220DMAddressGasGaugingCEDVProfile1StartDOD40 = 0x92C5, + BQ27220DMAddressGasGaugingCEDVProfile1StartDOD50 = 0x92C7, + BQ27220DMAddressGasGaugingCEDVProfile1StartDOD60 = 0x92C9, + BQ27220DMAddressGasGaugingCEDVProfile1StartDOD70 = 0x92CB, + BQ27220DMAddressGasGaugingCEDVProfile1StartDOD80 = 0x92CD, + BQ27220DMAddressGasGaugingCEDVProfile1StartDOD90 = 0x92CF, + BQ27220DMAddressGasGaugingCEDVProfile1StartDOD100 = 0x92D1, + BQ27220DMAddressCalibrationCurrentDeadband = 0x91DE, + BQ27220DMAddressConfigurationPowerSleepCurrent = 0x9217, + BQ27220DMAddressConfigurationCurrentThresholdsDischargeDetectionThreshold = 0x9228, + BQ27220DMAddressConfigurationDataInitialStandby = 0x923C, +} BQ27220DMAddress; + +typedef struct BQ27220DMData BQ27220DMData; + +struct BQ27220DMData { + uint16_t type; + uint16_t address; + union { + uint8_t u8; + uint16_t u16; + uint32_t u32; + int8_t i8; + int16_t i16; + int32_t i32; + float f32; + } value; +}; + +typedef struct { + // Low byte, Low bit first + const bool CCT : 1; + const bool CSYNC : 1; + const bool RSVD0 : 1; + const bool EDV_CMP : 1; + const bool SC : 1; + const bool FIXED_EDV0 : 1; + const uint8_t RSVD1 : 2; + // High byte, Low bit first + const bool FCC_LIM : 1; + const bool RSVD2 : 1; + const bool FC_FOR_VDQ : 1; + const bool IGNORE_SD : 1; + const bool SME0 : 1; + const uint8_t RSVD3 : 3; +} BQ27220DMGaugingConfig; diff --git a/lib/drivers/bq27220_reg.h b/lib/drivers/bq27220_reg.h index fa81b66e..2e6e54aa 100644 --- a/lib/drivers/bq27220_reg.h +++ b/lib/drivers/bq27220_reg.h @@ -66,28 +66,3 @@ #define Control_EXIT_CFG_UPDATE_REINIT 0x0091 #define Control_EXIT_CFG_UPDATE 0x0092 #define Control_RETURN_TO_ROM 0x0F00 - -#define AddressGaugingConfig 0x929B -#define AddressFullChargeCapacity 0x929D -#define AddressDesignCapacity 0x929F -#define AddressEMF 0x92A3 -#define AddressC0 0x92A9 -#define AddressR0 0x92AB -#define AddressT0 0x92AD -#define AddressR1 0x92AF -#define AddressTC 0x92B1 -#define AddressC1 0x92B2 -#define AddressEDV0 0x92B4 -#define AddressEDV1 0x92B7 -#define AddressEDV2 0x92BA -#define AddressStartDOD0 0x92BD -#define AddressStartDOD10 0x92BF -#define AddressStartDOD20 0x92C1 -#define AddressStartDOD30 0x92C3 -#define AddressStartDOD40 0x92C5 -#define AddressStartDOD50 0x92C7 -#define AddressStartDOD60 0x92C9 -#define AddressStartDOD70 0x92CB -#define AddressStartDOD80 0x92CD -#define AddressStartDOD90 0x92CF -#define AddressStartDOD100 0x92D1 diff --git a/lib/infrared/encoder_decoder/infrared.c b/lib/infrared/encoder_decoder/infrared.c index fcfc5da2..56f2c3f9 100644 --- a/lib/infrared/encoder_decoder/infrared.c +++ b/lib/infrared/encoder_decoder/infrared.c @@ -11,6 +11,7 @@ #include "rc6/infrared_protocol_rc6.h" #include "sirc/infrared_protocol_sirc.h" #include "kaseikyo/infrared_protocol_kaseikyo.h" +#include "rca/infrared_protocol_rca.h" typedef struct { InfraredAlloc alloc; @@ -127,6 +128,20 @@ static const InfraredEncoderDecoder infrared_encoder_decoder[] = { .free = infrared_encoder_kaseikyo_free}, .get_protocol_variant = infrared_protocol_kaseikyo_get_variant, }, + { + .decoder = + {.alloc = infrared_decoder_rca_alloc, + .decode = infrared_decoder_rca_decode, + .reset = infrared_decoder_rca_reset, + .check_ready = infrared_decoder_rca_check_ready, + .free = infrared_decoder_rca_free}, + .encoder = + {.alloc = infrared_encoder_rca_alloc, + .encode = infrared_encoder_rca_encode, + .reset = infrared_encoder_rca_reset, + .free = infrared_encoder_rca_free}, + .get_protocol_variant = infrared_protocol_rca_get_variant, + }, }; static int infrared_find_index_by_protocol(InfraredProtocol protocol); diff --git a/lib/infrared/encoder_decoder/infrared.h b/lib/infrared/encoder_decoder/infrared.h index 3ab46cbb..ada449b9 100644 --- a/lib/infrared/encoder_decoder/infrared.h +++ b/lib/infrared/encoder_decoder/infrared.h @@ -33,6 +33,7 @@ typedef enum { InfraredProtocolSIRC15, InfraredProtocolSIRC20, InfraredProtocolKaseikyo, + InfraredProtocolRCA, InfraredProtocolMAX, } InfraredProtocol; diff --git a/lib/infrared/encoder_decoder/rca/infrared_decoder_rca.c b/lib/infrared/encoder_decoder/rca/infrared_decoder_rca.c new file mode 100644 index 00000000..b6d02a38 --- /dev/null +++ b/lib/infrared/encoder_decoder/rca/infrared_decoder_rca.c @@ -0,0 +1,45 @@ +#include "infrared_protocol_rca_i.h" +#include + +InfraredMessage* infrared_decoder_rca_check_ready(void* ctx) { + return infrared_common_decoder_check_ready(ctx); +} + +bool infrared_decoder_rca_interpret(InfraredCommonDecoder* decoder) { + furi_assert(decoder); + + uint32_t* data = (void*)&decoder->data; + + uint8_t address = (*data & 0xF); + uint8_t command = (*data >> 4) & 0xFF; + uint8_t address_inverse = (*data >> 12) & 0xF; + uint8_t command_inverse = (*data >> 16) & 0xFF; + uint8_t inverse_address_inverse = (uint8_t)~address_inverse & 0xF; + uint8_t inverse_command_inverse = (uint8_t)~command_inverse; + + if((command == inverse_command_inverse) && (address == inverse_address_inverse)) { + decoder->message.protocol = InfraredProtocolRCA; + decoder->message.address = address; + decoder->message.command = command; + decoder->message.repeat = false; + return true; + } + + return false; +} + +void* infrared_decoder_rca_alloc(void) { + return infrared_common_decoder_alloc(&infrared_protocol_rca); +} + +InfraredMessage* infrared_decoder_rca_decode(void* decoder, bool level, uint32_t duration) { + return infrared_common_decode(decoder, level, duration); +} + +void infrared_decoder_rca_free(void* decoder) { + infrared_common_decoder_free(decoder); +} + +void infrared_decoder_rca_reset(void* decoder) { + infrared_common_decoder_reset(decoder); +} diff --git a/lib/infrared/encoder_decoder/rca/infrared_encoder_rca.c b/lib/infrared/encoder_decoder/rca/infrared_encoder_rca.c new file mode 100644 index 00000000..f0be4a6a --- /dev/null +++ b/lib/infrared/encoder_decoder/rca/infrared_encoder_rca.c @@ -0,0 +1,37 @@ +#include "infrared_protocol_rca_i.h" + +#include + +void infrared_encoder_rca_reset(void* encoder_ptr, const InfraredMessage* message) { + furi_assert(encoder_ptr); + furi_assert(message); + + InfraredCommonEncoder* encoder = encoder_ptr; + infrared_common_encoder_reset(encoder); + + uint32_t* data = (void*)encoder->data; + + uint8_t address = message->address; + uint8_t address_inverse = ~address; + uint8_t command = message->command; + uint8_t command_inverse = ~command; + + *data = address & 0xF; + *data |= command << 4; + *data |= (address_inverse & 0xF) << 12; + *data |= command_inverse << 16; + + encoder->bits_to_encode = encoder->protocol->databit_len[0]; +} + +void* infrared_encoder_rca_alloc(void) { + return infrared_common_encoder_alloc(&infrared_protocol_rca); +} + +void infrared_encoder_rca_free(void* encoder_ptr) { + infrared_common_encoder_free(encoder_ptr); +} + +InfraredStatus infrared_encoder_rca_encode(void* encoder_ptr, uint32_t* duration, bool* level) { + return infrared_common_encode(encoder_ptr, duration, level); +} diff --git a/lib/infrared/encoder_decoder/rca/infrared_protocol_rca.c b/lib/infrared/encoder_decoder/rca/infrared_protocol_rca.c new file mode 100644 index 00000000..8e1e76db --- /dev/null +++ b/lib/infrared/encoder_decoder/rca/infrared_protocol_rca.c @@ -0,0 +1,40 @@ +#include "infrared_protocol_rca_i.h" + +const InfraredCommonProtocolSpec infrared_protocol_rca = { + .timings = + { + .preamble_mark = INFRARED_RCA_PREAMBLE_MARK, + .preamble_space = INFRARED_RCA_PREAMBLE_SPACE, + .bit1_mark = INFRARED_RCA_BIT1_MARK, + .bit1_space = INFRARED_RCA_BIT1_SPACE, + .bit0_mark = INFRARED_RCA_BIT0_MARK, + .bit0_space = INFRARED_RCA_BIT0_SPACE, + .preamble_tolerance = INFRARED_RCA_PREAMBLE_TOLERANCE, + .bit_tolerance = INFRARED_RCA_BIT_TOLERANCE, + .silence_time = INFRARED_RCA_SILENCE, + .min_split_time = INFRARED_RCA_MIN_SPLIT_TIME, + }, + .databit_len[0] = 24, + .no_stop_bit = false, + .decode = infrared_common_decode_pdwm, + .encode = infrared_common_encode_pdwm, + .interpret = infrared_decoder_rca_interpret, + .decode_repeat = NULL, + .encode_repeat = NULL, +}; + +static const InfraredProtocolVariant infrared_protocol_variant_rca = { + .name = "RCA", + .address_length = 4, + .command_length = 8, + .frequency = INFRARED_COMMON_CARRIER_FREQUENCY, + .duty_cycle = INFRARED_COMMON_DUTY_CYCLE, + .repeat_count = INFRARED_RCA_REPEAT_COUNT_MIN, +}; + +const InfraredProtocolVariant* infrared_protocol_rca_get_variant(InfraredProtocol protocol) { + if(protocol == InfraredProtocolRCA) + return &infrared_protocol_variant_rca; + else + return NULL; +} diff --git a/lib/infrared/encoder_decoder/rca/infrared_protocol_rca.h b/lib/infrared/encoder_decoder/rca/infrared_protocol_rca.h new file mode 100644 index 00000000..d9cae48e --- /dev/null +++ b/lib/infrared/encoder_decoder/rca/infrared_protocol_rca.h @@ -0,0 +1,30 @@ +#pragma once + +#include "../infrared_i.h" + +/*************************************************************************************************** +* RCA protocol description +* https://www.sbprojects.net/knowledge/ir/rca.php +**************************************************************************************************** +* Preamble Preamble Pulse Distance/Width Pause Preamble Preamble +* mark space Modulation up to period repeat repeat +* mark space +* +* 4000 4000 24 bit ...8000 4000 4000 +* __________ _ _ _ _ _ _ _ _ _ _ _ _ _ ___________ +* ____ __________ _ _ _ __ __ __ _ _ __ __ _ _ ________________ ___________ +* +***************************************************************************************************/ + +void* infrared_decoder_rca_alloc(void); +void infrared_decoder_rca_reset(void* decoder); +void infrared_decoder_rca_free(void* decoder); +InfraredMessage* infrared_decoder_rca_check_ready(void* decoder); +InfraredMessage* infrared_decoder_rca_decode(void* decoder, bool level, uint32_t duration); + +void* infrared_encoder_rca_alloc(void); +InfraredStatus infrared_encoder_rca_encode(void* encoder_ptr, uint32_t* duration, bool* level); +void infrared_encoder_rca_reset(void* encoder_ptr, const InfraredMessage* message); +void infrared_encoder_rca_free(void* encoder_ptr); + +const InfraredProtocolVariant* infrared_protocol_rca_get_variant(InfraredProtocol protocol); diff --git a/lib/infrared/encoder_decoder/rca/infrared_protocol_rca_i.h b/lib/infrared/encoder_decoder/rca/infrared_protocol_rca_i.h new file mode 100644 index 00000000..9ec4fe3b --- /dev/null +++ b/lib/infrared/encoder_decoder/rca/infrared_protocol_rca_i.h @@ -0,0 +1,30 @@ +#pragma once + +#include "../common/infrared_common_i.h" + +#define INFRARED_RCA_PREAMBLE_MARK 4000 +#define INFRARED_RCA_PREAMBLE_SPACE 4000 +#define INFRARED_RCA_BIT1_MARK 500 +#define INFRARED_RCA_BIT1_SPACE 2000 +#define INFRARED_RCA_BIT0_MARK 500 +#define INFRARED_RCA_BIT0_SPACE 1000 +#define INFRARED_RCA_REPEAT_PERIOD 8000 +#define INFRARED_RCA_SILENCE INFRARED_RCA_REPEAT_PERIOD + +#define INFRARED_RCA_MIN_SPLIT_TIME INFRARED_RCA_REPEAT_PAUSE_MIN +#define INFRARED_RCA_REPEAT_PAUSE_MIN 4000 +#define INFRARED_RCA_REPEAT_PAUSE_MAX 150000 +#define INFRARED_RCA_REPEAT_COUNT_MIN 1 +#define INFRARED_RCA_REPEAT_MARK INFRARED_RCA_PREAMBLE_MARK +#define INFRARED_RCA_REPEAT_SPACE INFRARED_RCA_PREAMBLE_SPACE +#define INFRARED_RCA_PREAMBLE_TOLERANCE 200 // us +#define INFRARED_RCA_BIT_TOLERANCE 120 // us + +extern const InfraredCommonProtocolSpec infrared_protocol_rca; + +bool infrared_decoder_rca_interpret(InfraredCommonDecoder* decoder); +InfraredStatus infrared_decoder_rca_decode_repeat(InfraredCommonDecoder* decoder); +InfraredStatus infrared_encoder_rca_encode_repeat( + InfraredCommonEncoder* encoder, + uint32_t* duration, + bool* level); diff --git a/lib/nfc/SConscript b/lib/nfc/SConscript index b8551db8..7a0859ee 100644 --- a/lib/nfc/SConscript +++ b/lib/nfc/SConscript @@ -6,6 +6,11 @@ env.Append( ], SDK_HEADERS=[ File("nfc_device.h"), + File("nfc_worker.h"), + File("nfc_types.h"), + File("helpers/mfkey32.h"), + File("parsers/nfc_supported_card.h"), + File("helpers/nfc_generators.h"), File("protocols/nfc_util.h"), ], ) diff --git a/lib/nfc/helpers/mf_classic_dict.h b/lib/nfc/helpers/mf_classic_dict.h index 3b2d560a..b798b1c9 100644 --- a/lib/nfc/helpers/mf_classic_dict.h +++ b/lib/nfc/helpers/mf_classic_dict.h @@ -6,6 +6,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + typedef enum { MfClassicDictTypeUser, MfClassicDictTypeSystem, @@ -97,3 +101,7 @@ bool mf_classic_dict_find_index_str(MfClassicDict* dict, FuriString* key, uint32 * @return true on success */ bool mf_classic_dict_delete_index(MfClassicDict* dict, uint32_t target); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/lib/nfc/helpers/mfkey32.h b/lib/nfc/helpers/mfkey32.h index e1f472e5..e2904322 100644 --- a/lib/nfc/helpers/mfkey32.h +++ b/lib/nfc/helpers/mfkey32.h @@ -2,6 +2,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + typedef struct Mfkey32 Mfkey32; typedef enum { @@ -24,3 +28,7 @@ void mfkey32_process_data( void mfkey32_set_callback(Mfkey32* instance, Mfkey32ParseDataCallback callback, void* context); uint16_t mfkey32_get_auth_sectors(FuriString* string); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/lib/nfc/nfc_types.h b/lib/nfc/nfc_types.h index fb53ce7c..5ebb2d27 100644 --- a/lib/nfc/nfc_types.h +++ b/lib/nfc/nfc_types.h @@ -2,6 +2,10 @@ #include "nfc_device.h" +#ifdef __cplusplus +extern "C" { +#endif + const char* nfc_get_dev_type(FuriHalNfcType type); const char* nfc_guess_protocol(NfcProtocol protocol); @@ -9,3 +13,7 @@ const char* nfc_guess_protocol(NfcProtocol protocol); const char* nfc_mf_ul_type(MfUltralightType type, bool full_name); const char* nfc_mf_classic_type(MfClassicType type); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/lib/nfc/nfc_worker.c b/lib/nfc/nfc_worker.c index d2834fa4..145007bd 100644 --- a/lib/nfc/nfc_worker.c +++ b/lib/nfc/nfc_worker.c @@ -1022,7 +1022,9 @@ void nfc_worker_emulate_mf_classic(NfcWorker* nfc_worker) { furi_hal_nfc_listen_start(nfc_data); while(nfc_worker->state == NfcWorkerStateMfClassicEmulate) { //-V1044 if(furi_hal_nfc_listen_rx(&tx_rx, 300)) { - mf_classic_emulator(&emulator, &tx_rx, false); + if(!mf_classic_emulator(&emulator, &tx_rx, false)) { + furi_hal_nfc_listen_start(nfc_data); + } } } if(emulator.data_changed) { @@ -1297,8 +1299,6 @@ void nfc_worker_analyze_reader(NfcWorker* nfc_worker) { bool reader_no_data_notified = true; while(nfc_worker->state == NfcWorkerStateAnalyzeReader) { - furi_hal_nfc_stop_cmd(); - furi_delay_ms(5); furi_hal_nfc_listen_start(nfc_data); if(furi_hal_nfc_listen_rx(&tx_rx, 300)) { if(reader_no_data_notified) { @@ -1309,7 +1309,9 @@ void nfc_worker_analyze_reader(NfcWorker* nfc_worker) { NfcProtocol protocol = reader_analyzer_guess_protocol(reader_analyzer, tx_rx.rx_data, tx_rx.rx_bits / 8); if(protocol == NfcDeviceProtocolMifareClassic) { - mf_classic_emulator(&emulator, &tx_rx, true); + if(!mf_classic_emulator(&emulator, &tx_rx, true)) { + furi_hal_nfc_listen_start(nfc_data); + } } } else { reader_no_data_received_cnt++; @@ -1321,6 +1323,7 @@ void nfc_worker_analyze_reader(NfcWorker* nfc_worker) { FURI_LOG_D(TAG, "No data from reader"); continue; } + furi_delay_ms(1); } rfal_platform_spi_release(); diff --git a/lib/nfc/nfc_worker.h b/lib/nfc/nfc_worker.h index 722f1485..f9f5900b 100644 --- a/lib/nfc/nfc_worker.h +++ b/lib/nfc/nfc_worker.h @@ -2,6 +2,10 @@ #include "nfc_device.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef struct NfcWorker NfcWorker; typedef enum { @@ -97,4 +101,8 @@ void nfc_worker_start( void nfc_worker_stop(NfcWorker* nfc_worker); void nfc_worker_nfcv_unlock(NfcWorker* nfc_worker); void nfc_worker_nfcv_emulate(NfcWorker* nfc_worker); -void nfc_worker_nfcv_sniff(NfcWorker* nfc_worker); \ No newline at end of file +void nfc_worker_nfcv_sniff(NfcWorker* nfc_worker); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/lib/nfc/parsers/nfc_supported_card.h b/lib/nfc/parsers/nfc_supported_card.h index 877bda73..2e8c48a8 100644 --- a/lib/nfc/parsers/nfc_supported_card.h +++ b/lib/nfc/parsers/nfc_supported_card.h @@ -4,6 +4,10 @@ #include "../nfc_worker.h" #include "../nfc_device.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef enum { NfcSupportedCardTypePlantain, NfcSupportedCardTypeTroika, @@ -37,3 +41,7 @@ bool nfc_supported_card_verify_and_parse(NfcDeviceData* dev_data); // support the card. This is needed for DESFire card parsers which can't // provide keys, and only use NfcSupportedCard->parse. bool stub_parser_verify_read(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/lib/nfc/protocols/crypto1.h b/lib/nfc/protocols/crypto1.h index 450d1534..bbf6dc23 100644 --- a/lib/nfc/protocols/crypto1.h +++ b/lib/nfc/protocols/crypto1.h @@ -3,6 +3,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + typedef struct { uint32_t odd; uint32_t even; @@ -35,3 +39,7 @@ void crypto1_encrypt( uint16_t plain_data_bits, uint8_t* encrypted_data, uint8_t* encrypted_parity); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/lib/nfc/protocols/mifare_classic.c b/lib/nfc/protocols/mifare_classic.c index ebe49a4a..011747d5 100644 --- a/lib/nfc/protocols/mifare_classic.c +++ b/lib/nfc/protocols/mifare_classic.c @@ -851,16 +851,20 @@ bool mf_classic_emulator( bool is_reader_analyzer) { furi_assert(emulator); furi_assert(tx_rx); - bool command_processed = false; - bool is_encrypted = false; uint8_t plain_data[MF_CLASSIC_MAX_DATA_SIZE]; MfClassicKey access_key = MfClassicKeyA; + bool need_reset = false; + bool need_nack = false; + bool is_encrypted = false; + uint8_t sector = 0; + // Used for decrement and increment - copy to block on transfer - uint8_t transfer_buf[MF_CLASSIC_BLOCK_SIZE] = {}; + uint8_t transfer_buf[MF_CLASSIC_BLOCK_SIZE]; bool transfer_buf_valid = false; - // Read command - while(!command_processed) { //-V654 + // Process commands + while(!need_reset && !need_nack) { //-V654 + memset(plain_data, 0, MF_CLASSIC_MAX_DATA_SIZE); if(!is_encrypted) { crypto1_reset(&emulator->crypto); memcpy(plain_data, tx_rx->rx_data, tx_rx->rx_bits / 8); @@ -868,9 +872,10 @@ bool mf_classic_emulator( if(!furi_hal_nfc_tx_rx(tx_rx, 300)) { FURI_LOG_D( TAG, - "Error in tx rx. Tx :%d bits, Rx: %d bits", + "Error in tx rx. Tx: %d bits, Rx: %d bits", tx_rx->tx_bits, tx_rx->rx_bits); + need_reset = true; break; } crypto1_decrypt(&emulator->crypto, tx_rx->rx_data, tx_rx->rx_bits, plain_data); @@ -879,19 +884,28 @@ bool mf_classic_emulator( // After increment, decrement or restore the only allowed command is transfer uint8_t cmd = plain_data[0]; if(transfer_buf_valid && cmd != MF_CLASSIC_TRANSFER_CMD) { + need_nack = true; break; } - if(cmd == 0x50 && plain_data[1] == 0x00) { + if(cmd == NFCA_CMD_HALT && plain_data[1] == 0x00) { FURI_LOG_T(TAG, "Halt received"); - furi_hal_nfc_listen_sleep(); - command_processed = true; + need_reset = true; break; } + + if(cmd == NFCA_CMD_RATS) { + // Mifare Classic doesn't support ATS, NACK it and start listening again + FURI_LOG_T(TAG, "RATS received"); + need_nack = true; + break; + } + if(cmd == MF_CLASSIC_AUTH_KEY_A_CMD || cmd == MF_CLASSIC_AUTH_KEY_B_CMD) { uint8_t block = plain_data[1]; uint64_t key = 0; uint8_t sector_trailer_block = mf_classic_get_sector_trailer_num_by_block(block); + sector = mf_classic_get_sector_by_block(block); MfClassicSectorTrailer* sector_trailer = (MfClassicSectorTrailer*)emulator->data.block[sector_trailer_block].value; if(cmd == MF_CLASSIC_AUTH_KEY_A_CMD) { @@ -902,7 +916,7 @@ bool mf_classic_emulator( access_key = MfClassicKeyA; } else { FURI_LOG_D(TAG, "Key not known"); - command_processed = true; + need_nack = true; break; } } else { @@ -913,7 +927,7 @@ bool mf_classic_emulator( access_key = MfClassicKeyB; } else { FURI_LOG_D(TAG, "Key not known"); - command_processed = true; + need_nack = true; break; } } @@ -942,15 +956,15 @@ bool mf_classic_emulator( tx_rx->tx_bits = sizeof(nt) * 8; tx_rx->tx_rx_type = FuriHalNfcTxRxTransparent; } + if(!furi_hal_nfc_tx_rx(tx_rx, 500)) { FURI_LOG_E(TAG, "Error in NT exchange"); - command_processed = true; + need_reset = true; break; } if(tx_rx->rx_bits != 64) { - FURI_LOG_W(TAG, "Incorrect nr + ar length: %d", tx_rx->rx_bits); - command_processed = true; + need_reset = true; break; } @@ -960,9 +974,14 @@ bool mf_classic_emulator( crypto1_word(&emulator->crypto, nr, 1); uint32_t cardRr = ar ^ crypto1_word(&emulator->crypto, 0, 0); if(cardRr != prng_successor(nonce, 64)) { - FURI_LOG_T(TAG, "Wrong AUTH! %08lX != %08lX", cardRr, prng_successor(nonce, 64)); + FURI_LOG_T( + TAG, + "Wrong AUTH on block %u! %08lX != %08lX", + block, + cardRr, + prng_successor(nonce, 64)); // Don't send NACK, as the tag doesn't send it - command_processed = true; + need_reset = true; break; } @@ -985,11 +1004,25 @@ bool mf_classic_emulator( if(!is_encrypted) { FURI_LOG_T(TAG, "Invalid command before auth session established: %02X", cmd); + need_nack = true; break; } - if(cmd == MF_CLASSIC_READ_BLOCK_CMD) { - uint8_t block = plain_data[1]; + // Mifare Classic commands always have block number after command + uint8_t block = plain_data[1]; + if(mf_classic_get_sector_by_block(block) != sector) { + // Don't allow access to sectors other than authorized + FURI_LOG_T( + TAG, + "Trying to access block %u from not authorized sector (command: %02X)", + block, + cmd); + need_nack = true; + break; + } + + switch(cmd) { + case MF_CLASSIC_READ_BLOCK_CMD: { uint8_t block_data[MF_CLASSIC_BLOCK_SIZE + 2] = {}; memcpy(block_data, emulator->data.block[block].value, MF_CLASSIC_BLOCK_SIZE); if(mf_classic_is_sector_trailer(block)) { @@ -1005,17 +1038,14 @@ bool mf_classic_emulator( emulator, block, access_key, MfClassicActionACRead)) { memset(&block_data[6], 0, 4); } - } else if(!mf_classic_is_allowed_access( - emulator, block, access_key, MfClassicActionDataRead)) { - // Send NACK - uint8_t nack = 0x04; - crypto1_encrypt( - &emulator->crypto, NULL, &nack, 4, tx_rx->tx_data, tx_rx->tx_parity); - tx_rx->tx_rx_type = FuriHalNfcTxRxTransparent; - tx_rx->tx_bits = 4; - furi_hal_nfc_tx_rx(tx_rx, 300); + } else if( + !mf_classic_is_allowed_access( + emulator, block, access_key, MfClassicActionDataRead) || + !mf_classic_is_block_read(&emulator->data, block)) { + need_nack = true; break; } + nfca_append_crc16(block_data, 16); crypto1_encrypt( @@ -1027,23 +1057,36 @@ bool mf_classic_emulator( tx_rx->tx_parity); tx_rx->tx_bits = (MF_CLASSIC_BLOCK_SIZE + 2) * 8; tx_rx->tx_rx_type = FuriHalNfcTxRxTransparent; - } else if(cmd == MF_CLASSIC_WRITE_BLOCK_CMD) { - uint8_t block = plain_data[1]; - if(block > mf_classic_get_total_block_num(emulator->data.type)) { - break; - } + break; + } + + case MF_CLASSIC_WRITE_BLOCK_CMD: { // Send ACK uint8_t ack = MF_CLASSIC_ACK_CMD; crypto1_encrypt(&emulator->crypto, NULL, &ack, 4, tx_rx->tx_data, tx_rx->tx_parity); tx_rx->tx_rx_type = FuriHalNfcTxRxTransparent; tx_rx->tx_bits = 4; - if(!furi_hal_nfc_tx_rx(tx_rx, 300)) break; - if(tx_rx->rx_bits != (MF_CLASSIC_BLOCK_SIZE + 2) * 8) break; + if(!furi_hal_nfc_tx_rx(tx_rx, 300)) { + need_reset = true; + break; + } + + if(tx_rx->rx_bits != (MF_CLASSIC_BLOCK_SIZE + 2) * 8) { + need_reset = true; + break; + } crypto1_decrypt(&emulator->crypto, tx_rx->rx_data, tx_rx->rx_bits, plain_data); uint8_t block_data[MF_CLASSIC_BLOCK_SIZE] = {}; memcpy(block_data, emulator->data.block[block].value, MF_CLASSIC_BLOCK_SIZE); + + if(!mf_classic_is_block_read(&emulator->data, block)) { + // Don't allow writing to the block for which we haven't read data yet + need_nack = true; + break; + } + if(mf_classic_is_sector_trailer(block)) { if(mf_classic_is_allowed_access( emulator, block, access_key, MfClassicActionKeyAWrite)) { @@ -1062,38 +1105,39 @@ bool mf_classic_emulator( emulator, block, access_key, MfClassicActionDataWrite)) { memcpy(block_data, plain_data, MF_CLASSIC_BLOCK_SIZE); } else { + need_nack = true; break; } } + if(memcmp(block_data, emulator->data.block[block].value, MF_CLASSIC_BLOCK_SIZE) != 0) { memcpy(emulator->data.block[block].value, block_data, MF_CLASSIC_BLOCK_SIZE); emulator->data_changed = true; } + // Send ACK ack = MF_CLASSIC_ACK_CMD; crypto1_encrypt(&emulator->crypto, NULL, &ack, 4, tx_rx->tx_data, tx_rx->tx_parity); tx_rx->tx_rx_type = FuriHalNfcTxRxTransparent; tx_rx->tx_bits = 4; - } else if( - cmd == MF_CLASSIC_DECREMENT_CMD || cmd == MF_CLASSIC_INCREMENT_CMD || - cmd == MF_CLASSIC_RESTORE_CMD) { - uint8_t block = plain_data[1]; + break; + } - if(block > mf_classic_get_total_block_num(emulator->data.type)) { - break; - } + case MF_CLASSIC_DECREMENT_CMD: + case MF_CLASSIC_INCREMENT_CMD: + case MF_CLASSIC_RESTORE_CMD: { + MfClassicAction action = (cmd == MF_CLASSIC_INCREMENT_CMD) ? MfClassicActionDataInc : + MfClassicActionDataDec; - MfClassicAction action = MfClassicActionDataDec; - if(cmd == MF_CLASSIC_INCREMENT_CMD) { - action = MfClassicActionDataInc; - } if(!mf_classic_is_allowed_access(emulator, block, access_key, action)) { + need_nack = true; break; } int32_t prev_value; uint8_t addr; if(!mf_classic_block_to_value(emulator->data.block[block].value, &prev_value, &addr)) { + need_nack = true; break; } @@ -1103,8 +1147,15 @@ bool mf_classic_emulator( tx_rx->tx_rx_type = FuriHalNfcTxRxTransparent; tx_rx->tx_bits = 4; - if(!furi_hal_nfc_tx_rx(tx_rx, 300)) break; - if(tx_rx->rx_bits != (sizeof(int32_t) + 2) * 8) break; + if(!furi_hal_nfc_tx_rx(tx_rx, 300)) { + need_reset = true; + break; + } + + if(tx_rx->rx_bits != (sizeof(int32_t) + 2) * 8) { + need_reset = true; + break; + } crypto1_decrypt(&emulator->crypto, tx_rx->rx_data, tx_rx->rx_bits, plain_data); int32_t value = *(int32_t*)&plain_data[0]; @@ -1121,9 +1172,12 @@ bool mf_classic_emulator( transfer_buf_valid = true; // Commands do not ACK tx_rx->tx_bits = 0; - } else if(cmd == MF_CLASSIC_TRANSFER_CMD) { - uint8_t block = plain_data[1]; + break; + } + + case MF_CLASSIC_TRANSFER_CMD: { if(!mf_classic_is_allowed_access(emulator, block, access_key, MfClassicActionDataDec)) { + need_nack = true; break; } if(memcmp(transfer_buf, emulator->data.block[block].value, MF_CLASSIC_BLOCK_SIZE) != @@ -1137,13 +1191,17 @@ bool mf_classic_emulator( crypto1_encrypt(&emulator->crypto, NULL, &ack, 4, tx_rx->tx_data, tx_rx->tx_parity); tx_rx->tx_rx_type = FuriHalNfcTxRxTransparent; tx_rx->tx_bits = 4; - } else { + break; + } + + default: FURI_LOG_T(TAG, "Unknown command: %02X", cmd); + need_nack = true; break; } } - if(!command_processed) { + if(need_nack && !need_reset) { // Send NACK uint8_t nack = transfer_buf_valid ? MF_CLASSIC_NACK_BUF_VALID_CMD : MF_CLASSIC_NACK_BUF_INVALID_CMD; @@ -1155,15 +1213,16 @@ bool mf_classic_emulator( tx_rx->tx_rx_type = FuriHalNfcTxRxTransparent; tx_rx->tx_bits = 4; furi_hal_nfc_tx_rx(tx_rx, 300); + need_reset = true; } - return true; + return !need_reset; } void mf_classic_halt(FuriHalNfcTxRxContext* tx_rx, Crypto1* crypto) { furi_assert(tx_rx); - uint8_t plain_data[4] = {0x50, 0x00, 0x00, 0x00}; + uint8_t plain_data[4] = {NFCA_CMD_HALT, 0x00, 0x00, 0x00}; nfca_append_crc16(plain_data, 2); if(crypto) { diff --git a/lib/nfc/protocols/mifare_classic.h b/lib/nfc/protocols/mifare_classic.h index b3e3cbdf..7efe81b8 100644 --- a/lib/nfc/protocols/mifare_classic.h +++ b/lib/nfc/protocols/mifare_classic.h @@ -4,6 +4,10 @@ #include "crypto1.h" +#ifdef __cplusplus +extern "C" { +#endif + #define MF_CLASSIC_BLOCK_SIZE (16) #define MF_CLASSIC_TOTAL_BLOCKS_MAX (256) #define MF_MINI_TOTAL_SECTORS_NUM (5) @@ -241,3 +245,7 @@ bool mf_classic_write_sector( MfClassicData* dest_data, MfClassicData* src_data, uint8_t sec_num); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/lib/nfc/protocols/mifare_desfire.h b/lib/nfc/protocols/mifare_desfire.h index 3dc7c4c2..8faa98ec 100644 --- a/lib/nfc/protocols/mifare_desfire.h +++ b/lib/nfc/protocols/mifare_desfire.h @@ -5,6 +5,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + #define MF_DF_GET_VERSION (0x60) #define MF_DF_GET_FREE_MEMORY (0x6E) #define MF_DF_GET_KEY_SETTINGS (0x45) @@ -169,3 +173,7 @@ uint16_t mf_df_prepare_read_records(uint8_t* dest, uint8_t file_id, uint32_t off bool mf_df_parse_read_data_response(uint8_t* buf, uint16_t len, MifareDesfireFile* out); bool mf_df_read_card(FuriHalNfcTxRxContext* tx_rx, MifareDesfireData* data); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/lib/nfc/protocols/mifare_ultralight.h b/lib/nfc/protocols/mifare_ultralight.h index d444fa79..9cb7ca53 100644 --- a/lib/nfc/protocols/mifare_ultralight.h +++ b/lib/nfc/protocols/mifare_ultralight.h @@ -2,6 +2,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + // Largest tag is NTAG I2C Plus 2K, both data sectors plus SRAM #define MF_UL_MAX_DUMP_SIZE ((238 + 256 + 16) * 4) @@ -259,3 +263,7 @@ uint32_t mf_ul_pwdgen_amiibo(FuriHalNfcDevData* data); uint32_t mf_ul_pwdgen_xiaomi(FuriHalNfcDevData* data); bool mf_ul_is_full_capture(MfUltralightData* data); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/lib/nfc/protocols/nfca.c b/lib/nfc/protocols/nfca.c index c401f8cc..ab4f3f23 100644 --- a/lib/nfc/protocols/nfca.c +++ b/lib/nfc/protocols/nfca.c @@ -3,8 +3,6 @@ #include #include -#define NFCA_CMD_RATS (0xE0U) - #define NFCA_CRC_INIT (0x6363) #define NFCA_F_SIG (13560000.0) @@ -22,7 +20,7 @@ typedef struct { static uint8_t nfca_default_ats[] = {0x05, 0x78, 0x80, 0x80, 0x00}; -static uint8_t nfca_sleep_req[] = {0x50, 0x00}; +static uint8_t nfca_halt_req[] = {NFCA_CMD_HALT, 0x00}; uint16_t nfca_get_crc16(uint8_t* buff, uint16_t len) { uint16_t crc = NFCA_CRC_INIT; @@ -50,17 +48,17 @@ bool nfca_emulation_handler( uint16_t buff_rx_len, uint8_t* buff_tx, uint16_t* buff_tx_len) { - bool sleep = false; + bool halt = false; uint8_t rx_bytes = buff_rx_len / 8; - if(rx_bytes == sizeof(nfca_sleep_req) && !memcmp(buff_rx, nfca_sleep_req, rx_bytes)) { - sleep = true; + if(rx_bytes == sizeof(nfca_halt_req) && !memcmp(buff_rx, nfca_halt_req, rx_bytes)) { + halt = true; } else if(rx_bytes == sizeof(nfca_cmd_rats) && buff_rx[0] == NFCA_CMD_RATS) { memcpy(buff_tx, nfca_default_ats, sizeof(nfca_default_ats)); *buff_tx_len = sizeof(nfca_default_ats) * 8; } - return sleep; + return halt; } static void nfca_add_bit(DigitalSignal* signal, bool bit) { diff --git a/lib/nfc/protocols/nfca.h b/lib/nfc/protocols/nfca.h index 498ef284..e4978a3e 100644 --- a/lib/nfc/protocols/nfca.h +++ b/lib/nfc/protocols/nfca.h @@ -5,6 +5,9 @@ #include +#define NFCA_CMD_RATS (0xE0U) +#define NFCA_CMD_HALT (0x50U) + typedef struct { DigitalSignal* one; DigitalSignal* zero; diff --git a/lib/subghz/SConscript b/lib/subghz/SConscript index 2c42a515..82c925c1 100644 --- a/lib/subghz/SConscript +++ b/lib/subghz/SConscript @@ -20,6 +20,7 @@ env.Append( File("subghz_setting.h"), File("subghz_protocol_registry.h"), File("devices/cc1101_configs.h"), + File("devices/cc1101_int/cc1101_int_interconnect.h"), ], ) diff --git a/lib/subghz/subghz_protocol_registry.h b/lib/subghz/subghz_protocol_registry.h index 6a27da99..8e80071b 100644 --- a/lib/subghz/subghz_protocol_registry.h +++ b/lib/subghz/subghz_protocol_registry.h @@ -8,6 +8,31 @@ extern "C" { extern const SubGhzProtocolRegistry subghz_protocol_registry; +typedef struct SubGhzProtocolDecoderBinRAW SubGhzProtocolDecoderBinRAW; + +bool subghz_protocol_secplus_v2_create_data( + void* context, + FlipperFormat* flipper_format, + uint32_t serial, + uint8_t btn, + uint32_t cnt, + SubGhzRadioPreset* preset); + +bool subghz_protocol_keeloq_create_data( + void* context, + FlipperFormat* flipper_format, + uint32_t serial, + uint8_t btn, + uint16_t cnt, + const char* manufacture_name, + SubGhzRadioPreset* preset); + +void subghz_protocol_decoder_bin_raw_data_input_rssi( + SubGhzProtocolDecoderBinRAW* instance, + float rssi); + +bool subghz_protocol_secplus_v1_check_fixed(uint32_t fixed); + #ifdef __cplusplus } #endif diff --git a/lib/update_util/update_operation.c b/lib/update_util/update_operation.c index 6e05b023..0cecfc01 100644 --- a/lib/update_util/update_operation.c +++ b/lib/update_util/update_operation.c @@ -20,7 +20,8 @@ static const char* update_prepare_result_descr[] = { [UpdatePrepareResultManifestInvalid] = "Invalid manifest data", [UpdatePrepareResultStageMissing] = "Missing Stage2 loader", [UpdatePrepareResultStageIntegrityError] = "Corrupted Stage2 loader", - [UpdatePrepareResultManifestPointerError] = "Failed to create update pointer file", + [UpdatePrepareResultManifestPointerCreateError] = "Failed to create update pointer file", + [UpdatePrepareResultManifestPointerCheckError] = "Update pointer file error (corrupted FS?)", [UpdatePrepareResultTargetMismatch] = "Hardware target mismatch", [UpdatePrepareResultOutdatedManifestVersion] = "Update package is too old", [UpdatePrepareResultIntFull] = "Need more free space in internal storage", @@ -142,8 +143,8 @@ UpdatePrepareResult update_operation_prepare(const char* manifest_file_path) { File* file = storage_file_alloc(storage); uint64_t free_int_space; - FuriString* stage_path; - stage_path = furi_string_alloc(); + FuriString* stage_path = furi_string_alloc(); + FuriString* manifest_path_check = furi_string_alloc(); do { if((storage_common_fs_info(storage, STORAGE_INT_PATH_PREFIX, NULL, &free_int_space) != FSE_OK) || @@ -188,7 +189,18 @@ UpdatePrepareResult update_operation_prepare(const char* manifest_file_path) { } if(!update_operation_persist_manifest_path(storage, manifest_file_path)) { - result = UpdatePrepareResultManifestPointerError; + result = UpdatePrepareResultManifestPointerCreateError; + break; + } + + if(!update_operation_get_current_package_manifest_path(storage, manifest_path_check) || + (furi_string_cmpi_str(manifest_path_check, manifest_file_path) != 0)) { + FURI_LOG_E( + "update", + "Manifest pointer check failed: '%s' != '%s'", + furi_string_get_cstr(manifest_path_check), + manifest_file_path); + result = UpdatePrepareResultManifestPointerCheckError; break; } @@ -197,6 +209,7 @@ UpdatePrepareResult update_operation_prepare(const char* manifest_file_path) { } while(false); furi_string_free(stage_path); + furi_string_free(manifest_path_check); storage_file_free(file); update_manifest_free(manifest); diff --git a/lib/update_util/update_operation.h b/lib/update_util/update_operation.h index 65abf8e1..8e36b5a1 100644 --- a/lib/update_util/update_operation.h +++ b/lib/update_util/update_operation.h @@ -28,7 +28,8 @@ typedef enum { UpdatePrepareResultManifestInvalid, UpdatePrepareResultStageMissing, UpdatePrepareResultStageIntegrityError, - UpdatePrepareResultManifestPointerError, + UpdatePrepareResultManifestPointerCreateError, + UpdatePrepareResultManifestPointerCheckError, UpdatePrepareResultTargetMismatch, UpdatePrepareResultOutdatedManifestVersion, UpdatePrepareResultIntFull, diff --git a/scripts/fbt/appmanifest.py b/scripts/fbt/appmanifest.py index 73e5c777..067b4a26 100644 --- a/scripts/fbt/appmanifest.py +++ b/scripts/fbt/appmanifest.py @@ -18,6 +18,7 @@ class FlipperAppType(Enum): SETTINGS = "Settings" STARTUP = "StartupHook" EXTERNAL = "External" + MENUEXTERNAL = "MenuExternal" METAPACKAGE = "Package" PLUGIN = "Plugin" @@ -213,7 +214,7 @@ class AppBuildset: appmgr: AppManager, appnames: List[str], hw_target: str, - message_writer: Callable = None, + message_writer: Callable | None = None, ): self.appmgr = appmgr self.appnames = set(appnames) @@ -324,7 +325,13 @@ class AppBuildset: def get_sdk_headers(self): sdk_headers = [] for app in self.apps: - sdk_headers.extend([app._appdir.File(header) for header in app.sdk_headers]) + sdk_headers.extend( + [ + src._appdir.File(header) + for src in [app, *app._plugins] + for header in src.sdk_headers + ] + ) return sdk_headers def get_apps_of_type(self, apptype: FlipperAppType, all_known: bool = False): @@ -367,6 +374,11 @@ class ApplicationsCGenerator: ), } + APP_EXTERNAL_TYPE = ( + "FlipperExternalApplication", + "FLIPPER_EXTERNAL_APPS", + ) + def __init__(self, buildset: AppBuildset, autorun_app: str = ""): self.buildset = buildset self.autorun = autorun_app @@ -387,6 +399,17 @@ class ApplicationsCGenerator: .icon = {f"&{app.icon}" if app.icon else "NULL"}, .flags = {'|'.join(f"FlipperInternalApplicationFlag{flag}" for flag in app.flags)} }}""" + def get_external_app_descr(self, app: FlipperApplication): + app_path = "/ext/apps" + if app.fap_category: + app_path += f"/{app.fap_category}" + app_path += f"/{app.appid}.fap" + return f""" + {{ + .name = "{app.name}", + .icon = {f"&{app.icon}" if app.icon else "NULL"}, + .path = "{app_path}" }}""" + def generate(self): contents = [ '#include "applications.h"', @@ -418,4 +441,11 @@ class ApplicationsCGenerator: ] ) + entry_type, entry_block = self.APP_EXTERNAL_TYPE + external_apps = self.buildset.get_apps_of_type(FlipperAppType.MENUEXTERNAL) + contents.append(f"const {entry_type} {entry_block}[] = {{") + contents.append(",\n".join(map(self.get_external_app_descr, external_apps))) + contents.append("};") + contents.append(f"const size_t {entry_block}_COUNT = COUNT_OF({entry_block});") + return "\n".join(contents) diff --git a/scripts/fbt_tools/fbt_extapps.py b/scripts/fbt_tools/fbt_extapps.py index 69d70021..1766d4c4 100644 --- a/scripts/fbt_tools/fbt_extapps.py +++ b/scripts/fbt_tools/fbt_extapps.py @@ -3,7 +3,7 @@ import os import pathlib import shutil from dataclasses import dataclass, field -from typing import Optional +from typing import Optional, Dict, List import SCons.Warnings from ansi.color import fg @@ -400,22 +400,26 @@ def generate_embed_app_metadata_actions(source, target, env, for_signature): return Action(actions) -def AddAppLaunchTarget(env, appname, launch_target_name): - deploy_sources, flipp_dist_paths, validators = [], [], [] - run_script_extra_ars = "" +@dataclass +class AppDeploymentComponents: + deploy_sources: Dict[str, object] = field(default_factory=dict) + validators: List[object] = field(default_factory=list) + extra_launch_args: str = "" - def _add_dist_targets(app_artifacts): - validators.append(app_artifacts.validator) + def add_app(self, app_artifacts): for _, ext_path in app_artifacts.dist_entries: - deploy_sources.append(app_artifacts.compact) - flipp_dist_paths.append(f"/ext/{ext_path}") - return app_artifacts + self.deploy_sources[f"/ext/{ext_path}"] = app_artifacts.compact + self.validators.append(app_artifacts.validator) + + +def _gather_app_components(env, appname) -> AppDeploymentComponents: + components = AppDeploymentComponents() def _add_host_app_to_targets(host_app): artifacts_app_to_run = env["EXT_APPS"].get(host_app.appid, None) - _add_dist_targets(artifacts_app_to_run) + components.add_app(artifacts_app_to_run) for plugin in host_app._plugins: - _add_dist_targets(env["EXT_APPS"].get(plugin.appid, None)) + components.add_app(env["EXT_APPS"].get(plugin.appid, None)) artifacts_app_to_run = env.GetExtAppByIdOrPath(appname) if artifacts_app_to_run.app.apptype == FlipperAppType.PLUGIN: @@ -423,26 +427,39 @@ def AddAppLaunchTarget(env, appname, launch_target_name): host_app = env["APPMGR"].get(artifacts_app_to_run.app.requires[0]) if host_app: - if host_app.apptype == FlipperAppType.EXTERNAL: - _add_host_app_to_targets(host_app) + if host_app.apptype in [ + FlipperAppType.EXTERNAL, + FlipperAppType.MENUEXTERNAL, + ]: + components.add_app(host_app) else: # host app is a built-in app - run_script_extra_ars = f"-a {host_app.name}" - _add_dist_targets(artifacts_app_to_run) + components.add_app(artifacts_app_to_run) + components.extra_launch_args = f"-a {host_app.name}" else: raise UserError("Host app is unknown") else: _add_host_app_to_targets(artifacts_app_to_run.app) + return components - # print(deploy_sources, flipp_dist_paths) - env.PhonyTarget( + +def AddAppLaunchTarget(env, appname, launch_target_name): + components = _gather_app_components(env, appname) + target = env.PhonyTarget( launch_target_name, '${PYTHON3} "${APP_RUN_SCRIPT}" -p ${FLIP_PORT} ${EXTRA_ARGS} -s ${SOURCES} -t ${FLIPPER_FILE_TARGETS}', - source=deploy_sources, - FLIPPER_FILE_TARGETS=flipp_dist_paths, - EXTRA_ARGS=run_script_extra_ars, + source=components.deploy_sources.values(), + FLIPPER_FILE_TARGETS=components.deploy_sources.keys(), + EXTRA_ARGS=components.extra_launch_args, ) - env.Alias(launch_target_name, validators) + env.Alias(launch_target_name, components.validators) + return target + + +def AddAppBuildTarget(env, appname, build_target_name): + components = _gather_app_components(env, appname) + env.Alias(build_target_name, components.validators) + env.Alias(build_target_name, components.deploy_sources.values()) def generate(env, **kw): @@ -471,6 +488,7 @@ def generate(env, **kw): env.AddMethod(BuildAppElf) env.AddMethod(GetExtAppByIdOrPath) env.AddMethod(AddAppLaunchTarget) + env.AddMethod(AddAppBuildTarget) env.Append( BUILDERS={ diff --git a/scripts/fbt_tools/fbt_help.py b/scripts/fbt_tools/fbt_help.py index c7452af9..68fc2aaf 100644 --- a/scripts/fbt_tools/fbt_help.py +++ b/scripts/fbt_tools/fbt_help.py @@ -4,15 +4,16 @@ targets_help = """Configuration variables: tail_help = """ TASKS: -Building: +Firmware & apps: firmware_all, fw_dist: Build firmware; create distribution package faps, fap_dist: Build all FAP apps - fap_{APPID}, launch_app APPSRC={APPID}: + fap_{APPID}, build APPSRC={APPID}; launch APPSRC={APPID}: Build FAP app with appid={APPID}; upload & start it over USB fap_deploy: Build and upload all FAP apps over USB + Flashing & debugging: flash, flash_blackmagic, jflash: diff --git a/scripts/toolchain/fbtenv.cmd b/scripts/toolchain/fbtenv.cmd index 4ae04e2a..51708b8c 100644 --- a/scripts/toolchain/fbtenv.cmd +++ b/scripts/toolchain/fbtenv.cmd @@ -13,7 +13,7 @@ if not ["%FBT_NOENV%"] == [""] ( exit /b 0 ) -set "FLIPPER_TOOLCHAIN_VERSION=22" +set "FLIPPER_TOOLCHAIN_VERSION=23" if ["%FBT_TOOLCHAIN_PATH%"] == [""] ( set "FBT_TOOLCHAIN_PATH=%FBT_ROOT%" diff --git a/scripts/toolchain/fbtenv.sh b/scripts/toolchain/fbtenv.sh index e5548f48..85d13904 100755 --- a/scripts/toolchain/fbtenv.sh +++ b/scripts/toolchain/fbtenv.sh @@ -4,7 +4,7 @@ # public variables DEFAULT_SCRIPT_PATH="$(pwd -P)"; -FBT_TOOLCHAIN_VERSION="${FBT_TOOLCHAIN_VERSION:-"22"}"; +FBT_TOOLCHAIN_VERSION="${FBT_TOOLCHAIN_VERSION:-"23"}"; if [ -z ${FBT_TOOLCHAIN_PATH+x} ] ; then FBT_TOOLCHAIN_PATH_WAS_SET=0; diff --git a/scripts/ufbt/SConstruct b/scripts/ufbt/SConstruct index 8812a4e5..9a9e0938 100644 --- a/scripts/ufbt/SConstruct +++ b/scripts/ufbt/SConstruct @@ -262,6 +262,7 @@ apps_artifacts = appenv["EXT_APPS"] apps_to_build_as_faps = [ FlipperAppType.PLUGIN, FlipperAppType.EXTERNAL, + FlipperAppType.MENUEXTERNAL, ] known_extapps = [ @@ -335,8 +336,10 @@ def ambiguous_app_call(**kw): if app_to_launch: appenv.AddAppLaunchTarget(app_to_launch, "launch") + appenv.AddAppBuildTarget(app_to_launch, "build") else: dist_env.PhonyTarget("launch", Action(ambiguous_app_call, None)) + dist_env.PhonyTarget("build", Action(ambiguous_app_call, None)) # cli handler diff --git a/site_scons/extapps.scons b/site_scons/extapps.scons index 6db0e538..5c6f18d6 100644 --- a/site_scons/extapps.scons +++ b/site_scons/extapps.scons @@ -67,6 +67,7 @@ class FlipperExtAppBuildArtifacts: apps_to_build_as_faps = [ FlipperAppType.PLUGIN, FlipperAppType.EXTERNAL, + FlipperAppType.MENUEXTERNAL, FlipperAppType.DEBUG, ] @@ -113,8 +114,20 @@ extapps.resources_dist = appenv.FapDist(appenv["RESOURCES_ROOT"], []) if appsrc := appenv.subst("$APPSRC"): - appenv.AddAppLaunchTarget(appsrc, "launch_app") + launch_target = appenv.AddAppLaunchTarget(appsrc, "launch") + Alias("launch_app", launch_target) + appenv.PhonyTarget( + "launch_app", + Action( + lambda **kw: warn( + WarningOnByDefault, + "The 'launch_app' target is deprecated. Use 'launch' instead.", + ), + None, + ), + ) + appenv.AddAppBuildTarget(appsrc, "build") # SDK management