From 279662355149314b14af440a0d396e472419d3e2 Mon Sep 17 00:00:00 2001 From: valentinegb Date: Wed, 21 Dec 2022 01:30:40 -0800 Subject: [PATCH 01/34] Add VIZIO signals to tv.ir (#2167) * Add VIZIO signals to tv.ir * Fix improper formatting Co-authored-by: Georgii Surkov <37121527+gsurkov@users.noreply.github.com> --- assets/resources/infrared/assets/tv.ir | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/assets/resources/infrared/assets/tv.ir b/assets/resources/infrared/assets/tv.ir index 3965013da..cc5b0360e 100755 --- a/assets/resources/infrared/assets/tv.ir +++ b/assets/resources/infrared/assets/tv.ir @@ -1656,3 +1656,22 @@ type: parsed protocol: RC5 address: 01 00 00 00 command: 21 00 00 00 +# +# Model: VIZIO +name: Mute +type: parsed +protocol: NEC +address: 04 00 00 00 +command: 09 00 00 00 +# +name: Vol_up +type: parsed +protocol: NEC +address: 04 00 00 00 +command: 02 00 00 00 +# +name: Vol_dn +type: parsed +protocol: NEC +address: 04 00 00 00 +command: 03 00 00 00 From 7ff9414656c11da3164d97a15f670d8865ce77d5 Mon Sep 17 00:00:00 2001 From: Georgii Surkov <37121527+gsurkov@users.noreply.github.com> Date: Wed, 21 Dec 2022 12:42:51 +0300 Subject: [PATCH 02/34] Update CODEOWNERS (#2170) --- .github/CODEOWNERS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 6b77482c6..aa4ada1a8 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -42,6 +42,9 @@ /applications/debug/unit_tests/ @skotopes @DrZlo13 @hedger @nminaylov @gornekich @Astrrra @gsurkov @Skorpionm +# Assets +/assets/resources/infrared/ @skotopes @DrZlo13 @hedger @gsurkov + # Documentation /documentation/ @skotopes @DrZlo13 @hedger @drunkbatya /scripts/toolchain/ @skotopes @DrZlo13 @hedger @drunkbatya From a8541d519120ba68e924ff48e5ce7717a688be4f Mon Sep 17 00:00:00 2001 From: Eugene Kirzhanov Date: Thu, 22 Dec 2022 21:36:50 +0300 Subject: [PATCH 03/34] Games: Add 2048 game --- ReadMe.md | 1 + applications/plugins/game_2048/LICENSE | 21 + applications/plugins/game_2048/README.md | 17 + .../plugins/game_2048/application.fam | 14 + applications/plugins/game_2048/array_utils.c | 40 ++ applications/plugins/game_2048/array_utils.h | 22 + applications/plugins/game_2048/digits.h | 263 +++++++++ applications/plugins/game_2048/game_2048.c | 509 ++++++++++++++++++ applications/plugins/game_2048/game_2048.png | Bin 0 -> 89 bytes .../plugins/game_2048/images/screenshot1.png | Bin 0 -> 2038 bytes .../plugins/game_2048/images/screenshot2.png | Bin 0 -> 2183 bytes 11 files changed, 887 insertions(+) create mode 100644 applications/plugins/game_2048/LICENSE create mode 100644 applications/plugins/game_2048/README.md create mode 100644 applications/plugins/game_2048/application.fam create mode 100644 applications/plugins/game_2048/array_utils.c create mode 100644 applications/plugins/game_2048/array_utils.h create mode 100644 applications/plugins/game_2048/digits.h create mode 100644 applications/plugins/game_2048/game_2048.c create mode 100644 applications/plugins/game_2048/game_2048.png create mode 100644 applications/plugins/game_2048/images/screenshot1.png create mode 100644 applications/plugins/game_2048/images/screenshot2.png diff --git a/ReadMe.md b/ReadMe.md index d3567255b..3b2c3d914 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -130,6 +130,7 @@ Games: - Game15 [(by x27)](https://github.com/x27/flipperzero-game15) - Solitaire [(by teeebor)](https://github.com/teeebor/flipper_games) - BlackJack [(by teeebor)](https://github.com/teeebor/flipper_games) +- 2048 game [(by eugene-kirzhanov)](https://github.com/eugene-kirzhanov/flipper-zero-2048-game) ### Other changes diff --git a/applications/plugins/game_2048/LICENSE b/applications/plugins/game_2048/LICENSE new file mode 100644 index 000000000..f3da84264 --- /dev/null +++ b/applications/plugins/game_2048/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Eugene Kirzhanov + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/applications/plugins/game_2048/README.md b/applications/plugins/game_2048/README.md new file mode 100644 index 000000000..b743f1b59 --- /dev/null +++ b/applications/plugins/game_2048/README.md @@ -0,0 +1,17 @@ +# "2048" game for Flipper Zero +- play up to 65K +- progress is saved on exit + +![Game screen](images/screenshot1.png) +![Menu screen](images/screenshot2.png) + +#### TODO: + - add animations + +#### Thanks to: + - [DroomOne's FlappyBird](https://github.com/DroomOne/flipperzero-firmware/tree/dev/applications/flappy_bird) + - [x27's "15" Game](https://github.com/x27/flipperzero-game15) + +#### License +[MIT](LICENSE) +Copyright 2022 Eugene Kirzhanov diff --git a/applications/plugins/game_2048/application.fam b/applications/plugins/game_2048/application.fam new file mode 100644 index 000000000..eb51d65e8 --- /dev/null +++ b/applications/plugins/game_2048/application.fam @@ -0,0 +1,14 @@ +App( + appid="game_2048", + name="2048", + apptype=FlipperAppType.EXTERNAL, + entry_point="game_2048_app", + cdefines=["APP_GAME_2048"], + requires=[ + "gui", + ], + stack_size=1 * 1024, + order=90, + fap_icon="game_2048.png", + fap_category="Games" +) \ No newline at end of file diff --git a/applications/plugins/game_2048/array_utils.c b/applications/plugins/game_2048/array_utils.c new file mode 100644 index 000000000..f68570d1d --- /dev/null +++ b/applications/plugins/game_2048/array_utils.c @@ -0,0 +1,40 @@ +#include "array_utils.h" + +void reverse_array(int length, uint8_t arr[length]) { + uint8_t tmp; + for(int low = 0, high = length - 1; low < high; low++, high--) { + tmp = arr[low]; + arr[low] = arr[high]; + arr[high] = tmp; + } +} + +bool shift_array_to_left(int length, uint8_t arr[length], uint8_t from_index, uint8_t offset) { + if(from_index >= length) return false; + for(uint8_t i = from_index; i < length; i++) { + arr[i] = i < length - offset ? arr[i + offset] : 0; + } + return true; +} + +void get_column_from_array( + int rows, + int cols, + uint8_t arr[rows][cols], + uint8_t column_index, + uint8_t* out) { + for(uint8_t i = 0; i < rows; i++) { + out[i] = arr[i][column_index]; + } +} + +void set_column_to_array( + int rows, + int cols, + uint8_t arr[rows][cols], + uint8_t column_index, + uint8_t* src) { + for(uint8_t i = 0; i < rows; i++) { + arr[i][column_index] = src[i]; + } +} \ No newline at end of file diff --git a/applications/plugins/game_2048/array_utils.h b/applications/plugins/game_2048/array_utils.h new file mode 100644 index 000000000..371878446 --- /dev/null +++ b/applications/plugins/game_2048/array_utils.h @@ -0,0 +1,22 @@ +#pragma once + +#include +#include + +void reverse_array(int length, uint8_t arr[length]); + +bool shift_array_to_left(int length, uint8_t arr[length], uint8_t from_index, uint8_t offset); + +void get_column_from_array( + int rows, + int cols, + uint8_t arr[rows][cols], + uint8_t column_index, + uint8_t* out); + +void set_column_to_array( + int rows, + int cols, + uint8_t arr[rows][cols], + uint8_t column_index, + uint8_t* src); diff --git a/applications/plugins/game_2048/digits.h b/applications/plugins/game_2048/digits.h new file mode 100644 index 000000000..e79e7b033 --- /dev/null +++ b/applications/plugins/game_2048/digits.h @@ -0,0 +1,263 @@ +#pragma once + +#include + +uint8_t digits[16][14][14] = { + + // 2 + {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0}, + {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0}, + {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0}, + {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0}, + {0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0}, + {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + + // 4 + {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0}, + {0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0}, + {0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0}, + {0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0}, + {0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0}, + {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0}, + {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + + // 8 + {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0}, + {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0}, + {0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0}, + {0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0}, + {0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0}, + {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0}, + {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0}, + {0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0}, + {0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0}, + {0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0}, + {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0}, + {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + + // 16 + {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0}, + {0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0}, + {0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0}, + {0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0}, + {0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0}, + {0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0}, + {0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0}, + {0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0}, + {0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0}, + {0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + + // 32 + {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0}, + {0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0}, + {0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0}, + {0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0}, + {0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0}, + {0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0}, + {0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0}, + {0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0}, + {0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + + // 64 + {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0}, + {0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0}, + {0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0}, + {0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0}, + {0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0}, + {0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0}, + {0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0}, + {0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0}, + {0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0}, + {0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + + // 128 + {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0}, + {0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0}, + {0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0}, + {0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0}, + {0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + + // 256 + {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0}, + {0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0}, + {0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0}, + {0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0}, + {0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + + // 512 + {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0}, + {0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0}, + {0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0}, + {0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0}, + {0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + + // 1K + {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0}, + {0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + + // 2K + {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0}, + {0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0}, + {0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0}, + {0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0}, + {0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + + // 4K + {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0}, + {0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0}, + {0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + + // 8K + {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0}, + {0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0}, + {0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0}, + {0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0}, + {0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + + // 16K + {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0}, + {0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0}, + {0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0}, + {0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0}, + {0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + + // 32K + {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0}, + {0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0}, + {0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0}, + {0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0}, + {0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + + // 64K + {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0}, + {0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0}, + {0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0}, + {0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0}, + {0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}} + +}; diff --git a/applications/plugins/game_2048/game_2048.c b/applications/plugins/game_2048/game_2048.c new file mode 100644 index 000000000..e0c4a4cec --- /dev/null +++ b/applications/plugins/game_2048/game_2048.c @@ -0,0 +1,509 @@ +/* + * Copyright 2022 Eugene Kirzhanov + * Use of this source code is governed by an MIT-style + * license that can be found in the LICENSE file or at + * https://opensource.org/licenses/MIT + * + * Thanks to: + * - DroomOne: https://github.com/DroomOne/flipperzero-firmware + * - x27: https://github.com/x27/flipperzero-game15 + */ + +#include +#include +#include +#include + +#include "digits.h" +#include "array_utils.h" + +#define CELLS_COUNT 4 +#define CELL_INNER_SIZE 14 +#define FRAME_LEFT 10 +#define FRAME_TOP 1 +#define FRAME_SIZE 61 + +#define SAVING_DIRECTORY "/ext/apps/Games" +#define SAVING_FILENAME SAVING_DIRECTORY "/game_2048.save" + +typedef enum { + GameStateMenu, + GameStateInProgress, + GameStateGameOver, +} State; + +typedef struct { + State state; + uint8_t table[CELLS_COUNT][CELLS_COUNT]; + uint32_t score; + uint32_t moves; + int8_t selected_menu_item; + uint32_t top_score; +} GameState; + +typedef struct { + uint32_t points; + bool is_table_updated; +} MoveResult; + +#define MENU_ITEMS_COUNT 2 +static const char* popup_menu_strings[] = {"Resume", "New Game"}; + +static void input_callback(InputEvent* input_event, void* ctx) { + furi_assert(ctx); + FuriMessageQueue* event_queue = ctx; + furi_message_queue_put(event_queue, input_event, FuriWaitForever); +} + +static void draw_frame(Canvas* canvas) { + canvas_draw_frame(canvas, FRAME_LEFT, FRAME_TOP, FRAME_SIZE, FRAME_SIZE); + + uint8_t offs = FRAME_LEFT + CELL_INNER_SIZE + 1; + for(uint8_t i = 0; i < CELLS_COUNT - 1; i++) { + canvas_draw_line(canvas, offs, FRAME_TOP + 1, offs, FRAME_TOP + FRAME_SIZE - 2); + offs += CELL_INNER_SIZE + 1; + } + offs = FRAME_TOP + CELL_INNER_SIZE + 1; + for(uint8_t i = 0; i < CELLS_COUNT - 1; i++) { + canvas_draw_line(canvas, FRAME_LEFT + 1, offs, FRAME_LEFT + FRAME_SIZE - 2, offs); + offs += CELL_INNER_SIZE + 1; + } +} + +static void draw_digit(Canvas* canvas, uint8_t row, uint8_t column, uint8_t value) { + if(value == 0) return; + + uint8_t left = FRAME_LEFT + 1 + (column * (CELL_INNER_SIZE + 1)); + uint8_t top = FRAME_TOP + 1 + (row * (CELL_INNER_SIZE + 1)); + + for(uint8_t r = 0; r < CELL_INNER_SIZE; r++) { + for(u_int8_t c = 0; c < CELL_INNER_SIZE; c++) { + if(digits[value - 1][r][c] == 1) { + canvas_draw_dot(canvas, left + c, top + r); + } + } + } +} + +static void draw_table(Canvas* canvas, const uint8_t table[CELLS_COUNT][CELLS_COUNT]) { + for(uint8_t row = 0; row < CELLS_COUNT; row++) { + for(uint8_t column = 0; column < CELLS_COUNT; column++) { + draw_digit(canvas, row, column, table[row][column]); + } + } +} + +static void gray_canvas(Canvas* const canvas) { + canvas_set_color(canvas, ColorWhite); + for(int x = 0; x < 128; x += 2) { + for(int y = 0; y < 64; y++) { + canvas_draw_dot(canvas, x + (y % 2 == 1 ? 0 : 1), y); + } + } +} + +static void draw_callback(Canvas* const canvas, void* ctx) { + const GameState* game_state = acquire_mutex((ValueMutex*)ctx, 25); + if(game_state == NULL) return; + + canvas_clear(canvas); + + draw_frame(canvas); + draw_table(canvas, game_state->table); + + canvas_set_font(canvas, FontPrimary); + canvas_draw_str_aligned(canvas, 128, FRAME_TOP, AlignRight, AlignTop, "Score"); + canvas_draw_str_aligned(canvas, 128, FRAME_TOP + 20, AlignRight, AlignTop, "Moves"); + canvas_draw_str_aligned(canvas, 128, FRAME_TOP + 40, AlignRight, AlignTop, "Top Score"); + + int bufSize = 12; + char buf[bufSize]; + snprintf(buf, sizeof(buf), "%lu", game_state->score); + canvas_set_font(canvas, FontSecondary); + canvas_draw_str_aligned(canvas, 128, FRAME_TOP + 10, AlignRight, AlignTop, buf); + + memset(buf, 0, bufSize); + snprintf(buf, sizeof(buf), "%lu", game_state->moves); + canvas_set_font(canvas, FontSecondary); + canvas_draw_str_aligned(canvas, 128, FRAME_TOP + 30, AlignRight, AlignTop, buf); + + memset(buf, 0, bufSize); + snprintf(buf, sizeof(buf), "%lu", game_state->top_score); + canvas_set_font(canvas, FontSecondary); + canvas_draw_str_aligned(canvas, 128, FRAME_TOP + 50, AlignRight, AlignTop, buf); + + if(game_state->state == GameStateMenu) { + gray_canvas(canvas); + + canvas_set_color(canvas, ColorWhite); + canvas_draw_rbox(canvas, 28, 16, 72, 32, 4); + canvas_set_color(canvas, ColorBlack); + canvas_draw_rframe(canvas, 28, 16, 72, 32, 4); + + for(int i = 0; i < MENU_ITEMS_COUNT; i++) { + if(i == game_state->selected_menu_item) { + canvas_set_color(canvas, ColorBlack); + canvas_draw_box(canvas, 34, 20 + 12 * i, 60, 12); + } + + canvas_set_color( + canvas, i == game_state->selected_menu_item ? ColorWhite : ColorBlack); + canvas_draw_str_aligned( + canvas, 64, 26 + 12 * i, AlignCenter, AlignCenter, popup_menu_strings[i]); + } + + } else if(game_state->state == GameStateGameOver) { + gray_canvas(canvas); + + bool record_broken = game_state->score > game_state->top_score; + + canvas_set_color(canvas, ColorWhite); + canvas_draw_rbox(canvas, 14, 12, 100, 40, 4); + + canvas_set_color(canvas, ColorBlack); + canvas_draw_line(canvas, 14, 26, 114, 26); + canvas_draw_rframe(canvas, 14, 12, 100, 40, 4); + + canvas_set_font(canvas, FontPrimary); + canvas_draw_str_aligned(canvas, 64, 15, AlignCenter, AlignTop, "Game Over"); + + canvas_set_font(canvas, FontSecondary); + if(record_broken) { + canvas_draw_str_aligned(canvas, 64, 29, AlignCenter, AlignTop, "New Top Score!!!"); + } else { + canvas_draw_str_aligned(canvas, 64, 29, AlignCenter, AlignTop, "Your Score"); + } + + memset(buf, 0, bufSize); + snprintf(buf, sizeof(buf), "%lu", game_state->score); + canvas_set_font(canvas, FontPrimary); + canvas_draw_str_aligned(canvas, 64, 48, AlignCenter, AlignBottom, buf); + } + + release_mutex((ValueMutex*)ctx, game_state); +} + +void calculate_move_to_left(uint8_t arr[], MoveResult* const move_result) { + uint8_t index = 0; + uint8_t next_index; + uint8_t offset; + bool was_moved; + while(index < CELLS_COUNT - 1) { + // find offset from [index] to next non-empty value + offset = 1; + while(index + offset < CELLS_COUNT && arr[index + offset] == 0) offset++; + + // if all remaining values in this row are empty then go to next row + if(index + offset >= CELLS_COUNT) break; + + // if current cell is empty then shift all cells [index+offset .. CELLS_COUNT-1] to [index] + if(arr[index] == 0) { + was_moved = shift_array_to_left(CELLS_COUNT, arr, index, offset); + if(was_moved) move_result->is_table_updated = true; + } + + next_index = index + 1; + if(arr[next_index] == 0) { + // find offset from [next_index] to next non-empty value + offset = 1; + while(next_index + offset < CELLS_COUNT && arr[next_index + offset] == 0) offset++; + + // if all remaining values in this row are empty then go to next row + if(next_index + offset >= CELLS_COUNT) break; + + // if next cell is empty then shift cells [next_index+offset .. CELLS_COUNT-1] to [next_index] + was_moved = shift_array_to_left(CELLS_COUNT, arr, next_index, offset); + if(was_moved) move_result->is_table_updated = true; + } + + if(arr[index] == arr[next_index]) { + arr[index]++; + shift_array_to_left(CELLS_COUNT, arr, next_index, 1); + + move_result->is_table_updated = true; + move_result->points += 2 << (arr[index] - 1); + } + + index++; + } +} + +void move_left(uint8_t table[CELLS_COUNT][CELLS_COUNT], MoveResult* const move_result) { + for(uint8_t row_index = 0; row_index < CELLS_COUNT; row_index++) { + calculate_move_to_left(table[row_index], move_result); + } +} + +void move_right(uint8_t table[CELLS_COUNT][CELLS_COUNT], MoveResult* const move_result) { + for(uint8_t row_index = 0; row_index < CELLS_COUNT; row_index++) { + reverse_array(CELLS_COUNT, table[row_index]); + calculate_move_to_left(table[row_index], move_result); + reverse_array(CELLS_COUNT, table[row_index]); + } +} + +void move_up(uint8_t table[CELLS_COUNT][CELLS_COUNT], MoveResult* const move_result) { + uint8_t column[CELLS_COUNT]; + for(uint8_t column_index = 0; column_index < CELLS_COUNT; column_index++) { + get_column_from_array(CELLS_COUNT, CELLS_COUNT, table, column_index, column); + calculate_move_to_left(column, move_result); + set_column_to_array(CELLS_COUNT, CELLS_COUNT, table, column_index, column); + } +} + +void move_down(uint8_t table[CELLS_COUNT][CELLS_COUNT], MoveResult* const move_result) { + uint8_t column[CELLS_COUNT]; + for(uint8_t column_index = 0; column_index < CELLS_COUNT; column_index++) { + get_column_from_array(CELLS_COUNT, CELLS_COUNT, table, column_index, column); + reverse_array(CELLS_COUNT, column); + calculate_move_to_left(column, move_result); + reverse_array(CELLS_COUNT, column); + set_column_to_array(CELLS_COUNT, CELLS_COUNT, table, column_index, column); + } +} + +void add_new_digit(GameState* const game_state) { + uint8_t empty_cell_indexes[CELLS_COUNT * CELLS_COUNT]; + uint8_t empty_cells_count = 0; + for(u_int8_t i = 0; i < CELLS_COUNT; i++) { + for(u_int8_t j = 0; j < CELLS_COUNT; j++) { + if(game_state->table[i][j] == 0) { + empty_cell_indexes[empty_cells_count++] = i * CELLS_COUNT + j; + } + } + } + if(empty_cells_count == 0) return; + + int random_empty_cell_index = empty_cell_indexes[random() % empty_cells_count]; + u_int8_t row = random_empty_cell_index / CELLS_COUNT; + u_int8_t col = random_empty_cell_index % CELLS_COUNT; + + int random_value_percent = random() % 100; + game_state->table[row][col] = random_value_percent < 90 ? 1 : 2; // 90% for 2, 25% for 4 +} + +void init_game(GameState* const game_state, bool clear_top_score) { + memset(game_state->table, 0, CELLS_COUNT * CELLS_COUNT * sizeof(uint8_t)); + add_new_digit(game_state); + add_new_digit(game_state); + + game_state->score = 0; + game_state->moves = 0; + game_state->state = GameStateInProgress; + game_state->selected_menu_item = 0; + if(clear_top_score) { + game_state->top_score = 0; + } +} + +bool load_game(GameState* game_state) { + Storage* storage = furi_record_open(RECORD_STORAGE); + + File* file = storage_file_alloc(storage); + uint16_t bytes_readed = 0; + if(storage_file_open(file, SAVING_FILENAME, FSAM_READ, FSOM_OPEN_EXISTING)) { + bytes_readed = storage_file_read(file, game_state, sizeof(GameState)); + } + storage_file_close(file); + storage_file_free(file); + + furi_record_close(RECORD_STORAGE); + + return bytes_readed == sizeof(GameState); +} + +void save_game(GameState* game_state) { + Storage* storage = furi_record_open(RECORD_STORAGE); + + if(storage_common_stat(storage, SAVING_DIRECTORY, NULL) == FSE_NOT_EXIST) { + if(!storage_simply_mkdir(storage, SAVING_DIRECTORY)) { + return; + } + } + + File* file = storage_file_alloc(storage); + if(storage_file_open(file, SAVING_FILENAME, FSAM_WRITE, FSOM_CREATE_ALWAYS)) { + storage_file_write(file, game_state, sizeof(GameState)); + } + storage_file_close(file); + storage_file_free(file); + + furi_record_close(RECORD_STORAGE); +} + +bool is_game_over(GameState* const game_state) { + FURI_LOG_I("is_game_over", "====check===="); + + // check if table contains at least one empty cell + for(uint8_t i = 0; i < CELLS_COUNT; i++) { + for(u_int8_t j = 0; j < CELLS_COUNT; j++) { + if(game_state->table[i][j] == 0) { + FURI_LOG_I("is_game_over", "has empty cells"); + return false; + } + } + } + FURI_LOG_I("is_game_over", "no empty cells"); + + uint8_t tmp_table[CELLS_COUNT][CELLS_COUNT]; + MoveResult* tmp_move_result = malloc(sizeof(MoveResult)); + + // check if we can move to any direction + memcpy(tmp_table, game_state->table, CELLS_COUNT * CELLS_COUNT * sizeof(uint8_t)); + move_left(tmp_table, tmp_move_result); + if(tmp_move_result->is_table_updated) return false; + FURI_LOG_I("is_game_over", "can't move left"); + + memcpy(tmp_table, game_state->table, CELLS_COUNT * CELLS_COUNT * sizeof(uint8_t)); + move_right(tmp_table, tmp_move_result); + if(tmp_move_result->is_table_updated) return false; + FURI_LOG_I("is_game_over", "can't move right"); + + memcpy(tmp_table, game_state->table, CELLS_COUNT * CELLS_COUNT * sizeof(uint8_t)); + move_up(tmp_table, tmp_move_result); + if(tmp_move_result->is_table_updated) return false; + FURI_LOG_I("is_game_over", "can't move up"); + + memcpy(tmp_table, game_state->table, CELLS_COUNT * CELLS_COUNT * sizeof(uint8_t)); + move_down(tmp_table, tmp_move_result); + if(tmp_move_result->is_table_updated) return false; + FURI_LOG_I("is_game_over", "can't move down"); + + return true; +} + +int32_t game_2048_app() { + GameState* game_state = malloc(sizeof(GameState)); + if(!load_game(game_state)) { + init_game(game_state, true); + } + + MoveResult* move_result = malloc(sizeof(MoveResult)); + + ValueMutex state_mutex; + if(!init_mutex(&state_mutex, game_state, sizeof(GameState))) { + FURI_LOG_E("SnakeGame", "cannot create mutex\r\n"); + free(game_state); + return 255; + } + + InputEvent input; + FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(InputEvent)); + + ViewPort* view_port = view_port_alloc(); + view_port_draw_callback_set(view_port, draw_callback, &state_mutex); + view_port_input_callback_set(view_port, input_callback, event_queue); + + Gui* gui = furi_record_open(RECORD_GUI); + gui_add_view_port(gui, view_port, GuiLayerFullscreen); + + bool is_finished = false; + while(!is_finished) { + FuriStatus event_status = furi_message_queue_get(event_queue, &input, FuriWaitForever); + if(event_status == FuriStatusOk) { + // handle only press event, ignore repeat/release events + if(input.type != InputTypePress) continue; + + GameState* game_state = (GameState*)acquire_mutex_block(&state_mutex); + + switch(game_state->state) { + case GameStateMenu: + + switch(input.key) { + case InputKeyUp: + game_state->selected_menu_item--; + if(game_state->selected_menu_item < 0) { + game_state->selected_menu_item = MENU_ITEMS_COUNT - 1; + } + break; + case InputKeyDown: + game_state->selected_menu_item++; + if(game_state->selected_menu_item >= MENU_ITEMS_COUNT) { + game_state->selected_menu_item = 0; + } + break; + case InputKeyOk: + if(game_state->selected_menu_item == 1) { + // new game + init_game(game_state, false); + save_game(game_state); + } + game_state->state = GameStateInProgress; + break; + case InputKeyBack: + game_state->state = GameStateInProgress; + break; + default: + break; + } + + break; + case GameStateInProgress: + move_result->is_table_updated = false; + move_result->points = 0; + + switch(input.key) { + case InputKeyLeft: + move_left(game_state->table, move_result); + break; + case InputKeyRight: + move_right(game_state->table, move_result); + break; + case InputKeyUp: + move_up(game_state->table, move_result); + break; + case InputKeyDown: + move_down(game_state->table, move_result); + break; + case InputKeyOk: + game_state->state = GameStateMenu; + game_state->selected_menu_item = 0; + break; + case InputKeyBack: + save_game(game_state); + is_finished = true; + break; + case InputKeyMAX: + break; + } + game_state->score += move_result->points; + + if(move_result->is_table_updated) { + game_state->moves++; + add_new_digit(game_state); + } + + if(is_game_over(game_state)) { + game_state->state = GameStateGameOver; + if(game_state->score >= game_state->top_score) { + game_state->top_score = game_state->score; + } + } + + break; + case GameStateGameOver: + if(input.key == InputKeyOk || input.key == InputKeyBack) { + init_game(game_state, false); + save_game(game_state); + } + } + + view_port_update(view_port); + release_mutex(&state_mutex, game_state); + } + } + + gui_remove_view_port(gui, view_port); + furi_record_close(RECORD_GUI); + + view_port_free(view_port); + + furi_message_queue_free(event_queue); + + delete_mutex(&state_mutex); + + free(game_state); + free(move_result); + + return 0; +} diff --git a/applications/plugins/game_2048/game_2048.png b/applications/plugins/game_2048/game_2048.png new file mode 100644 index 0000000000000000000000000000000000000000..196e119c83b92229f85f626c98fc8fd99b685dd5 GIT binary patch literal 89 zcmeAS@N?(olHy`uVBq!ia0vp^AT}2xkYHHq`AGmsDR{a#hEy;n|EOnZ$+I?CV|C!e lCx*jonR#~0O6-zVc*Jo3Hea_&FOVx%f0t|zrXM2@%?^Jh6D%V z=Q_*<0DRD(7!maFLx;58hupA#fd<nzLKipkTf}KuJ+z^y)Tw_`(+zP9Ulg6$~Kdh$Lk0aUJC!Cp&Ey3n1b3m~Se9JwY3|U^75&;ttDnzCwAI(()}|S=Fc|=>*8H;uG5slbb{u(!{>Y zeQr9rG%27dRHoM8Aop{C3$wtVmquoljrM9HBlR4AXJWshtlomcL1Iq1J?5OA890lg zBDzE)6{EgfzIUGQb^DG``dIRcyf2=Y!#_(1I0#;cXV- z&4Zvi4Kv*OqDI5+Lkz-0Ui}{~;%CqyOXsIV4=f^O;gD|YiP!Q@83^+}p%n%lB0QCd zsPC96LikIoFvamrSQtDU`}W!*&wk}S&%evBys?pYehG5ai~ozan9K@QrAUVxMi(VF zk4R_?94WGCE=ra@kqFNjzG*sEPcX88tNjVrfc3Q$N9>*%V`hgGi zQ(`&;e_pqah6?I+wLOG9<|Xn8JVI;#jvjM&YgYWor5UNUsr6set^^>2#@d=K=~Yyc z;Sr`I#NFV{ox^y3kJ`F@KPjQINMBopKOAa|4rqDrTI+ff&nj79rbn3s&5d-&er_ca zrrkrn*8K||ecpF`{Jc+4K-nRbaL?>7Oa@kz;sAd+Hhg2`Y44m(ojWxuG{guj~z>i9%N#+%bm%HjzBU9}>4U+hyT!%K&zobWQ{)6v&A`KFh@9 z`C~S`s;iJRcVIY118r~1Z&m!soe7l~yBie4rP@8dL}tc3Sa-~9G>%R;O;#imI~!0lwkq3*x)*^h*Ai69;sT~rVAnG$ zC^OW_XAHO74*p|J&ac8{?yr&he9Fs6G1l+9x*)tfCDSFjNqjO{}(1Du#>wVpYTWWz;iylDE|(QDKRAsGV9d zsFqfI$@-oYW_>WW-Yx*AG;)#ObrtPJL$r3jf3$fFpoXaHx!*gXnJ})Foy|eLj`mX} zx+_+Yft6oapePpD)!8qA4W>t??SltejwX^p7akR7v|)xH`eK0g#=_$KR&z_CM=tJh z-!96OYV_DR^XsX6({D9N;z>JVz?rLlV}gDN%%-d8U&IMR7T2&2~YxefdGnWG?=VtHfs~e-bORMb>{xqd3W}G ze_zk<`MuA6m7ATpX4S@30Dv`FAExgGU1ysKR z!1u&S1(v6wqn$~$PhP(zY@JxdgfN{7!eRk<|79S~9dc0~D%dh!gZ(xn6P$th81Gjo zLnP5l(!9Q(pfn1aazqS*XaEvi0nWcRYoZ9%+?^DNgZyM=JC*49p$a)gj-P{7BO_ZEXVF zTG1wQqX)u)_>CZDsxvg!-?3vz`OG2J*ZG=-YAYEk!h>G2uT`G!6y6(^zUm;Sd)Wut z9zH(gw@y;;U$!JG==*F)d*t&@JS%!KG`9qb*Ur{_X4Azqd*B~80bqy-Hen0~T0?`V z!MDEgV7T~by@C58u)Ru^wPr)BMVJ$H+(`E_|H=fQDmvIBBDCrwyXw?S$ttWWhAYjp-%Rg$yL)@loy10yZ}1Ob^FN8142(m`Y$)BUBO>4}>_Y#*Mrxe7 zAD(4S>3e1?q|M972mx_ykmAW5;fMQpZpt*)v>k8ai^i74QEK5&gJr+vExeT4m7PG0 z7Lj$pwFah%QQ*)%IhZP}sao*YBQ`f@&*s}I>}gSyp$tEUM4jmV6iD6(7K@lqToSZ& z(?&QKov886e_K_UVDUJq>nFZrirG06l%94ysskzH-o{Q)H!K(6!%mPhT!2rLihB!s zbwr6^i74_#-qH`Z-X;+u)(bedE3^51LJH^W1CxCutCIFjy{c}!`JBV=5><9S*>vTc z|B&ajU4Y$Z6c@I=B6fy7FLZnd407a!oARgE?c?_AnRNq_dH$7? zGu~@Okvx2U++>TnjW{D0r*r}(kY*59&NK2N)D4B1PQOs7&%SOtpm4@9HL~VwfSE z5f!IhS254#!+VN0trSNGF697onBowJKeu01X2_ge%q+ldp7^@3-hTu~d}{?m{INIW zuq47D%QGR@TxmKNe$`59-CNqwM@=U+L!ND}(B9*0gDk?(FuD-JhU!La{vsFUcUOVi zA_9GH?t=xc%2Mhzdx7gAmxR+GN*QV3$r~++byaeG89qAS?&$K5P99+ZaCTi#9$>IW zWftZflbYsATTG-h9#9jdJo(K;5q&L0hRq8$D!9f^q{_dzlPUV?BsB@TvCvbA^Qkqw z;_5pKTh64t3Gzu{#)WpeQF_!|@w33Qlf+^#SbJPbZ0Q^*T)ubKfXe^HEs6yBg!Bev za0`*)Gt-#+nl>?UyMFsWpl?RnlWG&9$vQ!RLM@vizNV-=dVMK_G=95jy>|j)dLfD= z9lyJ$*ZjXiGD-HTbXsrT@;HA=Fuhhwmf~0!1<)^&%!3LZ(B6Q;c*8$UP+ZKH#nlmi P79eX^c6!_UhrjqQzp9wl literal 0 HcmV?d00001 From 566e80abf648c05d046cd4aa90730e173fd4dd70 Mon Sep 17 00:00:00 2001 From: Skorpionm <85568270+Skorpionm@users.noreply.github.com> Date: Fri, 23 Dec 2022 12:31:14 +0400 Subject: [PATCH 04/34] [FL-3063] SubGhz: fix start navigation (#2183) --- applications/main/subghz/views/receiver.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/applications/main/subghz/views/receiver.c b/applications/main/subghz/views/receiver.c index 999eef6a5..aaec2adda 100644 --- a/applications/main/subghz/views/receiver.c +++ b/applications/main/subghz/views/receiver.c @@ -309,7 +309,8 @@ bool subghz_view_receiver_input(InputEvent* event, void* context) { subghz_receiver->view, SubGhzViewReceiverModel * model, { - if(model->idx != model->history_item - 1) model->idx++; + if((model->history_item != 0) && (model->idx != model->history_item - 1)) + model->idx++; }, true); } else if(event->key == InputKeyLeft && event->type == InputTypeShort) { From 10580b51171d34c6993cfcd8151fb6a503ef8683 Mon Sep 17 00:00:00 2001 From: valentinegb Date: Fri, 23 Dec 2022 01:13:13 -0800 Subject: [PATCH 05/34] Add Edifier R1850DB signals to audio.ir (#2168) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: あく --- assets/resources/infrared/assets/audio.ir | 43 +++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/assets/resources/infrared/assets/audio.ir b/assets/resources/infrared/assets/audio.ir index dec6c05a9..bcf035df1 100644 --- a/assets/resources/infrared/assets/audio.ir +++ b/assets/resources/infrared/assets/audio.ir @@ -242,3 +242,46 @@ type: raw frequency: 38000 duty_cycle: 0.330000 data: 4639 4406 586 418 585 393 559 447 557 447 557 1477 532 1477 532 472 532 472 532 1476 533 1476 532 1476 532 1476 532 473 555 449 555 449 555 449 555 4455 554 450 554 450 554 450 554 450 554 1455 554 450 554 450 554 450 554 1455 554 1455 553 1455 553 450 554 450 554 1455 554 1455 554 1455 554 450 554 450 554 450 554 1455 554 55454 4557 4458 555 449 555 449 555 450 554 450 554 1455 554 1455 553 450 554 450 554 1455 554 1455 554 1454 554 1455 554 450 554 450 554 450 555 450 554 4455 553 450 554 450 554 450 554 450 554 1455 554 450 554 450 554 450 554 1455 554 1455 554 1455 553 450 554 450 554 1455 554 1455 553 1455 554 450 554 450 554 450 554 1455 554 +# +# Model: Edifier R1850DB +name: Power +type: parsed +protocol: NECext +address: 10 E7 00 00 +command: 46 B9 00 00 +# +name: Play +type: parsed +protocol: NECext +address: 10 E7 00 00 +command: 5E A1 00 00 +# +name: Vol_up +type: parsed +protocol: NECext +address: 10 E7 00 00 +command: 05 FA 00 00 +# +name: Vol_dn +type: parsed +protocol: NECext +address: 10 E7 00 00 +command: 49 B6 00 00 +# +name: Next +type: parsed +protocol: NECext +address: 10 E7 00 00 +command: 02 FD 00 00 +# +name: Prev +type: parsed +protocol: NECext +address: 10 E7 00 00 +command: 1E E1 00 00 +# +name: Mute +type: parsed +protocol: NECext +address: 10 E7 00 00 +command: 41 BE 00 00 From 4d9ecbacaeacf6ae41acf819cbfe417e2d36667b Mon Sep 17 00:00:00 2001 From: gid9798 <30450294+gid9798@users.noreply.github.com> Date: Fri, 23 Dec 2022 12:25:20 +0300 Subject: [PATCH 06/34] Barcode generator: add EAN-13 support --- .../barcode_generator/barcode_generator.c | 172 +++++++++++++----- .../barcode_generator/barcode_generator.h | 31 +++- 2 files changed, 155 insertions(+), 48 deletions(-) diff --git a/applications/plugins/barcode_generator/barcode_generator.c b/applications/plugins/barcode_generator/barcode_generator.c index 776862531..a07a12e6a 100644 --- a/applications/plugins/barcode_generator/barcode_generator.c +++ b/applications/plugins/barcode_generator/barcode_generator.c @@ -12,40 +12,88 @@ void init_types() { upcA->name = "UPC-A"; upcA->numberOfDigits = 12; upcA->startPos = 19; + upcA->bartype = BarTypeUPCA; barcodeTypes[0] = upcA; BarcodeType* ean8 = malloc(sizeof(BarcodeType)); ean8->name = "EAN-8"; ean8->numberOfDigits = 8; ean8->startPos = 33; + ean8->bartype = BarTypeEAN8; barcodeTypes[1] = ean8; + + BarcodeType* ean13 = malloc(sizeof(BarcodeType)); + ean13->name = "EAN-13"; + ean13->numberOfDigits = 13; + ean13->startPos = 19; + ean13->bartype = BarTypeEAN13; + barcodeTypes[2] = ean13; } -void draw_digit(Canvas* canvas, int digit, bool rightHand, int startingPosition) { +void draw_digit( + Canvas* canvas, + int digit, + BarEncodingType rightHand, + int startingPosition, + bool drawlines) { char digitStr[2]; snprintf(digitStr, 2, "%u", digit); canvas_set_color(canvas, ColorBlack); canvas_draw_str( canvas, startingPosition, BARCODE_Y_START + BARCODE_HEIGHT + BARCODE_TEXT_OFFSET, digitStr); - if(rightHand) { - canvas_set_color(canvas, ColorBlack); - } else { - canvas_set_color(canvas, ColorWhite); - } - int count = 0; - for(int i = 0; i < 4; i++) { - canvas_draw_box( - canvas, startingPosition + count, BARCODE_Y_START, DIGITS[digit][i], BARCODE_HEIGHT); - canvas_invert_color(canvas); - count += DIGITS[digit][i]; + if(drawlines) { + switch(rightHand) { + case BarEncodingTypeLeft: + case BarEncodingTypeRight: + canvas_set_color( + canvas, (rightHand == BarEncodingTypeRight) ? ColorBlack : ColorWhite); + //int count = 0; + for(int i = 0; i < 4; i++) { + canvas_draw_box( + canvas, startingPosition, BARCODE_Y_START, DIGITS[digit][i], BARCODE_HEIGHT); + canvas_invert_color(canvas); + startingPosition += DIGITS[digit][i]; + } + break; + case BarEncodingTypeG: + canvas_set_color(canvas, ColorWhite); + //int count = 0; + for(int i = 3; i >= 0; i--) { + canvas_draw_box( + canvas, startingPosition, BARCODE_Y_START, DIGITS[digit][i], BARCODE_HEIGHT); + canvas_invert_color(canvas); + startingPosition += DIGITS[digit][i]; + } + break; + default: + break; + } } } int get_digit_position(int index, BarcodeType* type) { - int pos = type->startPos + index * 7; - if(index >= type->numberOfDigits / 2) { - pos += 5; + int pos = 0; + switch(type->bartype) { + case BarTypeEAN8: + case BarTypeUPCA: + pos = type->startPos + index * 7; + if(index >= type->numberOfDigits / 2) { + pos += 5; + } + break; + case BarTypeEAN13: + if(index == 0) + pos = type->startPos - 10; + else { + pos = type->startPos + (index - 1) * 7; + if((index - 1) >= type->numberOfDigits / 2) { + pos += 5; + } + } + break; + default: + break; } return pos; } @@ -54,18 +102,30 @@ int get_menu_text_location(int index) { return 20 + 10 * index; } +int get_barcode_max_index(PluginState* plugin_state) { + return plugin_state->doParityCalculation ? + barcodeTypes[plugin_state->barcodeTypeIndex]->numberOfDigits - 1 : + barcodeTypes[plugin_state->barcodeTypeIndex]->numberOfDigits; +} + int calculate_check_digit(PluginState* plugin_state, BarcodeType* type) { int checkDigit = 0; + int checkDigitOdd = 0; + int checkDigitEven = 0; //add all odd positions. Confusing because 0index for(int i = 0; i < type->numberOfDigits - 1; i += 2) { - checkDigit += plugin_state->barcodeNumeral[i]; + checkDigitOdd += plugin_state->barcodeNumeral[i]; } - checkDigit = checkDigit * 3; //times 3 - //add all even positions to above. Confusing because 0index for(int i = 1; i < type->numberOfDigits - 1; i += 2) { - checkDigit += plugin_state->barcodeNumeral[i]; + checkDigitEven += plugin_state->barcodeNumeral[i]; + } + + if(type->bartype == BarTypeEAN13) { + checkDigit = checkDigitEven * 3 + checkDigitOdd; + } else { + checkDigit = checkDigitOdd * 3 + checkDigitEven; } checkDigit = checkDigit % 10; //mod 10 @@ -103,34 +163,57 @@ static void render_callback(Canvas* const canvas, void* ctx) { AlignCenter, (barcodeTypes[plugin_state->barcodeTypeIndex])->name); canvas_draw_disc( - canvas, 40, get_menu_text_location(plugin_state->menuIndex) - 1, 2); //draw menu cursor + canvas, + 40, + get_menu_text_location(plugin_state->menuIndex) - 1, + 2); //draw menu cursor } else { BarcodeType* type = barcodeTypes[plugin_state->barcodeTypeIndex]; + //start saftey canvas_set_color(canvas, ColorBlack); canvas_draw_box(canvas, type->startPos - 3, BARCODE_Y_START, 1, BARCODE_HEIGHT + 2); - canvas_draw_box( - canvas, - (type->startPos - 1), - BARCODE_Y_START, - 1, - BARCODE_HEIGHT + 2); //start saftey + canvas_draw_box(canvas, (type->startPos - 1), BARCODE_Y_START, 1, BARCODE_HEIGHT + 2); - for(int index = 0; index < type->numberOfDigits; index++) { - bool isOnRight = false; - if(index >= type->numberOfDigits / 2) { - isOnRight = true; - } - if((index == type->numberOfDigits - 1) && - (plugin_state->doParityCalculation)) { //calculate the check digit - int checkDigit = calculate_check_digit(plugin_state, type); - plugin_state->barcodeNumeral[type->numberOfDigits - 1] = checkDigit; + int startpos = 0; + int endpos = type->numberOfDigits; + if(type->bartype == BarTypeEAN13) { + startpos++; + draw_digit( + canvas, + plugin_state->barcodeNumeral[0], + BarEncodingTypeRight, + get_digit_position(0, barcodeTypes[plugin_state->barcodeTypeIndex]), + false); + } + if(plugin_state->doParityCalculation) { //calculate the check digit + plugin_state->barcodeNumeral[type->numberOfDigits - 1] = + calculate_check_digit(plugin_state, type); + } + for(int index = startpos; index < endpos; index++) { + BarEncodingType barEncodingType = BarEncodingTypeLeft; + if(type->bartype == BarTypeEAN13) { + if(index - 1 >= (type->numberOfDigits - 1) / 2) { + barEncodingType = BarEncodingTypeRight; + } else { + barEncodingType = + (FURI_BIT(EAN13ENCODE[plugin_state->barcodeNumeral[0]], index - 1)) ? + BarEncodingTypeG : + BarEncodingTypeLeft; + } + } else { + if(index >= type->numberOfDigits / 2) { + barEncodingType = BarEncodingTypeRight; + } } + int digitPosition = get_digit_position(index, barcodeTypes[plugin_state->barcodeTypeIndex]); - draw_digit(canvas, plugin_state->barcodeNumeral[index], isOnRight, digitPosition); + draw_digit( + canvas, plugin_state->barcodeNumeral[index], barEncodingType, digitPosition, true); } + //central separator canvas_set_color(canvas, ColorBlack); canvas_draw_box(canvas, 62, BARCODE_Y_START, 1, BARCODE_HEIGHT + 2); canvas_draw_box(canvas, 64, BARCODE_Y_START, 1, BARCODE_HEIGHT + 2); @@ -147,15 +230,11 @@ static void render_callback(Canvas* const canvas, void* ctx) { 1); //draw editing cursor } + //end safety int endSafetyPosition = get_digit_position(type->numberOfDigits - 1, type) + 7; canvas_set_color(canvas, ColorBlack); canvas_draw_box(canvas, endSafetyPosition, BARCODE_Y_START, 1, BARCODE_HEIGHT + 2); - canvas_draw_box( - canvas, - (endSafetyPosition + 2), - BARCODE_Y_START, - 1, - BARCODE_HEIGHT + 2); //end safety + canvas_draw_box(canvas, (endSafetyPosition + 2), BARCODE_Y_START, 1, BARCODE_HEIGHT + 2); } release_mutex((ValueMutex*)ctx, plugin_state); @@ -169,7 +248,7 @@ static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queu } static void barcode_generator_state_init(PluginState* const plugin_state) { - for(int i = 0; i < 12; ++i) { + for(int i = 0; i < BARCODE_MAX_LENS; ++i) { plugin_state->barcodeNumeral[i] = i % 10; } plugin_state->editingIndex = 0; @@ -194,9 +273,7 @@ static bool handle_key_press_view(InputKey key, PluginState* plugin_state) { } static bool handle_key_press_edit(InputKey key, PluginState* plugin_state) { - int barcodeMaxIndex = plugin_state->doParityCalculation ? - barcodeTypes[plugin_state->barcodeTypeIndex]->numberOfDigits - 1 : - barcodeTypes[plugin_state->barcodeTypeIndex]->numberOfDigits; + int barcodeMaxIndex = get_barcode_max_index(plugin_state); switch(key) { case InputKeyUp: @@ -286,6 +363,9 @@ static bool handle_key_press_menu(InputKey key, PluginState* plugin_state) { default: break; } + int barcodeMaxIndex = get_barcode_max_index(plugin_state); + if(plugin_state->editingIndex >= barcodeMaxIndex) + plugin_state->editingIndex = barcodeMaxIndex - 1; return true; } diff --git a/applications/plugins/barcode_generator/barcode_generator.h b/applications/plugins/barcode_generator/barcode_generator.h index 7e1a078e8..1b5ff9e15 100644 --- a/applications/plugins/barcode_generator/barcode_generator.h +++ b/applications/plugins/barcode_generator/barcode_generator.h @@ -1,7 +1,8 @@ #define BARCODE_HEIGHT 50 #define BARCODE_Y_START 3 #define BARCODE_TEXT_OFFSET 9 -#define NUMBER_OF_BARCODE_TYPES 2 +#define BARCODE_MAX_LENS 13 +#define NUMBER_OF_BARCODE_TYPES 3 #define MENU_INDEX_VIEW 0 #define MENU_INDEX_EDIT 1 #define MENU_INDEX_PARITY 2 @@ -23,14 +24,27 @@ typedef enum { MenuMode, } Mode; +typedef enum { + BarEncodingTypeLeft, + BarEncodingTypeRight, + BarEncodingTypeG, +} BarEncodingType; + +typedef enum { + BarTypeEAN8, + BarTypeUPCA, + BarTypeEAN13, +} BarType; + typedef struct { char* name; int numberOfDigits; int startPos; + BarType bartype; } BarcodeType; typedef struct { - int barcodeNumeral[12]; //The current barcode number + int barcodeNumeral[BARCODE_MAX_LENS]; //The current barcode number int editingIndex; //The index of the editing symbol int menuIndex; //The index of the menu cursor Mode mode; //View, edit or menu @@ -50,3 +64,16 @@ static const int DIGITS[10][4] = { {1, 2, 1, 3}, {3, 1, 1, 2}, }; + +static const uint8_t EAN13ENCODE[10] = { + 0b000000, + 0b110100, + 0b101100, + 0b011100, + 0b110010, + 0b100110, + 0b001110, + 0b101010, + 0b011010, + 0b010110, +}; \ No newline at end of file From 2f96fad7c29b994da14100d7fe2ae6af804a7ed5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=82=E3=81=8F?= Date: Fri, 23 Dec 2022 18:46:11 +0900 Subject: [PATCH 07/34] [FL-3026] Documentation: subghz file formats (#2175) Co-authored-by: hedger --- .../file_formats/SubGhzFileFormats.md | 270 ++++++++++++++++++ 1 file changed, 270 insertions(+) create mode 100644 documentation/file_formats/SubGhzFileFormats.md diff --git a/documentation/file_formats/SubGhzFileFormats.md b/documentation/file_formats/SubGhzFileFormats.md new file mode 100644 index 000000000..ae80e6e0e --- /dev/null +++ b/documentation/file_formats/SubGhzFileFormats.md @@ -0,0 +1,270 @@ +# File Formats for Flipper's SubGhz Subsystem + +## `.sub` File Format + +Flipper uses `.sub` files to store SubGhz transmissions. They are text files in Flipper File Format. `.sub` files can contain either a SubGhz Key with a certain protocol or SubGhz RAW data. + +A `.sub` files consist of 3 parts: + +- **header**: contains file type, version, and frequency +- **preset information**: preset type and, in case of a custom preset, transceiver configuration data +- **protocol and its data**: contains protocol name and its specific data, such as key, bit length, etc., or RAW data + +Flipper's SubGhz subsystem uses presets to configure radio transceiver. Presets are used to configure modulation, bandwidth, filters, etc. There are several presets available in stock firmware, and there is a way to create custom presets. See [SubGhz Presets](#adding-a-custom-preset) for more details. + +## Header Format + +Header is a mandatory part of `.sub` file. It contains file type, version, and frequency. + +| Field | Type | Description | +| --- | --- | --- | +| `Filetype` | string | Filetype of subghz file format, must be `Flipper SubGhz Key File` | +| `Version` | uint | Version of subghz file format, current version is 1 | +| `Frequency` | uint | Frequency in Hertz | + +## Preset Information + +Preset information is a mandatory part of `.sub` file. It contains preset type and, in case of custom preset, transceiver configuration data. + +When using one of the standard presets, only `Preset` field is required. When using custom preset, `Custom_preset_module` and `Custom_preset_data` fields are required. + +| Field | Description | +| --- | --- | +| `Preset` | Radio preset name (configures modulation, bandwidth, filters, etc.). When using a custom preset, must be `FuriHalSubGhzPresetCustom` | +| `Custom_preset_module` | Transceiver identifier, `CC1101` for Flipper Zero | +| `Custom_preset_data` | Transceiver configuration data | + +Built-in presets: + +- `FuriHalSubGhzPresetOok270Async` - On/Off Keying, 270kHz bandwidth, async(IO throw GP0) +- `FuriHalSubGhzPresetOok650Async` - On/Off Keying, 650kHz bandwidth, async(IO throw GP0) +- `FuriHalSubGhzPreset2FSKDev238Async` - 2 Frequency Shift Keying, deviation 2kHz, 270kHz bandwidth, async(IO throw GP0) +- `FuriHalSubGhzPreset2FSKDev476Async` - 2 Frequency Shift Keying, deviation 47kHz, 270kHz bandwidth, async(IO throw GP0) + +### Transceiver Configuration Data + +Transceiver configuration data is a string of bytes, encoded in hex format, separated by spaces. For CC1101 data structure is: `XX YY XX YY .. 00 00 ZZ ZZ ZZ ZZ ZZ ZZ ZZ ZZ`, where: + +- XX holds register address, +- YY contains register value, +- 00 00: marks register block end, +- `ZZ ZZ ZZ ZZ ZZ ZZ ZZ ZZ`: 8 byte PA table (Power amplifier ramp table). + +More details can be found in [CC1101 datasheet](https://www.ti.com/lit/ds/symlink/cc1101.pdf) and `furi_hal_subghz` code. + +## File Data + +`.sub` file data section contains either key data — protocol name and its specific data, bit length, etc., or RAW data — an array of signal timings, recorded without any protocol-specific processing. + +### Key Files + +`.sub` files with key data files contain protocol name and its specific data, such as key value, bit length, etc. +Check out protocol registry for full list of supported protocol names. + +Example of key data block in Princeton format: + +``` +... +Protocol: Princeton +Bit: 24 +Key: 00 00 00 00 00 95 D5 D4 +TE: 400 +``` + +Protocol-specific fields in this example: + +| Field | Description | +| --- | --- | +| `Bit` | Princeton payload length, in bits | +| `Key` | Princeton payload data | +| `TE` | Princeton quantization interval | + +This file may contain additional fields, more details on available fields can be found in subghz protocols library. + +### RAW Files + +RAW `.sub` files contain raw signal data that is not processed through protocol-specific decoding. These files are useful for testing purposes, or for sending data that is not supported by any known protocol. + +For RAW files, 2 fields are required: + + * `Protocol`, must be `RAW` + * `RAW_Data`, contains an array of timings, specified in micro seconds. Values must be non-zero, start with a positive number, and interleaved (change sign with each value). Up to 512 values per line. Can be specified multiple times to store multiple lines of data. + +Example of RAW data: + + Protocol: RAW + RAW_Data: 29262 361 -68 2635 -66 24113 -66 11 ... + + +Long payload not fitting into internal memory buffer and consisting of short duration timings (<10us) may not be read fast enough from SD Card. That might cause signal transmission to stop before reaching the end of the payload. Ensure that your SD Card has good performance before transmitting long or complex RAW payloads. + + +## File Examples + +### Key File, Standard Preset + + Filetype: Flipper SubGhz Key File + Version: 1 + Frequency: 433920000 + Preset: FuriHalSubGhzPresetOok650Async + Protocol: Princeton + Bit: 24 + Key: 00 00 00 00 00 95 D5 D4 + TE: 400 + + +### Key File, Custom Preset + + Filetype: Flipper SubGhz Key File + Version: 1 + Frequency: 433920000 + Preset: FuriHalSubGhzPresetCustom + Custom_preset_module: CC1101 + Custom_preset_data: 02 0D 03 07 08 32 0B 06 14 00 13 00 12 30 11 32 10 17 18 18 19 18 1D 91 1C 00 1B 07 20 FB 22 11 21 B6 00 00 00 C0 00 00 00 00 00 00 + Protocol: Princeton + Bit: 24 + Key: 00 00 00 00 00 95 D5 D4 + TE: 400 + +### RAW File, Standard Preset + + Filetype: Flipper SubGhz RAW File + Version: 1 + Frequency: 433920000 + Preset: FuriHalSubGhzPresetOok650Async + Protocol: RAW + RAW_Data: 29262 361 -68 2635 -66 24113 -66 11 ... + RAW_Data: -424 205 -412 159 -412 381 -240 181 ... + RAW_Data: -1448 361 -17056 131 -134 233 -1462 131 -166 953 -100 ... + +### RAW File, Custom Preset + + Filetype: Flipper SubGhz RAW File + Version: 1 + Frequency: 433920000 + Preset: FuriHalSubGhzPresetCustom + Custom_preset_module: CC1101 + Сustom_preset_data: 02 0D 03 07 08 32 0B 06 14 00 13 00 12 30 11 32 10 17 18 18 19 18 1D 91 1C 00 1B 07 20 FB 22 11 21 B6 00 00 00 C0 00 00 00 00 00 00 + Protocol: RAW + RAW_Data: 29262 361 -68 2635 -66 24113 -66 11 ... + RAW_Data: -424 205 -412 159 -412 381 -240 181 ... + RAW_Data: -1448 361 -17056 131 -134 233 -1462 131 -166 953 -100 ... + +# SubGhz Configuration Files + +SubGhz application provides support for adding extra radio presets and additional keys for decoding transmissions in certain protocols. + +## SubGhz `keeloq_mfcodes_user` File + +This file contains additional manufacturer keys for Keeloq protocol. It is used to decode Keeloq transmissions. +This file is loaded at subghz application start and is located at path `/ext/subghz/assets/keeloq_mfcodes_user`. + +### File Format + +File contains a header and a list of manufacturer keys. + +File header format: + +| Field | Type | Description | +| --- | | --- | +| `Filetype` | string | SubGhz Keystore file format, always `Flipper SubGhz Keystore File` | +| `Version` | uint | File format version, 0 | +| `Encryption` | uint | File encryption: for user-provided file, set to 0 (disabled) | + +Following the header, file contains a list of user-provided manufacture keys, one key per line. +For each key, a name and encryption method must be specified, according to comment in file header. More information can be found in keeloq decoder source code. + +### Example + + # to use manual settings and prevent them from being deleted on upgrade, rename *_user.example files to *_user + # for adding manufacture keys + # AABBCCDDEEFFAABB:X:NAME + # AABBCCDDEEFFAABB - man 64 bit + # X - encryption method: + # - 0 - iterates over both previous and man in direct and reverse byte sequence + # - 1 - Simple Learning + # - 2 - Normal_Learning + # - 3 - Secure_Learning + # - 4 - Magic_xor_type1 Learning + # + # NAME - name (string without spaces) max 64 characters long + Filetype: Flipper SubGhz Keystore File + Version: 0 + Encryption: 0 + AABBCCDDEEFFAABB:1:Test1 + AABBCCDDEEFFAABB:1:Test2 + + +## SubGhz `setting_user` File + +This file contains additional radio presets and frequencies for SubGhz application. It is used to add new presets and frequencies for existing presets. This file is be loaded on subghz application start and is located at path `/ext/subghz/assets/setting_user`. + +### File Format + +File contains a header, basic options, and optional lists of presets and frequencies. + +Header must contain following fields: + +- `Filetype`: SubGhz setting file format, must be `Flipper SubGhz Setting File`. +- `Version`: file format version, current is `1`. + +#### Basic Settings + +- `Add_standard_frequencies`: bool, flag indicating whether to load standard frequencies shipped with firmware. If set to `false`, only frequencies specified in this file will be used. +- `Default_frequency`: uint, default frequency used in SubGhz application. + +#### Adding More Frequencies + +- `Frequency`: uint — additional frequency for the subghz application frequency list. Used in Read and Read RAW. You can specify multiple frequencies, one per line. + +#### Adding More Hopper Frequencies + +- `Hopper_frequency`: uint — additional frequency for subghz application frequency hopping. Used in Frequency Analyzer. You can specify multiple frequencies, one per line. + +Repeating same frequency will cause Flipper to listen on this frequency more often. + +#### Adding a Custom Preset + +You can have as many presets as you want. Presets are embedded into `.sub` files, so another Flipper can load them directly from that file. +Each preset is defined by following fields: + +| Field | Description | +| --- | --- | +| `Custom_preset_name` | string, preset name that will be shown in SubGHz application | +| `Custom_preset_module` | string, transceiver identifier. Set to `CC1101` for Flipper Zero | +| `Custom_preset_data` | transceiver configuration data. See [Transceiver Configuration Data](#transceiver-configuration-data) for details. | + +### Example + +``` +# to use manual settings and prevent them from being deleted on upgrade, rename *_user.example files to *_user +Filetype: Flipper SubGhz Setting File +Version: 1 + +# Add Standard frequencies for your region +Add_standard_frequencies: true + +# Default Frequency: used as default for "Read" and "Read Raw" +Default_frequency: 433920000 + +# Frequencies used for "Read", "Read Raw" and "Frequency Analyzer" +Frequency: 300000000 +Frequency: 310000000 +Frequency: 320000000 + +# Frequencies used for hopping mode (keep this list small or flipper will miss signal) +Hopper_frequency: 300000000 +Hopper_frequency: 310000000 +Hopper_frequency: 310000000 + +# Custom preset +# format for CC1101 "Custom_preset_data:" XX YY XX YY .. 00 00 ZZ ZZ ZZ ZZ ZZ ZZ ZZ ZZ, where: XX-register, YY - register data, 00 00 - end load register, ZZ - 8 byte Pa table register + +#Custom_preset_name: AM_1 +Custom_preset_module: CC1101 +Custom_preset_data: 02 0D 03 07 08 32 0B 06 14 00 13 00 12 30 11 32 10 17 18 18 19 18 1D 91 1C 00 1B 07 20 FB 22 11 21 B6 00 00 00 C0 00 00 00 00 00 00 + +#Custom_preset_name: AM_2 +#Custom_preset_module: CC1101 +#Custom_preset_data: 02 0D 03 07 08 32 0B 06 14 00 13 00 12 30 11 32 10 17 18 18 19 18 1D 91 1C 00 1B 07 20 FB 22 11 21 B6 00 00 00 C0 00 00 00 00 00 00 +``` From dff73dfd388baffea5e57b9efbe8ad34e8da9bb0 Mon Sep 17 00:00:00 2001 From: Nikolay Minaylov Date: Fri, 23 Dec 2022 13:25:29 +0300 Subject: [PATCH 08/34] [FL-3037, FL-3038, FL-3039] File format docs: RFID, iButton, BadUSB (#2177) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: あく --- .../file_formats/BadUsbScriptFormat.md | 92 +++++++++++++++++++ .../file_formats/LfRfidFileFormat.md | 47 ++++++++++ .../file_formats/iButtonFileFormat.md | 27 ++++++ 3 files changed, 166 insertions(+) create mode 100644 documentation/file_formats/BadUsbScriptFormat.md create mode 100644 documentation/file_formats/LfRfidFileFormat.md create mode 100644 documentation/file_formats/iButtonFileFormat.md diff --git a/documentation/file_formats/BadUsbScriptFormat.md b/documentation/file_formats/BadUsbScriptFormat.md new file mode 100644 index 000000000..321eff246 --- /dev/null +++ b/documentation/file_formats/BadUsbScriptFormat.md @@ -0,0 +1,92 @@ +# Command syntax +BadUsb app uses extended Duckyscript syntax. It is compatible with classic USB Rubber Ducky 1.0 scripts, but provides some additional commands and features, such as custom USB ID, ALT+Numpad input method, SYSRQ command and more fuctional keys. +# Script file format +BadUsb app can execute only text scrips from .txt files, no compilation is required. Both `\n` and `\r\n` line endings are supported. Empty lines are allowed. You can use spaces ore tabs for line indentation. +# Command set +## Comment line +Just a single comment line. All text after REM command will be ignored by interpreter +|Command|Parameters|Notes| +|-|-|-| +|REM|Comment text|| + +## Delay +Pause script execution by defined time +|Command|Parameters|Notes| +|-|-|-| +|DELAY|Delay value in ms|Single delay| +|DEFAULT_DELAY|Delay value in ms|Add delay before every next command| +|DEFAULTDELAY|Delay value in ms|Same as DEFAULT_DELAY| + +## Special keys +|Command|Notes| +|-|-| +|DOWNARROW / DOWN|| +|LEFTARROW / LEFT|| +|RIGHTARROW / RIGHT|| +|UPARROW / UP|| +|ENTER|| +|DELETE|| +|BACKSPACE|| +|END|| +|HOME|| +|ESCAPE / ESC|| +|INSERT|| +|PAGEUP|| +|PAGEDOWN|| +|CAPSLOCK|| +|NUMLOCK|| +|SCROLLLOCK|| +|PRINTSCREEN|| +|BREAK|Pause/Break key| +|PAUSE|Pause/Break key| +|SPACE|| +|TAB|| +|MENU|Context menu key| +|APP|Same as MENU| +|Fx|F1-F12 keys| + +## Modifier keys +Can be combined with special key command or single character +|Command|Notes| +|-|-| +|CONTROL / CTRL|| +|SHIFT|| +|ALT|| +|WINDOWS / GUI|| +|CTRL-ALT|CTRL+ALT| +|CTRL-SHIFT|CTRL+SHIFT| +|ALT-SHIFT|ALT+SHIFT| +|ALT-GUI|ALT+WIN| +|GUI-SHIFT|WIN+SHIFT| +## String +|Command|Parameters|Notes| +|-|-|-| +|STRING|Text string|Print text string| +## Repeat +|Command|Parameters|Notes| +|-|-|-| +|REPEAT|Number of additional repeats|Repeat previous command| +## ALT+Numpad input +On Windows and some Linux systems you can print character by pressing ALT key and entering its code on numpad +|Command|Parameters|Notes| +|-|-|-| +|ALTCHAR|Character code|Print single character| +|ALTSTRING|Text string|Print text string using ALT+Numpad method| +|ALTCODE|Text string|Same as ALTSTRING, presents in some Duckyscript implementations| +## SysRq +Send [SysRq command](https://en.wikipedia.org/wiki/Magic_SysRq_key) +|Command|Parameters|Notes| +|-|-|-| +|SYSRQ|Single character|| +## USB device ID +You can set custom ID of Flipper USB HID device. ID command should be in the **first line** of script, it is executed before script run. + +|Command|Parameters|Notes| +|-|-|-| +|ID|VID:PID Manufacturer:Product|| + +Example: +`ID 1234:abcd Flipper Devices:Flipper Zero` + +VID and PID are hex codes and are mandatory, Manufacturer and Product are text strings and are optional. + diff --git a/documentation/file_formats/LfRfidFileFormat.md b/documentation/file_formats/LfRfidFileFormat.md new file mode 100644 index 000000000..715c49f6a --- /dev/null +++ b/documentation/file_formats/LfRfidFileFormat.md @@ -0,0 +1,47 @@ +# LF RFID key file format + +## Example +``` +Filetype: Flipper RFID key +Version: 1 +Key type: EM4100 +Data: 01 23 45 67 89 +``` +## Description + +Filename extension: `.rfid` + +The file stores single RFID key of type defined by `Key type` parameter + +### Version history + +1. Initial version. + +### Format fields + +|Name|Description| +|-|-| +|Key type|Key protocol type| +|Data|Key data (HEX values)| + +### Supported key types + +|Type|Full name| +|-|-| +|EM4100|EM-Micro EM4100| +|H10301|HID H10301| +|Idteck|IDTECK| +|Indala26|Motorola Indala26| +|IOProxXSF|Kantech IOProxXSF| +|AWID|AWID| +|FDX-A|FECAVA FDX-A| +|FDX-B|ISO FDX-B| +|HIDProx|Generic HIDProx| +|HIDExt|Generic HIDExt| +|Pyramid|Farpointe Pyramid| +|Viking|Viking| +|Jablotron|Jablotron| +|Paradox|Paradox| +|PAC/Stanley|PAC/Stanley| +|Keri|Keri| +|Gallagher|Gallagher| \ No newline at end of file diff --git a/documentation/file_formats/iButtonFileFormat.md b/documentation/file_formats/iButtonFileFormat.md new file mode 100644 index 000000000..a5d41b495 --- /dev/null +++ b/documentation/file_formats/iButtonFileFormat.md @@ -0,0 +1,27 @@ +# iButton key file format + +## Example +``` +Filetype: Flipper iButton key +Version: 1 +# Key type can be Cyfral, Dallas or Metakom +Key type: Dallas +# Data size for Cyfral is 2, for Metakom is 4, for Dallas is 8 +Data: 12 34 56 78 9A BC DE F0 +``` +## Description + +Filename extension: `.ibtn` + +The file stores single iButton key of type defined by `Key type` parameter + +### Version history + +1. Initial version. + +### Format fields + +|Name|Description| +|-|-| +|Key type|Currently supported: Cyfral, Dallas, Metakom| +|Data|Key data (HEX values)| \ No newline at end of file From b0970953b9e29065a809e0a16abe960397fa373a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=82=E3=81=8F?= Date: Fri, 23 Dec 2022 22:46:35 +0900 Subject: [PATCH 09/34] [FL-3067] WeatherStation: fix incorrect history index increment (#2186) --- .../plugins/weather_station/views/weather_station_receiver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/applications/plugins/weather_station/views/weather_station_receiver.c b/applications/plugins/weather_station/views/weather_station_receiver.c index 124065e32..de5d7b1a3 100644 --- a/applications/plugins/weather_station/views/weather_station_receiver.c +++ b/applications/plugins/weather_station/views/weather_station_receiver.c @@ -303,7 +303,7 @@ bool ws_view_receiver_input(InputEvent* event, void* context) { ws_receiver->view, WSReceiverModel * model, { - if(model->idx != model->history_item - 1) model->idx++; + if(model->history_item && model->idx != model->history_item - 1) model->idx++; }, true); } else if(event->key == InputKeyLeft && event->type == InputTypeShort) { From c2cb14834d5ef65c36ffcc00ae6bc6ffaf69ca02 Mon Sep 17 00:00:00 2001 From: Sergey Gavrilov Date: Sun, 25 Dec 2022 00:13:21 +1000 Subject: [PATCH 10/34] [FL-3062] Fix unit tests (#2180) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * SubGHZ unit test: fail if async_tx is not started * Memgr unit test: fix for multithreaded enviroment * Unit tests: fix failed_tests count * Unit tests: remove debug code * Double update test: increase flipper detection time Co-authored-by: あく --- .../debug/unit_tests/furi/furi_memmgr_test.c | 99 ++++--------------- .../debug/unit_tests/subghz/subghz_test.c | 5 +- applications/debug/unit_tests/test_index.c | 38 +++---- scripts/testing/await_flipper.py | 2 +- 4 files changed, 44 insertions(+), 100 deletions(-) diff --git a/applications/debug/unit_tests/furi/furi_memmgr_test.c b/applications/debug/unit_tests/furi/furi_memmgr_test.c index cf3848747..f7bc234a0 100644 --- a/applications/debug/unit_tests/furi/furi_memmgr_test.c +++ b/applications/debug/unit_tests/furi/furi_memmgr_test.c @@ -3,98 +3,37 @@ #include #include -// this test is not accurate, but gives a basic understanding -// that memory management is working fine - -// do not include memmgr.h here -// we also test that we are linking against stdlib -extern size_t memmgr_get_free_heap(void); -extern size_t memmgr_get_minimum_free_heap(void); - -// current heap management realization consume: -// X bytes after allocate and 0 bytes after allocate and free, -// where X = sizeof(void*) + sizeof(size_t), look to BlockLink_t -const size_t heap_overhead_max_size = sizeof(void*) + sizeof(size_t); - -bool heap_equal(size_t heap_size, size_t heap_size_old) { - // heap borders with overhead - const size_t heap_low = heap_size_old - heap_overhead_max_size; - const size_t heap_high = heap_size_old + heap_overhead_max_size; - - // not exact, so we must test it against bigger numbers than "overhead size" - const bool result = ((heap_size >= heap_low) && (heap_size <= heap_high)); - - // debug allocation info - if(!result) { - printf("\n(hl: %zu) <= (p: %zu) <= (hh: %zu)\n", heap_low, heap_size, heap_high); - } - - return result; -} - void test_furi_memmgr() { - size_t heap_size = 0; - size_t heap_size_old = 0; - const int alloc_size = 128; - - void* ptr = NULL; - void* original_ptr = NULL; - - // do not include furi memmgr.h case -#ifdef FURI_MEMMGR_GUARD - mu_fail("do not link against furi memmgr.h"); -#endif + void* ptr; // allocate memory case - heap_size_old = memmgr_get_free_heap(); - ptr = malloc(alloc_size); - heap_size = memmgr_get_free_heap(); - mu_assert_pointers_not_eq(ptr, NULL); - mu_assert(heap_equal(heap_size, heap_size_old - alloc_size), "allocate failed"); - - // free memory case - heap_size_old = memmgr_get_free_heap(); + ptr = malloc(100); + mu_check(ptr != NULL); + // test that memory is zero-initialized after allocation + for(int i = 0; i < 100; i++) { + mu_assert_int_eq(0, ((uint8_t*)ptr)[i]); + } free(ptr); - ptr = NULL; - heap_size = memmgr_get_free_heap(); - mu_assert(heap_equal(heap_size, heap_size_old + alloc_size), "free failed"); // reallocate memory case + ptr = malloc(100); + memset(ptr, 66, 100); + ptr = realloc(ptr, 200); + mu_check(ptr != NULL); - // get filled array with some data - original_ptr = malloc(alloc_size); - mu_assert_pointers_not_eq(original_ptr, NULL); - for(int i = 0; i < alloc_size; i++) { - *(unsigned char*)(original_ptr + i) = i; + // test that memory is really reallocated + for(int i = 0; i < 100; i++) { + mu_assert_int_eq(66, ((uint8_t*)ptr)[i]); } - // malloc array and copy data - ptr = malloc(alloc_size); - mu_assert_pointers_not_eq(ptr, NULL); - memcpy(ptr, original_ptr, alloc_size); - - // reallocate array - heap_size_old = memmgr_get_free_heap(); - ptr = realloc(ptr, alloc_size * 2); - heap_size = memmgr_get_free_heap(); - mu_assert(heap_equal(heap_size, heap_size_old - alloc_size), "reallocate failed"); - mu_assert_int_eq(memcmp(original_ptr, ptr, alloc_size), 0); - free(original_ptr); + // TODO: fix realloc to copy only old size, and write testcase that leftover of reallocated memory is zero-initialized free(ptr); // allocate and zero-initialize array (calloc) - original_ptr = malloc(alloc_size); - mu_assert_pointers_not_eq(original_ptr, NULL); - - for(int i = 0; i < alloc_size; i++) { - *(unsigned char*)(original_ptr + i) = 0; + ptr = calloc(100, 2); + mu_check(ptr != NULL); + for(int i = 0; i < 100 * 2; i++) { + mu_assert_int_eq(0, ((uint8_t*)ptr)[i]); } - heap_size_old = memmgr_get_free_heap(); - ptr = calloc(1, alloc_size); - heap_size = memmgr_get_free_heap(); - mu_assert(heap_equal(heap_size, heap_size_old - alloc_size), "callocate failed"); - mu_assert_int_eq(memcmp(original_ptr, ptr, alloc_size), 0); - - free(original_ptr); free(ptr); } diff --git a/applications/debug/unit_tests/subghz/subghz_test.c b/applications/debug/unit_tests/subghz/subghz_test.c index d954ddd94..cb89e1f02 100644 --- a/applications/debug/unit_tests/subghz/subghz_test.c +++ b/applications/debug/unit_tests/subghz/subghz_test.c @@ -318,7 +318,10 @@ bool subghz_hal_async_tx_test_run(SubGhzHalAsyncTxTestType type) { furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async); furi_hal_subghz_set_frequency_and_path(433920000); - furi_hal_subghz_start_async_tx(subghz_hal_async_tx_test_yield, &test); + if(!furi_hal_subghz_start_async_tx(subghz_hal_async_tx_test_yield, &test)) { + return false; + } + while(!furi_hal_subghz_is_async_tx_complete()) { furi_delay_ms(10); } diff --git a/applications/debug/unit_tests/test_index.c b/applications/debug/unit_tests/test_index.c index 36c2b4aef..5bc53c82e 100644 --- a/applications/debug/unit_tests/test_index.c +++ b/applications/debug/unit_tests/test_index.c @@ -73,7 +73,6 @@ void unit_tests_cli(Cli* cli, FuriString* args, void* context) { UNUSED(cli); UNUSED(args); UNUSED(context); - uint32_t failed_tests = 0; minunit_run = 0; minunit_assert = 0; minunit_fail = 0; @@ -99,32 +98,35 @@ void unit_tests_cli(Cli* cli, FuriString* args, void* context) { if(furi_string_size(args)) { if(furi_string_cmp_str(args, unit_tests[i].name) == 0) { - failed_tests += unit_tests[i].entry(); + unit_tests[i].entry(); } else { printf("Skipping %s\r\n", unit_tests[i].name); } } else { - failed_tests += unit_tests[i].entry(); + unit_tests[i].entry(); } } - printf("\r\nFailed tests: %lu\r\n", failed_tests); - // Time report - cycle_counter = (furi_get_tick() - cycle_counter); - printf("Consumed: %lu ms\r\n", cycle_counter); + if(minunit_run != 0) { + printf("\r\nFailed tests: %u\r\n", minunit_fail); - // Wait for tested services and apps to deallocate memory - furi_delay_ms(200); - uint32_t heap_after = memmgr_get_free_heap(); - printf("Leaked: %ld\r\n", heap_before - heap_after); + // Time report + cycle_counter = (furi_get_tick() - cycle_counter); + printf("Consumed: %lu ms\r\n", cycle_counter); - // Final Report - if(failed_tests == 0) { - notification_message(notification, &sequence_success); - printf("Status: PASSED\r\n"); - } else { - notification_message(notification, &sequence_error); - printf("Status: FAILED\r\n"); + // Wait for tested services and apps to deallocate memory + furi_delay_ms(200); + uint32_t heap_after = memmgr_get_free_heap(); + printf("Leaked: %ld\r\n", heap_before - heap_after); + + // Final Report + if(minunit_fail == 0) { + notification_message(notification, &sequence_success); + printf("Status: PASSED\r\n"); + } else { + notification_message(notification, &sequence_error); + printf("Status: FAILED\r\n"); + } } } diff --git a/scripts/testing/await_flipper.py b/scripts/testing/await_flipper.py index efae6765d..704d75a75 100755 --- a/scripts/testing/await_flipper.py +++ b/scripts/testing/await_flipper.py @@ -24,7 +24,7 @@ def flp_serial_by_name(flp_name): return "" -UPDATE_TIMEOUT = 60 +UPDATE_TIMEOUT = 60 * 4 # 4 minutes def main(): From ad3bff0b6793d351080e7cd0be6780d9caaa57fb Mon Sep 17 00:00:00 2001 From: Dmitry Eroshenko Date: Sun, 25 Dec 2022 01:44:04 +0700 Subject: [PATCH 11/34] Update ac.ir (#2184) Co-authored-by: Georgii Surkov <37121527+gsurkov@users.noreply.github.com> --- assets/resources/infrared/assets/ac.ir | 75 ++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/assets/resources/infrared/assets/ac.ir b/assets/resources/infrared/assets/ac.ir index af776706d..d9410a300 100644 --- a/assets/resources/infrared/assets/ac.ir +++ b/assets/resources/infrared/assets/ac.ir @@ -185,4 +185,79 @@ type: raw frequency: 38000 duty_cycle: 0.330000 data: 4403 4333 563 1615 563 528 561 1618 560 1618 560 531 558 561 538 1614 564 556 533 558 541 1611 557 562 537 555 534 1619 559 1618 560 558 541 1613 565 551 538 1614 564 1614 564 1614 564 1613 565 528 561 1617 561 1619 559 1617 561 557 532 535 564 528 561 533 566 1611 557 562 537 558 531 1619 559 1619 559 1619 559 559 540 553 536 557 532 561 538 557 532 559 540 553 536 557 532 1620 558 1620 558 1620 558 1620 558 1618 560 5188 4398 4346 561 1618 560 558 531 1621 557 1621 557 561 538 555 534 1619 559 561 538 553 536 1616 562 556 533 560 539 1614 564 1613 565 554 535 1619 559 557 532 1621 557 1620 558 1620 558 1620 558 560 539 1613 565 1615 563 1613 565 553 536 557 532 535 564 554 535 1618 560 558 531 564 535 1615 563 1615 563 1614 564 555 534 559 540 552 537 530 559 536 563 528 561 532 557 562 537 1615 563 1615 563 1614 564 1614 564 1616 562 +# +# Model: Sharp AH-X9VEW. Doesn't have heat function. +name: Dh +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 307 125509 3831 1867 489 482 491 1392 461 468 485 1397 456 489 464 1411 463 466 487 1397 456 488 465 1390 463 482 481 1402 462 1402 483 471 461 1412 462 468 485 1400 464 1401 484 1397 488 1395 458 471 461 485 457 1408 487 1393 460 485 457 473 459 486 456 474 489 1394 459 471 461 485 457 473 459 488 465 466 455 490 463 467 465 480 462 468 464 482 460 470 483 1399 465 464 457 488 465 465 488 1393 460 484 458 471 461 485 457 1415 459 1405 511 408 482 489 464 466 487 1377 456 489 464 481 461 469 463 482 460 470 462 483 459 470 462 484 458 472 460 485 457 473 459 487 455 474 489 1395 458 471 461 485 457 472 460 486 456 473 459 486 456 474 458 487 455 474 458 488 465 466 487 1396 457 487 434 496 457 488 433 496 457 489 432 497 466 479 432 498 465 480 431 499 464 482 439 490 463 482 460 1394 491 1389 485 1395 490 1392 461 468 464 482 460 469 484 1399 465 1399 465 480 462 483 491 77962 300 +# +name: Cool_hi +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 345 2685 478 1170 176 29680 3832 1891 465 481 482 1400 464 465 488 1395 458 470 483 1396 457 487 466 1406 458 471 492 1389 464 481 461 1411 463 1408 456 489 464 1407 457 473 490 1392 482 1383 481 1399 486 1396 458 462 459 497 456 1409 486 1394 459 459 483 473 459 487 455 474 489 1392 461 468 464 481 461 469 463 483 459 471 482 1398 487 1379 464 481 461 485 457 1416 458 487 466 1407 457 472 460 460 482 474 489 1393 460 469 463 483 459 471 461 485 457 1408 456 488 465 481 461 469 484 1381 462 483 459 486 456 473 459 487 455 474 458 487 455 475 457 489 464 467 465 481 461 1410 485 1380 484 1397 488 1392 461 483 459 471 461 485 457 473 459 486 456 474 458 488 454 476 456 490 463 467 465 481 461 1411 464 481 440 491 462 484 437 492 461 485 436 494 459 487 434 495 458 488 433 497 456 489 432 498 486 450 482 1408 467 1389 485 1394 480 1384 459 486 456 489 464 466 487 1393 460 485 457 1415 459 1406 510 +# +name: Cool_lo +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 181 11813 3819 1899 457 488 486 1421 433 472 491 1416 438 481 461 1417 437 482 492 1416 437 467 486 1419 435 485 457 1439 435 1403 461 483 480 1408 435 484 490 1416 438 1401 484 1395 490 1392 461 467 465 480 462 1427 458 1396 457 486 456 473 459 486 456 472 481 1426 438 466 466 480 462 467 465 480 462 467 465 479 463 1426 438 481 461 484 458 1438 436 1409 486 1378 465 480 462 483 459 471 482 1425 428 475 457 487 455 474 458 487 455 1434 430 489 464 481 461 468 485 1404 439 480 462 483 459 470 462 483 459 469 463 482 460 470 462 483 459 470 462 483 459 1437 458 1381 483 1395 490 1390 463 481 461 469 463 482 460 468 464 481 461 468 464 481 461 469 463 482 460 469 463 481 461 1434 430 474 458 486 456 473 459 486 456 473 459 486 456 473 459 486 456 473 459 485 457 472 460 485 489 449 462 1434 461 1378 486 1393 481 1397 519 400 479 476 456 489 464 1431 433 486 435 495 458 487 487 +# +name: Off +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 3826 1866 490 481 482 1382 461 484 490 1392 461 467 486 1396 457 471 482 1400 464 479 463 1390 463 481 482 1399 465 1398 518 401 510 1379 464 480 483 1398 456 1408 487 1392 482 1399 517 386 483 487 466 1399 486 1392 461 483 459 470 462 482 460 469 484 1397 456 473 459 459 483 472 460 484 458 471 461 483 459 1411 463 480 462 467 486 1377 487 1392 482 1396 457 486 456 472 460 486 456 473 480 1400 464 465 456 488 454 475 488 1393 460 468 464 480 462 467 486 1395 458 470 462 483 459 485 436 493 460 469 463 481 461 486 435 500 463 463 458 486 456 1397 488 1390 484 1394 480 1400 464 465 456 488 465 464 457 487 455 474 458 487 455 473 459 485 457 472 460 485 457 472 481 1399 517 401 458 497 456 473 459 485 457 487 434 495 458 471 461 484 458 488 433 502 430 507 435 500 432 498 455 1409 486 1392 482 1399 454 1409 455 488 465 480 462 467 465 480 462 1408 456 473 459 486 488 +# +# Model: Electrolux ESV09CRO-B21. Doesn't have heat function. +name: Dh +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 3092 3057 3092 4438 579 1675 545 534 576 1650 571 535 575 531 569 1656 575 1652 579 527 573 533 577 1648 572 1655 576 1651 580 526 573 532 578 1647 573 532 578 1647 573 1654 577 529 571 535 575 530 570 535 575 529 571 534 576 529 571 534 576 528 571 534 576 528 572 533 577 528 572 533 577 527 573 1651 580 526 573 532 578 527 572 532 568 537 573 531 568 536 574 1650 571 535 575 531 569 536 574 530 569 535 575 529 571 534 576 529 571 533 577 528 572 533 577 527 572 532 568 536 574 531 569 1655 576 530 570 535 575 530 570 535 575 529 571 534 576 528 572 533 577 527 573 532 578 527 572 531 569 536 574 531 569 535 575 530 570 534 576 529 571 534 576 528 571 533 577 527 573 532 567 537 573 531 569 536 574 530 570 535 575 529 571 534 576 528 571 533 577 527 572 532 578 526 573 531 569 536 574 530 570 535 575 529 571 534 576 528 572 533 577 1646 574 532 578 1646 574 1652 579 527 572 533 577 1647 573 1653 578 1675 545 534 576 1649 571 +# +name: Cool_hi +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 315 101050 3094 3056 3093 4437 580 1648 572 534 576 1649 582 525 574 530 580 1646 574 1653 578 529 570 534 576 529 571 534 576 529 570 1655 576 1651 580 527 572 532 578 1647 573 1654 577 1651 580 526 573 531 579 526 573 531 579 526 573 531 579 526 573 531 579 526 573 531 579 525 574 531 579 525 574 531 579 1646 574 532 578 526 573 531 579 526 573 531 579 526 573 1652 579 527 572 1653 578 528 571 534 576 528 571 533 577 528 571 533 577 528 572 533 577 528 572 532 578 527 572 532 578 527 572 532 578 526 573 1652 579 527 572 532 578 527 572 532 578 527 572 532 578 526 573 531 579 526 573 531 579 526 573 531 579 525 574 530 580 525 574 530 580 525 574 530 580 524 575 529 581 524 575 529 571 534 576 528 571 533 577 528 571 533 577 528 571 533 577 527 572 532 578 527 572 532 578 526 573 531 579 526 573 531 579 525 574 531 579 525 574 530 580 525 574 1650 581 525 574 1651 580 1647 573 533 577 527 572 1653 578 528 572 1654 577 1650 581 1646 574 71637 254 +# +name: Cool_lo +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 284 19161 3098 3053 3096 4435 572 1656 575 532 578 1648 572 534 576 530 570 1682 549 1652 579 527 572 534 576 1649 571 1656 575 1652 579 1649 571 1656 575 531 579 527 572 1653 578 1649 571 1656 575 531 579 527 572 532 578 527 572 533 577 527 572 533 577 527 573 532 578 527 572 532 578 527 573 532 578 527 572 1652 579 527 572 533 577 528 571 533 577 528 571 533 577 1648 572 533 577 1649 571 535 575 530 569 536 574 531 569 536 574 530 569 536 574 530 570 535 575 530 570 535 575 530 569 535 575 530 569 535 575 1649 571 535 575 531 568 536 574 531 568 536 574 531 568 536 574 531 569 536 574 530 569 536 574 530 569 535 575 530 569 535 575 530 569 535 575 530 570 535 575 529 570 534 576 529 570 534 576 529 570 534 576 528 571 534 576 528 571 534 576 528 571 534 576 528 571 534 576 528 571 533 577 528 571 533 577 528 572 533 577 528 571 533 577 528 572 1652 579 527 572 1653 578 529 570 534 576 529 570 535 575 529 570 1654 577 1677 554 1673 547 +# +name: Off +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 3093 3058 3090 4441 576 1652 579 528 571 1654 577 531 579 526 573 1652 579 1649 582 525 574 1652 579 528 571 1654 577 1651 580 527 572 533 577 528 571 533 577 1649 582 1646 574 1653 578 529 581 525 574 530 580 525 574 530 580 525 574 531 579 526 573 531 579 526 573 531 579 526 573 531 579 526 573 531 579 526 573 531 579 526 573 531 579 526 573 532 578 1647 573 533 577 1648 572 535 575 530 569 535 575 530 580 525 574 531 579 525 574 531 579 526 573 531 579 526 573 531 579 526 573 531 579 526 573 1651 580 527 572 533 577 528 571 533 577 528 571 533 577 528 571 533 577 528 571 534 576 528 571 534 576 529 570 534 576 529 570 534 576 529 570 534 576 529 570 534 576 529 570 534 576 529 570 534 576 529 570 534 576 529 570 534 576 529 570 534 576 529 570 534 576 529 570 534 576 529 570 534 576 529 570 534 576 529 570 534 576 529 570 534 576 1649 582 525 574 1650 581 1647 573 1654 577 1651 580 1647 573 1654 577 531 579 1646 574 1653 578 +# +# Model: Daikin FTE35KV1. Doesn't have heat function. +name: Dh +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 5045 2158 335 1768 358 690 357 723 335 716 331 1771 355 694 364 686 361 720 327 723 335 1767 359 690 357 1775 362 1770 356 692 366 1767 359 1772 354 1777 360 1771 355 1776 361 687 360 690 357 1776 361 687 360 690 357 693 365 716 331 719 328 692 366 1767 359 1772 354 1777 360 1771 355 1776 361 687 360 1773 364 1767 360 689 358 692 366 685 362 688 359 721 326 724 334 717 330 720 327 723 335 715 332 718 329 721 326 1777 360 1771 355 1776 361 1770 356 692 366 715 332 718 329 721 326 29460 5042 2161 332 1770 356 692 366 685 362 688 359 1774 363 685 362 688 359 721 326 694 364 1769 357 691 367 1767 360 1771 355 693 365 1769 358 1773 364 1768 359 1772 365 1766 361 688 359 691 367 1767 360 689 358 692 366 684 363 717 330 720 327 693 365 686 361 689 358 722 336 684 363 1770 357 1774 363 686 361 689 358 1774 363 686 361 1771 356 1776 361 1770 357 692 366 685 362 688 359 690 357 1776 361 687 360 690 357 1776 361 688 359 691 356 694 364 716 331 689 358 1775 362 686 361 689 358 692 366 685 362 688 359 691 356 724 334 716 331 689 358 722 336 685 362 688 359 721 326 693 365 716 331 689 358 692 366 684 363 718 329 690 357 693 365 716 331 689 358 722 336 1767 360 689 358 1774 363 686 361 1771 356 693 365 686 361 689 358 722 336 684 363 717 330 720 327 1776 361 687 360 690 357 693 365 716 331 1771 355 693 365 686 361 1772 355 1776 361 688 359 1773 364 1768 359 +# +name: Cool_hi +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 5038 2165 328 1772 365 686 361 689 358 692 366 1765 362 719 328 692 366 684 363 717 330 1771 366 684 363 1768 359 1774 363 686 361 1771 355 1776 361 1770 357 1775 362 1769 358 691 356 694 364 1767 360 691 356 694 364 686 361 689 358 692 366 685 362 1769 358 1775 362 1769 358 1774 363 1768 359 690 357 1776 361 1770 357 692 366 684 363 687 360 690 357 693 365 686 361 689 358 692 366 684 363 687 360 690 357 693 365 1766 361 1773 364 1767 360 1772 355 694 364 686 361 689 358 692 366 25151 319 3980 5041 2131 362 1769 358 693 365 686 361 689 358 1772 365 686 361 689 358 692 366 684 363 1768 359 692 366 1765 361 1772 354 694 364 1769 358 1774 363 1768 359 1773 364 1767 359 719 328 692 366 1796 331 719 328 692 366 685 362 688 359 691 356 694 364 686 361 689 358 692 366 685 362 1768 359 1775 362 686 361 689 358 1773 364 686 361 1770 357 1777 360 1771 355 693 365 686 361 689 358 1772 365 1769 358 690 357 694 364 1767 360 691 356 694 364 686 361 689 358 723 335 1766 361 690 357 693 365 685 362 688 359 691 356 694 364 687 360 690 357 693 365 685 362 688 359 691 356 694 364 687 360 690 357 693 365 685 362 688 359 691 367 684 363 687 360 1771 366 684 363 687 360 690 357 693 365 1767 360 690 357 1804 333 687 360 690 357 693 365 686 361 689 358 692 366 685 362 1768 359 692 366 685 362 688 359 690 357 1774 363 688 359 691 356 1774 363 1770 356 1775 362 1769 358 691 356 +# +name: Cool_lo +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 301 132136 5036 2167 337 1766 361 689 358 692 366 684 363 1770 357 692 366 684 363 718 329 690 357 1776 361 687 360 1773 364 1767 360 689 358 1775 362 1769 357 1774 363 1768 359 1773 364 684 363 718 329 1773 364 684 363 718 329 691 356 694 364 716 331 719 328 1775 362 1769 358 1774 363 1768 359 1772 365 714 333 1770 357 1774 363 716 331 719 328 722 336 715 332 718 329 721 326 724 334 716 331 719 328 722 336 715 332 718 329 1773 364 1767 360 1772 354 1777 360 719 328 721 326 725 333 717 330 29455 5036 2139 354 1777 360 688 359 691 367 714 333 1770 356 692 366 684 363 687 360 690 357 1776 361 688 359 1773 364 1768 359 689 358 1775 362 1769 357 1774 363 1768 359 1773 364 684 363 687 360 1773 364 685 362 688 359 691 356 694 364 686 361 689 358 692 366 685 362 688 359 691 356 1777 360 1771 355 693 365 685 362 1771 355 693 365 1768 359 1773 364 1767 360 689 358 692 366 685 362 1771 355 1775 362 687 360 690 357 1775 362 687 360 690 357 693 365 716 331 689 358 1774 363 686 361 689 358 692 366 685 362 688 359 691 356 694 364 686 361 689 358 692 366 685 362 688 359 691 356 694 364 686 361 689 358 692 366 685 362 1771 355 693 365 1768 358 1773 364 684 363 687 360 690 357 693 365 1768 359 690 357 1776 361 688 359 691 356 694 364 686 361 689 358 692 366 685 362 1770 356 693 365 685 362 688 359 691 356 1777 360 1771 355 693 365 686 361 689 358 692 366 685 362 1770 356 +# +name: Off +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 5043 2132 361 1770 356 723 335 715 332 718 329 1774 363 715 332 719 328 722 336 714 333 1770 356 722 336 1767 360 1772 354 724 334 1769 357 1774 363 1768 358 1773 364 1767 359 720 327 723 335 1768 359 720 327 723 335 716 331 719 328 722 336 714 333 1770 356 1774 363 1769 357 1773 364 1767 360 720 327 1775 362 1769 357 721 326 725 333 717 330 720 327 723 335 716 331 719 328 722 336 714 333 717 330 720 327 723 335 1768 359 1773 364 1767 360 1772 354 724 334 717 330 720 327 723 335 29451 5041 2134 359 1772 354 724 334 717 330 720 327 1775 362 717 330 720 327 723 335 715 332 1771 355 723 335 1768 358 1773 364 715 332 1770 357 1775 362 1769 357 1774 363 1768 359 720 327 723 335 1768 359 720 327 724 334 716 331 719 328 722 336 715 332 718 329 720 327 723 335 716 331 1771 355 1776 361 718 329 721 326 1776 361 718 329 1773 364 1767 360 720 327 723 335 715 332 718 329 1774 363 1768 359 720 327 723 335 1768 358 721 326 724 334 716 331 719 328 722 336 1767 360 719 328 722 336 715 332 718 329 721 326 724 334 717 330 720 327 723 335 715 332 719 328 722 325 725 333 717 330 720 327 723 335 716 331 719 328 1774 363 716 331 1771 355 1776 361 718 329 721 326 724 334 717 330 1772 365 714 333 1770 356 722 336 715 332 718 329 721 326 724 334 717 330 719 328 1775 362 717 330 720 327 723 335 715 332 718 329 1774 363 715 332 718 329 721 326 725 333 717 330 1772 365 From 8582670a341030e43ddf277aad625e9063802cd7 Mon Sep 17 00:00:00 2001 From: Georgii Surkov <37121527+gsurkov@users.noreply.github.com> Date: Mon, 26 Dec 2022 15:13:30 +0300 Subject: [PATCH 12/34] [FL-2811] Fix PVS-Studio warnings (#2142) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: あく Co-authored-by: gornekich --- .github/workflows/pvs_studio.yml | 3 +- .pvsconfig | 23 +++++++ .pvsoptions | 2 +- .../unit_tests/float_tools/float_tools_test.c | 60 ++++++++++++++++ applications/debug/unit_tests/test_index.c | 2 + .../main/archive/helpers/archive_apps.c | 2 +- .../main/archive/helpers/archive_favorites.c | 2 +- .../archive/scenes/archive_scene_browser.c | 2 +- applications/main/bad_usb/bad_usb_script.c | 14 ++-- applications/main/fap_loader/fap_loader_app.c | 4 +- applications/main/ibutton/ibutton.c | 6 +- applications/main/infrared/infrared.c | 4 +- .../main/infrared/infrared_brute_force.c | 2 +- applications/main/infrared/infrared_cli.c | 10 +-- applications/main/infrared/infrared_remote.c | 14 ++-- applications/main/infrared/infrared_signal.c | 6 +- .../infrared/scenes/infrared_scene_debug.c | 2 +- applications/main/lfrfid/lfrfid.c | 4 +- applications/main/lfrfid/lfrfid_cli.c | 26 +++---- .../main/nfc/scenes/nfc_scene_emulate_uid.c | 2 +- .../nfc/scenes/nfc_scene_mf_classic_emulate.c | 2 +- .../nfc/scenes/nfc_scene_mf_classic_keys.c | 4 +- .../scenes/nfc_scene_mf_classic_keys_list.c | 2 +- .../nfc_scene_mf_desfire_read_success.c | 6 +- .../scenes/nfc_scene_mf_ultralight_emulate.c | 2 +- .../main/nfc/scenes/nfc_scene_nfc_data_info.c | 8 +-- applications/main/nfc/scenes/nfc_scene_read.c | 2 +- .../main/nfc/scenes/nfc_scene_save_name.c | 2 +- .../subghz_frequency_analyzer_worker.c | 5 +- .../subghz/scenes/subghz_scene_read_raw.c | 3 +- .../subghz/scenes/subghz_scene_save_name.c | 2 +- .../subghz/scenes/subghz_scene_set_type.c | 2 +- applications/main/subghz/subghz_cli.c | 19 +++--- applications/main/subghz/subghz_i.c | 5 +- .../subghz/views/subghz_frequency_analyzer.c | 13 ++-- .../main/subghz/views/subghz_read_raw.c | 4 +- .../main/subghz/views/subghz_test_packet.c | 2 +- applications/main/u2f/scenes/u2f_scene_main.c | 2 +- applications/main/u2f/u2f_data.c | 6 +- applications/main/u2f/u2f_hid.c | 6 +- .../plugins/dap_link/usb/dap_v2_usb.c | 8 +-- .../plugins/hid_app/views/hid_keyboard.c | 21 ++---- .../plugins/music_player/music_player.c | 2 +- .../picopass/lib/loclass/optimized_cipher.c | 35 +++------- .../plugins/picopass/picopass_worker.c | 10 ++- .../scenes/picopass_scene_save_name.c | 2 +- .../scenes/signal_gen_scene_pwm.c | 4 +- .../signal_generator/views/signal_gen_pwm.c | 6 +- applications/plugins/snake_game/snake_game.c | 4 +- .../weather_station/protocols/oregon2.c | 2 +- .../weather_station/protocols/oregon_v1.c | 2 +- .../weather_station/protocols/ws_generic.c | 4 +- .../views/weather_station_receiver_info.c | 5 +- .../weather_station/weather_station_app_i.c | 3 - .../weather_station/weather_station_history.c | 2 +- applications/services/bt/bt_service/bt.c | 6 +- .../services/bt/bt_service/bt_keys_storage.c | 2 +- applications/services/cli/cli.c | 4 +- applications/services/cli/cli_command_gpio.c | 68 +++++++++---------- applications/services/cli/cli_commands.c | 14 ++-- applications/services/crypto/crypto_cli.c | 2 +- .../desktop/animations/animation_manager.c | 10 ++- .../desktop/animations/animation_storage.c | 5 +- .../services/desktop/helpers/slideshow.c | 2 +- .../desktop/views/desktop_view_debug.c | 8 +-- .../desktop/views/desktop_view_lock_menu.c | 6 +- .../desktop/views/desktop_view_pin_timeout.c | 2 +- .../services/dolphin/helpers/dolphin_state.c | 2 +- applications/services/gui/elements.c | 2 +- .../services/gui/modules/button_panel.c | 2 +- .../services/gui/modules/byte_input.c | 9 ++- .../services/gui/modules/file_browser.c | 6 +- .../gui/modules/file_browser_worker.c | 4 +- applications/services/gui/modules/submenu.c | 10 +-- .../services/gui/modules/text_input.c | 15 ++-- .../services/gui/modules/validators.c | 7 +- .../services/gui/modules/variable_item_list.c | 4 +- .../widget_elements/widget_element_button.c | 4 +- .../widget_elements/widget_element_string.c | 2 +- .../widget_element_string_multiline.c | 2 +- .../widget_elements/widget_element_text_box.c | 2 +- .../widget_element_text_scroll.c | 2 +- applications/services/gui/view.c | 4 +- applications/services/input/input.c | 4 +- applications/services/input/input_cli.c | 2 +- applications/services/loader/loader.c | 2 +- .../power/power_service/views/power_off.c | 2 +- applications/services/rpc/rpc_app.c | 22 +++--- applications/services/rpc/rpc_cli.c | 2 +- applications/services/rpc/rpc_debug.c | 14 ++-- applications/services/rpc/rpc_storage.c | 2 +- applications/services/rpc/rpc_system.c | 1 - .../services/storage/storage_external_api.c | 8 +-- applications/services/storage/storage_glue.c | 3 +- .../services/storage/storages/storage_int.c | 46 ++++--------- applications/settings/about/about.c | 4 +- .../scenes/desktop_settings_scene_favorite.c | 2 +- .../desktop_settings_scene_pin_setup_howto.c | 4 +- .../desktop_settings_scene_pin_setup_howto2.c | 4 +- .../power_settings_app/views/battery_info.c | 12 ++-- .../storage_settings_scene_format_confirm.c | 2 - .../scenes/storage_settings_scene_sd_info.c | 2 - .../storage_settings_scene_unmount_confirm.c | 2 - .../updater/util/update_task_worker_backup.c | 2 +- .../updater/util/update_task_worker_flasher.c | 8 +-- debug/gdbinit | 10 +++ firmware/targets/f7/Src/update.c | 2 +- firmware/targets/f7/ble_glue/ble_glue.c | 22 +++--- firmware/targets/f7/ble_glue/gap.c | 4 +- firmware/targets/f7/ble_glue/hid_service.c | 2 +- firmware/targets/f7/ble_glue/hw_ipcc.c | 4 +- firmware/targets/f7/fatfs/stm32_adafruit_sd.c | 10 +-- firmware/targets/f7/furi_hal/furi_hal_bt.c | 2 +- .../targets/f7/furi_hal/furi_hal_bt_hid.c | 6 +- .../targets/f7/furi_hal/furi_hal_i2c_config.c | 4 +- .../targets/f7/furi_hal/furi_hal_memory.c | 6 +- firmware/targets/f7/furi_hal/furi_hal_nfc.c | 10 +-- firmware/targets/f7/furi_hal/furi_hal_os.c | 4 +- firmware/targets/f7/furi_hal/furi_hal_pwm.c | 2 +- firmware/targets/f7/furi_hal/furi_hal_rtc.c | 2 +- firmware/targets/f7/furi_hal/furi_hal_uart.c | 4 +- .../targets/f7/furi_hal/furi_hal_usb_hid.c | 4 +- .../targets/f7/furi_hal/furi_hal_version.c | 2 - furi/core/check.c | 2 +- furi/core/core_defines.h | 2 +- furi/core/event_flag.c | 6 +- furi/core/memmgr_heap.c | 5 +- furi/core/message_queue.c | 5 +- furi/core/mutex.c | 2 + furi/core/stream_buffer.c | 10 ++- furi/core/string.c | 10 +-- furi/core/thread.c | 8 +-- furi/core/timer.c | 44 ++++-------- .../view_modules/popup_vm.cpp | 3 +- lib/drivers/cc1101.c | 2 +- lib/drivers/lp5562.c | 4 +- lib/flipper_application/elf/elf_file.c | 22 +++--- lib/flipper_format/flipper_format_stream.c | 4 +- .../common/infrared_common_decoder.c | 2 +- .../common/infrared_common_encoder.c | 1 - .../common/infrared_common_i.h | 2 +- lib/infrared/worker/infrared_transmit.c | 5 +- lib/infrared/worker/infrared_worker.c | 6 +- lib/infrared/worker/infrared_worker.h | 2 +- lib/lfrfid/lfrfid_raw_worker.c | 5 +- lib/lfrfid/lfrfid_worker.c | 4 +- lib/lfrfid/lfrfid_worker_modes.c | 6 +- lib/lfrfid/protocols/protocol_indala26.c | 2 +- lib/lfrfid/protocols/protocol_pac_stanley.c | 8 +-- lib/lfrfid/tools/bit_lib.c | 10 +-- lib/lfrfid/tools/bit_lib.h | 8 +-- lib/lfrfid/tools/varint_pair.c | 4 +- lib/nfc/helpers/mf_classic_dict.c | 10 +-- lib/nfc/helpers/reader_analyzer.c | 4 +- lib/nfc/nfc_device.c | 4 +- lib/nfc/nfc_worker.c | 22 +++--- lib/nfc/parsers/all_in_one.c | 14 +--- lib/nfc/parsers/plantain_4k_parser.c | 19 +----- lib/nfc/parsers/plantain_parser.c | 19 +----- lib/nfc/parsers/two_cities.c | 18 +---- lib/nfc/protocols/crypto1.c | 3 +- lib/nfc/protocols/mifare_classic.c | 45 +++++------- lib/nfc/protocols/mifare_desfire.c | 16 +++-- lib/nfc/protocols/mifare_ultralight.c | 24 +++---- lib/one_wire/ibutton/ibutton_key.c | 2 - lib/one_wire/ibutton/ibutton_worker_modes.c | 1 - lib/one_wire/ibutton/ibutton_writer.c | 2 +- .../ibutton/protocols/protocol_cyfral.c | 6 +- .../ibutton/protocols/protocol_metakom.c | 8 +-- lib/one_wire/one_wire_slave.c | 12 ++-- lib/print/printf_tiny.c | 2 +- lib/subghz/blocks/generic.c | 2 +- lib/subghz/blocks/math.h | 3 +- lib/subghz/protocols/bett.c | 1 - lib/subghz/protocols/holtek.c | 1 - lib/subghz/protocols/keeloq.c | 9 +-- lib/subghz/protocols/kia.c | 2 +- lib/subghz/protocols/megacode.c | 2 +- lib/subghz/protocols/nero_radio.c | 2 +- lib/subghz/protocols/princeton.c | 2 +- lib/subghz/protocols/princeton_for_testing.c | 4 +- lib/subghz/protocols/scher_khan.c | 4 +- lib/subghz/protocols/secplus_v1.c | 8 +-- lib/subghz/protocols/secplus_v2.c | 20 +++--- lib/subghz/protocols/smc5326.c | 4 +- lib/subghz/subghz_file_encoder_worker.c | 2 +- lib/subghz/subghz_keystore.c | 12 ++-- lib/subghz/subghz_setting.c | 10 ++- lib/toolbox/dir_walk.c | 7 +- lib/toolbox/float_tools.c | 8 +++ lib/toolbox/float_tools.h | 19 ++++++ lib/toolbox/hex.c | 16 ++--- lib/toolbox/md5.c | 12 ++-- lib/toolbox/sha256.c | 10 +-- lib/toolbox/stream/stream.c | 4 +- lib/toolbox/tar/tar_archive.c | 4 +- lib/toolbox/varint.c | 4 +- lib/update_util/dfu_file.c | 2 +- lib/update_util/resources/manifest.c | 2 +- lib/update_util/update_operation.c | 4 +- scripts/fbt_tools/fbt_debugopts.py | 4 +- 201 files changed, 719 insertions(+), 743 deletions(-) create mode 100644 applications/debug/unit_tests/float_tools/float_tools_test.c create mode 100644 debug/gdbinit create mode 100644 lib/toolbox/float_tools.c create mode 100644 lib/toolbox/float_tools.h diff --git a/.github/workflows/pvs_studio.yml b/.github/workflows/pvs_studio.yml index 5bb04afcb..c521fbca4 100644 --- a/.github/workflows/pvs_studio.yml +++ b/.github/workflows/pvs_studio.yml @@ -50,7 +50,7 @@ jobs: - name: 'Generate compile_comands.json' run: | - ./fbt COMPACT=1 version_json proto_ver icons firmware_cdb dolphin_internal dolphin_blocking _fap_icons + ./fbt COMPACT=1 version_json proto_ver icons firmware_cdb dolphin_internal dolphin_blocking _fap_icons api_syms - name: 'Static code analysis' run: | @@ -58,6 +58,7 @@ jobs: pvs-studio-analyzer credentials ${{ secrets.PVS_STUDIO_CREDENTIALS }} pvs-studio-analyzer analyze \ @.pvsoptions \ + -C gccarm \ -j$(grep -c processor /proc/cpuinfo) \ -f build/f7-firmware-DC/compile_commands.json \ -o PVS-Studio.log diff --git a/.pvsconfig b/.pvsconfig index 5f1ffb7cb..a9ab9c9f6 100644 --- a/.pvsconfig +++ b/.pvsconfig @@ -1,4 +1,5 @@ # MLib macros we can't do much about. +//-V:M_LET:1048,1044 //-V:M_EACH:1048,1044 //-V:ARRAY_DEF:760,747,568,776,729,712,654 //-V:LIST_DEF:760,747,568,712,729,654,776 @@ -16,8 +17,30 @@ # Potentially null argument warnings //-V:memset:575 //-V:memcpy:575 +//-V:memcmp:575 +//-V:strlen:575 //-V:strcpy:575 +//-V:strncpy:575 //-V:strchr:575 # For loop warning on M_FOREACH //-V:for:1044 + +# Bitwise OR +//-V:bit:792 + +# Do not complain about similar code +//-V::525 + +# Common embedded development pointer operations +//-V::566 +//-V::1032 + +# Warnings about length mismatch +//-V:property_value_out:666 + +# Model-related warnings +//-V:with_view_model:1044,1048 + +# Functions that always return the same error code +//-V:picopass_device_decrypt:1048 diff --git a/.pvsoptions b/.pvsoptions index 4c80ab667..31bc4b804 100644 --- a/.pvsoptions +++ b/.pvsoptions @@ -1 +1 @@ ---rules-config .pvsconfig -e lib/fatfs -e lib/fnv1a-hash -e lib/FreeRTOS-Kernel -e lib/heatshrink -e lib/libusb_stm32 -e lib/littlefs -e lib/mbedtls -e lib/micro-ecc -e lib/microtar -e lib/mlib -e lib/qrcode -e lib/ST25RFAL002 -e lib/STM32CubeWB -e lib/u8g2 -e */arm-none-eabi/* +--rules-config .pvsconfig -e lib/fatfs -e lib/fnv1a-hash -e lib/FreeRTOS-Kernel -e lib/heatshrink -e lib/libusb_stm32 -e lib/littlefs -e lib/mbedtls -e lib/micro-ecc -e lib/microtar -e lib/mlib -e lib/qrcode -e lib/ST25RFAL002 -e lib/STM32CubeWB -e lib/u8g2 -e lib/nanopb -e */arm-none-eabi/* -e applications/plugins/dap_link/lib/free-dap diff --git a/applications/debug/unit_tests/float_tools/float_tools_test.c b/applications/debug/unit_tests/float_tools/float_tools_test.c new file mode 100644 index 000000000..fc5b4ecfd --- /dev/null +++ b/applications/debug/unit_tests/float_tools/float_tools_test.c @@ -0,0 +1,60 @@ +#include +#include + +#include "../minunit.h" + +MU_TEST(float_tools_equal_test) { + mu_check(float_is_equal(FLT_MAX, FLT_MAX)); + mu_check(float_is_equal(FLT_MIN, FLT_MIN)); + mu_check(float_is_equal(-FLT_MAX, -FLT_MAX)); + mu_check(float_is_equal(-FLT_MIN, -FLT_MIN)); + + mu_check(!float_is_equal(FLT_MIN, FLT_MAX)); + mu_check(!float_is_equal(-FLT_MIN, FLT_MAX)); + mu_check(!float_is_equal(FLT_MIN, -FLT_MAX)); + mu_check(!float_is_equal(-FLT_MIN, -FLT_MAX)); + + const float pi = 3.14159f; + mu_check(float_is_equal(pi, pi)); + mu_check(float_is_equal(-pi, -pi)); + mu_check(!float_is_equal(pi, -pi)); + mu_check(!float_is_equal(-pi, pi)); + + const float one_third = 1.f / 3.f; + const float one_third_dec = 0.3333333f; + mu_check(one_third != one_third_dec); + mu_check(float_is_equal(one_third, one_third_dec)); + + const float big_num = 1.e12f; + const float med_num = 95.389f; + const float smol_num = 1.e-12f; + mu_check(float_is_equal(big_num, big_num)); + mu_check(float_is_equal(med_num, med_num)); + mu_check(float_is_equal(smol_num, smol_num)); + mu_check(!float_is_equal(smol_num, big_num)); + mu_check(!float_is_equal(med_num, smol_num)); + mu_check(!float_is_equal(big_num, med_num)); + + const float more_than_one = 1.f + FLT_EPSILON; + const float less_than_one = 1.f - FLT_EPSILON; + mu_check(!float_is_equal(more_than_one, less_than_one)); + mu_check(!float_is_equal(more_than_one, -less_than_one)); + mu_check(!float_is_equal(-more_than_one, less_than_one)); + mu_check(!float_is_equal(-more_than_one, -less_than_one)); + + const float slightly_more_than_one = 1.f + FLT_EPSILON / 2.f; + const float slightly_less_than_one = 1.f - FLT_EPSILON / 2.f; + mu_check(float_is_equal(slightly_more_than_one, slightly_less_than_one)); + mu_check(float_is_equal(-slightly_more_than_one, -slightly_less_than_one)); + mu_check(!float_is_equal(slightly_more_than_one, -slightly_less_than_one)); + mu_check(!float_is_equal(-slightly_more_than_one, slightly_less_than_one)); +} + +MU_TEST_SUITE(float_tools_suite) { + MU_RUN_TEST(float_tools_equal_test); +} + +int run_minunit_test_float_tools() { + MU_RUN_SUITE(float_tools_suite); + return MU_EXIT_CODE; +} diff --git a/applications/debug/unit_tests/test_index.c b/applications/debug/unit_tests/test_index.c index 5bc53c82e..ccf471531 100644 --- a/applications/debug/unit_tests/test_index.c +++ b/applications/debug/unit_tests/test_index.c @@ -24,6 +24,7 @@ int run_minunit_test_protocol_dict(); int run_minunit_test_lfrfid_protocols(); int run_minunit_test_nfc(); int run_minunit_test_bit_lib(); +int run_minunit_test_float_tools(); int run_minunit_test_bt(); typedef int (*UnitTestEntry)(); @@ -50,6 +51,7 @@ const UnitTest unit_tests[] = { {.name = "protocol_dict", .entry = run_minunit_test_protocol_dict}, {.name = "lfrfid", .entry = run_minunit_test_lfrfid_protocols}, {.name = "bit_lib", .entry = run_minunit_test_bit_lib}, + {.name = "float_tools", .entry = run_minunit_test_float_tools}, {.name = "bt", .entry = run_minunit_test_bt}, }; diff --git a/applications/main/archive/helpers/archive_apps.c b/applications/main/archive/helpers/archive_apps.c index 72084f113..c8ad67625 100644 --- a/applications/main/archive/helpers/archive_apps.c +++ b/applications/main/archive/helpers/archive_apps.c @@ -13,7 +13,7 @@ ArchiveAppTypeEnum archive_get_app_type(const char* path) { } app_name++; - for(size_t i = 0; i < COUNT_OF(known_apps); i++) { + for(size_t i = 0; i < COUNT_OF(known_apps); i++) { //-V1008 if(strncmp(app_name, known_apps[i], strlen(known_apps[i])) == 0) { return i; } diff --git a/applications/main/archive/helpers/archive_favorites.c b/applications/main/archive/helpers/archive_favorites.c index 86a294f78..8bbcb5213 100644 --- a/applications/main/archive/helpers/archive_favorites.c +++ b/applications/main/archive/helpers/archive_favorites.c @@ -177,7 +177,7 @@ bool archive_favorites_read(void* context) { archive_set_item_count(browser, file_count); - if(need_refresh) { + if(need_refresh) { //-V547 archive_favourites_rescan(); } diff --git a/applications/main/archive/scenes/archive_scene_browser.c b/applications/main/archive/scenes/archive_scene_browser.c index 2f4693548..c28f91f52 100644 --- a/applications/main/archive/scenes/archive_scene_browser.c +++ b/applications/main/archive/scenes/archive_scene_browser.c @@ -116,7 +116,7 @@ bool archive_scene_browser_on_event(void* context, SceneManagerEvent event) { case ArchiveBrowserEventFileMenuPin: { const char* name = archive_get_name(browser); if(favorites) { - archive_favorites_delete(name); + archive_favorites_delete("%s", name); archive_file_array_rm_selected(browser); archive_show_file_menu(browser, false); } else if(archive_is_known_app(selected->type)) { diff --git a/applications/main/bad_usb/bad_usb_script.c b/applications/main/bad_usb/bad_usb_script.c index aa465351e..92c7466f1 100644 --- a/applications/main/bad_usb/bad_usb_script.c +++ b/applications/main/bad_usb/bad_usb_script.c @@ -218,8 +218,8 @@ static bool ducky_string(const char* param) { } static uint16_t ducky_get_keycode(const char* param, bool accept_chars) { - for(uint8_t i = 0; i < (sizeof(ducky_keys) / sizeof(ducky_keys[0])); i++) { - uint8_t key_cmd_len = strlen(ducky_keys[i].name); + for(size_t i = 0; i < (sizeof(ducky_keys) / sizeof(ducky_keys[0])); i++) { + size_t key_cmd_len = strlen(ducky_keys[i].name); if((strncmp(param, ducky_keys[i].name, key_cmd_len) == 0) && (ducky_is_line_end(param[key_cmd_len]))) { return ducky_keys[i].keycode; @@ -417,7 +417,7 @@ static int32_t ducky_script_execute_next(BadUsbScript* bad_usb, File* script_fil return 0; } else if(delay_val < 0) { // Script error bad_usb->st.error_line = bad_usb->st.line_cur - 1; - FURI_LOG_E(WORKER_TAG, "Unknown command at line %u", bad_usb->st.line_cur - 1); + FURI_LOG_E(WORKER_TAG, "Unknown command at line %u", bad_usb->st.line_cur - 1U); return SCRIPT_STATE_ERROR; } else { return (delay_val + bad_usb->defdelay); @@ -596,7 +596,9 @@ static int32_t bad_usb_worker(void* context) { } bad_usb->st.state = worker_state; continue; - } else if((flags == FuriFlagErrorTimeout) || (flags == FuriFlagErrorResource)) { + } else if( + (flags == (unsigned)FuriFlagErrorTimeout) || + (flags == (unsigned)FuriFlagErrorResource)) { if(delay_val > 0) { bad_usb->st.delay_remain--; continue; @@ -650,7 +652,7 @@ static int32_t bad_usb_worker(void* context) { BadUsbScript* bad_usb_script_open(FuriString* file_path) { furi_assert(file_path); - BadUsbScript* bad_usb = malloc(sizeof(BadUsbScript)); //-V773 + BadUsbScript* bad_usb = malloc(sizeof(BadUsbScript)); bad_usb->file_path = furi_string_alloc(); furi_string_set(bad_usb->file_path, file_path); @@ -660,7 +662,7 @@ BadUsbScript* bad_usb_script_open(FuriString* file_path) { bad_usb->thread = furi_thread_alloc_ex("BadUsbWorker", 2048, bad_usb_worker, bad_usb); furi_thread_start(bad_usb->thread); return bad_usb; -} +} //-V773 void bad_usb_script_close(BadUsbScript* bad_usb) { furi_assert(bad_usb); diff --git a/applications/main/fap_loader/fap_loader_app.c b/applications/main/fap_loader/fap_loader_app.c index 901866746..7911aa068 100644 --- a/applications/main/fap_loader/fap_loader_app.c +++ b/applications/main/fap_loader/fap_loader_app.c @@ -156,7 +156,7 @@ static bool fap_loader_select_app(FapLoader* loader) { } static FapLoader* fap_loader_alloc(const char* path) { - FapLoader* loader = malloc(sizeof(FapLoader)); //-V773 + FapLoader* loader = malloc(sizeof(FapLoader)); //-V799 loader->fap_path = furi_string_alloc_set(path); loader->storage = furi_record_open(RECORD_STORAGE); loader->dialogs = furi_record_open(RECORD_DIALOGS); @@ -167,7 +167,7 @@ static FapLoader* fap_loader_alloc(const char* path) { loader->view_dispatcher, loader->gui, ViewDispatcherTypeFullscreen); view_dispatcher_add_view(loader->view_dispatcher, 0, loading_get_view(loader->loading)); return loader; -} +} //-V773 static void fap_loader_free(FapLoader* loader) { view_dispatcher_remove_view(loader->view_dispatcher, 0); diff --git a/applications/main/ibutton/ibutton.c b/applications/main/ibutton/ibutton.c index b7c8223b0..85212f42b 100644 --- a/applications/main/ibutton/ibutton.c +++ b/applications/main/ibutton/ibutton.c @@ -278,7 +278,7 @@ bool ibutton_save_key(iButton* ibutton, const char* key_name) { flipper_format_free(file); - if(!result) { + if(!result) { //-V547 dialog_message_show_storage_error(ibutton->dialogs, "Cannot save\nkey file"); } @@ -302,7 +302,7 @@ void ibutton_text_store_set(iButton* ibutton, const char* text, ...) { } void ibutton_text_store_clear(iButton* ibutton) { - memset(ibutton->text_store, 0, IBUTTON_TEXT_STORE_SIZE); + memset(ibutton->text_store, 0, IBUTTON_TEXT_STORE_SIZE + 1); } void ibutton_notification_message(iButton* ibutton, uint32_t message) { @@ -343,7 +343,7 @@ int32_t ibutton_app(void* p) { } else { view_dispatcher_attach_to_gui( ibutton->view_dispatcher, ibutton->gui, ViewDispatcherTypeFullscreen); - if(key_loaded) { + if(key_loaded) { //-V547 scene_manager_next_scene(ibutton->scene_manager, iButtonSceneEmulate); DOLPHIN_DEED(DolphinDeedIbuttonEmulate); } else { diff --git a/applications/main/infrared/infrared.c b/applications/main/infrared/infrared.c index f62db14c1..9d78a09b6 100644 --- a/applications/main/infrared/infrared.c +++ b/applications/main/infrared/infrared.c @@ -360,7 +360,7 @@ void infrared_text_store_set(Infrared* infrared, uint32_t bank, const char* text } void infrared_text_store_clear(Infrared* infrared, uint32_t bank) { - memset(infrared->text_store[bank], 0, INFRARED_TEXT_STORE_SIZE); + memset(infrared->text_store[bank], 0, INFRARED_TEXT_STORE_SIZE + 1); } void infrared_play_notification_message(Infrared* infrared, uint32_t message) { @@ -455,7 +455,7 @@ int32_t infrared_app(void* p) { } else { view_dispatcher_attach_to_gui( infrared->view_dispatcher, infrared->gui, ViewDispatcherTypeFullscreen); - if(is_remote_loaded) { + if(is_remote_loaded) { //-V547 scene_manager_next_scene(infrared->scene_manager, InfraredSceneRemote); } else { scene_manager_next_scene(infrared->scene_manager, InfraredSceneStart); diff --git a/applications/main/infrared/infrared_brute_force.c b/applications/main/infrared/infrared_brute_force.c index 3f426f1dc..3ca5c409f 100644 --- a/applications/main/infrared/infrared_brute_force.c +++ b/applications/main/infrared/infrared_brute_force.c @@ -65,7 +65,7 @@ bool infrared_brute_force_calculate_messages(InfraredBruteForce* brute_force) { while(flipper_format_read_string(ff, "name", signal_name)) { InfraredBruteForceRecord* record = InfraredBruteForceRecordDict_get(brute_force->records, signal_name); - if(record) { + if(record) { //-V547 ++(record->count); } } diff --git a/applications/main/infrared/infrared_cli.c b/applications/main/infrared/infrared_cli.c index 8f35a8fd1..5f5e2d4bb 100644 --- a/applications/main/infrared/infrared_cli.c +++ b/applications/main/infrared/infrared_cli.c @@ -55,7 +55,7 @@ static void signal_received_callback(void* context, InfraredWorkerSignal* receiv size_t timings_cnt; infrared_worker_get_raw_signal(received_signal, &timings, &timings_cnt); - buf_cnt = snprintf(buf, sizeof(buf), "RAW, %d samples:\r\n", timings_cnt); + buf_cnt = snprintf(buf, sizeof(buf), "RAW, %zu samples:\r\n", timings_cnt); cli_write(cli, (uint8_t*)buf, buf_cnt); for(size_t i = 0; i < timings_cnt; ++i) { buf_cnt = snprintf(buf, sizeof(buf), "%lu ", timings[i]); @@ -276,7 +276,9 @@ static bool infrared_cli_decode_file(FlipperFormat* input_file, FlipperFormat* o } InfraredRawSignal* raw_signal = infrared_signal_get_raw_signal(signal); printf( - "Raw signal: %s, %u samples\r\n", furi_string_get_cstr(tmp), raw_signal->timings_size); + "Raw signal: %s, %zu samples\r\n", + furi_string_get_cstr(tmp), + raw_signal->timings_size); if(!infrared_cli_decode_raw_signal( raw_signal, decoder, output_file, furi_string_get_cstr(tmp))) break; @@ -382,7 +384,7 @@ static void infrared_cli_list_remote_signals(FuriString* remote_name) { while(flipper_format_read_string(ff, "name", signal_name)) { furi_string_set_str(key, furi_string_get_cstr(signal_name)); int* v = dict_signals_get(signals_dict, key); - if(v != NULL) { + if(v != NULL) { //-V547 (*v)++; max = M_MAX(*v, max); } else { @@ -436,7 +438,7 @@ static void break; } - printf("Sending %ld signal(s)...\r\n", record_count); + printf("Sending %lu signal(s)...\r\n", record_count); printf("Press Ctrl-C to stop.\r\n"); int records_sent = 0; diff --git a/applications/main/infrared/infrared_remote.c b/applications/main/infrared/infrared_remote.c index 3a528a656..d3dfc2cce 100644 --- a/applications/main/infrared/infrared_remote.c +++ b/applications/main/infrared/infrared_remote.c @@ -145,15 +145,14 @@ bool infrared_remote_load(InfraredRemote* remote, FuriString* path) { buf = furi_string_alloc(); FURI_LOG_I(TAG, "load file: \'%s\'", furi_string_get_cstr(path)); - bool success = flipper_format_buffered_file_open_existing(ff, furi_string_get_cstr(path)); + bool success = false; - if(success) { + do { + if(!flipper_format_buffered_file_open_existing(ff, furi_string_get_cstr(path))) break; uint32_t version; - success = flipper_format_read_header(ff, buf, &version) && - !furi_string_cmp(buf, "IR signals file") && (version == 1); - } + if(!flipper_format_read_header(ff, buf, &version)) break; + if(!furi_string_equal(buf, "IR signals file") || (version != 1)) break; - if(success) { path_extract_filename(path, buf, true); infrared_remote_clear_buttons(remote); infrared_remote_set_name(remote, furi_string_get_cstr(buf)); @@ -169,7 +168,8 @@ bool infrared_remote_load(InfraredRemote* remote, FuriString* path) { infrared_remote_button_free(button); } } - } + success = true; + } while(false); furi_string_free(buf); flipper_format_free(ff); diff --git a/applications/main/infrared/infrared_signal.c b/applications/main/infrared/infrared_signal.c index d399b9587..9154dfbf6 100644 --- a/applications/main/infrared/infrared_signal.c +++ b/applications/main/infrared/infrared_signal.c @@ -74,7 +74,7 @@ static bool infrared_signal_is_raw_valid(InfraredRawSignal* raw) { } else if((raw->timings_size <= 0) || (raw->timings_size > MAX_TIMINGS_AMOUNT)) { FURI_LOG_E( TAG, - "Timings amount is out of range (0 - %X): %X", + "Timings amount is out of range (0 - %X): %zX", MAX_TIMINGS_AMOUNT, raw->timings_size); return false; @@ -275,8 +275,8 @@ bool infrared_signal_search_and_read( is_name_found = furi_string_equal(name, tmp); if(is_name_found) break; } - if(!is_name_found) break; - if(!infrared_signal_read_body(signal, ff)) break; + if(!is_name_found) break; //-V547 + if(!infrared_signal_read_body(signal, ff)) break; //-V779 success = true; } while(false); diff --git a/applications/main/infrared/scenes/infrared_scene_debug.c b/applications/main/infrared/scenes/infrared_scene_debug.c index dd0609b56..204978697 100644 --- a/applications/main/infrared/scenes/infrared_scene_debug.c +++ b/applications/main/infrared/scenes/infrared_scene_debug.c @@ -26,7 +26,7 @@ bool infrared_scene_debug_on_event(void* context, SceneManagerEvent event) { InfraredRawSignal* raw = infrared_signal_get_raw_signal(signal); infrared_debug_view_set_text(debug_view, "RAW\n%d samples\n", raw->timings_size); - printf("RAW, %d samples:\r\n", raw->timings_size); + printf("RAW, %zu samples:\r\n", raw->timings_size); for(size_t i = 0; i < raw->timings_size; ++i) { printf("%lu ", raw->timings[i]); } diff --git a/applications/main/lfrfid/lfrfid.c b/applications/main/lfrfid/lfrfid.c index 2207e7e07..85a00eea0 100644 --- a/applications/main/lfrfid/lfrfid.c +++ b/applications/main/lfrfid/lfrfid.c @@ -32,7 +32,7 @@ static void rpc_command_callback(RpcAppSystemEvent rpc_event, void* context) { } static LfRfid* lfrfid_alloc() { - LfRfid* lfrfid = malloc(sizeof(LfRfid)); //-V773 + LfRfid* lfrfid = malloc(sizeof(LfRfid)); lfrfid->storage = furi_record_open(RECORD_STORAGE); lfrfid->dialogs = furi_record_open(RECORD_DIALOGS); @@ -100,7 +100,7 @@ static LfRfid* lfrfid_alloc() { lfrfid->view_dispatcher, LfRfidViewRead, lfrfid_view_read_get_view(lfrfid->read_view)); return lfrfid; -} +} //-V773 static void lfrfid_free(LfRfid* lfrfid) { furi_assert(lfrfid); diff --git a/applications/main/lfrfid/lfrfid_cli.c b/applications/main/lfrfid/lfrfid_cli.c index 640274529..ce3e987e8 100644 --- a/applications/main/lfrfid/lfrfid_cli.c +++ b/applications/main/lfrfid/lfrfid_cli.c @@ -87,7 +87,7 @@ static void lfrfid_cli_read(Cli* cli, FuriString* args) { uint32_t flags = furi_event_flag_wait(context.event, available_flags, FuriFlagWaitAny, 100); - if(flags != FuriFlagErrorTimeout) { + if(flags != (unsigned)FuriFlagErrorTimeout) { if(FURI_BIT(flags, LFRFIDWorkerReadDone)) { break; } @@ -153,7 +153,7 @@ static bool lfrfid_cli_parse_args(FuriString* args, ProtocolDict* dict, Protocol for(ProtocolId i = 0; i < LFRFIDProtocolMax; i++) { printf( - "\t%s, %d bytes long\r\n", + "\t%s, %zu bytes long\r\n", protocol_dict_get_name(dict, i), protocol_dict_get_data_size(dict, i)); } @@ -165,7 +165,7 @@ static bool lfrfid_cli_parse_args(FuriString* args, ProtocolDict* dict, Protocol // check data arg if(!args_read_hex_bytes(data_text, data, data_size)) { printf( - "%s data needs to be %d bytes long\r\n", + "%s data needs to be %zu bytes long\r\n", protocol_dict_get_name(dict, *protocol), data_size); break; @@ -211,7 +211,7 @@ static void lfrfid_cli_write(Cli* cli, FuriString* args) { while(!cli_cmd_interrupt_received(cli)) { uint32_t flags = furi_event_flag_wait(event, available_flags, FuriFlagWaitAny, 100); - if(flags != FuriFlagErrorTimeout) { + if(flags != (unsigned)FuriFlagErrorTimeout) { if(FURI_BIT(flags, LFRFIDWorkerWriteOK)) { printf("Written!\r\n"); break; @@ -309,9 +309,9 @@ static void lfrfid_cli_raw_analyze(Cli* cli, FuriString* args) { warn = true; } - furi_string_printf(info_string, "[%ld %ld]", pulse, duration); + furi_string_printf(info_string, "[%lu %lu]", pulse, duration); printf("%-16s", furi_string_get_cstr(info_string)); - furi_string_printf(info_string, "[%ld %ld]", pulse, duration - pulse); + furi_string_printf(info_string, "[%lu %lu]", pulse, duration - pulse); printf("%-16s", furi_string_get_cstr(info_string)); if(warn) { @@ -335,7 +335,7 @@ static void lfrfid_cli_raw_analyze(Cli* cli, FuriString* args) { total_pulse += pulse; total_duration += duration; - if(total_protocol != PROTOCOL_NO) { + if(total_protocol != PROTOCOL_NO) { //-V1051 break; } } else { @@ -346,9 +346,9 @@ static void lfrfid_cli_raw_analyze(Cli* cli, FuriString* args) { printf(" Frequency: %f\r\n", (double)frequency); printf(" Duty Cycle: %f\r\n", (double)duty_cycle); - printf(" Warns: %ld\r\n", total_warns); - printf(" Pulse sum: %ld\r\n", total_pulse); - printf("Duration sum: %ld\r\n", total_duration); + printf(" Warns: %lu\r\n", total_warns); + printf(" Pulse sum: %lu\r\n", total_pulse); + printf("Duration sum: %lu\r\n", total_duration); printf(" Average: %f\r\n", (double)((float)total_pulse / (float)total_duration)); printf(" Protocol: "); @@ -435,7 +435,7 @@ static void lfrfid_cli_raw_read(Cli* cli, FuriString* args) { while(true) { uint32_t flags = furi_event_flag_wait(event, available_flags, FuriFlagWaitAny, 100); - if(flags != FuriFlagErrorTimeout) { + if(flags != (unsigned)FuriFlagErrorTimeout) { if(FURI_BIT(flags, LFRFIDWorkerReadRawFileError)) { printf("File is not RFID raw file\r\n"); break; @@ -510,7 +510,7 @@ static void lfrfid_cli_raw_emulate(Cli* cli, FuriString* args) { while(true) { uint32_t flags = furi_event_flag_wait(event, available_flags, FuriFlagWaitAny, 100); - if(flags != FuriFlagErrorTimeout) { + if(flags != (unsigned)FuriFlagErrorTimeout) { if(FURI_BIT(flags, LFRFIDWorkerEmulateRawFileError)) { printf("File is not RFID raw file\r\n"); break; @@ -573,4 +573,4 @@ static void lfrfid_cli(Cli* cli, FuriString* args, void* context) { } furi_string_free(cmd); -} \ No newline at end of file +} diff --git a/applications/main/nfc/scenes/nfc_scene_emulate_uid.c b/applications/main/nfc/scenes/nfc_scene_emulate_uid.c index f90197679..7316eebe0 100644 --- a/applications/main/nfc/scenes/nfc_scene_emulate_uid.c +++ b/applications/main/nfc/scenes/nfc_scene_emulate_uid.c @@ -39,7 +39,7 @@ static void nfc_scene_emulate_uid_widget_config(Nfc* nfc, bool data_received) { widget_add_icon_element(widget, 0, 3, &I_NFC_dolphin_emulation_47x61); widget_add_string_element(widget, 57, 13, AlignLeft, AlignTop, FontPrimary, "Emulating UID"); - if(strcmp(nfc->dev->dev_name, "")) { + if(strcmp(nfc->dev->dev_name, "") != 0) { furi_string_printf(info_str, "%s", nfc->dev->dev_name); } else { for(uint8_t i = 0; i < data->uid_len; i++) { diff --git a/applications/main/nfc/scenes/nfc_scene_mf_classic_emulate.c b/applications/main/nfc/scenes/nfc_scene_mf_classic_emulate.c index 1bd9a85a8..8c0f493e1 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_classic_emulate.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_classic_emulate.c @@ -18,7 +18,7 @@ void nfc_scene_mf_classic_emulate_on_enter(void* context) { // Setup view Popup* popup = nfc->popup; popup_set_header(popup, "Emulating", 67, 13, AlignLeft, AlignTop); - if(strcmp(nfc->dev->dev_name, "")) { + if(strcmp(nfc->dev->dev_name, "") != 0) { nfc_text_store_set(nfc, "%s", nfc->dev->dev_name); } else { nfc_text_store_set(nfc, "MIFARE\nClassic"); diff --git a/applications/main/nfc/scenes/nfc_scene_mf_classic_keys.c b/applications/main/nfc/scenes/nfc_scene_mf_classic_keys.c index 54cc18d32..dee9553d4 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_classic_keys.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_classic_keys.c @@ -28,9 +28,9 @@ void nfc_scene_mf_classic_keys_on_enter(void* context) { widget_add_string_element( nfc->widget, 0, 0, AlignLeft, AlignTop, FontPrimary, "Mifare Classic Keys"); char temp_str[32]; - snprintf(temp_str, sizeof(temp_str), "Flipper list: %ld", flipper_dict_keys_total); + snprintf(temp_str, sizeof(temp_str), "Flipper list: %lu", flipper_dict_keys_total); widget_add_string_element(nfc->widget, 0, 20, AlignLeft, AlignTop, FontSecondary, temp_str); - snprintf(temp_str, sizeof(temp_str), "User list: %ld", user_dict_keys_total); + snprintf(temp_str, sizeof(temp_str), "User list: %lu", user_dict_keys_total); widget_add_string_element(nfc->widget, 0, 32, AlignLeft, AlignTop, FontSecondary, temp_str); widget_add_button_element( nfc->widget, GuiButtonTypeCenter, "Add", nfc_scene_mf_classic_keys_widget_callback, nfc); diff --git a/applications/main/nfc/scenes/nfc_scene_mf_classic_keys_list.c b/applications/main/nfc/scenes/nfc_scene_mf_classic_keys_list.c index 19d2f556f..57f9fe656 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_classic_keys_list.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_classic_keys_list.c @@ -27,7 +27,7 @@ void nfc_scene_mf_classic_keys_list_prepare(Nfc* nfc, MfClassicDict* dict) { char* current_key = (char*)malloc(sizeof(char) * 13); strncpy(current_key, furi_string_get_cstr(temp_key), 12); MfClassicUserKeys_push_back(nfc->mfc_key_strs, current_key); - FURI_LOG_D("ListKeys", "Key %ld: %s", index, current_key); + FURI_LOG_D("ListKeys", "Key %lu: %s", index, current_key); submenu_add_item( submenu, current_key, index++, nfc_scene_mf_classic_keys_list_submenu_callback, nfc); } diff --git a/applications/main/nfc/scenes/nfc_scene_mf_desfire_read_success.c b/applications/main/nfc/scenes/nfc_scene_mf_desfire_read_success.c index 2ab0355ca..39030397f 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_desfire_read_success.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_desfire_read_success.c @@ -26,13 +26,13 @@ void nfc_scene_mf_desfire_read_success_on_enter(void* context) { furi_string_cat_printf(temp_str, " %02X", nfc_data->uid[i]); } - uint32_t bytes_total = 1 << (data->version.sw_storage >> 1); + uint32_t bytes_total = 1UL << (data->version.sw_storage >> 1); uint32_t bytes_free = data->free_memory ? data->free_memory->bytes : 0; - furi_string_cat_printf(temp_str, "\n%ld", bytes_total); + furi_string_cat_printf(temp_str, "\n%lu", bytes_total); if(data->version.sw_storage & 1) { furi_string_push_back(temp_str, '+'); } - furi_string_cat_printf(temp_str, " bytes, %ld bytes free\n", bytes_free); + furi_string_cat_printf(temp_str, " bytes, %lu bytes free\n", bytes_free); uint16_t n_apps = 0; uint16_t n_files = 0; diff --git a/applications/main/nfc/scenes/nfc_scene_mf_ultralight_emulate.c b/applications/main/nfc/scenes/nfc_scene_mf_ultralight_emulate.c index c9c617cbe..9d8f17f9a 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_ultralight_emulate.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_ultralight_emulate.c @@ -21,7 +21,7 @@ void nfc_scene_mf_ultralight_emulate_on_enter(void* context) { (type == MfUltralightTypeUnknown); Popup* popup = nfc->popup; popup_set_header(popup, "Emulating", 67, 13, AlignLeft, AlignTop); - if(strcmp(nfc->dev->dev_name, "")) { + if(strcmp(nfc->dev->dev_name, "") != 0) { nfc_text_store_set(nfc, "%s", nfc->dev->dev_name); } else if(is_ultralight) { nfc_text_store_set(nfc, "MIFARE\nUltralight"); diff --git a/applications/main/nfc/scenes/nfc_scene_nfc_data_info.c b/applications/main/nfc/scenes/nfc_scene_nfc_data_info.c index d1767a458..b44ab7823 100644 --- a/applications/main/nfc/scenes/nfc_scene_nfc_data_info.c +++ b/applications/main/nfc/scenes/nfc_scene_nfc_data_info.c @@ -57,13 +57,13 @@ void nfc_scene_nfc_data_info_on_enter(void* context) { // Set application specific data if(protocol == NfcDeviceProtocolMifareDesfire) { MifareDesfireData* data = &dev_data->mf_df_data; - uint32_t bytes_total = 1 << (data->version.sw_storage >> 1); + uint32_t bytes_total = 1UL << (data->version.sw_storage >> 1); uint32_t bytes_free = data->free_memory ? data->free_memory->bytes : 0; - furi_string_cat_printf(temp_str, "\n%ld", bytes_total); + furi_string_cat_printf(temp_str, "\n%lu", bytes_total); if(data->version.sw_storage & 1) { furi_string_push_back(temp_str, '+'); } - furi_string_cat_printf(temp_str, " bytes, %ld bytes free\n", bytes_free); + furi_string_cat_printf(temp_str, " bytes, %lu bytes free\n", bytes_free); uint16_t n_apps = 0; uint16_t n_files = 0; @@ -147,4 +147,4 @@ void nfc_scene_nfc_data_info_on_exit(void* context) { Nfc* nfc = context; widget_reset(nfc->widget); -} \ No newline at end of file +} diff --git a/applications/main/nfc/scenes/nfc_scene_read.c b/applications/main/nfc/scenes/nfc_scene_read.c index a64d4d00d..2607cbd8f 100644 --- a/applications/main/nfc/scenes/nfc_scene_read.c +++ b/applications/main/nfc/scenes/nfc_scene_read.c @@ -71,7 +71,7 @@ bool nfc_scene_read_on_event(void* context, SceneManagerEvent event) { } else if(event.event == NfcWorkerEventReadMfUltralight) { notification_message(nfc->notifications, &sequence_success); // Set unlock password input to 0xFFFFFFFF only on fresh read - memset(nfc->byte_input_store, 0xFF, 4); + memset(nfc->byte_input_store, 0xFF, sizeof(nfc->byte_input_store)); scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightReadSuccess); DOLPHIN_DEED(DolphinDeedNfcReadSuccess); consumed = true; diff --git a/applications/main/nfc/scenes/nfc_scene_save_name.c b/applications/main/nfc/scenes/nfc_scene_save_name.c index ca4b1a350..007274226 100644 --- a/applications/main/nfc/scenes/nfc_scene_save_name.c +++ b/applications/main/nfc/scenes/nfc_scene_save_name.c @@ -55,7 +55,7 @@ bool nfc_scene_save_name_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { if(event.event == NfcCustomEventTextInputDone) { - if(strcmp(nfc->dev->dev_name, "")) { + if(strcmp(nfc->dev->dev_name, "") != 0) { nfc_device_delete(nfc->dev, true); } if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSetUid)) { diff --git a/applications/main/subghz/helpers/subghz_frequency_analyzer_worker.c b/applications/main/subghz/helpers/subghz_frequency_analyzer_worker.c index 7463cfaf9..5d1a80a39 100644 --- a/applications/main/subghz/helpers/subghz_frequency_analyzer_worker.c +++ b/applications/main/subghz/helpers/subghz_frequency_analyzer_worker.c @@ -2,6 +2,7 @@ #include #include +#include #define TAG "SubghzFrequencyAnalyzerWorker" @@ -197,7 +198,7 @@ static int32_t subghz_frequency_analyzer_worker_thread(void* context) { rssi_temp = (rssi_temp + frequency_rssi.rssi_fine) / 2; frequency_temp = frequency_rssi.frequency_fine; - if(instance->filVal) { + if(!float_is_equal(instance->filVal, 0.f)) { frequency_rssi.frequency_fine = subghz_frequency_analyzer_worker_expRunningAverageAdaptive( instance, frequency_rssi.frequency_fine); @@ -219,7 +220,7 @@ static int32_t subghz_frequency_analyzer_worker_thread(void* context) { instance->sample_hold_counter = 20; rssi_temp = (rssi_temp + frequency_rssi.rssi_coarse) / 2; frequency_temp = frequency_rssi.frequency_coarse; - if(instance->filVal) { + if(!float_is_equal(instance->filVal, 0.f)) { frequency_rssi.frequency_coarse = subghz_frequency_analyzer_worker_expRunningAverageAdaptive( instance, frequency_rssi.frequency_coarse); diff --git a/applications/main/subghz/scenes/subghz_scene_read_raw.c b/applications/main/subghz/scenes/subghz_scene_read_raw.c index b270dd482..6f95c4169 100644 --- a/applications/main/subghz/scenes/subghz_scene_read_raw.c +++ b/applications/main/subghz/scenes/subghz_scene_read_raw.c @@ -3,6 +3,7 @@ #include #include #include +#include #define RAW_FILE_NAME "Raw_signal_" #define TAG "SubGhzSceneReadRAW" @@ -358,7 +359,7 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) { float rssi = furi_hal_subghz_get_rssi(); - if(subghz->txrx->raw_threshold_rssi == SUBGHZ_RAW_TRESHOLD_MIN) { + if(float_is_equal(subghz->txrx->raw_threshold_rssi, SUBGHZ_RAW_TRESHOLD_MIN)) { subghz_read_raw_add_data_rssi(subghz->subghz_read_raw, rssi, true); subghz_protocol_raw_save_to_file_pause( (SubGhzProtocolDecoderRAW*)subghz->txrx->decoder_result, false); diff --git a/applications/main/subghz/scenes/subghz_scene_save_name.c b/applications/main/subghz/scenes/subghz_scene_save_name.c index 33846c283..255ba228b 100644 --- a/applications/main/subghz/scenes/subghz_scene_save_name.c +++ b/applications/main/subghz/scenes/subghz_scene_save_name.c @@ -94,7 +94,7 @@ bool subghz_scene_save_name_on_event(void* context, SceneManagerEvent event) { return true; } else if(event.type == SceneManagerEventTypeCustom) { if(event.event == SubGhzCustomEventSceneSaveName) { - if(strcmp(subghz->file_name_tmp, "")) { + if(strcmp(subghz->file_name_tmp, "") != 0) { furi_string_cat_printf( subghz->file_path, "/%s%s", subghz->file_name_tmp, SUBGHZ_APP_EXTENSION); if(subghz_path_is_file(subghz->file_path_tmp)) { diff --git a/applications/main/subghz/scenes/subghz_scene_set_type.c b/applications/main/subghz/scenes/subghz_scene_set_type.c index 2ed537193..eaa3ccefe 100644 --- a/applications/main/subghz/scenes/subghz_scene_set_type.c +++ b/applications/main/subghz/scenes/subghz_scene_set_type.c @@ -46,7 +46,7 @@ bool subghz_scene_set_type_submenu_gen_data_protocol( uint8_t key_data[sizeof(uint64_t)] = {0}; for(size_t i = 0; i < sizeof(uint64_t); i++) { - key_data[sizeof(uint64_t) - i - 1] = (key >> i * 8) & 0xFF; + key_data[sizeof(uint64_t) - i - 1] = (key >> (i * 8)) & 0xFF; } if(!flipper_format_update_hex(subghz->txrx->fff_data, "Key", key_data, sizeof(uint64_t))) { FURI_LOG_E(TAG, "Unable to update Key"); diff --git a/applications/main/subghz/subghz_cli.c b/applications/main/subghz/subghz_cli.c index b6471b33c..536cb535e 100644 --- a/applications/main/subghz/subghz_cli.c +++ b/applications/main/subghz/subghz_cli.c @@ -152,11 +152,11 @@ void subghz_cli_command_tx(Cli* cli, FuriString* args, void* context) { "Protocol: Princeton\n" "Bit: 24\n" "Key: 00 00 00 00 00 %02X %02X %02X\n" - "TE: %ld\n" - "Repeat: %ld\n", - (uint8_t)((key >> 16) & 0xFF), - (uint8_t)((key >> 8) & 0xFF), - (uint8_t)(key & 0xFF), + "TE: %lu\n" + "Repeat: %lu\n", + (uint8_t)((key >> 16) & 0xFFU), + (uint8_t)((key >> 8) & 0xFFU), + (uint8_t)(key & 0xFFU), te, repeat); FlipperFormat* flipper_format = flipper_format_string_alloc(); @@ -300,7 +300,7 @@ void subghz_cli_command_rx(Cli* cli, FuriString* args, void* context) { furi_hal_power_suppress_charge_exit(); - printf("\r\nPackets received %u\r\n", instance->packet_count); + printf("\r\nPackets received %zu\r\n", instance->packet_count); // Cleanup subghz_receiver_free(receiver); @@ -787,8 +787,9 @@ static bool subghz_on_system_start_istream_decode_band( } region->bands_count += 1; - region = - realloc(region, sizeof(FuriHalRegion) + sizeof(FuriHalRegionBand) * region->bands_count); + region = realloc( //-V701 + region, + sizeof(FuriHalRegion) + sizeof(FuriHalRegionBand) * region->bands_count); size_t pos = region->bands_count - 1; region->bands[pos].start = band.start; region->bands[pos].end = band.end; @@ -798,7 +799,7 @@ static bool subghz_on_system_start_istream_decode_band( FURI_LOG_I( "SubGhzOnStart", - "Add allowed band: start %ldHz, stop %ldHz, power_limit %ddBm, duty_cycle %d%%", + "Add allowed band: start %luHz, stop %luHz, power_limit %ddBm, duty_cycle %u%%", band.start, band.end, band.power_limit, diff --git a/applications/main/subghz/subghz_i.c b/applications/main/subghz/subghz_i.c index 0bcd70061..7de020a54 100644 --- a/applications/main/subghz/subghz_i.c +++ b/applications/main/subghz/subghz_i.c @@ -164,7 +164,7 @@ bool subghz_tx_start(SubGhz* subghz, FlipperFormat* flipper_format) { if(subghz->txrx->transmitter) { if(subghz_transmitter_deserialize(subghz->txrx->transmitter, flipper_format)) { - if(strcmp(furi_string_get_cstr(subghz->txrx->preset->name), "")) { + if(strcmp(furi_string_get_cstr(subghz->txrx->preset->name), "") != 0) { subghz_begin( subghz, subghz_setting_get_preset_data_by_name( @@ -544,11 +544,8 @@ void subghz_hopper_update(SubGhz* subghz) { switch(subghz->txrx->hopper_state) { case SubGhzHopperStateOFF: - return; - break; case SubGhzHopperStatePause: return; - break; case SubGhzHopperStateRSSITimeOut: if(subghz->txrx->hopper_timeout != 0) { subghz->txrx->hopper_timeout--; diff --git a/applications/main/subghz/views/subghz_frequency_analyzer.c b/applications/main/subghz/views/subghz_frequency_analyzer.c index 129898400..94419084b 100644 --- a/applications/main/subghz/views/subghz_frequency_analyzer.c +++ b/applications/main/subghz/views/subghz_frequency_analyzer.c @@ -11,6 +11,7 @@ #include "../helpers/subghz_frequency_analyzer_log_item_array.h" #include +#include #define LOG_FREQUENCY_MAX_ITEMS 60 // uint8_t (limited by 'seq' of SubGhzFrequencyAnalyzerLogItem) @@ -47,7 +48,8 @@ typedef struct { } SubGhzFrequencyAnalyzerModel; static inline uint8_t rssi_sanitize(float rssi) { - return (rssi ? (uint8_t)(rssi - SUBGHZ_FREQUENCY_ANALYZER_THRESHOLD) : 0); + return ( + !float_is_equal(rssi, 0.f) ? (uint8_t)(rssi - SUBGHZ_FREQUENCY_ANALYZER_THRESHOLD) : 0); } void subghz_frequency_analyzer_set_callback( @@ -294,9 +296,6 @@ static bool subghz_frequency_analyzer_log_frequency_insert(SubGhzFrequencyAnalyz if(items_count < LOG_FREQUENCY_MAX_ITEMS) { SubGhzFrequencyAnalyzerLogItem_t* item = SubGhzFrequencyAnalyzerLogItemArray_push_new(model->log_frequency); - if(item == NULL) { - return false; - } (*item)->frequency = model->frequency; (*item)->count = 1; (*item)->rssi_max = model->rssi; @@ -340,7 +339,7 @@ void subghz_frequency_analyzer_pair_callback( float rssi, bool signal) { SubGhzFrequencyAnalyzer* instance = context; - if((rssi == 0.f) && (instance->locked)) { + if(float_is_equal(rssi, 0.f) && instance->locked) { if(instance->callback) { instance->callback(SubGhzCustomEventSceneAnalyzerUnlock, instance->context); } @@ -355,13 +354,13 @@ void subghz_frequency_analyzer_pair_callback( model->history_frequency[0] = model->frequency; }, false); - } else if((rssi != 0.f) && (!instance->locked)) { + } else if(!float_is_equal(rssi, 0.f) && !instance->locked) { if(instance->callback) { instance->callback(SubGhzCustomEventSceneAnalyzerLock, instance->context); } } - instance->locked = (rssi != 0.f); + instance->locked = !float_is_equal(rssi, 0.f); with_view_model( instance->view, SubGhzFrequencyAnalyzerModel * model, diff --git a/applications/main/subghz/views/subghz_read_raw.c b/applications/main/subghz/views/subghz_read_raw.c index 6120a210b..87c8a3082 100644 --- a/applications/main/subghz/views/subghz_read_raw.c +++ b/applications/main/subghz/views/subghz_read_raw.c @@ -91,7 +91,7 @@ void subghz_read_raw_update_sample_write(SubGhzReadRAW* instance, size_t sample) with_view_model( instance->view, SubGhzReadRAWModel * model, - { furi_string_printf(model->sample_write, "%d spl.", sample); }, + { furi_string_printf(model->sample_write, "%zu spl.", sample); }, false); } @@ -161,7 +161,7 @@ void subghz_read_raw_draw_sin(Canvas* canvas, SubGhzReadRAWModel* model) { canvas_draw_line( canvas, i + 1, - 32 - subghz_read_raw_tab_sin((i + model->ind_sin * 16)) / SUBGHZ_RAW_SIN_AMPLITUDE, + 32 - subghz_read_raw_tab_sin(i + model->ind_sin * 16) / SUBGHZ_RAW_SIN_AMPLITUDE, i + 2, 32 + subghz_read_raw_tab_sin((i + model->ind_sin * 16 + 1) * 2) / SUBGHZ_RAW_SIN_AMPLITUDE); diff --git a/applications/main/subghz/views/subghz_test_packet.c b/applications/main/subghz/views/subghz_test_packet.c index a42898f77..43502180c 100644 --- a/applications/main/subghz/views/subghz_test_packet.c +++ b/applications/main/subghz/views/subghz_test_packet.c @@ -114,7 +114,7 @@ static void subghz_test_packet_draw(Canvas* canvas, SubGhzTestPacketModel* model snprintf(buffer, sizeof(buffer), "Path: %d - %s", model->path, path_name); canvas_draw_str(canvas, 0, 31, buffer); - snprintf(buffer, sizeof(buffer), "Packets: %d", model->packets); + snprintf(buffer, sizeof(buffer), "Packets: %zu", model->packets); canvas_draw_str(canvas, 0, 42, buffer); if(model->status == SubGhzTestPacketModelStatusRx) { diff --git a/applications/main/u2f/scenes/u2f_scene_main.c b/applications/main/u2f/scenes/u2f_scene_main.c index 60ed71c78..af7f1159b 100644 --- a/applications/main/u2f/scenes/u2f_scene_main.c +++ b/applications/main/u2f/scenes/u2f_scene_main.c @@ -58,7 +58,7 @@ bool u2f_scene_main_on_event(void* context, SceneManagerEvent event) { app->event_cur = event.event; if(event.event == U2fCustomEventRegister) u2f_view_set_state(app->u2f_view, U2fMsgRegister); - else if(event.event == U2fCustomEventAuth) + else if(event.event == U2fCustomEventAuth) //-V547 u2f_view_set_state(app->u2f_view, U2fMsgAuth); notification_message(app->notifications, &sequence_display_backlight_on); notification_message(app->notifications, &sequence_single_vibro); diff --git a/applications/main/u2f/u2f_data.c b/applications/main/u2f/u2f_data.c index 900af462a..66604d166 100644 --- a/applications/main/u2f/u2f_data.c +++ b/applications/main/u2f/u2f_data.c @@ -402,9 +402,9 @@ bool u2f_data_cnt_read(uint32_t* cnt_val) { FURI_LOG_E(TAG, "Unable to load encryption key"); break; } - memset(&cnt, 0, 32); - if(!furi_hal_crypto_decrypt(cnt_encr, (uint8_t*)&cnt, 32)) { - memset(&cnt, 0, 32); + memset(&cnt, 0, sizeof(U2fCounterData)); + if(!furi_hal_crypto_decrypt(cnt_encr, (uint8_t*)&cnt, sizeof(U2fCounterData))) { + memset(&cnt, 0, sizeof(U2fCounterData)); FURI_LOG_E(TAG, "Decryption failed"); break; } diff --git a/applications/main/u2f/u2f_hid.c b/applications/main/u2f/u2f_hid.c index 6e1a51f33..9b625c1f3 100644 --- a/applications/main/u2f/u2f_hid.c +++ b/applications/main/u2f/u2f_hid.c @@ -94,7 +94,7 @@ static void u2f_hid_send_response(U2fHid* u2f_hid) { uint16_t data_ptr = 0; memset(packet_buf, 0, HID_U2F_PACKET_LEN); - memcpy(packet_buf, &(u2f_hid->packet.cid), 4); + memcpy(packet_buf, &(u2f_hid->packet.cid), sizeof(uint32_t)); //-V1086 // Init packet packet_buf[4] = u2f_hid->packet.cmd; @@ -166,7 +166,7 @@ static bool u2f_hid_parse_request(U2fHid* u2f_hid) { return false; u2f_hid->packet.len = 17; uint32_t random_cid = furi_hal_random_get(); - memcpy(&(u2f_hid->packet.payload[8]), &random_cid, 4); + memcpy(&(u2f_hid->packet.payload[8]), &random_cid, sizeof(uint32_t)); //-V1086 u2f_hid->packet.payload[12] = 2; // Protocol version u2f_hid->packet.payload[13] = 1; // Device version major u2f_hid->packet.payload[14] = 0; // Device version minor @@ -177,7 +177,7 @@ static bool u2f_hid_parse_request(U2fHid* u2f_hid) { } else if(u2f_hid->packet.cmd == U2F_HID_WINK) { // WINK - notify user if(u2f_hid->packet.len != 0) return false; u2f_wink(u2f_hid->u2f_instance); - u2f_hid->packet.len = 0; + u2f_hid->packet.len = 0; //-V1048 u2f_hid_send_response(u2f_hid); } else return false; diff --git a/applications/plugins/dap_link/usb/dap_v2_usb.c b/applications/plugins/dap_link/usb/dap_v2_usb.c index b42df2836..cba786648 100644 --- a/applications/plugins/dap_link/usb/dap_v2_usb.c +++ b/applications/plugins/dap_link/usb/dap_v2_usb.c @@ -568,12 +568,12 @@ void dap_common_usb_set_state_callback(DapStateCallback callback) { static void* dap_usb_alloc_string_descr(const char* str) { furi_assert(str); - uint8_t len = strlen(str); - uint8_t wlen = (len + 1) * sizeof(uint16_t); + size_t len = strlen(str); + size_t wlen = (len + 1) * sizeof(uint16_t); struct usb_string_descriptor* dev_str_desc = malloc(wlen); dev_str_desc->bLength = wlen; dev_str_desc->bDescriptorType = USB_DTYPE_STRING; - for(uint8_t i = 0; i < len; i++) { + for(size_t i = 0; i < len; i++) { dev_str_desc->wString[i] = str[i]; } @@ -974,4 +974,4 @@ static usbd_respond hid_control(usbd_device* dev, usbd_ctlreq* req, usbd_rqc_cal } return usbd_fail; -} \ No newline at end of file +} diff --git a/applications/plugins/hid_app/views/hid_keyboard.c b/applications/plugins/hid_app/views/hid_keyboard.c index dff4a7df7..3e3b63284 100644 --- a/applications/plugins/hid_app/views/hid_keyboard.c +++ b/applications/plugins/hid_app/views/hid_keyboard.c @@ -249,30 +249,19 @@ static void hid_keyboard_draw_callback(Canvas* canvas, void* context) { static uint8_t hid_keyboard_get_selected_key(HidKeyboardModel* model) { HidKeyboardKey key = hid_keyboard_keyset[model->y][model->x]; - // Use upper case if shift is toggled - bool useUppercase = model->shift; - // Check if the key has an upper case version - bool hasUppercase = key.shift_key != 0; - if(useUppercase && hasUppercase) - return key.value; - else - return key.value; + return key.value; } static void hid_keyboard_get_select_key(HidKeyboardModel* model, HidKeyboardPoint delta) { // Keep going until a valid spot is found, this allows for nulls and zero width keys in the map do { - if(((int8_t)model->y) + delta.y < 0) - model->y = ROW_COUNT - 1; - else - model->y = (model->y + delta.y) % ROW_COUNT; + const int delta_sum = model->y + delta.y; + model->y = delta_sum < 0 ? ROW_COUNT - 1 : delta_sum % ROW_COUNT; } while(delta.y != 0 && hid_keyboard_keyset[model->y][model->x].value == 0); do { - if(((int8_t)model->x) + delta.x < 0) - model->x = COLUMN_COUNT - 1; - else - model->x = (model->x + delta.x) % COLUMN_COUNT; + const int delta_sum = model->x + delta.x; + model->x = delta_sum < 0 ? COLUMN_COUNT - 1 : delta_sum % COLUMN_COUNT; } while(delta.x != 0 && hid_keyboard_keyset[model->y][model->x].width == 0); // Skip zero width keys, pretend they are one key } diff --git a/applications/plugins/music_player/music_player.c b/applications/plugins/music_player/music_player.c index 07d4e2df4..28127a575 100644 --- a/applications/plugins/music_player/music_player.c +++ b/applications/plugins/music_player/music_player.c @@ -180,7 +180,7 @@ static void render_callback(Canvas* canvas, void* ctx) { // note stack view_port x_pos = 73; - y_pos = 0; + y_pos = 0; //-V1048 canvas_set_color(canvas, ColorBlack); canvas_set_font(canvas, FontPrimary); canvas_draw_frame(canvas, x_pos, y_pos, 49, 64); diff --git a/applications/plugins/picopass/lib/loclass/optimized_cipher.c b/applications/plugins/picopass/lib/loclass/optimized_cipher.c index eba95538f..94df07bae 100644 --- a/applications/plugins/picopass/lib/loclass/optimized_cipher.c +++ b/applications/plugins/picopass/lib/loclass/optimized_cipher.c @@ -111,9 +111,9 @@ static void init_opt_select_LUT(void) { ***********************************************************************************/ #define loclass_opt__select(x, y, r) \ - (4 & (((r & (r << 2)) >> 5) ^ ((r & ~(r << 2)) >> 4) ^ ((r | r << 2) >> 3))) | \ - (2 & (((r | r << 2) >> 6) ^ ((r | r << 2) >> 1) ^ (r >> 5) ^ r ^ ((x ^ y) << 1))) | \ - (1 & (((r & ~(r << 2)) >> 4) ^ ((r & (r << 2)) >> 3) ^ r ^ x)) + (4 & ((((r) & ((r) << 2)) >> 5) ^ (((r) & ~((r) << 2)) >> 4) ^ (((r) | (r) << 2) >> 3))) | \ + (2 & ((((r) | (r) << 2) >> 6) ^ (((r) | (r) << 2) >> 1) ^ ((r) >> 5) ^ (r) ^ (((x) ^ (y)) << 1))) | \ + (1 & ((((r) & ~((r) << 2)) >> 4) ^ (((r) & ((r) << 2)) >> 3) ^ (r) ^ (x))) static void loclass_opt_successor(const uint8_t* k, LoclassState_t* s, uint8_t y) { uint16_t Tt = s->t & 0xc533; @@ -149,30 +149,11 @@ static void loclass_opt_suc( uint8_t length, bool add32Zeroes) { for(int i = 0; i < length; i++) { - uint8_t head; - head = in[i]; - loclass_opt_successor(k, s, head); - - head >>= 1; - loclass_opt_successor(k, s, head); - - head >>= 1; - loclass_opt_successor(k, s, head); - - head >>= 1; - loclass_opt_successor(k, s, head); - - head >>= 1; - loclass_opt_successor(k, s, head); - - head >>= 1; - loclass_opt_successor(k, s, head); - - head >>= 1; - loclass_opt_successor(k, s, head); - - head >>= 1; - loclass_opt_successor(k, s, head); + uint8_t head = in[i]; + for(int j = 0; j < 8; j++) { + loclass_opt_successor(k, s, head); + head >>= 1; + } } //For tag MAC, an additional 32 zeroes if(add32Zeroes) { diff --git a/applications/plugins/picopass/picopass_worker.c b/applications/plugins/picopass/picopass_worker.c index c2a32cb6a..bb1e513a2 100644 --- a/applications/plugins/picopass/picopass_worker.c +++ b/applications/plugins/picopass/picopass_worker.c @@ -143,7 +143,7 @@ ReturnCode picopass_read_preauth(PicopassBlock* AA1) { AA1[PICOPASS_CSN_BLOCK_INDEX].data[7]); rfalPicoPassReadBlockRes cfg = {0}; - err = rfalPicoPassPollerReadBlock(PICOPASS_CONFIG_BLOCK_INDEX, &cfg); + rfalPicoPassPollerReadBlock(PICOPASS_CONFIG_BLOCK_INDEX, &cfg); memcpy(AA1[PICOPASS_CONFIG_BLOCK_INDEX].data, cfg.data, sizeof(cfg.data)); FURI_LOG_D( TAG, @@ -158,7 +158,7 @@ ReturnCode picopass_read_preauth(PicopassBlock* AA1) { AA1[PICOPASS_CONFIG_BLOCK_INDEX].data[7]); rfalPicoPassReadBlockRes aia; - err = rfalPicoPassPollerReadBlock(PICOPASS_AIA_BLOCK_INDEX, &aia); + rfalPicoPassPollerReadBlock(PICOPASS_AIA_BLOCK_INDEX, &aia); memcpy(AA1[PICOPASS_AIA_BLOCK_INDEX].data, aia.data, sizeof(aia.data)); FURI_LOG_D( TAG, @@ -221,7 +221,7 @@ ReturnCode picopass_auth(PicopassBlock* AA1, PicopassPacs* pacs) { while(iclass_elite_dict_get_next_key(dict, key)) { FURI_LOG_D( TAG, - "Try to auth with key %d %02x%02x%02x%02x%02x%02x%02x%02x", + "Try to auth with key %zu %02x%02x%02x%02x%02x%02x%02x%02x", index++, key[0], key[1], @@ -249,9 +249,7 @@ ReturnCode picopass_auth(PicopassBlock* AA1, PicopassPacs* pacs) { } } - if(dict) { - iclass_elite_dict_free(dict); - } + iclass_elite_dict_free(dict); return err; } diff --git a/applications/plugins/picopass/scenes/picopass_scene_save_name.c b/applications/plugins/picopass/scenes/picopass_scene_save_name.c index 17ad5927a..59f33c79a 100644 --- a/applications/plugins/picopass/scenes/picopass_scene_save_name.c +++ b/applications/plugins/picopass/scenes/picopass_scene_save_name.c @@ -54,7 +54,7 @@ bool picopass_scene_save_name_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { if(event.event == PicopassCustomEventTextInputDone) { - if(strcmp(picopass->dev->dev_name, "")) { + if(strcmp(picopass->dev->dev_name, "") != 0) { // picopass_device_delete(picopass->dev, true); } strlcpy( diff --git a/applications/plugins/signal_generator/scenes/signal_gen_scene_pwm.c b/applications/plugins/signal_generator/scenes/signal_gen_scene_pwm.c index f302c0232..7ac3fadda 100644 --- a/applications/plugins/signal_generator/scenes/signal_gen_scene_pwm.c +++ b/applications/plugins/signal_generator/scenes/signal_gen_scene_pwm.c @@ -15,12 +15,12 @@ static void app->pwm_freq = freq; app->pwm_duty = duty; - if(app->pwm_ch != pwm_ch_id[channel_id]) { + if(app->pwm_ch != pwm_ch_id[channel_id]) { //-V1051 app->pwm_ch_prev = app->pwm_ch; app->pwm_ch = pwm_ch_id[channel_id]; view_dispatcher_send_custom_event(app->view_dispatcher, SignalGenPwmEventChannelChange); } else { - app->pwm_ch = pwm_ch_id[channel_id]; + app->pwm_ch = pwm_ch_id[channel_id]; //-V1048 view_dispatcher_send_custom_event(app->view_dispatcher, SignalGenPwmEventUpdate); } } diff --git a/applications/plugins/signal_generator/views/signal_gen_pwm.c b/applications/plugins/signal_generator/views/signal_gen_pwm.c index 8e618f8a9..b6ba47ab0 100644 --- a/applications/plugins/signal_generator/views/signal_gen_pwm.c +++ b/applications/plugins/signal_generator/views/signal_gen_pwm.c @@ -127,12 +127,12 @@ static void signal_gen_pwm_draw_callback(Canvas* canvas, void* _model) { char* line_label = NULL; char val_text[16]; - for(uint8_t line = 0; line < LineIndexTotalCount; line++) { + for(size_t line = 0; line < LineIndexTotalCount; line++) { if(line == LineIndexChannel) { line_label = "GPIO Pin"; } else if(line == LineIndexFrequency) { line_label = "Frequency"; - } else if(line == LineIndexDuty) { + } else if(line == LineIndexDuty) { //-V547 line_label = "Pulse width"; } @@ -169,7 +169,7 @@ static void signal_gen_pwm_draw_callback(Canvas* canvas, void* _model) { canvas_draw_icon(canvas, icon_x, text_y - 9, &I_SmallArrowUp_3x5); canvas_draw_icon(canvas, icon_x, text_y + 5, &I_SmallArrowDown_3x5); } - } else if(line == LineIndexDuty) { + } else if(line == LineIndexDuty) { //-V547 snprintf(val_text, sizeof(val_text), "%d%%", model->duty); canvas_draw_str_aligned(canvas, VALUE_X, text_y, AlignCenter, AlignCenter, val_text); if(model->duty != 0) { diff --git a/applications/plugins/snake_game/snake_game.c b/applications/plugins/snake_game/snake_game.c index ef4ae2ee8..f9b4d30af 100644 --- a/applications/plugins/snake_game/snake_game.c +++ b/applications/plugins/snake_game/snake_game.c @@ -130,7 +130,7 @@ static void snake_game_render_callback(Canvas* const canvas, void* ctx) { canvas_set_font(canvas, FontSecondary); char buffer[12]; - snprintf(buffer, sizeof(buffer), "Score: %u", snake_state->len - 7); + snprintf(buffer, sizeof(buffer), "Score: %u", snake_state->len - 7U); canvas_draw_str_aligned(canvas, 64, 41, AlignCenter, AlignBottom, buffer); } @@ -153,7 +153,7 @@ static void snake_game_update_timer_callback(FuriMessageQueue* event_queue) { static void snake_game_init_game(SnakeState* const snake_state) { Point p[] = {{8, 6}, {7, 6}, {6, 6}, {5, 6}, {4, 6}, {3, 6}, {2, 6}}; - memcpy(snake_state->points, p, sizeof(p)); + memcpy(snake_state->points, p, sizeof(p)); //-V1086 snake_state->len = 7; diff --git a/applications/plugins/weather_station/protocols/oregon2.c b/applications/plugins/weather_station/protocols/oregon2.c index 8779e9596..8ca80bbe2 100644 --- a/applications/plugins/weather_station/protocols/oregon2.c +++ b/applications/plugins/weather_station/protocols/oregon2.c @@ -343,7 +343,7 @@ bool ws_protocol_decoder_oregon2_deserialize(void* context, FlipperFormat* flipp flipper_format, "VarData", (uint8_t*)&instance->var_data, - sizeof(instance->var_data))) { + sizeof(instance->var_data))) { //-V1051 FURI_LOG_E(TAG, "Missing VarData"); break; } diff --git a/applications/plugins/weather_station/protocols/oregon_v1.c b/applications/plugins/weather_station/protocols/oregon_v1.c index d1cc4c7a7..1ed9da205 100644 --- a/applications/plugins/weather_station/protocols/oregon_v1.c +++ b/applications/plugins/weather_station/protocols/oregon_v1.c @@ -147,7 +147,7 @@ static void ws_protocol_oregon_v1_remote_controller(WSBlockGeneric* instance) { instance->temp = -temp_raw; } - instance->battery_low = !(instance->data >> 23) & 1; + instance->battery_low = !((instance->data >> 23) & 1ULL); instance->btn = WS_NO_BTN; instance->humidity = WS_NO_HUMIDITY; diff --git a/applications/plugins/weather_station/protocols/ws_generic.c b/applications/plugins/weather_station/protocols/ws_generic.c index dcacda2e4..8a88ed52f 100644 --- a/applications/plugins/weather_station/protocols/ws_generic.c +++ b/applications/plugins/weather_station/protocols/ws_generic.c @@ -79,7 +79,7 @@ bool ws_block_generic_serialize( uint8_t key_data[sizeof(uint64_t)] = {0}; for(size_t i = 0; i < sizeof(uint64_t); i++) { - key_data[sizeof(uint64_t) - i - 1] = (instance->data >> i * 8) & 0xFF; + key_data[sizeof(uint64_t) - i - 1] = (instance->data >> (i * 8)) & 0xFF; } if(!flipper_format_write_hex(flipper_format, "Data", key_data, sizeof(uint64_t))) { @@ -208,4 +208,4 @@ bool ws_block_generic_deserialize(WSBlockGeneric* instance, FlipperFormat* flipp } while(0); return res; -} +} \ No newline at end of file diff --git a/applications/plugins/weather_station/views/weather_station_receiver_info.c b/applications/plugins/weather_station/views/weather_station_receiver_info.c index 55d239aad..b3b3f2193 100644 --- a/applications/plugins/weather_station/views/weather_station_receiver_info.c +++ b/applications/plugins/weather_station/views/weather_station_receiver_info.c @@ -4,8 +4,7 @@ #include "../protocols/ws_generic.h" #include #include - -#define abs(x) ((x) > 0 ? (x) : -(x)) +#include struct WSReceiverInfo { View* view; @@ -79,7 +78,7 @@ void ws_view_receiver_info_draw(Canvas* canvas, WSReceiverInfoModel* model) { elements_bold_rounded_frame(canvas, 0, 38, 127, 25); canvas_set_font(canvas, FontPrimary); - if(model->generic->temp != WS_NO_TEMPERATURE) { + if(!float_is_equal(model->generic->temp, WS_NO_TEMPERATURE)) { canvas_draw_icon(canvas, 6, 43, &I_Therm_7x16); uint8_t temp_x1 = 0; diff --git a/applications/plugins/weather_station/weather_station_app_i.c b/applications/plugins/weather_station/weather_station_app_i.c index 052bb8533..712634a2c 100644 --- a/applications/plugins/weather_station/weather_station_app_i.c +++ b/applications/plugins/weather_station/weather_station_app_i.c @@ -111,11 +111,8 @@ void ws_hopper_update(WeatherStationApp* app) { switch(app->txrx->hopper_state) { case WSHopperStateOFF: - return; - break; case WSHopperStatePause: return; - break; case WSHopperStateRSSITimeOut: if(app->txrx->hopper_timeout != 0) { app->txrx->hopper_timeout--; diff --git a/applications/plugins/weather_station/weather_station_history.c b/applications/plugins/weather_station/weather_station_history.c index b37009c46..9adff39c6 100644 --- a/applications/plugins/weather_station/weather_station_history.c +++ b/applications/plugins/weather_station/weather_station_history.c @@ -186,7 +186,7 @@ WSHistoryStateAddKey } // or add new record - if(!sensor_found) { + if(!sensor_found) { //-V547 WSHistoryItem* item = WSHistoryItemArray_push_raw(instance->history->data); item->preset = malloc(sizeof(SubGhzRadioPreset)); item->type = decoder_base->protocol->type; diff --git a/applications/services/bt/bt_service/bt.c b/applications/services/bt/bt_service/bt.c index 024cb6e50..9e5782690 100644 --- a/applications/services/bt/bt_service/bt.c +++ b/applications/services/bt/bt_service/bt.c @@ -36,7 +36,7 @@ static void bt_pin_code_view_port_draw_callback(Canvas* canvas, void* context) { Bt* bt = context; char pin_code_info[24]; canvas_draw_icon(canvas, 0, 0, &I_BLE_Pairing_128x64); - snprintf(pin_code_info, sizeof(pin_code_info), "Pairing code\n%06ld", bt->pin_code); + snprintf(pin_code_info, sizeof(pin_code_info), "Pairing code\n%06lu", bt->pin_code); elements_multiline_text_aligned(canvas, 64, 4, AlignCenter, AlignTop, pin_code_info); elements_button_left(canvas, "Quit"); } @@ -78,7 +78,7 @@ static bool bt_pin_code_verify_event_handler(Bt* bt, uint32_t pin) { notification_message(bt->notification, &sequence_display_backlight_on); FuriString* pin_str; dialog_message_set_icon(bt->dialog_message, &I_BLE_Pairing_128x64, 0, 0); - pin_str = furi_string_alloc_printf("Verify code\n%06ld", pin); + pin_str = furi_string_alloc_printf("Verify code\n%06lu", pin); dialog_message_set_text( bt->dialog_message, furi_string_get_cstr(pin_str), 64, 4, AlignCenter, AlignTop); dialog_message_set_buttons(bt->dialog_message, "Cancel", "OK", NULL); @@ -163,7 +163,7 @@ static uint16_t bt_serial_event_callback(SerialServiceEvent event, void* context rpc_session_feed(bt->rpc_session, event.data.buffer, event.data.size, 1000); if(bytes_processed != event.data.size) { FURI_LOG_E( - TAG, "Only %d of %d bytes processed by RPC", bytes_processed, event.data.size); + TAG, "Only %zu of %u bytes processed by RPC", bytes_processed, event.data.size); } ret = rpc_session_get_available_size(bt->rpc_session); } else if(event.event == SerialServiceEventTypeDataSent) { diff --git a/applications/services/bt/bt_service/bt_keys_storage.c b/applications/services/bt/bt_service/bt_keys_storage.c index 7cff99944..215f19a89 100644 --- a/applications/services/bt/bt_service/bt_keys_storage.c +++ b/applications/services/bt/bt_service/bt_keys_storage.c @@ -115,7 +115,7 @@ bool bt_keys_storage_update(BtKeysStorage* instance, uint8_t* start_addr, uint32 FURI_LOG_I( TAG, - "Base address: %p. Start update address: %p. Size changed: %ld", + "Base address: %p. Start update address: %p. Size changed: %lu", (void*)instance->nvm_sram_buff, start_addr, size); diff --git a/applications/services/cli/cli.c b/applications/services/cli/cli.c index f29dca9ce..384d17808 100644 --- a/applications/services/cli/cli.c +++ b/applications/services/cli/cli.c @@ -225,7 +225,7 @@ static void cli_handle_enter(Cli* cli) { furi_check(furi_mutex_acquire(cli->mutex, FuriWaitForever) == FuriStatusOk); CliCommand* cli_command_ptr = CliCommandTree_get(cli->commands, command); - if(cli_command_ptr) { + if(cli_command_ptr) { //-V547 CliCommand cli_command; memcpy(&cli_command, cli_command_ptr, sizeof(CliCommand)); furi_check(furi_mutex_release(cli->mutex) == FuriStatusOk); @@ -353,7 +353,7 @@ void cli_process_input(Cli* cli) { cli_handle_backspace(cli); } else if(in_chr == CliSymbolAsciiCR) { cli_handle_enter(cli); - } else if(in_chr >= 0x20 && in_chr < 0x7F) { + } else if(in_chr >= 0x20 && in_chr < 0x7F) { //-V560 if(cli->cursor_position == furi_string_size(cli->line)) { furi_string_push_back(cli->line, in_chr); cli_putc(cli, in_chr); diff --git a/applications/services/cli/cli_command_gpio.c b/applications/services/cli/cli_command_gpio.c index 0b29f4853..f0d487bec 100644 --- a/applications/services/cli/cli_command_gpio.c +++ b/applications/services/cli/cli_command_gpio.c @@ -1,5 +1,6 @@ #include "cli_command_gpio.h" +#include "core/string.h" #include #include #include @@ -36,26 +37,24 @@ void cli_command_gpio_print_usage() { } static bool pin_name_to_int(FuriString* pin_name, size_t* result) { - bool found = false; - bool debug = furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug); + bool is_debug_mode = furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug); for(size_t i = 0; i < COUNT_OF(cli_command_gpio_pins); i++) { - if(!furi_string_cmp(pin_name, cli_command_gpio_pins[i].name)) { - if(!cli_command_gpio_pins[i].debug || debug) { + if(furi_string_equal(pin_name, cli_command_gpio_pins[i].name)) { + if(!cli_command_gpio_pins[i].debug || is_debug_mode) { *result = i; - found = true; - break; + return true; } } } - return found; + return false; } static void gpio_print_pins(void) { printf("Wrong pin name. Available pins: "); - bool debug = furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug); + bool is_debug_mode = furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug); for(size_t i = 0; i < COUNT_OF(cli_command_gpio_pins); i++) { - if(!cli_command_gpio_pins[i].debug || debug) { + if(!cli_command_gpio_pins[i].debug || is_debug_mode) { printf("%s ", cli_command_gpio_pins[i].name); } } @@ -69,34 +68,29 @@ typedef enum { } GpioParseReturn; static GpioParseReturn gpio_command_parse(FuriString* args, size_t* pin_num, uint8_t* value) { - FuriString* pin_name; - pin_name = furi_string_alloc(); + GpioParseReturn ret = GpioParseReturnOk; + FuriString* pin_name = furi_string_alloc(); - size_t ws = furi_string_search_char(args, ' '); - if(ws == FURI_STRING_FAILURE) { - return GpioParseReturnCmdSyntaxError; - } + do { + if(!args_read_string_and_trim(args, pin_name)) { + ret = GpioParseReturnCmdSyntaxError; + break; + } else if(!pin_name_to_int(pin_name, pin_num)) { + ret = GpioParseReturnPinError; + break; + } - furi_string_set_n(pin_name, args, 0, ws); - furi_string_right(args, ws); - furi_string_trim(args); + int pin_mode; //-V779 + if(!args_read_int_and_trim(args, &pin_mode) || pin_mode < 0 || pin_mode > 1) { + ret = GpioParseReturnValueError; + break; + } - if(!pin_name_to_int(pin_name, pin_num)) { - furi_string_free(pin_name); - return GpioParseReturnPinError; - } + *value = pin_mode; + } while(false); furi_string_free(pin_name); - - if(!furi_string_cmp(args, "0")) { - *value = 0; - } else if(!furi_string_cmp(args, "1")) { - *value = 1; - } else { - return GpioParseReturnValueError; - } - - return GpioParseReturnOk; + return ret; } void cli_command_gpio_mode(Cli* cli, FuriString* args, void* context) { @@ -111,7 +105,7 @@ void cli_command_gpio_mode(Cli* cli, FuriString* args, void* context) { if(err == GpioParseReturnCmdSyntaxError) { cli_print_usage("gpio mode", " <0|1>", furi_string_get_cstr(args)); return; - } else if(err == GpioParseReturnPinError) { + } else if(err == GpioParseReturnPinError) { //-V547 gpio_print_pins(); return; } else if(err == GpioParseReturnValueError) { @@ -119,7 +113,7 @@ void cli_command_gpio_mode(Cli* cli, FuriString* args, void* context) { return; } - if(cli_command_gpio_pins[num].debug) { + if(cli_command_gpio_pins[num].debug) { //-V779 printf( "Changing this pin mode may damage hardware. Are you sure you want to continue? (y/n)?\r\n"); char c = cli_getc(cli); @@ -149,7 +143,7 @@ void cli_command_gpio_read(Cli* cli, FuriString* args, void* context) { return; } - if(LL_GPIO_MODE_INPUT != + if(LL_GPIO_MODE_INPUT != //-V779 LL_GPIO_GetPinMode( cli_command_gpio_pins[num].pin->port, cli_command_gpio_pins[num].pin->pin)) { printf("Err: pin %s is not set as an input.", cli_command_gpio_pins[num].name); @@ -171,7 +165,7 @@ void cli_command_gpio_set(Cli* cli, FuriString* args, void* context) { if(err == GpioParseReturnCmdSyntaxError) { cli_print_usage("gpio set", " <0|1>", furi_string_get_cstr(args)); return; - } else if(err == GpioParseReturnPinError) { + } else if(err == GpioParseReturnPinError) { //-V547 gpio_print_pins(); return; } else if(err == GpioParseReturnValueError) { @@ -179,7 +173,7 @@ void cli_command_gpio_set(Cli* cli, FuriString* args, void* context) { return; } - if(LL_GPIO_MODE_OUTPUT != + if(LL_GPIO_MODE_OUTPUT != //-V779 LL_GPIO_GetPinMode( cli_command_gpio_pins[num].pin->port, cli_command_gpio_pins[num].pin->pin)) { printf("Err: pin %s is not set as an output.", cli_command_gpio_pins[num].name); diff --git a/applications/services/cli/cli_commands.c b/applications/services/cli/cli_commands.c index 3534a5418..4414d365f 100644 --- a/applications/services/cli/cli_commands.c +++ b/applications/services/cli/cli_commands.c @@ -354,7 +354,7 @@ void cli_command_ps(Cli* cli, FuriString* args, void* context) { for(uint8_t i = 0; i < thread_num; i++) { TaskControlBlock* tcb = (TaskControlBlock*)threads_ids[i]; printf( - "%-20s 0x%-12lx %-8d %-8ld %-8ld\r\n", + "%-20s 0x%-12lx %-8zu %-8lu %-8lu\r\n", furi_thread_get_name(threads_ids[i]), (uint32_t)tcb->pxStack, memmgr_heap_get_thread_memory(threads_ids[i]), @@ -369,13 +369,13 @@ void cli_command_free(Cli* cli, FuriString* args, void* context) { UNUSED(args); UNUSED(context); - printf("Free heap size: %d\r\n", memmgr_get_free_heap()); - printf("Total heap size: %d\r\n", memmgr_get_total_heap()); - printf("Minimum heap size: %d\r\n", memmgr_get_minimum_free_heap()); - printf("Maximum heap block: %d\r\n", memmgr_heap_get_max_free_block()); + printf("Free heap size: %zu\r\n", memmgr_get_free_heap()); + printf("Total heap size: %zu\r\n", memmgr_get_total_heap()); + printf("Minimum heap size: %zu\r\n", memmgr_get_minimum_free_heap()); + printf("Maximum heap block: %zu\r\n", memmgr_heap_get_max_free_block()); - printf("Pool free: %d\r\n", memmgr_pool_get_free()); - printf("Maximum pool block: %d\r\n", memmgr_pool_get_max_block()); + printf("Pool free: %zu\r\n", memmgr_pool_get_free()); + printf("Maximum pool block: %zu\r\n", memmgr_pool_get_max_block()); } void cli_command_free_blocks(Cli* cli, FuriString* args, void* context) { diff --git a/applications/services/crypto/crypto_cli.c b/applications/services/crypto/crypto_cli.c index 1b26ba9fb..a286f4457 100644 --- a/applications/services/crypto/crypto_cli.c +++ b/applications/services/crypto/crypto_cli.c @@ -142,7 +142,7 @@ void crypto_cli_decrypt(Cli* cli, FuriString* args) { if(args_read_hex_bytes(hex_input, input, size)) { if(furi_hal_crypto_decrypt(input, output, size)) { printf("Decrypted data:\r\n"); - printf("%s\r\n", output); + printf("%s\r\n", output); //-V576 } else { printf("Failed to decrypt\r\n"); } diff --git a/applications/services/desktop/animations/animation_manager.c b/applications/services/desktop/animations/animation_manager.c index 9c22d1314..f4c8f17a3 100644 --- a/applications/services/desktop/animations/animation_manager.c +++ b/applications/services/desktop/animations/animation_manager.c @@ -244,10 +244,8 @@ static bool animation_manager_check_blocking(AnimationManager* animation_manager furi_record_close(RECORD_DOLPHIN); if(!blocking_animation && stats.level_up_is_pending) { blocking_animation = animation_storage_find_animation(NEW_MAIL_ANIMATION_NAME); - furi_assert(blocking_animation); - if(blocking_animation) { - animation_manager->levelup_pending = true; - } + furi_check(blocking_animation); + animation_manager->levelup_pending = true; } if(blocking_animation) { @@ -448,7 +446,7 @@ void animation_manager_unload_and_stall_animation(AnimationManager* animation_ma if(animation_manager->state == AnimationManagerStateBlocked) { animation_manager->state = AnimationManagerStateFreezedBlocked; - } else if(animation_manager->state == AnimationManagerStateIdle) { + } else if(animation_manager->state == AnimationManagerStateIdle) { //-V547 animation_manager->state = AnimationManagerStateFreezedIdle; animation_manager->freezed_animation_time_left = @@ -491,7 +489,7 @@ void animation_manager_load_and_continue_animation(AnimationManager* animation_m furi_assert(restore_animation); animation_manager_replace_current_animation(animation_manager, restore_animation); animation_manager->state = AnimationManagerStateBlocked; - } else if(animation_manager->state == AnimationManagerStateFreezedIdle) { + } else if(animation_manager->state == AnimationManagerStateFreezedIdle) { //-V547 /* check if we missed some system notifications, and set current_animation */ bool blocked = animation_manager_check_blocking(animation_manager); if(!blocked) { diff --git a/applications/services/desktop/animations/animation_storage.c b/applications/services/desktop/animations/animation_storage.c index 0727fd6ae..2c16cf726 100644 --- a/applications/services/desktop/animations/animation_storage.c +++ b/applications/services/desktop/animations/animation_storage.c @@ -360,7 +360,6 @@ static bool animation_storage_load_bubbles(BubbleAnimation* animation, FlipperFo if(u32value > 20) break; animation->frame_bubble_sequences_count = u32value; if(animation->frame_bubble_sequences_count == 0) { - animation->frame_bubble_sequences = NULL; success = true; break; } @@ -481,7 +480,7 @@ static BubbleAnimation* animation_storage_load_animation(const char* name) { if(!animation_storage_load_frames(storage, name, animation, u32array, width, height)) break; - if(!flipper_format_read_uint32(ff, "Active cycles", &u32value, 1)) break; + if(!flipper_format_read_uint32(ff, "Active cycles", &u32value, 1)) break; //-V779 animation->active_cycles = u32value; if(!flipper_format_read_uint32(ff, "Frame rate", &u32value, 1)) break; FURI_CONST_ASSIGN(animation->icon_animation.frame_rate, u32value); @@ -500,7 +499,7 @@ static BubbleAnimation* animation_storage_load_animation(const char* name) { free(u32array); } - if(!success) { + if(!success) { //-V547 if(animation->frame_order) { free((void*)animation->frame_order); } diff --git a/applications/services/desktop/helpers/slideshow.c b/applications/services/desktop/helpers/slideshow.c index b4d85cb90..a8e132779 100644 --- a/applications/services/desktop/helpers/slideshow.c +++ b/applications/services/desktop/helpers/slideshow.c @@ -41,7 +41,7 @@ Slideshow* slideshow_alloc() { void slideshow_free(Slideshow* slideshow) { Icon* icon = &slideshow->icon; - if(icon) { + if(icon) { //-V547 for(int frame_idx = 0; frame_idx < icon->frame_count; ++frame_idx) { uint8_t* frame_data = (uint8_t*)icon->frames[frame_idx]; free(frame_data); diff --git a/applications/services/desktop/views/desktop_view_debug.c b/applications/services/desktop/views/desktop_view_debug.c index f9c8aedc2..e679cf636 100644 --- a/applications/services/desktop/views/desktop_view_debug.c +++ b/applications/services/desktop/views/desktop_view_debug.c @@ -52,7 +52,7 @@ void desktop_debug_render(Canvas* canvas, void* model) { #ifdef SRV_BT c2_ver = ble_glue_get_c2_info(); #endif - if(!ver) { + if(!ver) { //-V1051 canvas_draw_str(canvas, 0, 30 + STATUS_BAR_Y_SHIFT, "No info"); return; } @@ -88,19 +88,19 @@ void desktop_debug_render(Canvas* canvas, void* model) { uint32_t remaining = dolphin_state_xp_to_levelup(m->icounter); canvas_set_font(canvas, FontSecondary); - snprintf(buffer, sizeof(buffer), "Icounter: %ld Butthurt %ld", m->icounter, m->butthurt); + 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: %ld To level up: %ld", + "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), "%ld", (uint32_t)m->timestamp); + 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"); diff --git a/applications/services/desktop/views/desktop_view_lock_menu.c b/applications/services/desktop/views/desktop_view_lock_menu.c index 486be23b5..52570f8ca 100644 --- a/applications/services/desktop/views/desktop_view_lock_menu.c +++ b/applications/services/desktop/views/desktop_view_lock_menu.c @@ -53,7 +53,7 @@ void desktop_lock_menu_draw_callback(Canvas* canvas, void* model) { canvas_draw_icon(canvas, 116, 0 + STATUS_BAR_Y_SHIFT, &I_DoorRight_70x55); canvas_set_font(canvas, FontSecondary); - for(uint8_t i = 0; i < DesktopLockMenuIndexTotalCount; ++i) { + for(size_t i = 0; i < DesktopLockMenuIndexTotalCount; ++i) { const char* str = NULL; if(i == DesktopLockMenuIndexLock) { @@ -64,7 +64,7 @@ void desktop_lock_menu_draw_callback(Canvas* canvas, void* model) { } else { str = "Set PIN"; } - } else if(i == DesktopLockMenuIndexDummy) { + } else if(i == DesktopLockMenuIndexDummy) { //-V547 if(m->dummy_mode) { str = "Brainiac Mode"; } else { @@ -72,7 +72,7 @@ void desktop_lock_menu_draw_callback(Canvas* canvas, void* model) { } } - if(str) + if(str) //-V547 canvas_draw_str_aligned( canvas, 64, 9 + (i * 17) + STATUS_BAR_Y_SHIFT, AlignCenter, AlignCenter, str); diff --git a/applications/services/desktop/views/desktop_view_pin_timeout.c b/applications/services/desktop/views/desktop_view_pin_timeout.c index 6e1e807fd..e64c264ff 100644 --- a/applications/services/desktop/views/desktop_view_pin_timeout.c +++ b/applications/services/desktop/views/desktop_view_pin_timeout.c @@ -67,7 +67,7 @@ static void desktop_view_pin_timeout_draw(Canvas* canvas, void* _model) { canvas_set_font(canvas, FontSecondary); char str[30] = {0}; - snprintf(str, sizeof(str), "Timeout: %lds", model->time_left); + snprintf(str, sizeof(str), "Timeout: %lus", model->time_left); canvas_draw_str_aligned(canvas, 64, 38, AlignCenter, AlignCenter, str); } diff --git a/applications/services/dolphin/helpers/dolphin_state.c b/applications/services/dolphin/helpers/dolphin_state.c index 10cb85c28..14f080464 100644 --- a/applications/services/dolphin/helpers/dolphin_state.c +++ b/applications/services/dolphin/helpers/dolphin_state.c @@ -171,7 +171,7 @@ void dolphin_state_on_deed(DolphinState* dolphin_state, DolphinDeed deed) { FURI_LOG_D( TAG, - "icounter %ld, butthurt %ld", + "icounter %lu, butthurt %ld", dolphin_state->data.icounter, dolphin_state->data.butthurt); } diff --git a/applications/services/gui/elements.c b/applications/services/gui/elements.c index 6b796ed5b..cd4c105ae 100644 --- a/applications/services/gui/elements.c +++ b/applications/services/gui/elements.c @@ -291,11 +291,11 @@ void elements_multiline_text(Canvas* canvas, uint8_t x, uint8_t y, const char* t end = strchr(start, '\n'); if(end) { furi_string_set_strn(str, start, end - start); + start = end + 1; } else { furi_string_set(str, start); } canvas_draw_str(canvas, x, y, furi_string_get_cstr(str)); - start = end + 1; y += font_height; } while(end && y < 64); furi_string_free(str); diff --git a/applications/services/gui/modules/button_panel.c b/applications/services/gui/modules/button_panel.c index 47b6ed488..8f29c6542 100644 --- a/applications/services/gui/modules/button_panel.c +++ b/applications/services/gui/modules/button_panel.c @@ -172,7 +172,7 @@ void button_panel_add_item( void* callback_context) { furi_assert(button_panel); - with_view_model( + with_view_model( //-V773 button_panel->view, ButtonPanelModel * model, { diff --git a/applications/services/gui/modules/byte_input.c b/applications/services/gui/modules/byte_input.c index bc19f0eee..82de129f5 100644 --- a/applications/services/gui/modules/byte_input.c +++ b/applications/services/gui/modules/byte_input.c @@ -71,11 +71,13 @@ static uint8_t byte_input_get_row_size(uint8_t row_index) { switch(row_index + 1) { case 1: - row_size = sizeof(keyboard_keys_row_1) / sizeof(ByteInputKey); + row_size = COUNT_OF(keyboard_keys_row_1); break; case 2: - row_size = sizeof(keyboard_keys_row_2) / sizeof(ByteInputKey); + row_size = COUNT_OF(keyboard_keys_row_2); break; + default: + furi_crash(NULL); } return row_size; @@ -97,6 +99,8 @@ static const ByteInputKey* byte_input_get_row(uint8_t row_index) { case 2: row = keyboard_keys_row_2; break; + default: + furi_crash(NULL); } return row; @@ -383,6 +387,7 @@ static void byte_input_dec_selected_byte(ByteInputModel* model) { if(model->selected_byte > 0) { model->selected_byte -= 1; + furi_assert(model->selected_byte >= model->first_visible_byte); if(model->selected_byte - model->first_visible_byte < 1) { if(model->first_visible_byte > 0) { model->first_visible_byte--; diff --git a/applications/services/gui/modules/file_browser.c b/applications/services/gui/modules/file_browser.c index 57e0018ec..d21a48b54 100644 --- a/applications/services/gui/modules/file_browser.c +++ b/applications/services/gui/modules/file_browser.c @@ -514,7 +514,7 @@ static void browser_draw_list(Canvas* canvas, FileBrowserModel* model) { scroll_counter = 0; } - if(custom_icon_data) { + if(custom_icon_data) { //-V547 // Currently only 10*10 icons are supported canvas_draw_bitmap( canvas, 2, Y_OFFSET + 1 + i * FRAME_HEIGHT, 10, 10, custom_icon_data); @@ -657,9 +657,7 @@ static bool file_browser_view_input_callback(InputEvent* event, void* context) { if(!is_root && !file_browser_worker_is_in_start_folder(browser->worker)) { consumed = true; - if(!is_root) { - file_browser_worker_folder_exit(browser->worker); - } + file_browser_worker_folder_exit(browser->worker); } } } diff --git a/applications/services/gui/modules/file_browser_worker.c b/applications/services/gui/modules/file_browser_worker.c index d8b515d03..a97a4d71a 100644 --- a/applications/services/gui/modules/file_browser_worker.c +++ b/applications/services/gui/modules/file_browser_worker.c @@ -375,7 +375,7 @@ BrowserWorker* file_browser_worker_alloc( const char* filter_ext, bool skip_assets, bool hide_dot_files) { - BrowserWorker* browser = malloc(sizeof(BrowserWorker)); //-V773 + BrowserWorker* browser = malloc(sizeof(BrowserWorker)); idx_last_array_init(browser->idx_last); @@ -395,7 +395,7 @@ BrowserWorker* file_browser_worker_alloc( furi_thread_start(browser->thread); return browser; -} +} //-V773 void file_browser_worker_free(BrowserWorker* browser) { furi_assert(browser); diff --git a/applications/services/gui/modules/submenu.c b/applications/services/gui/modules/submenu.c index b7152a3d2..f8af44fdb 100644 --- a/applications/services/gui/modules/submenu.c +++ b/applications/services/gui/modules/submenu.c @@ -225,8 +225,11 @@ void submenu_set_selected_item(Submenu* submenu, uint32_t index) { if(items_size <= items_on_screen) { model->window_position = 0; - } else if(model->window_position >= items_size - items_on_screen) { - model->window_position = items_size - items_on_screen; + } else { + const size_t pos = items_size - items_on_screen; + if(model->window_position > pos) { + model->window_position = pos; + } } }, true); @@ -242,8 +245,7 @@ void submenu_process_up(Submenu* submenu) { if(model->position > 0) { model->position--; - if((model->position - model->window_position < 1) && - (model->window_position > 0)) { + if((model->position == model->window_position) && (model->window_position > 0)) { model->window_position--; } } else { diff --git a/applications/services/gui/modules/text_input.c b/applications/services/gui/modules/text_input.c index 540e4b7c4..7c419d96a 100644 --- a/applications/services/gui/modules/text_input.c +++ b/applications/services/gui/modules/text_input.c @@ -92,14 +92,16 @@ static uint8_t get_row_size(uint8_t row_index) { switch(row_index + 1) { case 1: - row_size = sizeof(keyboard_keys_row_1) / sizeof(TextInputKey); + row_size = COUNT_OF(keyboard_keys_row_1); break; case 2: - row_size = sizeof(keyboard_keys_row_2) / sizeof(TextInputKey); + row_size = COUNT_OF(keyboard_keys_row_2); break; case 3: - row_size = sizeof(keyboard_keys_row_3) / sizeof(TextInputKey); + row_size = COUNT_OF(keyboard_keys_row_3); break; + default: + furi_crash(NULL); } return row_size; @@ -118,6 +120,8 @@ static const TextInputKey* get_row(uint8_t row_index) { case 3: row = keyboard_keys_row_3; break; + default: + furi_crash(NULL); } return row; @@ -184,7 +188,7 @@ static void text_input_view_draw_callback(Canvas* canvas, void* _model) { canvas_set_font(canvas, FontKeyboard); - for(uint8_t row = 0; row <= keyboard_row_count; row++) { + for(uint8_t row = 0; row < keyboard_row_count; row++) { const uint8_t column_count = get_row_size(row); const TextInputKey* keys = get_row(row); @@ -303,7 +307,7 @@ static void text_input_handle_right(TextInput* text_input, TextInputModel* model static void text_input_handle_ok(TextInput* text_input, TextInputModel* model, bool shift) { char selected = get_selected_char(model); - uint8_t text_length = strlen(model->text_buffer); + size_t text_length = strlen(model->text_buffer); if(shift) { selected = char_to_uppercase(selected); @@ -481,7 +485,6 @@ void text_input_reset(TextInput* text_input) { text_input->view, TextInputModel * model, { - model->text_buffer_size = 0; model->header = ""; model->selected_row = 0; model->selected_column = 0; diff --git a/applications/services/gui/modules/validators.c b/applications/services/gui/modules/validators.c index 0463b1c26..9c5d0be84 100644 --- a/applications/services/gui/modules/validators.c +++ b/applications/services/gui/modules/validators.c @@ -18,15 +18,12 @@ bool validator_is_file_callback(const char* text, FuriString* error, void* conte } } - bool ret = true; FuriString* path = furi_string_alloc_printf( "%s/%s%s", instance->app_path_folder, text, instance->app_extension); Storage* storage = furi_record_open(RECORD_STORAGE); - if(storage_common_stat(storage, furi_string_get_cstr(path), NULL) == FSE_OK) { - ret = false; + const bool ret = storage_common_stat(storage, furi_string_get_cstr(path), NULL) != FSE_OK; + if(!ret) { furi_string_printf(error, "This name\nexists!\nChoose\nanother one."); - } else { - ret = true; } furi_string_free(path); furi_record_close(RECORD_STORAGE); diff --git a/applications/services/gui/modules/variable_item_list.c b/applications/services/gui/modules/variable_item_list.c index a9b89d63b..5060985e1 100644 --- a/applications/services/gui/modules/variable_item_list.c +++ b/applications/services/gui/modules/variable_item_list.c @@ -188,8 +188,8 @@ void variable_item_list_process_up(VariableItemList* variable_item_list) { uint8_t items_on_screen = 4; if(model->position > 0) { model->position--; - if(((model->position - model->window_position) < 1) && - model->window_position > 0) { + + if((model->position == model->window_position) && (model->window_position > 0)) { model->window_position--; } } else { diff --git a/applications/services/gui/modules/widget_elements/widget_element_button.c b/applications/services/gui/modules/widget_elements/widget_element_button.c index e3267058e..3bfae9df3 100644 --- a/applications/services/gui/modules/widget_elements/widget_element_button.c +++ b/applications/services/gui/modules/widget_elements/widget_element_button.c @@ -60,7 +60,7 @@ WidgetElement* widget_element_button_create( ButtonCallback callback, void* context) { // Allocate and init model - GuiButtonModel* model = malloc(sizeof(GuiButtonModel)); //-V773 + GuiButtonModel* model = malloc(sizeof(GuiButtonModel)); model->button_type = button_type; model->callback = callback; model->context = context; @@ -75,4 +75,4 @@ WidgetElement* widget_element_button_create( gui_button->model = model; return gui_button; -} +} //-V773 diff --git a/applications/services/gui/modules/widget_elements/widget_element_string.c b/applications/services/gui/modules/widget_elements/widget_element_string.c index feb22ad1c..4bf7dd693 100644 --- a/applications/services/gui/modules/widget_elements/widget_element_string.c +++ b/applications/services/gui/modules/widget_elements/widget_element_string.c @@ -62,4 +62,4 @@ WidgetElement* widget_element_string_create( gui_string->model = model; return gui_string; -} +} //-V773 diff --git a/applications/services/gui/modules/widget_elements/widget_element_string_multiline.c b/applications/services/gui/modules/widget_elements/widget_element_string_multiline.c index 9ad2a1a83..3fc6b309c 100644 --- a/applications/services/gui/modules/widget_elements/widget_element_string_multiline.c +++ b/applications/services/gui/modules/widget_elements/widget_element_string_multiline.c @@ -63,4 +63,4 @@ WidgetElement* widget_element_string_multiline_create( gui_string->model = model; return gui_string; -} +} //-V773 diff --git a/applications/services/gui/modules/widget_elements/widget_element_text_box.c b/applications/services/gui/modules/widget_elements/widget_element_text_box.c index 2c6948202..98f8e83d8 100644 --- a/applications/services/gui/modules/widget_elements/widget_element_text_box.c +++ b/applications/services/gui/modules/widget_elements/widget_element_text_box.c @@ -71,4 +71,4 @@ WidgetElement* widget_element_text_box_create( gui_string->model = model; return gui_string; -} +} //-V773 diff --git a/applications/services/gui/modules/widget_elements/widget_element_text_scroll.c b/applications/services/gui/modules/widget_elements/widget_element_text_scroll.c index a4d766389..d8fc11311 100644 --- a/applications/services/gui/modules/widget_elements/widget_element_text_scroll.c +++ b/applications/services/gui/modules/widget_elements/widget_element_text_scroll.c @@ -241,4 +241,4 @@ WidgetElement* widget_element_text_scroll_create( text_scroll->model_mutex = furi_mutex_alloc(FuriMutexTypeNormal); return text_scroll; -} +} //-V773 diff --git a/applications/services/gui/view.c b/applications/services/gui/view.c index 7ab6d15b7..50c05a406 100644 --- a/applications/services/gui/view.c +++ b/applications/services/gui/view.c @@ -86,7 +86,7 @@ void view_allocate_model(View* view, ViewModelType type, size_t size) { model->data = malloc(size); view->model = model; } else { - furi_assert(false); + furi_crash(NULL); } } @@ -103,7 +103,7 @@ void view_free_model(View* view) { free(model); view->model = NULL; } else { - furi_assert(false); + furi_crash(NULL); } } diff --git a/applications/services/input/input.c b/applications/services/input/input.c index 1d02df1e5..e1e581c9f 100644 --- a/applications/services/input/input.c +++ b/applications/services/input/input.c @@ -80,9 +80,7 @@ int32_t input_srv(void* p) { #ifdef SRV_CLI input->cli = furi_record_open(RECORD_CLI); - if(input->cli) { - cli_add_command(input->cli, "input", CliCommandFlagParallelSafe, input_cli, input); - } + cli_add_command(input->cli, "input", CliCommandFlagParallelSafe, input_cli, input); #endif input->pin_states = malloc(input_pins_count * sizeof(InputPinState)); diff --git a/applications/services/input/input_cli.c b/applications/services/input/input_cli.c index d9a8eaeba..f7e904b17 100644 --- a/applications/services/input/input_cli.c +++ b/applications/services/input/input_cli.c @@ -89,7 +89,7 @@ static void input_cli_send(Cli* cli, FuriString* args, Input* input) { parsed = true; } while(false); - if(parsed) { + if(parsed) { //-V547 furi_pubsub_publish(input->event_pubsub, &event); } else { input_cli_send_print_usage(); diff --git a/applications/services/loader/loader.c b/applications/services/loader/loader.c index 931719723..97d1e6e4e 100644 --- a/applications/services/loader/loader.c +++ b/applications/services/loader/loader.c @@ -280,7 +280,7 @@ static void loader_thread_state_callback(FuriThreadState thread_state, void* con furi_hal_power_insomnia_enter(); } } else if(thread_state == FuriThreadStateStopped) { - FURI_LOG_I(TAG, "Application stopped. Free heap: %d", memmgr_get_free_heap()); + FURI_LOG_I(TAG, "Application stopped. Free heap: %zu", memmgr_get_free_heap()); if(loader_instance->application_arguments) { free(loader_instance->application_arguments); diff --git a/applications/services/power/power_service/views/power_off.c b/applications/services/power/power_service/views/power_off.c index f14a18d7e..3a1addbac 100644 --- a/applications/services/power/power_service/views/power_off.c +++ b/applications/services/power/power_service/views/power_off.c @@ -26,7 +26,7 @@ static void power_off_draw_callback(Canvas* canvas, void* _model) { canvas_set_font(canvas, FontSecondary); if(model->response == PowerOffResponseDefault) { - snprintf(buff, sizeof(buff), "Charge me!\nOff in %lds!", model->time_left_sec); + snprintf(buff, sizeof(buff), "Charge me!\nOff in %lus!", model->time_left_sec); elements_multiline_text_aligned(canvas, 70, 23, AlignLeft, AlignTop, buff); elements_button_left(canvas, "Cancel"); diff --git a/applications/services/rpc/rpc_app.c b/applications/services/rpc/rpc_app.c index b96f043ac..cc18b6cec 100644 --- a/applications/services/rpc/rpc_app.c +++ b/applications/services/rpc/rpc_app.c @@ -39,9 +39,9 @@ static void rpc_system_app_start_process(const PB_Main* request, void* context) furi_assert(!rpc_app->last_id); furi_assert(!rpc_app->last_data); - FURI_LOG_D(TAG, "StartProcess: id %ld", request->command_id); + FURI_LOG_D(TAG, "StartProcess: id %lu", request->command_id); - PB_CommandStatus result = PB_CommandStatus_ERROR_APP_CANT_START; + PB_CommandStatus result; Loader* loader = furi_record_open(RECORD_LOADER); const char* app_name = request->content.app_start_request.name; @@ -62,7 +62,7 @@ static void rpc_system_app_start_process(const PB_Main* request, void* context) } else if(status == LoaderStatusOk) { result = PB_CommandStatus_OK; } else { - furi_crash("Programming Error"); + furi_crash(NULL); } } else { result = PB_CommandStatus_ERROR_INVALID_PARAMETERS; @@ -70,7 +70,7 @@ static void rpc_system_app_start_process(const PB_Main* request, void* context) furi_record_close(RECORD_LOADER); - FURI_LOG_D(TAG, "StartProcess: response id %ld, result %d", request->command_id, result); + FURI_LOG_D(TAG, "StartProcess: response id %lu, result %d", request->command_id, result); rpc_send_and_release_empty(session, request->command_id, result); } @@ -117,7 +117,7 @@ static void rpc_system_app_exit_request(const PB_Main* request, void* context) { PB_CommandStatus status; if(rpc_app->app_callback) { - FURI_LOG_D(TAG, "ExitRequest: id %ld", request->command_id); + FURI_LOG_D(TAG, "ExitRequest: id %lu", request->command_id); furi_assert(!rpc_app->last_id); furi_assert(!rpc_app->last_data); rpc_app->last_id = request->command_id; @@ -125,7 +125,7 @@ static void rpc_system_app_exit_request(const PB_Main* request, void* context) { } else { status = PB_CommandStatus_ERROR_APP_NOT_RUNNING; FURI_LOG_E( - TAG, "ExitRequest: APP_NOT_RUNNING, id %ld, status: %d", request->command_id, status); + TAG, "ExitRequest: APP_NOT_RUNNING, id %lu, status: %d", request->command_id, status); rpc_send_and_release_empty(session, request->command_id, status); } } @@ -142,7 +142,7 @@ static void rpc_system_app_load_file(const PB_Main* request, void* context) { PB_CommandStatus status; if(rpc_app->app_callback) { - FURI_LOG_D(TAG, "LoadFile: id %ld", request->command_id); + FURI_LOG_D(TAG, "LoadFile: id %lu", request->command_id); furi_assert(!rpc_app->last_id); furi_assert(!rpc_app->last_data); rpc_app->last_id = request->command_id; @@ -151,7 +151,7 @@ static void rpc_system_app_load_file(const PB_Main* request, void* context) { } else { status = PB_CommandStatus_ERROR_APP_NOT_RUNNING; FURI_LOG_E( - TAG, "LoadFile: APP_NOT_RUNNING, id %ld, status: %d", request->command_id, status); + TAG, "LoadFile: APP_NOT_RUNNING, id %lu, status: %d", request->command_id, status); rpc_send_and_release_empty(session, request->command_id, status); } } @@ -177,7 +177,7 @@ static void rpc_system_app_button_press(const PB_Main* request, void* context) { } else { status = PB_CommandStatus_ERROR_APP_NOT_RUNNING; FURI_LOG_E( - TAG, "ButtonPress: APP_NOT_RUNNING, id %ld, status: %d", request->command_id, status); + TAG, "ButtonPress: APP_NOT_RUNNING, id %lu, status: %d", request->command_id, status); rpc_send_and_release_empty(session, request->command_id, status); } } @@ -202,7 +202,7 @@ static void rpc_system_app_button_release(const PB_Main* request, void* context) } else { status = PB_CommandStatus_ERROR_APP_NOT_RUNNING; FURI_LOG_E( - TAG, "ButtonRelease: APP_NOT_RUNNING, id %ld, status: %d", request->command_id, status); + TAG, "ButtonRelease: APP_NOT_RUNNING, id %lu, status: %d", request->command_id, status); rpc_send_and_release_empty(session, request->command_id, status); } } @@ -300,7 +300,7 @@ void rpc_system_app_confirm(RpcAppSystem* rpc_app, RpcAppSystemEvent event, bool free(rpc_app->last_data); rpc_app->last_data = NULL; } - FURI_LOG_D(TAG, "AppConfirm: event %d last_id %ld status %d", event, last_id, status); + FURI_LOG_D(TAG, "AppConfirm: event %d last_id %lu status %d", event, last_id, status); rpc_send_and_release_empty(session, last_id, status); break; default: diff --git a/applications/services/rpc/rpc_cli.c b/applications/services/rpc/rpc_cli.c index 82023e316..d14b8eee2 100644 --- a/applications/services/rpc/rpc_cli.c +++ b/applications/services/rpc/rpc_cli.c @@ -44,7 +44,7 @@ void rpc_cli_command_start_session(Cli* cli, FuriString* args, void* context) { Rpc* rpc = context; uint32_t mem_before = memmgr_get_free_heap(); - FURI_LOG_D(TAG, "Free memory %ld", mem_before); + FURI_LOG_D(TAG, "Free memory %lu", mem_before); furi_hal_usb_lock(); RpcSession* rpc_session = rpc_session_open(rpc); diff --git a/applications/services/rpc/rpc_debug.c b/applications/services/rpc/rpc_debug.c index 8eb81dece..edc2b0025 100644 --- a/applications/services/rpc/rpc_debug.c +++ b/applications/services/rpc/rpc_debug.c @@ -10,7 +10,7 @@ static size_t rpc_debug_print_file_msg( for(size_t i = 0; i < msg_files_size; ++i, ++msg_file) { furi_string_cat_printf( str, - "%s[%c] size: %5ld", + "%s[%c] size: %5lu", prefix, msg_file->type == PB_Storage_File_FileType_DIR ? 'd' : 'f', msg_file->size); @@ -40,7 +40,7 @@ void rpc_debug_print_data(const char* prefix, uint8_t* buffer, size_t size) { str = furi_string_alloc(); furi_string_reserve(str, 100 + size * 5); - furi_string_cat_printf(str, "\r\n%s DEC(%d): {", prefix, size); + furi_string_cat_printf(str, "\r\n%s DEC(%zu): {", prefix, size); for(size_t i = 0; i < size; ++i) { furi_string_cat_printf(str, "%d, ", buffer[i]); } @@ -50,7 +50,7 @@ void rpc_debug_print_data(const char* prefix, uint8_t* buffer, size_t size) { furi_string_reset(str); furi_string_reserve(str, 100 + size * 3); - furi_string_cat_printf(str, "%s HEX(%d): {", prefix, size); + furi_string_cat_printf(str, "%s HEX(%zu): {", prefix, size); for(size_t i = 0; i < size; ++i) { furi_string_cat_printf(str, "%02X", buffer[i]); } @@ -66,7 +66,7 @@ void rpc_debug_print_message(const PB_Main* message) { furi_string_cat_printf( str, - "PB_Main: {\r\n\tresult: %d cmd_id: %ld (%s)\r\n", + "PB_Main: {\r\n\tresult: %d cmd_id: %lu (%s)\r\n", message->command_status, message->command_id, message->has_next ? "has_next" : "last"); @@ -110,9 +110,9 @@ void rpc_debug_print_message(const PB_Main* message) { } case PB_Main_storage_md5sum_response_tag: { furi_string_cat_printf(str, "\tmd5sum_response {\r\n"); - const char* path = message->content.storage_md5sum_response.md5sum; - if(path) { - furi_string_cat_printf(str, "\t\tmd5sum: %s\r\n", path); + const char* md5sum = message->content.storage_md5sum_response.md5sum; + if(md5sum) { //-V547 + furi_string_cat_printf(str, "\t\tmd5sum: %s\r\n", md5sum); } break; } diff --git a/applications/services/rpc/rpc_storage.c b/applications/services/rpc/rpc_storage.c index 3c6ff7f94..c4493cc74 100644 --- a/applications/services/rpc/rpc_storage.c +++ b/applications/services/rpc/rpc_storage.c @@ -597,7 +597,7 @@ static void rpc_system_storage_md5sum_process(const PB_Main* request, void* cont char* md5sum = response.content.storage_md5sum_response.md5sum; size_t md5sum_size = sizeof(response.content.storage_md5sum_response.md5sum); (void)md5sum_size; - furi_assert(hash_size <= ((md5sum_size - 1) / 2)); + furi_assert(hash_size <= ((md5sum_size - 1) / 2)); //-V547 for(uint8_t i = 0; i < hash_size; i++) { md5sum += snprintf(md5sum, md5sum_size, "%02x", hash[i]); } diff --git a/applications/services/rpc/rpc_system.c b/applications/services/rpc/rpc_system.c index a17be7d2d..77dca4a1a 100644 --- a/applications/services/rpc/rpc_system.c +++ b/applications/services/rpc/rpc_system.c @@ -30,7 +30,6 @@ static void rpc_system_system_ping_process(const PB_Main* request, void* context } PB_Main response = PB_Main_init_default; - response.has_next = false; response.command_status = PB_CommandStatus_OK; response.command_id = request->command_id; response.which_content = PB_Main_system_ping_response_tag; diff --git a/applications/services/storage/storage_external_api.c b/applications/services/storage/storage_external_api.c index 2c3a7bfc9..6929a9cbd 100644 --- a/applications/services/storage/storage_external_api.c +++ b/applications/services/storage/storage_external_api.c @@ -385,9 +385,7 @@ FS_Error storage_common_remove(Storage* storage, const char* path) { FS_Error storage_common_rename(Storage* storage, const char* old_path, const char* new_path) { FS_Error error = storage_common_copy(storage, old_path, new_path); if(error == FSE_OK) { - if(storage_simply_remove_recursive(storage, old_path)) { - error = FSE_OK; - } else { + if(!storage_simply_remove_recursive(storage, old_path)) { error = FSE_INTERNAL; } } @@ -743,7 +741,7 @@ bool storage_simply_remove_recursive(Storage* storage, const char* path) { return true; } - char* name = malloc(MAX_NAME_LENGTH + 1); + char* name = malloc(MAX_NAME_LENGTH + 1); //-V799 File* dir = storage_file_alloc(storage); cur_dir = furi_string_alloc_set(path); bool go_deeper = false; @@ -790,7 +788,7 @@ bool storage_simply_remove_recursive(Storage* storage, const char* path) { furi_string_free(cur_dir); free(name); return result; -} +} //-V773 bool storage_simply_remove(Storage* storage, const char* path) { FS_Error result; diff --git a/applications/services/storage/storage_glue.c b/applications/services/storage/storage_glue.c index c6ff08bdc..22f2e3dfa 100644 --- a/applications/services/storage/storage_glue.c +++ b/applications/services/storage/storage_glue.c @@ -17,7 +17,7 @@ void storage_file_init_set(StorageFile* obj, const StorageFile* src) { obj->path = furi_string_alloc_set(src->path); } -void storage_file_set(StorageFile* obj, const StorageFile* src) { +void storage_file_set(StorageFile* obj, const StorageFile* src) { //-V524 obj->file = src->file; obj->type = src->type; obj->file_data = src->file_data; @@ -172,7 +172,6 @@ void storage_push_storage_file( StorageType type, StorageData* storage) { StorageFile* storage_file = StorageFileList_push_new(storage->files); - furi_check(storage_file != NULL); file->file_id = (uint32_t)storage_file; storage_file->file = file; diff --git a/applications/services/storage/storages/storage_int.c b/applications/services/storage/storages/storage_int.c index 4fa5d130c..2534d47a1 100644 --- a/applications/services/storage/storages/storage_int.c +++ b/applications/services/storage/storages/storage_int.c @@ -77,7 +77,7 @@ static int storage_int_device_read( FURI_LOG_T( TAG, - "Device read: block %ld, off %ld, buffer: %p, size %ld, translated address: %p", + "Device read: block %lu, off %lu, buffer: %p, size %lu, translated address: %p", block, off, buffer, @@ -100,7 +100,7 @@ static int storage_int_device_prog( FURI_LOG_T( TAG, - "Device prog: block %ld, off %ld, buffer: %p, size %ld, translated address: %p", + "Device prog: block %lu, off %lu, buffer: %p, size %lu, translated address: %p", block, off, buffer, @@ -122,7 +122,7 @@ static int storage_int_device_erase(const struct lfs_config* c, lfs_block_t bloc LFSData* lfs_data = c->context; size_t page = lfs_data->start_page + block; - FURI_LOG_D(TAG, "Device erase: page %ld, translated page: %x", block, page); + FURI_LOG_D(TAG, "Device erase: page %lu, translated page: %zx", block, page); furi_hal_flash_erase(page); return 0; @@ -240,56 +240,38 @@ static void storage_int_lfs_mount(LFSData* lfs_data, StorageData* storage) { /****************** Common Functions ******************/ static FS_Error storage_int_parse_error(int error) { - FS_Error result = FSE_INTERNAL; + FS_Error result; if(error >= LFS_ERR_OK) { result = FSE_OK; } else { switch(error) { - case LFS_ERR_IO: - result = FSE_INTERNAL; - break; - case LFS_ERR_CORRUPT: - result = FSE_INTERNAL; - break; case LFS_ERR_NOENT: result = FSE_NOT_EXIST; break; case LFS_ERR_EXIST: result = FSE_EXIST; break; - case LFS_ERR_NOTDIR: - result = FSE_INVALID_NAME; - break; - case LFS_ERR_ISDIR: - result = FSE_INVALID_NAME; - break; case LFS_ERR_NOTEMPTY: result = FSE_DENIED; break; - case LFS_ERR_BADF: - result = FSE_INVALID_NAME; - break; - case LFS_ERR_FBIG: - result = FSE_INTERNAL; - break; case LFS_ERR_INVAL: - result = FSE_INVALID_PARAMETER; - break; - case LFS_ERR_NOSPC: - result = FSE_INTERNAL; - break; - case LFS_ERR_NOMEM: - result = FSE_INTERNAL; - break; case LFS_ERR_NOATTR: result = FSE_INVALID_PARAMETER; break; + case LFS_ERR_BADF: + case LFS_ERR_ISDIR: + case LFS_ERR_NOTDIR: case LFS_ERR_NAMETOOLONG: result = FSE_INVALID_NAME; break; + case LFS_ERR_IO: + case LFS_ERR_FBIG: + case LFS_ERR_NOSPC: + case LFS_ERR_NOMEM: + case LFS_ERR_CORRUPT: default: - break; + result = FSE_INTERNAL; } } @@ -740,7 +722,7 @@ void storage_int_init(StorageData* storage) { LFSData* lfs_data = storage_int_lfs_data_alloc(); FURI_LOG_I( TAG, - "Config: start %p, read %ld, write %ld, page size: %ld, page count: %ld, cycles: %ld", + "Config: start %p, read %lu, write %lu, page size: %lu, page count: %lu, cycles: %ld", (void*)lfs_data->start_address, lfs_data->config.read_size, lfs_data->config.prog_size, diff --git a/applications/settings/about/about.c b/applications/settings/about/about.c index 1719e188d..560a683cf 100644 --- a/applications/settings/about/about.c +++ b/applications/settings/about/about.c @@ -119,7 +119,7 @@ static DialogMessageButton fw_version_screen(DialogsApp* dialogs, DialogMessage* c2_ver = ble_glue_get_c2_info(); #endif - if(!ver) { + if(!ver) { //-V1051 furi_string_cat_printf(buffer, "No info\n"); } else { furi_string_cat_printf( @@ -208,4 +208,4 @@ int32_t about_settings_app(void* p) { furi_record_close(RECORD_GUI); return 0; -} \ No newline at end of file +} 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 cf474c546..94c5ee9f0 100644 --- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_favorite.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_favorite.c @@ -84,7 +84,7 @@ bool desktop_settings_scene_favorite_on_event(void* context, SceneManagerEvent e scene_manager_get_scene_state(app->scene_manager, DesktopSettingsAppSceneFavorite); if(event.type == SceneManagerEventTypeCustom) { - if(strcmp(FLIPPER_APPS[event.event].name, FAP_LOADER_APP_NAME)) { + if(strcmp(FLIPPER_APPS[event.event].name, FAP_LOADER_APP_NAME) != 0) { if(primary_favorite) { app->settings.favorite_primary.is_external = false; strncpy( diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_setup_howto.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_setup_howto.c index b8d630f2e..ec128246f 100644 --- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_setup_howto.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_setup_howto.c @@ -32,9 +32,7 @@ bool desktop_settings_scene_pin_setup_howto_on_event(void* context, SceneManager consumed = true; break; default: - furi_assert(0); - consumed = true; - break; + furi_crash(NULL); } } return consumed; diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_setup_howto2.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_setup_howto2.c index 477d1f27a..44b8e1bf7 100644 --- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_setup_howto2.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_setup_howto2.c @@ -52,9 +52,7 @@ bool desktop_settings_scene_pin_setup_howto2_on_event(void* context, SceneManage break; } default: - furi_assert(0); - consumed = true; - break; + furi_crash(NULL); } } return consumed; diff --git a/applications/settings/power_settings_app/views/battery_info.c b/applications/settings/power_settings_app/views/battery_info.c index d760164b9..5353a2e2a 100644 --- a/applications/settings/power_settings_app/views/battery_info.c +++ b/applications/settings/power_settings_app/views/battery_info.c @@ -49,7 +49,7 @@ static void draw_battery(Canvas* canvas, BatteryInfoModel* data, int x, int y) { snprintf( value, sizeof(value), - "%ld.%ldV %ldmA", + "%lu.%luV %lumA", (uint32_t)(data->vbus_voltage), (uint32_t)(data->vbus_voltage * 10) % 10, charge_current); @@ -75,7 +75,7 @@ static void draw_battery(Canvas* canvas, BatteryInfoModel* data, int x, int y) { snprintf( value, sizeof(value), - "%ld.%ldV", + "%lu.%luV", (uint32_t)(data->charging_voltage), (uint32_t)(data->charging_voltage * 10) % 10); } else { @@ -100,14 +100,14 @@ static void battery_info_draw_callback(Canvas* canvas, void* context) { char voltage[10]; char health[10]; - snprintf(batt_level, sizeof(batt_level), "%ld%%", (uint32_t)model->charge); - snprintf(temperature, sizeof(temperature), "%ld C", (uint32_t)model->gauge_temperature); + snprintf(batt_level, sizeof(batt_level), "%lu%%", (uint32_t)model->charge); + snprintf(temperature, sizeof(temperature), "%lu C", (uint32_t)model->gauge_temperature); snprintf( voltage, sizeof(voltage), - "%ld.%01ld V", + "%lu.%01lu V", (uint32_t)model->gauge_voltage, - (uint32_t)(model->gauge_voltage * 10) % 10); + (uint32_t)(model->gauge_voltage * 10) % 10UL); snprintf(health, sizeof(health), "%d%%", model->health); draw_stat(canvas, 8, 42, &I_Battery_16x16, batt_level); diff --git a/applications/settings/storage_settings/scenes/storage_settings_scene_format_confirm.c b/applications/settings/storage_settings/scenes/storage_settings_scene_format_confirm.c index 261ef1997..8af065bf8 100644 --- a/applications/settings/storage_settings/scenes/storage_settings_scene_format_confirm.c +++ b/applications/settings/storage_settings/scenes/storage_settings_scene_format_confirm.c @@ -40,8 +40,6 @@ bool storage_settings_scene_format_confirm_on_event(void* context, SceneManagerE if(event.type == SceneManagerEventTypeCustom) { switch(event.event) { case DialogExResultLeft: - consumed = scene_manager_previous_scene(app->scene_manager); - break; case DialogExResultCenter: consumed = scene_manager_previous_scene(app->scene_manager); break; diff --git a/applications/settings/storage_settings/scenes/storage_settings_scene_sd_info.c b/applications/settings/storage_settings/scenes/storage_settings_scene_sd_info.c index ede610d0e..0c398ed5b 100644 --- a/applications/settings/storage_settings/scenes/storage_settings_scene_sd_info.c +++ b/applications/settings/storage_settings/scenes/storage_settings_scene_sd_info.c @@ -47,8 +47,6 @@ bool storage_settings_scene_sd_info_on_event(void* context, SceneManagerEvent ev if(event.type == SceneManagerEventTypeCustom) { switch(event.event) { case DialogExResultLeft: - consumed = scene_manager_previous_scene(app->scene_manager); - break; case DialogExResultCenter: consumed = scene_manager_previous_scene(app->scene_manager); break; diff --git a/applications/settings/storage_settings/scenes/storage_settings_scene_unmount_confirm.c b/applications/settings/storage_settings/scenes/storage_settings_scene_unmount_confirm.c index 2b485b7f7..0c15116be 100644 --- a/applications/settings/storage_settings/scenes/storage_settings_scene_unmount_confirm.c +++ b/applications/settings/storage_settings/scenes/storage_settings_scene_unmount_confirm.c @@ -41,8 +41,6 @@ bool storage_settings_scene_unmount_confirm_on_event(void* context, SceneManager if(event.type == SceneManagerEventTypeCustom) { switch(event.event) { case DialogExResultCenter: - consumed = scene_manager_previous_scene(app->scene_manager); - break; case DialogExResultLeft: consumed = scene_manager_previous_scene(app->scene_manager); break; diff --git a/applications/system/updater/util/update_task_worker_backup.c b/applications/system/updater/util/update_task_worker_backup.c index ce62da2a1..1f88d4f44 100644 --- a/applications/system/updater/util/update_task_worker_backup.c +++ b/applications/system/updater/util/update_task_worker_backup.c @@ -176,7 +176,7 @@ int32_t update_task_worker_backup_restore(void* context) { if(boot_mode == FuriHalRtcBootModePreUpdate) { success = update_task_pre_update(update_task); - } else if(boot_mode == FuriHalRtcBootModePostUpdate) { + } else if(boot_mode == FuriHalRtcBootModePostUpdate) { //-V547 success = update_task_post_update(update_task); if(success) { update_operation_disarm(); diff --git a/applications/system/updater/util/update_task_worker_flasher.c b/applications/system/updater/util/update_task_worker_flasher.c index 7358a6334..63024ced9 100644 --- a/applications/system/updater/util/update_task_worker_flasher.c +++ b/applications/system/updater/util/update_task_worker_flasher.c @@ -143,7 +143,6 @@ static void update_task_wait_for_restart(UpdateTask* update_task) { } static bool update_task_write_stack(UpdateTask* update_task) { - bool success = false; UpdateManifest* manifest = update_task->manifest; do { FURI_LOG_W(TAG, "Writing stack"); @@ -162,13 +161,11 @@ static bool update_task_write_stack(UpdateTask* update_task) { update_task_set_progress(update_task, UpdateTaskStageRadioInstall, 100); /* ...system will restart here. */ update_task_wait_for_restart(update_task); - success = true; } while(false); - return success; + return false; /* will return only in the case of failure */ } static bool update_task_remove_stack(UpdateTask* update_task) { - bool success = false; do { FURI_LOG_W(TAG, "Removing stack"); update_task_set_progress(update_task, UpdateTaskStageRadioErase, 30); @@ -178,9 +175,8 @@ static bool update_task_remove_stack(UpdateTask* update_task) { update_task_set_progress(update_task, UpdateTaskStageRadioErase, 100); /* ...system will restart here. */ update_task_wait_for_restart(update_task); - success = true; } while(false); - return success; + return false; /* will return only in the case of failure */ } static bool update_task_manage_radiostack(UpdateTask* update_task) { diff --git a/debug/gdbinit b/debug/gdbinit new file mode 100644 index 000000000..cba5d6b1a --- /dev/null +++ b/debug/gdbinit @@ -0,0 +1,10 @@ +set confirm off +set pagination off +set print pretty on +set print object on +set print static-members on +set print vtbl on +set print demangle on +set demangle-style gnu-v3 +set print sevenbit-strings off + diff --git a/firmware/targets/f7/Src/update.c b/firmware/targets/f7/Src/update.c index 722a7b616..a68a8b7a7 100644 --- a/firmware/targets/f7/Src/update.c +++ b/firmware/targets/f7/Src/update.c @@ -149,7 +149,7 @@ static UpdateManifest* flipper_update_process_manifest(const FuriString* manifes do { uint16_t size_read = 0; - if(f_read(&file, manifest_data + bytes_read, MAX_READ, &size_read) != FR_OK) { + if(f_read(&file, manifest_data + bytes_read, MAX_READ, &size_read) != FR_OK) { //-V769 break; } bytes_read += size_read; diff --git a/firmware/targets/f7/ble_glue/ble_glue.c b/firmware/targets/f7/ble_glue/ble_glue.c index b3752f17f..83562c73e 100644 --- a/firmware/targets/f7/ble_glue/ble_glue.c +++ b/firmware/targets/f7/ble_glue/ble_glue.c @@ -456,17 +456,15 @@ BleGlueCommandResult ble_glue_fus_get_status() { BleGlueCommandResult ble_glue_fus_wait_operation() { furi_check(ble_glue->c2_info.mode == BleGlueC2ModeFUS); - bool wip; - do { - BleGlueCommandResult fus_status = ble_glue_fus_get_status(); - if(fus_status == BleGlueCommandResultError) { - return BleGlueCommandResultError; - } - wip = fus_status == BleGlueCommandResultOperationOngoing; - if(wip) { - furi_delay_ms(20); - } - } while(wip); - return BleGlueCommandResultOK; + while(true) { + BleGlueCommandResult fus_status = ble_glue_fus_get_status(); + if(fus_status == BleGlueCommandResultOperationOngoing) { + furi_delay_ms(20); + } else if(fus_status == BleGlueCommandResultError) { + return BleGlueCommandResultError; + } else { + return BleGlueCommandResultOK; + } + } } diff --git a/firmware/targets/f7/ble_glue/gap.c b/firmware/targets/f7/ble_glue/gap.c index 3e29527ec..8ef037d6b 100644 --- a/firmware/targets/f7/ble_glue/gap.c +++ b/firmware/targets/f7/ble_glue/gap.c @@ -227,7 +227,7 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void* pckt) { case EVT_BLUE_GAP_NUMERIC_COMPARISON_VALUE: { uint32_t pin = ((aci_gap_numeric_comparison_value_event_rp0*)(blue_evt->data))->Numeric_Value; - FURI_LOG_I(TAG, "Verify numeric comparison: %06ld", pin); + FURI_LOG_I(TAG, "Verify numeric comparison: %06lu", pin); GapEvent event = {.type = GapEventTypePinCodeVerify, .data.pin_code = pin}; bool result = gap->on_event_cb(event, gap->context); aci_gap_numeric_comparison_value_confirm_yesno(gap->service.connection_handle, result); @@ -245,7 +245,7 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void* pckt) { } else { FURI_LOG_I(TAG, "Pairing complete"); GapEvent event = {.type = GapEventTypeConnected}; - gap->on_event_cb(event, gap->context); + gap->on_event_cb(event, gap->context); //-V595 } break; diff --git a/firmware/targets/f7/ble_glue/hid_service.c b/firmware/targets/f7/ble_glue/hid_service.c index d0ca9685a..47d242d4d 100644 --- a/firmware/targets/f7/ble_glue/hid_service.c +++ b/firmware/targets/f7/ble_glue/hid_service.c @@ -87,7 +87,7 @@ void hid_svc_start() { #if(HID_SVC_REPORT_COUNT != 0) for(uint8_t i = 0; i < HID_SVC_REPORT_COUNT; i++) { - if(i < HID_SVC_INPUT_REPORT_COUNT) { + if(i < HID_SVC_INPUT_REPORT_COUNT) { //-V547 uint8_t buf[2] = {i + 1, 1}; // 1 input char_uuid.Char_UUID_16 = REPORT_CHAR_UUID; status = aci_gatt_add_char( diff --git a/firmware/targets/f7/ble_glue/hw_ipcc.c b/firmware/targets/f7/ble_glue/hw_ipcc.c index 64dd9ef9b..7c84df09f 100644 --- a/firmware/targets/f7/ble_glue/hw_ipcc.c +++ b/firmware/targets/f7/ble_glue/hw_ipcc.c @@ -24,9 +24,9 @@ /* Global variables ---------------------------------------------------------*/ /* Private defines -----------------------------------------------------------*/ #define HW_IPCC_TX_PENDING(channel) \ - (!(LL_C1_IPCC_IsActiveFlag_CHx(IPCC, channel))) && (((~(IPCC->C1MR)) & (channel << 16U))) + (!(LL_C1_IPCC_IsActiveFlag_CHx(IPCC, channel))) && (((~(IPCC->C1MR)) & ((channel) << 16U))) #define HW_IPCC_RX_PENDING(channel) \ - (LL_C2_IPCC_IsActiveFlag_CHx(IPCC, channel)) && (((~(IPCC->C1MR)) & (channel << 0U))) + (LL_C2_IPCC_IsActiveFlag_CHx(IPCC, channel)) && (((~(IPCC->C1MR)) & ((channel) << 0U))) /* Private macros ------------------------------------------------------------*/ /* Private typedef -----------------------------------------------------------*/ diff --git a/firmware/targets/f7/fatfs/stm32_adafruit_sd.c b/firmware/targets/f7/fatfs/stm32_adafruit_sd.c index 07cae31fe..b9b65f06a 100644 --- a/firmware/targets/f7/fatfs/stm32_adafruit_sd.c +++ b/firmware/targets/f7/fatfs/stm32_adafruit_sd.c @@ -405,9 +405,9 @@ uint8_t BSP_SD_GetCardInfo(SD_CardInfo* pCardInfo) { pCardInfo->LogBlockNbr = (pCardInfo->CardCapacity) / (pCardInfo->LogBlockSize); } else { pCardInfo->CardCapacity = (pCardInfo->Csd.version.v1.DeviceSize + 1); - pCardInfo->CardCapacity *= (1 << (pCardInfo->Csd.version.v1.DeviceSizeMul + 2)); + pCardInfo->CardCapacity *= (1UL << (pCardInfo->Csd.version.v1.DeviceSizeMul + 2)); pCardInfo->LogBlockSize = 512; - pCardInfo->CardBlockSize = 1 << (pCardInfo->Csd.RdBlockLen); + pCardInfo->CardBlockSize = 1UL << (pCardInfo->Csd.RdBlockLen); pCardInfo->CardCapacity *= pCardInfo->CardBlockSize; pCardInfo->LogBlockNbr = (pCardInfo->CardCapacity) / (pCardInfo->LogBlockSize); } @@ -982,7 +982,8 @@ uint8_t SD_GoIdleState(void) { SD_IO_WriteByte(SD_DUMMY_BYTE); /* Send ACMD41 (SD_CMD_SD_APP_OP_COND) to initialize SDHC or SDXC cards: R1 response (0x00: no errors) */ - response = SD_SendCmd(SD_CMD_SD_APP_OP_COND, 0x00000000, 0xFF, SD_ANSWER_R1_EXPECTED); + response = //-V519 + SD_SendCmd(SD_CMD_SD_APP_OP_COND, 0x00000000, 0xFF, SD_ANSWER_R1_EXPECTED); SD_IO_CSState(1); SD_IO_WriteByte(SD_DUMMY_BYTE); if(counter >= SD_MAX_TRY) { @@ -1001,7 +1002,8 @@ uint8_t SD_GoIdleState(void) { SD_IO_WriteByte(SD_DUMMY_BYTE); /* Send ACMD41 (SD_CMD_SD_APP_OP_COND) to initialize SDHC or SDXC cards: R1 response (0x00: no errors) */ - response = SD_SendCmd(SD_CMD_SD_APP_OP_COND, 0x40000000, 0xFF, SD_ANSWER_R1_EXPECTED); + response = //-V519 + SD_SendCmd(SD_CMD_SD_APP_OP_COND, 0x40000000, 0xFF, SD_ANSWER_R1_EXPECTED); SD_IO_CSState(1); SD_IO_WriteByte(SD_DUMMY_BYTE); if(counter >= SD_MAX_TRY) { diff --git a/firmware/targets/f7/furi_hal/furi_hal_bt.c b/firmware/targets/f7/furi_hal/furi_hal_bt.c index fc1c25c7e..0857fe4ee 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_bt.c +++ b/firmware/targets/f7/furi_hal/furi_hal_bt.c @@ -415,7 +415,7 @@ float furi_hal_bt_get_rssi() { val += 6.0; rssi >>= 1; } - val += (417 * rssi + 18080) >> 10; + val += (float)((417 * rssi + 18080) >> 10); } return val; } diff --git a/firmware/targets/f7/furi_hal/furi_hal_bt_hid.c b/firmware/targets/f7/furi_hal/furi_hal_bt_hid.c index 22415199c..ab3855f42 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_bt_hid.c +++ b/firmware/targets/f7/furi_hal/furi_hal_bt_hid.c @@ -216,7 +216,7 @@ bool furi_hal_bt_hid_kb_release_all() { bool furi_hal_bt_hid_consumer_key_press(uint16_t button) { furi_assert(consumer_report); - for(uint8_t i = 0; i < FURI_HAL_BT_HID_CONSUMER_MAX_KEYS; i++) { + for(uint8_t i = 0; i < FURI_HAL_BT_HID_CONSUMER_MAX_KEYS; i++) { //-V1008 if(consumer_report->key[i] == 0) { consumer_report->key[i] = button; break; @@ -228,7 +228,7 @@ bool furi_hal_bt_hid_consumer_key_press(uint16_t button) { bool furi_hal_bt_hid_consumer_key_release(uint16_t button) { furi_assert(consumer_report); - for(uint8_t i = 0; i < FURI_HAL_BT_HID_CONSUMER_MAX_KEYS; i++) { + for(uint8_t i = 0; i < FURI_HAL_BT_HID_CONSUMER_MAX_KEYS; i++) { //-V1008 if(consumer_report->key[i] == button) { consumer_report->key[i] = 0; break; @@ -240,7 +240,7 @@ bool furi_hal_bt_hid_consumer_key_release(uint16_t button) { bool furi_hal_bt_hid_consumer_key_release_all() { furi_assert(consumer_report); - for(uint8_t i = 0; i < FURI_HAL_BT_HID_CONSUMER_MAX_KEYS; i++) { + for(uint8_t i = 0; i < FURI_HAL_BT_HID_CONSUMER_MAX_KEYS; i++) { //-V1008 consumer_report->key[i] = 0; } return hid_svc_update_input_report( diff --git a/firmware/targets/f7/furi_hal/furi_hal_i2c_config.c b/firmware/targets/f7/furi_hal/furi_hal_i2c_config.c index d832c4f66..678eb2965 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_i2c_config.c +++ b/firmware/targets/f7/furi_hal/furi_hal_i2c_config.c @@ -108,7 +108,7 @@ void furi_hal_i2c_bus_handle_power_event( GpioSpeedLow, GpioAltFn4I2C1); - LL_I2C_InitTypeDef I2C_InitStruct = {0}; + LL_I2C_InitTypeDef I2C_InitStruct; I2C_InitStruct.PeripheralMode = LL_I2C_MODE_I2C; I2C_InitStruct.AnalogFilter = LL_I2C_ANALOGFILTER_ENABLE; I2C_InitStruct.DigitalFilter = 0; @@ -152,7 +152,7 @@ void furi_hal_i2c_bus_handle_external_event( furi_hal_gpio_init_ex( &gpio_ext_pc1, GpioModeAltFunctionOpenDrain, GpioPullNo, GpioSpeedLow, GpioAltFn4I2C3); - LL_I2C_InitTypeDef I2C_InitStruct = {0}; + LL_I2C_InitTypeDef I2C_InitStruct; I2C_InitStruct.PeripheralMode = LL_I2C_MODE_I2C; I2C_InitStruct.AnalogFilter = LL_I2C_ANALOGFILTER_ENABLE; I2C_InitStruct.DigitalFilter = 0; diff --git a/firmware/targets/f7/furi_hal/furi_hal_memory.c b/firmware/targets/f7/furi_hal/furi_hal_memory.c index ec71e6660..9716f1e52 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_memory.c +++ b/firmware/targets/f7/furi_hal/furi_hal_memory.c @@ -55,9 +55,9 @@ void furi_hal_memory_init() { memory->region[SRAM_B].size = sram2b_unprotected_size; FURI_LOG_I( - TAG, "SRAM2A: 0x%p, %ld", memory->region[SRAM_A].start, memory->region[SRAM_A].size); + TAG, "SRAM2A: 0x%p, %lu", memory->region[SRAM_A].start, memory->region[SRAM_A].size); FURI_LOG_I( - TAG, "SRAM2B: 0x%p, %ld", memory->region[SRAM_B].start, memory->region[SRAM_B].size); + TAG, "SRAM2B: 0x%p, %lu", memory->region[SRAM_B].start, memory->region[SRAM_B].size); if((memory->region[SRAM_A].size > 0) || (memory->region[SRAM_B].size > 0)) { if((memory->region[SRAM_A].size > 0)) { @@ -120,4 +120,4 @@ size_t furi_hal_memory_max_pool_block() { } } return max; -} \ No newline at end of file +} diff --git a/firmware/targets/f7/furi_hal/furi_hal_nfc.c b/firmware/targets/f7/furi_hal/furi_hal_nfc.c index 75c695afb..6381d1a91 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_nfc.c +++ b/firmware/targets/f7/furi_hal/furi_hal_nfc.c @@ -425,7 +425,7 @@ bool furi_hal_nfc_emulate_nfca( buff_rx_len = 0; buff_tx_len = 0; uint32_t flag = furi_event_flag_wait(event, EVENT_FLAG_ALL, FuriFlagWaitAny, timeout); - if(flag == FuriFlagErrorTimeout || flag == EVENT_FLAG_STOP) { + if(flag == (unsigned)FuriFlagErrorTimeout || flag == EVENT_FLAG_STOP) { break; } bool data_received = false; @@ -609,9 +609,9 @@ static uint16_t furi_hal_nfc_data_and_parity_to_bitstream( out[curr_bit_pos / 8] = next_par_bit; curr_bit_pos++; } else { - out[curr_bit_pos / 8] |= data[i] << curr_bit_pos % 8; + out[curr_bit_pos / 8] |= data[i] << (curr_bit_pos % 8); out[curr_bit_pos / 8 + 1] = data[i] >> (8 - curr_bit_pos % 8); - out[curr_bit_pos / 8 + 1] |= next_par_bit << curr_bit_pos % 8; + out[curr_bit_pos / 8 + 1] |= next_par_bit << (curr_bit_pos % 8); curr_bit_pos += 9; } } @@ -635,7 +635,7 @@ uint16_t furi_hal_nfc_bitstream_to_data_and_parity( uint16_t bit_processed = 0; memset(out_parity, 0, in_buff_bits / 9); while(bit_processed < in_buff_bits) { - out_data[curr_byte] = in_buff[bit_processed / 8] >> bit_processed % 8; + out_data[curr_byte] = in_buff[bit_processed / 8] >> (bit_processed % 8); out_data[curr_byte] |= in_buff[bit_processed / 8 + 1] << (8 - bit_processed % 8); out_parity[curr_byte / 8] |= FURI_BIT(in_buff[bit_processed / 8 + 1], bit_processed % 8) << (7 - curr_byte % 8); @@ -802,4 +802,4 @@ FuriHalNfcReturn furi_hal_nfc_ll_txrx_bits( void furi_hal_nfc_ll_poll() { rfalWorker(); -} \ No newline at end of file +} diff --git a/firmware/targets/f7/furi_hal/furi_hal_os.c b/firmware/targets/f7/furi_hal/furi_hal_os.c index 97d022c93..ee9743e62 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_os.c +++ b/firmware/targets/f7/furi_hal/furi_hal_os.c @@ -15,8 +15,8 @@ #define FURI_HAL_IDLE_TIMER_CLK_HZ 32768 #define FURI_HAL_OS_TICK_HZ configTICK_RATE_HZ -#define FURI_HAL_OS_IDLE_CNT_TO_TICKS(x) ((x * FURI_HAL_OS_TICK_HZ) / FURI_HAL_IDLE_TIMER_CLK_HZ) -#define FURI_HAL_OS_TICKS_TO_IDLE_CNT(x) ((x * FURI_HAL_IDLE_TIMER_CLK_HZ) / FURI_HAL_OS_TICK_HZ) +#define FURI_HAL_OS_IDLE_CNT_TO_TICKS(x) (((x)*FURI_HAL_OS_TICK_HZ) / FURI_HAL_IDLE_TIMER_CLK_HZ) +#define FURI_HAL_OS_TICKS_TO_IDLE_CNT(x) (((x)*FURI_HAL_IDLE_TIMER_CLK_HZ) / FURI_HAL_OS_TICK_HZ) #define FURI_HAL_IDLE_TIMER_TICK_PER_EPOCH (FURI_HAL_OS_IDLE_CNT_TO_TICKS(FURI_HAL_IDLE_TIMER_MAX)) #define FURI_HAL_OS_MAX_SLEEP (FURI_HAL_IDLE_TIMER_TICK_PER_EPOCH - 1) diff --git a/firmware/targets/f7/furi_hal/furi_hal_pwm.c b/firmware/targets/f7/furi_hal/furi_hal_pwm.c index e484808d5..e47f752ab 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_pwm.c +++ b/firmware/targets/f7/furi_hal/furi_hal_pwm.c @@ -110,7 +110,7 @@ void furi_hal_pwm_set_params(FuriHalPwmOutputId channel, uint32_t freq, uint8_t bool clock_lse = false; do { - period = freq_div / (1 << prescaler); + period = freq_div / (1UL << prescaler); if(period <= 0xFFFF) { break; } diff --git a/firmware/targets/f7/furi_hal/furi_hal_rtc.c b/firmware/targets/f7/furi_hal/furi_hal_rtc.c index e5fa8c767..e011406ad 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_rtc.c +++ b/firmware/targets/f7/furi_hal/furi_hal_rtc.c @@ -154,7 +154,7 @@ void furi_hal_rtc_deinit_early() { } void furi_hal_rtc_init() { - LL_RTC_InitTypeDef RTC_InitStruct = {0}; + LL_RTC_InitTypeDef RTC_InitStruct; RTC_InitStruct.HourFormat = LL_RTC_HOURFORMAT_24HOUR; RTC_InitStruct.AsynchPrescaler = 127; RTC_InitStruct.SynchPrescaler = 255; diff --git a/firmware/targets/f7/furi_hal/furi_hal_uart.c b/firmware/targets/f7/furi_hal/furi_hal_uart.c index cb44b6d16..54232e67f 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_uart.c +++ b/firmware/targets/f7/furi_hal/furi_hal_uart.c @@ -26,7 +26,7 @@ static void furi_hal_usart_init(uint32_t baud) { GpioSpeedVeryHigh, GpioAltFn7USART1); - LL_USART_InitTypeDef USART_InitStruct = {0}; + LL_USART_InitTypeDef USART_InitStruct; USART_InitStruct.PrescalerValue = LL_USART_PRESCALER_DIV1; USART_InitStruct.BaudRate = baud; USART_InitStruct.DataWidth = LL_USART_DATAWIDTH_8B; @@ -62,7 +62,7 @@ static void furi_hal_lpuart_init(uint32_t baud) { GpioSpeedVeryHigh, GpioAltFn8LPUART1); - LL_LPUART_InitTypeDef LPUART_InitStruct = {0}; + LL_LPUART_InitTypeDef LPUART_InitStruct; LPUART_InitStruct.PrescalerValue = LL_LPUART_PRESCALER_DIV1; LPUART_InitStruct.BaudRate = 115200; LPUART_InitStruct.DataWidth = LL_LPUART_DATAWIDTH_8B; diff --git a/firmware/targets/f7/furi_hal/furi_hal_usb_hid.c b/firmware/targets/f7/furi_hal/furi_hal_usb_hid.c index a7253223b..fc1ce024c 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_usb_hid.c +++ b/firmware/targets/f7/furi_hal/furi_hal_usb_hid.c @@ -360,11 +360,11 @@ bool furi_hal_hid_consumer_key_release(uint16_t button) { static void* hid_set_string_descr(char* str) { furi_assert(str); - uint8_t len = strlen(str); + size_t len = strlen(str); struct usb_string_descriptor* dev_str_desc = malloc(len * 2 + 2); dev_str_desc->bLength = len * 2 + 2; dev_str_desc->bDescriptorType = USB_DTYPE_STRING; - for(uint8_t i = 0; i < len; i++) dev_str_desc->wString[i] = str[i]; + for(size_t i = 0; i < len; i++) dev_str_desc->wString[i] = str[i]; return dev_str_desc; } diff --git a/firmware/targets/f7/furi_hal/furi_hal_version.c b/firmware/targets/f7/furi_hal/furi_hal_version.c index 697d65931..b7827ac7f 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_version.c +++ b/firmware/targets/f7/furi_hal/furi_hal_version.c @@ -174,8 +174,6 @@ static void furi_hal_version_load_otp_v2() { void furi_hal_version_init() { switch(furi_hal_version_get_otp_version()) { case FuriHalVersionOtpVersionUnknown: - furi_hal_version_load_otp_default(); - break; case FuriHalVersionOtpVersionEmpty: furi_hal_version_load_otp_default(); break; diff --git a/furi/core/check.c b/furi/core/check.c index 1c2a005f3..910527cee 100644 --- a/furi/core/check.c +++ b/furi/core/check.c @@ -117,7 +117,7 @@ FURI_NORETURN void __furi_crash() { if(debug) { furi_hal_console_puts("\r\nSystem halted. Connect debugger for more info\r\n"); furi_hal_console_puts("\033[0m\r\n"); - RESTORE_REGISTERS_AND_HALT_MCU(debug); + RESTORE_REGISTERS_AND_HALT_MCU(true); } else { furi_hal_rtc_set_fault_data((uint32_t)__furi_check_message); furi_hal_console_puts("\r\nRebooting system.\r\n"); diff --git a/furi/core/core_defines.h b/furi/core/core_defines.h index 487fe2ca3..a0f50aff9 100644 --- a/furi/core/core_defines.h +++ b/furi/core/core_defines.h @@ -93,7 +93,7 @@ extern "C" { #endif #ifndef FURI_BIT_CLEAR -#define FURI_BIT_CLEAR(x, n) ((x) &= ~(1 << (n))) +#define FURI_BIT_CLEAR(x, n) ((x) &= ~(1UL << (n))) #endif #define FURI_SW_MEMBARRIER() asm volatile("" : : : "memory") diff --git a/furi/core/event_flag.c b/furi/core/event_flag.c index 07dd30a16..87de65f2d 100644 --- a/furi/core/event_flag.c +++ b/furi/core/event_flag.c @@ -9,7 +9,11 @@ FuriEventFlag* furi_event_flag_alloc() { furi_assert(!FURI_IS_IRQ_MODE()); - return ((FuriEventFlag*)xEventGroupCreate()); + + EventGroupHandle_t handle = xEventGroupCreate(); + furi_check(handle); + + return ((FuriEventFlag*)handle); } void furi_event_flag_free(FuriEventFlag* instance) { diff --git a/furi/core/memmgr_heap.c b/furi/core/memmgr_heap.c index 01153fe57..ca206cd39 100644 --- a/furi/core/memmgr_heap.c +++ b/furi/core/memmgr_heap.c @@ -212,7 +212,8 @@ static inline void traceFREE(void* pointer, size_t size) { MemmgrHeapThreadDict_get(memmgr_heap_thread_dict, (uint32_t)thread_id); if(alloc_dict) { // In some cases thread may want to release memory that was not allocated by it - (void)MemmgrHeapAllocDict_erase(*alloc_dict, (uint32_t)pointer); + const bool res = MemmgrHeapAllocDict_erase(*alloc_dict, (uint32_t)pointer); + UNUSED(res); } memmgr_heap_thread_trace_depth--; } @@ -520,8 +521,8 @@ void vPortFree(void* pv) { { furi_assert((size_t)pv >= SRAM_BASE); furi_assert((size_t)pv < SRAM_BASE + 1024 * 256); + furi_assert(pxLink->xBlockSize >= xHeapStructSize); furi_assert((pxLink->xBlockSize - xHeapStructSize) < 1024 * 256); - furi_assert((int32_t)(pxLink->xBlockSize - xHeapStructSize) >= 0); /* Add this block to the list of free blocks. */ xFreeBytesRemaining += pxLink->xBlockSize; diff --git a/furi/core/message_queue.c b/furi/core/message_queue.c index 2658d6ff7..9a41f8775 100644 --- a/furi/core/message_queue.c +++ b/furi/core/message_queue.c @@ -7,7 +7,10 @@ FuriMessageQueue* furi_message_queue_alloc(uint32_t msg_count, uint32_t msg_size) { furi_assert((furi_is_irq_context() == 0U) && (msg_count > 0U) && (msg_size > 0U)); - return ((FuriMessageQueue*)xQueueCreate(msg_count, msg_size)); + QueueHandle_t handle = xQueueCreate(msg_count, msg_size); + furi_check(handle); + + return ((FuriMessageQueue*)handle); } void furi_message_queue_free(FuriMessageQueue* instance) { diff --git a/furi/core/mutex.c b/furi/core/mutex.c index ab66b0f18..9fb964a1e 100644 --- a/furi/core/mutex.c +++ b/furi/core/mutex.c @@ -30,6 +30,8 @@ FuriMutex* furi_mutex_alloc(FuriMutexType type) { void furi_mutex_free(FuriMutex* instance) { furi_assert(!FURI_IS_IRQ_MODE()); + furi_assert(instance); + vSemaphoreDelete((SemaphoreHandle_t)((uint32_t)instance & ~1U)); } diff --git a/furi/core/stream_buffer.c b/furi/core/stream_buffer.c index 2df84fa5b..bf483948b 100644 --- a/furi/core/stream_buffer.c +++ b/furi/core/stream_buffer.c @@ -1,18 +1,26 @@ #include "base.h" +#include "check.h" #include "stream_buffer.h" #include "common_defines.h" #include #include FuriStreamBuffer* furi_stream_buffer_alloc(size_t size, size_t trigger_level) { - return xStreamBufferCreate(size, trigger_level); + furi_assert(size != 0); + + StreamBufferHandle_t handle = xStreamBufferCreate(size, trigger_level); + furi_check(handle); + + return handle; }; void furi_stream_buffer_free(FuriStreamBuffer* stream_buffer) { + furi_assert(stream_buffer); vStreamBufferDelete(stream_buffer); }; bool furi_stream_set_trigger_level(FuriStreamBuffer* stream_buffer, size_t trigger_level) { + furi_assert(stream_buffer); return xStreamBufferSetTriggerLevel(stream_buffer, trigger_level) == pdTRUE; }; diff --git a/furi/core/string.c b/furi/core/string.c index 901b1f625..4384fe06a 100644 --- a/furi/core/string.c +++ b/furi/core/string.c @@ -29,16 +29,16 @@ FuriString* furi_string_alloc() { } FuriString* furi_string_alloc_set(const FuriString* s) { - FuriString* string = malloc(sizeof(FuriString)); //-V773 + FuriString* string = malloc(sizeof(FuriString)); //-V799 string_init_set(string->string, s->string); return string; -} +} //-V773 FuriString* furi_string_alloc_set_str(const char cstr[]) { - FuriString* string = malloc(sizeof(FuriString)); //-V773 + FuriString* string = malloc(sizeof(FuriString)); //-V799 string_init_set(string->string, cstr); return string; -} +} //-V773 FuriString* furi_string_alloc_printf(const char format[], ...) { va_list args; @@ -299,4 +299,4 @@ void furi_string_utf8_decode(char c, FuriStringUTF8State* state, FuriStringUnico m_str1ng_utf8_state_e m_state = furi_state_to_state(*state); m_str1ng_utf8_decode(c, &m_state, unicode); *state = state_to_furi_state(m_state); -} \ No newline at end of file +} diff --git a/furi/core/thread.c b/furi/core/thread.c index 34cc7d987..c966dd572 100644 --- a/furi/core/thread.c +++ b/furi/core/thread.c @@ -49,9 +49,9 @@ static size_t __furi_thread_stdout_write(FuriThread* thread, const char* data, s static int32_t __furi_thread_stdout_flush(FuriThread* thread); /** Catch threads that are trying to exit wrong way */ -__attribute__((__noreturn__)) void furi_thread_catch() { +__attribute__((__noreturn__)) void furi_thread_catch() { //-V1082 asm volatile("nop"); // extra magic - furi_crash("You are doing it wrong"); + furi_crash("You are doing it wrong"); //-V779 __builtin_unreachable(); } @@ -84,10 +84,10 @@ static void furi_thread_body(void* context) { if(thread->heap_trace_enabled == true) { furi_delay_ms(33); thread->heap_size = memmgr_heap_get_thread_memory((FuriThreadId)task_handle); - furi_log_print_format( + furi_log_print_format( //-V576 thread->heap_size ? FuriLogLevelError : FuriLogLevelInfo, TAG, - "%s allocation balance: %d", + "%s allocation balance: %u", thread->name ? thread->name : "Thread", thread->heap_size); memmgr_heap_disable_thread_trace((FuriThreadId)task_handle); diff --git a/furi/core/timer.c b/furi/core/timer.c index c42b0c2ac..be7efebe2 100644 --- a/furi/core/timer.c +++ b/furi/core/timer.c @@ -32,44 +32,28 @@ FuriTimer* furi_timer_alloc(FuriTimerCallback func, FuriTimerType type, void* co TimerHandle_t hTimer; TimerCallback_t* callb; UBaseType_t reload; - uint32_t callb_dyn; hTimer = NULL; - callb = NULL; - callb_dyn = 0U; /* Dynamic memory allocation is available: if memory for callback and */ /* its context is not provided, allocate it from dynamic memory pool */ - if(callb == NULL) { - callb = (TimerCallback_t*)malloc(sizeof(TimerCallback_t)); + callb = (TimerCallback_t*)malloc(sizeof(TimerCallback_t)); - if(callb != NULL) { - /* Callback memory was allocated from dynamic pool, set flag */ - callb_dyn = 1U; - } + callb->func = func; + callb->context = context; + + if(type == FuriTimerTypeOnce) { + reload = pdFALSE; + } else { + reload = pdTRUE; } - if(callb != NULL) { - callb->func = func; - callb->context = context; - - if(type == FuriTimerTypeOnce) { - reload = pdFALSE; - } else { - reload = pdTRUE; - } - - /* Store callback memory dynamic allocation flag */ - callb = (TimerCallback_t*)((uint32_t)callb | callb_dyn); - // TimerCallback function is always provided as a callback and is used to call application - // specified function with its context both stored in structure callb. - hTimer = xTimerCreate(NULL, 1, reload, callb, TimerCallback); - if((hTimer == NULL) && (callb != NULL) && (callb_dyn == 1U)) { - /* Failed to create a timer, release allocated resources */ - callb = (TimerCallback_t*)((uint32_t)callb & ~1U); - free(callb); - } - } + /* Store callback memory dynamic allocation flag */ + callb = (TimerCallback_t*)((uint32_t)callb | 1U); + // TimerCallback function is always provided as a callback and is used to call application + // specified function with its context both stored in structure callb. + hTimer = xTimerCreate(NULL, 1, reload, callb, TimerCallback); + furi_check(hTimer); /* Return timer ID */ return ((FuriTimer*)hTimer); diff --git a/lib/app-scened-template/view_modules/popup_vm.cpp b/lib/app-scened-template/view_modules/popup_vm.cpp index c378d9cc9..e2c8732e8 100644 --- a/lib/app-scened-template/view_modules/popup_vm.cpp +++ b/lib/app-scened-template/view_modules/popup_vm.cpp @@ -1,4 +1,5 @@ #include "popup_vm.h" +#include "gui/modules/popup.h" PopupVM::PopupVM() { popup = popup_alloc(); } @@ -50,5 +51,5 @@ void PopupVM::enable_timeout() { } void PopupVM::disable_timeout() { - popup_enable_timeout(popup); + popup_disable_timeout(popup); } diff --git a/lib/drivers/cc1101.c b/lib/drivers/cc1101.c index f28165e89..d563c30c3 100644 --- a/lib/drivers/cc1101.c +++ b/lib/drivers/cc1101.c @@ -121,7 +121,7 @@ uint32_t cc1101_set_intermediate_frequency(FuriHalSpiBusHandle* handle, uint32_t } void cc1101_set_pa_table(FuriHalSpiBusHandle* handle, const uint8_t value[8]) { - uint8_t tx[9] = {CC1101_PATABLE | CC1101_BURST}; + uint8_t tx[9] = {CC1101_PATABLE | CC1101_BURST}; //-V1009 CC1101Status rx[9] = {0}; memcpy(&tx[1], &value[0], 8); diff --git a/lib/drivers/lp5562.c b/lib/drivers/lp5562.c index f5d765fa9..e755d2d60 100644 --- a/lib/drivers/lp5562.c +++ b/lib/drivers/lp5562.c @@ -105,7 +105,7 @@ void lp5562_set_channel_src(FuriHalI2cBusHandle* handle, LP5562Channel channel, reg_val &= ~(0x3 << bit_offset); reg_val |= ((src & 0x03) << bit_offset); furi_hal_i2c_write_reg_8(handle, LP5562_ADDRESS, 0x70, reg_val, LP5562_I2C_TIMEOUT); - } while(channel); + } while(channel != 0); } void lp5562_execute_program( @@ -166,7 +166,7 @@ void lp5562_stop_program(FuriHalI2cBusHandle* handle, LP5562Engine eng) { bit_offset = (3 - eng) * 2; furi_hal_i2c_read_reg_8(handle, LP5562_ADDRESS, 0x01, ®_val, LP5562_I2C_TIMEOUT); reg_val &= ~(0x3 << bit_offset); - reg_val |= (0x00 << bit_offset); // Disabled + // Not setting lowest 2 bits here furi_hal_i2c_write_reg_8(handle, LP5562_ADDRESS, 0x01, reg_val, LP5562_I2C_TIMEOUT); } diff --git a/lib/flipper_application/elf/elf_file.c b/lib/flipper_application/elf/elf_file.c index 2082e550f..bf98650a2 100644 --- a/lib/flipper_application/elf/elf_file.c +++ b/lib/flipper_application/elf/elf_file.c @@ -6,8 +6,8 @@ #define TAG "elf" #define ELF_NAME_BUFFER_LEN 32 -#define SECTION_OFFSET(e, n) (e->section_table + n * sizeof(Elf32_Shdr)) -#define IS_FLAGS_SET(v, m) ((v & m) == m) +#define SECTION_OFFSET(e, n) ((e)->section_table + (n) * sizeof(Elf32_Shdr)) +#define IS_FLAGS_SET(v, m) (((v) & (m)) == (m)) #define RESOLVER_THREAD_YIELD_STEP 30 // #define ELF_DEBUG_LOG 1 @@ -758,15 +758,13 @@ ELFFileLoadStatus elf_file_load_sections(ELFFile* elf) { AddressCache_init(elf->relocation_cache); - if(status == ELFFileLoadStatusSuccess) { - for(ELFSectionDict_it(it, elf->sections); !ELFSectionDict_end_p(it); - ELFSectionDict_next(it)) { - ELFSectionDict_itref_t* itref = ELFSectionDict_ref(it); - FURI_LOG_D(TAG, "Relocating section '%s'", itref->key); - if(!elf_relocate_section(elf, &itref->value)) { - FURI_LOG_E(TAG, "Error relocating section '%s'", itref->key); - status = ELFFileLoadStatusMissingImports; - } + for(ELFSectionDict_it(it, elf->sections); !ELFSectionDict_end_p(it); + ELFSectionDict_next(it)) { + ELFSectionDict_itref_t* itref = ELFSectionDict_ref(it); + FURI_LOG_D(TAG, "Relocating section '%s'", itref->key); + if(!elf_relocate_section(elf, &itref->value)) { + FURI_LOG_E(TAG, "Error relocating section '%s'", itref->key); + status = ELFFileLoadStatusMissingImports; } } @@ -793,7 +791,7 @@ ELFFileLoadStatus elf_file_load_sections(ELFFile* elf) { ELFSectionDict_itref_t* itref = ELFSectionDict_ref(it); total_size += itref->value.size; } - FURI_LOG_I(TAG, "Total size of loaded sections: %u", total_size); + FURI_LOG_I(TAG, "Total size of loaded sections: %u", total_size); //-V576 } return status; diff --git a/lib/flipper_format/flipper_format_stream.c b/lib/flipper_format/flipper_format_stream.c index 9cce95d47..405b819a7 100644 --- a/lib/flipper_format/flipper_format_stream.c +++ b/lib/flipper_format/flipper_format_stream.c @@ -298,7 +298,7 @@ bool flipper_format_stream_write_value_line(Stream* stream, FlipperStreamWriteDa }; break; case FlipperStreamValueUint32: { const uint32_t* data = write_data->data; - furi_string_printf(value, "%" PRId32, data[i]); + furi_string_printf(value, "%" PRIu32, data[i]); }; break; case FlipperStreamValueHexUint64: { const uint64_t* data = write_data->data; @@ -396,7 +396,7 @@ bool flipper_format_stream_read_value_line( }; break; case FlipperStreamValueUint32: { uint32_t* data = _data; - scan_values = sscanf(furi_string_get_cstr(value), "%" PRId32, &data[i]); + scan_values = sscanf(furi_string_get_cstr(value), "%" PRIu32, &data[i]); }; break; case FlipperStreamValueHexUint64: { uint64_t* data = _data; diff --git a/lib/infrared/encoder_decoder/common/infrared_common_decoder.c b/lib/infrared/encoder_decoder/common/infrared_common_decoder.c index 7f1c3a4fd..8acb6751b 100644 --- a/lib/infrared/encoder_decoder/common/infrared_common_decoder.c +++ b/lib/infrared/encoder_decoder/common/infrared_common_decoder.c @@ -107,7 +107,7 @@ static InfraredStatus infrared_common_decode_bits(InfraredCommonDecoder* decoder decoder->timings_cnt = consume_samples(decoder->timings, decoder->timings_cnt, 1); /* check if largest protocol version can be decoded */ - if(level && (decoder->protocol->databit_len[0] == decoder->databit_cnt) && + if(level && (decoder->protocol->databit_len[0] == decoder->databit_cnt) && //-V1051 !timings->min_split_time) { status = InfraredStatusReady; break; diff --git a/lib/infrared/encoder_decoder/common/infrared_common_encoder.c b/lib/infrared/encoder_decoder/common/infrared_common_encoder.c index dcf63acc8..9c774617e 100644 --- a/lib/infrared/encoder_decoder/common/infrared_common_encoder.c +++ b/lib/infrared/encoder_decoder/common/infrared_common_encoder.c @@ -94,7 +94,6 @@ InfraredStatus case InfraredCommonEncoderStateSilence: *duration = encoder->protocol->timings.silence_time; *level = false; - status = InfraredStatusOk; encoder->state = InfraredCommonEncoderStatePreamble; ++encoder->timings_encoded; encoder->timings_sum = 0; diff --git a/lib/infrared/encoder_decoder/common/infrared_common_i.h b/lib/infrared/encoder_decoder/common/infrared_common_i.h index 20dbeb79d..f34e81eda 100644 --- a/lib/infrared/encoder_decoder/common/infrared_common_i.h +++ b/lib/infrared/encoder_decoder/common/infrared_common_i.h @@ -4,7 +4,7 @@ #include "infrared.h" #include "infrared_i.h" -#define MATCH_TIMING(x, v, delta) (((x) < (v + delta)) && ((x) > (v - delta))) +#define MATCH_TIMING(x, v, delta) (((x) < ((v) + (delta))) && ((x) > ((v) - (delta)))) typedef struct InfraredCommonDecoder InfraredCommonDecoder; typedef struct InfraredCommonEncoder InfraredCommonEncoder; diff --git a/lib/infrared/worker/infrared_transmit.c b/lib/infrared/worker/infrared_transmit.c index 695be8d1f..1a5083019 100644 --- a/lib/infrared/worker/infrared_transmit.c +++ b/lib/infrared/worker/infrared_transmit.c @@ -67,7 +67,7 @@ void infrared_send_raw(const uint32_t timings[], uint32_t timings_cnt, bool star FuriHalInfraredTxGetDataState infrared_get_data_callback(void* context, uint32_t* duration, bool* level) { - FuriHalInfraredTxGetDataState state = FuriHalInfraredTxGetDataStateLastDone; + FuriHalInfraredTxGetDataState state; InfraredEncoderHandler* handler = context; InfraredStatus status = InfraredStatusError; @@ -82,9 +82,10 @@ FuriHalInfraredTxGetDataState } else if(status == InfraredStatusOk) { state = FuriHalInfraredTxGetDataStateOk; } else if(status == InfraredStatusDone) { - state = FuriHalInfraredTxGetDataStateDone; if(--infrared_tx_number_of_transmissions == 0) { state = FuriHalInfraredTxGetDataStateLastDone; + } else { + state = FuriHalInfraredTxGetDataStateDone; } } else { furi_crash(NULL); diff --git a/lib/infrared/worker/infrared_worker.c b/lib/infrared/worker/infrared_worker.c index 57288f3c3..033dba525 100644 --- a/lib/infrared/worker/infrared_worker.c +++ b/lib/infrared/worker/infrared_worker.c @@ -7,6 +7,7 @@ #include #include #include +#include #include @@ -397,8 +398,9 @@ static bool infrared_get_new_signal(InfraredWorker* instance) { } instance->tx.tx_raw_cnt = 0; - instance->tx.need_reinitialization = (new_tx_frequency != instance->tx.frequency) || - (new_tx_duty_cycle != instance->tx.duty_cycle); + instance->tx.need_reinitialization = + (new_tx_frequency != instance->tx.frequency) || + !float_is_equal(new_tx_duty_cycle, instance->tx.duty_cycle); instance->tx.frequency = new_tx_frequency; instance->tx.duty_cycle = new_tx_duty_cycle; if(instance->signal.decoded) { diff --git a/lib/infrared/worker/infrared_worker.h b/lib/infrared/worker/infrared_worker.h index 26919c4f5..1a8cd9a76 100644 --- a/lib/infrared/worker/infrared_worker.h +++ b/lib/infrared/worker/infrared_worker.h @@ -7,7 +7,7 @@ extern "C" { #endif -#define MAX_TIMINGS_AMOUNT 1024 +#define MAX_TIMINGS_AMOUNT 1024U /** Interface struct of infrared worker */ typedef struct InfraredWorker InfraredWorker; diff --git a/lib/lfrfid/lfrfid_raw_worker.c b/lib/lfrfid/lfrfid_raw_worker.c index 8c69acedb..22c0bbd02 100644 --- a/lib/lfrfid/lfrfid_raw_worker.c +++ b/lib/lfrfid/lfrfid_raw_worker.c @@ -114,7 +114,6 @@ void lfrfid_raw_worker_stop(LFRFIDRawWorker* worker) { worker->emulate_callback = NULL; worker->context = NULL; worker->read_callback = NULL; - worker->context = NULL; furi_event_flag_set(worker->events, 1 << LFRFIDRawWorkerEventStop); furi_thread_join(worker->thread); } @@ -335,7 +334,7 @@ static int32_t lfrfid_raw_emulate_worker_thread(void* thread_context) { } if(data->ctx.overrun_count) { - FURI_LOG_E(TAG_EMULATE, "overruns: %u", data->ctx.overrun_count); + FURI_LOG_E(TAG_EMULATE, "overruns: %zu", data->ctx.overrun_count); } furi_stream_buffer_free(data->ctx.stream); @@ -344,4 +343,4 @@ static int32_t lfrfid_raw_emulate_worker_thread(void* thread_context) { free(data); return 0; -} \ No newline at end of file +} diff --git a/lib/lfrfid/lfrfid_worker.c b/lib/lfrfid/lfrfid_worker.c index f33c1aed6..1e491c6b7 100644 --- a/lib/lfrfid/lfrfid_worker.c +++ b/lib/lfrfid/lfrfid_worker.c @@ -139,7 +139,7 @@ static int32_t lfrfid_worker_thread(void* thread_context) { while(true) { uint32_t flags = furi_thread_flags_wait(LFRFIDEventAll, FuriFlagWaitAny, FuriWaitForever); - if(flags != FuriFlagErrorTimeout) { + if(flags != (unsigned)FuriFlagErrorTimeout) { // stop thread if(flags & LFRFIDEventStopThread) break; @@ -161,4 +161,4 @@ static int32_t lfrfid_worker_thread(void* thread_context) { } return 0; -} \ No newline at end of file +} diff --git a/lib/lfrfid/lfrfid_worker_modes.c b/lib/lfrfid/lfrfid_worker_modes.c index 1fbae04c8..9b6f16eb1 100644 --- a/lib/lfrfid/lfrfid_worker_modes.c +++ b/lib/lfrfid/lfrfid_worker_modes.c @@ -276,7 +276,7 @@ static LFRFIDWorkerReadState lfrfid_worker_read_internal( FURI_LOG_D( TAG, - "%s, %d, [%s]", + "%s, %zu, [%s]", protocol_dict_get_name(worker->protocols, protocol), last_read_count, furi_string_get_cstr(string_info)); @@ -335,9 +335,9 @@ static LFRFIDWorkerReadState lfrfid_worker_read_internal( } static void lfrfid_worker_mode_read_process(LFRFIDWorker* worker) { - LFRFIDFeature feature = LFRFIDFeatureASK; ProtocolId read_result = PROTOCOL_NO; LFRFIDWorkerReadState state; + LFRFIDFeature feature; if(worker->read_type == LFRFIDWorkerReadTypePSKOnly) { feature = LFRFIDFeaturePSK; @@ -635,4 +635,4 @@ const LFRFIDWorkerModeType lfrfid_worker_modes[] = { [LFRFIDWorkerEmulate] = {.process = lfrfid_worker_mode_emulate_process}, [LFRFIDWorkerReadRaw] = {.process = lfrfid_worker_mode_read_raw_process}, [LFRFIDWorkerEmulateRaw] = {.process = lfrfid_worker_mode_emulate_raw_process}, -}; \ No newline at end of file +}; diff --git a/lib/lfrfid/protocols/protocol_indala26.c b/lib/lfrfid/protocols/protocol_indala26.c index cafc58489..8319f0a93 100644 --- a/lib/lfrfid/protocols/protocol_indala26.c +++ b/lib/lfrfid/protocols/protocol_indala26.c @@ -353,4 +353,4 @@ const ProtocolBase protocol_indala26 = { .render_data = (ProtocolRenderData)protocol_indala26_render_data, .render_brief_data = (ProtocolRenderData)protocol_indala26_render_brief_data, .write_data = (ProtocolWriteData)protocol_indala26_write_data, -}; \ No newline at end of file +}; diff --git a/lib/lfrfid/protocols/protocol_pac_stanley.c b/lib/lfrfid/protocols/protocol_pac_stanley.c index 59aaf1e6a..11c642402 100644 --- a/lib/lfrfid/protocols/protocol_pac_stanley.c +++ b/lib/lfrfid/protocols/protocol_pac_stanley.c @@ -12,7 +12,7 @@ #define PAC_STANLEY_ENCODED_BYTE_FULL_SIZE \ (PAC_STANLEY_ENCODED_BYTE_SIZE + PAC_STANLEY_PREAMBLE_BYTE_SIZE) #define PAC_STANLEY_BYTE_LENGTH (10) // start bit, 7 data bits, parity bit, stop bit -#define PAC_STANLEY_DATA_START_INDEX 8 + (3 * PAC_STANLEY_BYTE_LENGTH) + 1 +#define PAC_STANLEY_DATA_START_INDEX (8 + (3 * PAC_STANLEY_BYTE_LENGTH) + 1) #define PAC_STANLEY_DECODED_DATA_SIZE (4) #define PAC_STANLEY_ENCODED_DATA_SIZE (sizeof(ProtocolPACStanley)) @@ -128,7 +128,7 @@ bool protocol_pac_stanley_decoder_feed(ProtocolPACStanley* protocol, bool level, } bool protocol_pac_stanley_encoder_start(ProtocolPACStanley* protocol) { - memset(protocol->encoded_data, 0, PAC_STANLEY_ENCODED_BYTE_SIZE); + memset(protocol->encoded_data, 0, sizeof(protocol->encoded_data)); uint8_t idbytes[10]; idbytes[0] = '2'; @@ -137,7 +137,7 @@ bool protocol_pac_stanley_encoder_start(ProtocolPACStanley* protocol) { uint8_to_hex_chars(protocol->data, &idbytes[2], 8); // insert start and stop bits - for(size_t i = 0; i < 16; i++) protocol->encoded_data[i] = 0x40 >> (i + 3) % 5 * 2; + for(size_t i = 0; i < 16; i++) protocol->encoded_data[i] = 0x40 >> ((i + 3) % 5 * 2); protocol->encoded_data[0] = 0xFF; // mark + stop protocol->encoded_data[1] = 0x20; // start + reflect8(STX) @@ -228,4 +228,4 @@ const ProtocolBase protocol_pac_stanley = { .render_data = (ProtocolRenderData)protocol_pac_stanley_render_data, .render_brief_data = (ProtocolRenderData)protocol_pac_stanley_render_data, .write_data = (ProtocolWriteData)protocol_pac_stanley_write_data, -}; \ No newline at end of file +}; diff --git a/lib/lfrfid/tools/bit_lib.c b/lib/lfrfid/tools/bit_lib.c index c84f4b7ed..54decb3e8 100644 --- a/lib/lfrfid/tools/bit_lib.c +++ b/lib/lfrfid/tools/bit_lib.c @@ -25,7 +25,7 @@ void bit_lib_set_bits(uint8_t* data, size_t position, uint8_t byte, uint8_t leng for(uint8_t i = 0; i < length; ++i) { uint8_t shift = (length - 1) - i; - bit_lib_set_bit(data, position + i, (byte >> shift) & 1); + bit_lib_set_bit(data, position + i, (byte >> shift) & 1); //-V610 } } @@ -69,9 +69,9 @@ uint32_t bit_lib_get_bits_32(const uint8_t* data, size_t position, uint8_t lengt value |= bit_lib_get_bits(data, position + 8, 8) << (length - 16); value |= bit_lib_get_bits(data, position + 16, length - 16); } else { - value = bit_lib_get_bits(data, position, 8) << (length - 8); - value |= bit_lib_get_bits(data, position + 8, 8) << (length - 16); - value |= bit_lib_get_bits(data, position + 16, 8) << (length - 24); + value = (uint32_t)bit_lib_get_bits(data, position, 8) << (length - 8); + value |= (uint32_t)bit_lib_get_bits(data, position + 8, 8) << (length - 16); + value |= (uint32_t)bit_lib_get_bits(data, position + 16, 8) << (length - 24); value |= bit_lib_get_bits(data, position + 24, length - 24); } @@ -364,4 +364,4 @@ uint16_t bit_lib_crc16( crc ^= xor_out; return crc; -} \ No newline at end of file +} diff --git a/lib/lfrfid/tools/bit_lib.h b/lib/lfrfid/tools/bit_lib.h index 1b048db35..bae95462d 100644 --- a/lib/lfrfid/tools/bit_lib.h +++ b/lib/lfrfid/tools/bit_lib.h @@ -7,7 +7,7 @@ extern "C" { #endif -#define TOPBIT(X) (1 << (X - 1)) +#define TOPBIT(X) (1 << ((X)-1)) typedef enum { BitLibParityEven, @@ -26,13 +26,13 @@ typedef enum { * @param data value to test * @param index bit index to test */ -#define bit_lib_bit_is_set(data, index) ((data & (1 << (index))) != 0) +#define bit_lib_bit_is_set(data, index) (((data) & (1 << (index))) != 0) /** @brief Test if a bit is not set. * @param data value to test * @param index bit index to test */ -#define bit_lib_bit_is_not_set(data, index) ((data & (1 << (index))) == 0) +#define bit_lib_bit_is_not_set(data, index) (((data) & (1 << (index))) == 0) /** @brief Push a bit into a byte array. * @param data array to push bit into @@ -269,4 +269,4 @@ uint16_t bit_lib_crc16( #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/lib/lfrfid/tools/varint_pair.c b/lib/lfrfid/tools/varint_pair.c index c59ba55b4..1e6c82eee 100644 --- a/lib/lfrfid/tools/varint_pair.c +++ b/lib/lfrfid/tools/varint_pair.c @@ -28,11 +28,9 @@ bool varint_pair_pack(VarintPair* pair, bool first, uint32_t value) { pair->data_length = 0; } } else { - if(pair->data_length > 0) { + if(pair->data_length != 0) { pair->data_length += varint_uint32_pack(value, pair->data + pair->data_length); result = true; - } else { - pair->data_length = 0; } } diff --git a/lib/nfc/helpers/mf_classic_dict.c b/lib/nfc/helpers/mf_classic_dict.c index 690bba61b..98076479f 100644 --- a/lib/nfc/helpers/mf_classic_dict.c +++ b/lib/nfc/helpers/mf_classic_dict.c @@ -90,7 +90,7 @@ MfClassicDict* mf_classic_dict_alloc(MfClassicDictType dict_type) { } FURI_LOG_T( TAG, - "Read line: %s, len: %d", + "Read line: %s, len: %zu", furi_string_get_cstr(next_line), furi_string_size(next_line)); if(furi_string_get_char(next_line, 0) == '#') continue; @@ -101,7 +101,7 @@ MfClassicDict* mf_classic_dict_alloc(MfClassicDictType dict_type) { stream_rewind(dict->stream); dict_loaded = true; - FURI_LOG_I(TAG, "Loaded dictionary with %ld keys", dict->total_keys); + FURI_LOG_I(TAG, "Loaded dictionary with %lu keys", dict->total_keys); } while(false); if(!dict_loaded) { @@ -136,7 +136,7 @@ static void mf_classic_dict_str_to_int(FuriString* key_str, uint64_t* key_int) { for(uint8_t i = 0; i < 12; i += 2) { args_char_to_hex( furi_string_get_char(key_str, i), furi_string_get_char(key_str, i + 1), &key_byte_tmp); - *key_int |= (uint64_t)key_byte_tmp << 8 * (5 - i / 2); + *key_int |= (uint64_t)key_byte_tmp << (8 * (5 - i / 2)); } } @@ -193,7 +193,7 @@ bool mf_classic_dict_is_key_present_str(MfClassicDict* dict, FuriString* key) { bool key_found = false; stream_rewind(dict->stream); - while(!key_found) { + while(!key_found) { //-V654 if(!stream_read_line(dict->stream, next_line)) break; if(furi_string_get_char(next_line, 0) == '#') continue; if(furi_string_size(next_line) != NFC_MF_CLASSIC_KEY_LEN) continue; @@ -294,7 +294,7 @@ bool mf_classic_dict_find_index_str(MfClassicDict* dict, FuriString* key, uint32 bool key_found = false; uint32_t index = 0; stream_rewind(dict->stream); - while(!key_found) { + while(!key_found) { //-V654 if(!stream_read_line(dict->stream, next_line)) break; if(furi_string_get_char(next_line, 0) == '#') continue; if(furi_string_size(next_line) != NFC_MF_CLASSIC_KEY_LEN) continue; diff --git a/lib/nfc/helpers/reader_analyzer.c b/lib/nfc/helpers/reader_analyzer.c index 73b4b125e..af4869ca9 100644 --- a/lib/nfc/helpers/reader_analyzer.c +++ b/lib/nfc/helpers/reader_analyzer.c @@ -221,11 +221,11 @@ static void reader_analyzer_write( data_sent = furi_stream_buffer_send( instance->stream, &header, sizeof(ReaderAnalyzerHeader), FuriWaitForever); if(data_sent != sizeof(ReaderAnalyzerHeader)) { - FURI_LOG_W(TAG, "Sent %d out of %d bytes", data_sent, sizeof(ReaderAnalyzerHeader)); + FURI_LOG_W(TAG, "Sent %zu out of %zu bytes", data_sent, sizeof(ReaderAnalyzerHeader)); } data_sent = furi_stream_buffer_send(instance->stream, data, len, FuriWaitForever); if(data_sent != len) { - FURI_LOG_W(TAG, "Sent %d out of %d bytes", data_sent, len); + FURI_LOG_W(TAG, "Sent %zu out of %u bytes", data_sent, len); } } diff --git a/lib/nfc/nfc_device.c b/lib/nfc/nfc_device.c index 49eebc37d..52bff24e3 100644 --- a/lib/nfc/nfc_device.c +++ b/lib/nfc/nfc_device.c @@ -576,7 +576,7 @@ static bool nfc_device_save_mifare_df_data(FlipperFormat* file, NfcDevice* dev) tmp = malloc(n_apps * 3); int i = 0; for(MifareDesfireApplication* app = data->app_head; app; app = app->next) { - memcpy(tmp + i, app->id, 3); + memcpy(tmp + i, app->id, 3); //-V769 i += 3; } if(!flipper_format_write_hex(file, "Application IDs", tmp, n_apps * 3)) break; @@ -1085,7 +1085,7 @@ bool nfc_device_save(NfcDevice* dev, const char* dev_name) { saved = true; } while(0); - if(!saved) { + if(!saved) { //-V547 dialog_message_show_storage_error(dev->dialogs, "Can not save\nkey file"); } furi_string_free(temp_str); diff --git a/lib/nfc/nfc_worker.c b/lib/nfc/nfc_worker.c index 450428a18..0ffe1d07b 100644 --- a/lib/nfc/nfc_worker.c +++ b/lib/nfc/nfc_worker.c @@ -453,11 +453,11 @@ void nfc_worker_read_type(NfcWorker* nfc_worker) { event = NfcWorkerEventReadUidNfcA; break; } - } else { - if(!card_not_detected_notified) { - nfc_worker->callback(NfcWorkerEventNoCardDetected, nfc_worker->context); - card_not_detected_notified = true; - } + } + } else { + if(!card_not_detected_notified) { + nfc_worker->callback(NfcWorkerEventNoCardDetected, nfc_worker->context); + card_not_detected_notified = true; } } furi_hal_nfc_sleep(); @@ -509,7 +509,7 @@ void nfc_worker_emulate_apdu(NfcWorker* nfc_worker) { reader_analyzer_start(nfc_worker->reader_analyzer, ReaderAnalyzerModeDebugLog); } - while(nfc_worker->state == NfcWorkerStateEmulateApdu) { + while(nfc_worker->state == NfcWorkerStateEmulateApdu) { //-V1044 if(furi_hal_nfc_listen(params.uid, params.uid_len, params.atqa, params.sak, false, 300)) { FURI_LOG_D(TAG, "POS terminal detected"); if(emv_card_emulation(&tx_rx)) { @@ -657,7 +657,7 @@ void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker) { } FURI_LOG_D( - TAG, "Start Dictionary attack, Key Count %ld", mf_classic_dict_get_total_keys(dict)); + TAG, "Start Dictionary attack, Key Count %lu", mf_classic_dict_get_total_keys(dict)); for(size_t i = 0; i < total_sectors; i++) { FURI_LOG_I(TAG, "Sector %d", i); nfc_worker->callback(NfcWorkerEventNewSector, nfc_worker->context); @@ -742,7 +742,7 @@ void nfc_worker_emulate_mf_classic(NfcWorker* nfc_worker) { rfal_platform_spi_acquire(); furi_hal_nfc_listen_start(nfc_data); - while(nfc_worker->state == NfcWorkerStateMfClassicEmulate) { + while(nfc_worker->state == NfcWorkerStateMfClassicEmulate) { //-V1044 if(furi_hal_nfc_listen_rx(&tx_rx, 300)) { mf_classic_emulator(&emulator, &tx_rx); } @@ -776,7 +776,8 @@ void nfc_worker_write_mf_classic(NfcWorker* nfc_worker) { furi_hal_nfc_sleep(); FURI_LOG_I(TAG, "Check low level nfc data"); - if(memcmp(&nfc_data, &nfc_worker->dev_data->nfc_data, sizeof(FuriHalNfcDevData))) { + if(memcmp(&nfc_data, &nfc_worker->dev_data->nfc_data, sizeof(FuriHalNfcDevData)) != + 0) { FURI_LOG_E(TAG, "Wrong card"); nfc_worker->callback(NfcWorkerEventWrongCard, nfc_worker->context); break; @@ -848,7 +849,8 @@ void nfc_worker_update_mf_classic(NfcWorker* nfc_worker) { furi_hal_nfc_sleep(); FURI_LOG_I(TAG, "Check low level nfc data"); - if(memcmp(&nfc_data, &nfc_worker->dev_data->nfc_data, sizeof(FuriHalNfcDevData))) { + if(memcmp(&nfc_data, &nfc_worker->dev_data->nfc_data, sizeof(FuriHalNfcDevData)) != + 0) { FURI_LOG_E(TAG, "Low level nfc data mismatch"); nfc_worker->callback(NfcWorkerEventWrongCard, nfc_worker->context); break; diff --git a/lib/nfc/parsers/all_in_one.c b/lib/nfc/parsers/all_in_one.c index 05cfe5764..c02710a29 100644 --- a/lib/nfc/parsers/all_in_one.c +++ b/lib/nfc/parsers/all_in_one.c @@ -73,24 +73,14 @@ bool all_in_one_parser_parse(NfcDeviceData* dev_data) { return false; } - // If the layout is a then the ride count is stored in the first byte of page 8 uint8_t ride_count = 0; uint32_t serial = 0; if(all_in_one_get_layout(dev_data) == ALL_IN_ONE_LAYOUT_A) { + // If the layout is A then the ride count is stored in the first byte of page 8 ride_count = dev_data->mf_ul_data.data[4 * 8]; } else if(all_in_one_get_layout(dev_data) == ALL_IN_ONE_LAYOUT_D) { // If the layout is D, the ride count is stored in the second byte of page 9 ride_count = dev_data->mf_ul_data.data[4 * 9 + 1]; - // I hate this with a burning passion. - - // The number starts at the second half of the third byte on page 4, and is 32 bits long - // So we get the second half of the third byte, then bytes 4-6, and then the first half of the 7th byte - // B8 17 A2 A4 BD becomes 81 7A 2A 4B - serial = (dev_data->mf_ul_data.data[4 * 4 + 2] & 0x0F) << 28 | - dev_data->mf_ul_data.data[4 * 4 + 3] << 20 | - dev_data->mf_ul_data.data[4 * 4 + 4] << 12 | - dev_data->mf_ul_data.data[4 * 4 + 5] << 4 | - (dev_data->mf_ul_data.data[4 * 4 + 6] >> 4); } else { FURI_LOG_I("all_in_one", "Unknown layout: %d", all_in_one_get_layout(dev_data)); ride_count = 137; @@ -110,4 +100,4 @@ bool all_in_one_parser_parse(NfcDeviceData* dev_data) { furi_string_printf( dev_data->parsed_data, "\e#All-In-One\nNumber: %lu\nRides left: %u", serial, ride_count); return true; -} \ No newline at end of file +} diff --git a/lib/nfc/parsers/plantain_4k_parser.c b/lib/nfc/parsers/plantain_4k_parser.c index 348b5a64c..9a51cdeaf 100644 --- a/lib/nfc/parsers/plantain_4k_parser.c +++ b/lib/nfc/parsers/plantain_4k_parser.c @@ -116,26 +116,9 @@ bool plantain_4k_parser_parse(NfcDeviceData* dev_data) { for(size_t i = 0; i < 7; i++) { card_number = (card_number << 8) | card_number_arr[i]; } - // Convert card number to string - FuriString* card_number_str; - card_number_str = furi_string_alloc(); - // Should look like "361301047292848684" - furi_string_printf(card_number_str, "%llu", card_number); - // Add suffix with luhn checksum (1 digit) to the card number string - FuriString* card_number_suffix; - card_number_suffix = furi_string_alloc(); - - furi_string_cat_printf(card_number_suffix, "-"); - furi_string_cat_printf(card_number_str, furi_string_get_cstr(card_number_suffix)); - // Free all not needed strings - furi_string_free(card_number_suffix); furi_string_printf( - dev_data->parsed_data, - "\e#Plantain\nN:%s\nBalance:%ld\n", - furi_string_get_cstr(card_number_str), - balance); - furi_string_free(card_number_str); + dev_data->parsed_data, "\e#Plantain\nN:%llu-\nBalance:%ld\n", card_number, balance); return true; } diff --git a/lib/nfc/parsers/plantain_parser.c b/lib/nfc/parsers/plantain_parser.c index 5328b5c4f..799262171 100644 --- a/lib/nfc/parsers/plantain_parser.c +++ b/lib/nfc/parsers/plantain_parser.c @@ -89,26 +89,9 @@ bool plantain_parser_parse(NfcDeviceData* dev_data) { for(size_t i = 0; i < 7; i++) { card_number = (card_number << 8) | card_number_arr[i]; } - // Convert card number to string - FuriString* card_number_str; - card_number_str = furi_string_alloc(); - // Should look like "361301047292848684" - furi_string_printf(card_number_str, "%llu", card_number); - // Add suffix with luhn checksum (1 digit) to the card number string - FuriString* card_number_suffix; - card_number_suffix = furi_string_alloc(); - - furi_string_cat_printf(card_number_suffix, "-"); - furi_string_cat_printf(card_number_str, furi_string_get_cstr(card_number_suffix)); - // Free all not needed strings - furi_string_free(card_number_suffix); furi_string_printf( - dev_data->parsed_data, - "\e#Plantain\nN:%s\nBalance:%ld\n", - furi_string_get_cstr(card_number_str), - balance); - furi_string_free(card_number_str); + dev_data->parsed_data, "\e#Plantain\nN:%llu-\nBalance:%ld\n", card_number, balance); return true; } diff --git a/lib/nfc/parsers/two_cities.c b/lib/nfc/parsers/two_cities.c index 2c6184a71..2f4b7dd0d 100644 --- a/lib/nfc/parsers/two_cities.c +++ b/lib/nfc/parsers/two_cities.c @@ -117,19 +117,6 @@ bool two_cities_parser_parse(NfcDeviceData* dev_data) { for(size_t i = 0; i < 7; i++) { card_number = (card_number << 8) | card_number_arr[i]; } - // Convert card number to string - FuriString* card_number_str; - card_number_str = furi_string_alloc(); - // Should look like "361301047292848684" - furi_string_printf(card_number_str, "%llu", card_number); - // Add suffix with luhn checksum (1 digit) to the card number string - FuriString* card_number_suffix; - card_number_suffix = furi_string_alloc(); - - furi_string_cat_printf(card_number_suffix, "-"); - furi_string_cat_printf(card_number_str, furi_string_get_cstr(card_number_suffix)); - // Free all not needed strings - furi_string_free(card_number_suffix); // ===== // --PLANTAIN-- @@ -149,12 +136,11 @@ bool two_cities_parser_parse(NfcDeviceData* dev_data) { furi_string_printf( dev_data->parsed_data, - "\e#Troika+Plantain\nPN: %s\nPB: %ld rur.\nTN: %ld\nTB: %d rur.\n", - furi_string_get_cstr(card_number_str), + "\e#Troika+Plantain\nPN: %llu-\nPB: %ld rur.\nTN: %ld\nTB: %d rur.\n", + card_number, balance, troika_number, troika_balance); - furi_string_free(card_number_str); return true; } diff --git a/lib/nfc/protocols/crypto1.c b/lib/nfc/protocols/crypto1.c index 2ac0ff081..f59651cf4 100644 --- a/lib/nfc/protocols/crypto1.c +++ b/lib/nfc/protocols/crypto1.c @@ -4,7 +4,8 @@ // Algorithm from https://github.com/RfidResearchGroup/proxmark3.git -#define SWAPENDIAN(x) (x = (x >> 8 & 0xff00ff) | (x & 0xff00ff) << 8, x = x >> 16 | x << 16) +#define SWAPENDIAN(x) \ + ((x) = ((x) >> 8 & 0xff00ff) | ((x)&0xff00ff) << 8, (x) = (x) >> 16 | (x) << 16) #define LF_POLY_ODD (0x29CE5C) #define LF_POLY_EVEN (0x870804) diff --git a/lib/nfc/protocols/mifare_classic.c b/lib/nfc/protocols/mifare_classic.c index f4c7353a8..e26dfd7f7 100644 --- a/lib/nfc/protocols/mifare_classic.c +++ b/lib/nfc/protocols/mifare_classic.c @@ -245,7 +245,8 @@ bool mf_classic_is_allowed_access_sector_trailer( case MfClassicActionKeyARead: { return false; } - case MfClassicActionKeyAWrite: { + case MfClassicActionKeyAWrite: + case MfClassicActionKeyBWrite: { return ( (key == MfClassicKeyA && (AC == 0x00 || AC == 0x01)) || (key == MfClassicKeyB && (AC == 0x04 || AC == 0x03))); @@ -253,11 +254,6 @@ bool mf_classic_is_allowed_access_sector_trailer( case MfClassicActionKeyBRead: { return (key == MfClassicKeyA && (AC == 0x00 || AC == 0x02 || AC == 0x01)); } - case MfClassicActionKeyBWrite: { - return ( - (key == MfClassicKeyA && (AC == 0x00 || AC == 0x01)) || - (key == MfClassicKeyB && (AC == 0x04 || AC == 0x03))); - } case MfClassicActionACRead: { return ( (key == MfClassicKeyA) || @@ -734,7 +730,7 @@ bool mf_classic_emulator(MfClassicEmulator* emulator, FuriHalNfcTxRxContext* tx_ MfClassicKey access_key = MfClassicKeyA; // Read command - while(!command_processed) { + while(!command_processed) { //-V654 if(!is_encrypted) { crypto1_reset(&emulator->crypto); memcpy(plain_data, tx_rx->rx_data, tx_rx->rx_bits / 8); @@ -850,7 +846,7 @@ bool mf_classic_emulator(MfClassicEmulator* emulator, FuriHalNfcTxRxContext* tx_ if(mf_classic_is_sector_trailer(block)) { if(!mf_classic_is_allowed_access( emulator, block, access_key, MfClassicActionKeyARead)) { - memset(block_data, 0, 6); + memset(block_data, 0, 6); //-V1086 } if(!mf_classic_is_allowed_access( emulator, block, access_key, MfClassicActionKeyBRead)) { @@ -860,22 +856,16 @@ bool mf_classic_emulator(MfClassicEmulator* emulator, FuriHalNfcTxRxContext* tx_ 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; - if(is_encrypted) { - crypto1_encrypt( - &emulator->crypto, NULL, &nack, 4, tx_rx->tx_data, tx_rx->tx_parity); - } else { - tx_rx->tx_data[0] = nack; - } - tx_rx->tx_rx_type = FuriHalNfcTxRxTransparent; - tx_rx->tx_bits = 4; - furi_hal_nfc_tx_rx(tx_rx, 300); - break; - } + } 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); + break; } nfca_append_crc16(block_data, 16); @@ -908,7 +898,7 @@ bool mf_classic_emulator(MfClassicEmulator* emulator, FuriHalNfcTxRxContext* tx_ if(mf_classic_is_sector_trailer(block)) { if(mf_classic_is_allowed_access( emulator, block, access_key, MfClassicActionKeyAWrite)) { - memcpy(block_data, plain_data, 6); + memcpy(block_data, plain_data, 6); //-V1086 } if(mf_classic_is_allowed_access( emulator, block, access_key, MfClassicActionKeyBWrite)) { @@ -924,7 +914,7 @@ bool mf_classic_emulator(MfClassicEmulator* emulator, FuriHalNfcTxRxContext* tx_ memcpy(block_data, plain_data, MF_CLASSIC_BLOCK_SIZE); } } - if(memcmp(block_data, emulator->data.block[block].value, MF_CLASSIC_BLOCK_SIZE)) { + 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; } @@ -1060,7 +1050,8 @@ bool mf_classic_write_sector( bool write_success = true; for(size_t i = first_block; i < first_block + total_blocks; i++) { // Compare blocks - if(memcmp(dest_data->block[i].value, src_data->block[i].value, MF_CLASSIC_BLOCK_SIZE)) { + if(memcmp(dest_data->block[i].value, src_data->block[i].value, MF_CLASSIC_BLOCK_SIZE) != + 0) { bool key_a_write_allowed = mf_classic_is_allowed_access_data_block( dest_data, i, MfClassicKeyA, MfClassicActionDataWrite); bool key_b_write_allowed = mf_classic_is_allowed_access_data_block( diff --git a/lib/nfc/protocols/mifare_desfire.c b/lib/nfc/protocols/mifare_desfire.c index b2247bf20..23308ae95 100644 --- a/lib/nfc/protocols/mifare_desfire.c +++ b/lib/nfc/protocols/mifare_desfire.c @@ -108,7 +108,7 @@ void mf_df_cat_version(MifareDesfireVersion* version, FuriString* out) { } void mf_df_cat_free_mem(MifareDesfireFreeMemory* free_mem, FuriString* out) { - furi_string_cat_printf(out, "freeMem %ld\n", free_mem->bytes); + furi_string_cat_printf(out, "freeMem %lu\n", free_mem->bytes); } void mf_df_cat_key_settings(MifareDesfireKeySettings* ks, FuriString* out) { @@ -191,10 +191,10 @@ void mf_df_cat_file(MifareDesfireFile* file, FuriString* out) { case MifareDesfireFileTypeValue: size = 4; furi_string_cat_printf( - out, "lo %ld hi %ld\n", file->settings.value.lo_limit, file->settings.value.hi_limit); + out, "lo %lu hi %lu\n", file->settings.value.lo_limit, file->settings.value.hi_limit); furi_string_cat_printf( out, - "limit %ld enabled %d\n", + "limit %lu enabled %d\n", file->settings.value.limited_credit_value, file->settings.value.limited_credit_enabled); break; @@ -203,7 +203,7 @@ void mf_df_cat_file(MifareDesfireFile* file, FuriString* out) { size = file->settings.record.size; num = file->settings.record.cur; furi_string_cat_printf(out, "size %d\n", size); - furi_string_cat_printf(out, "num %d max %ld\n", num, file->settings.record.max); + furi_string_cat_printf(out, "num %d max %lu\n", num, file->settings.record.max); break; } uint8_t* data = file->contents; @@ -220,8 +220,9 @@ void mf_df_cat_file(MifareDesfireFile* file, FuriString* out) { } } for(int i = 0; i < 4 && ch + i < size; i++) { - if(isprint(data[rec * size + ch + i])) { - furi_string_cat_printf(out, "%c", data[rec * size + ch + i]); + const size_t data_index = rec * size + ch + i; + if(isprint(data[data_index])) { + furi_string_cat_printf(out, "%c", data[data_index]); } else { furi_string_cat_printf(out, "."); } @@ -547,7 +548,8 @@ bool mf_df_read_card(FuriHalNfcTxRxContext* tx_rx, MifareDesfireData* data) { for(MifareDesfireApplication* app = data->app_head; app; app = app->next) { tx_rx->tx_bits = 8 * mf_df_prepare_select_application(tx_rx->tx_data, app->id); if(!furi_hal_nfc_tx_rx_full(tx_rx) || - !mf_df_parse_select_application_response(tx_rx->rx_data, tx_rx->rx_bits / 8)) { + !mf_df_parse_select_application_response( + tx_rx->rx_data, tx_rx->rx_bits / 8)) { //-V1051 FURI_LOG_W(TAG, "Bad exchange selecting application"); continue; } diff --git a/lib/nfc/protocols/mifare_ultralight.c b/lib/nfc/protocols/mifare_ultralight.c index 85e234bd9..d642e290a 100644 --- a/lib/nfc/protocols/mifare_ultralight.c +++ b/lib/nfc/protocols/mifare_ultralight.c @@ -170,6 +170,7 @@ bool mf_ultralight_read_version( } bool mf_ultralight_authenticate(FuriHalNfcTxRxContext* tx_rx, uint32_t key, uint16_t* pack) { + furi_assert(pack); bool authenticated = false; do { @@ -189,9 +190,7 @@ bool mf_ultralight_authenticate(FuriHalNfcTxRxContext* tx_rx, uint32_t key, uint break; } - if(pack != NULL) { - *pack = (tx_rx->rx_data[1] << 8) | tx_rx->rx_data[0]; - } + *pack = (tx_rx->rx_data[1] << 8) | tx_rx->rx_data[0]; FURI_LOG_I(TAG, "Auth success. Password: %08lX. PACK: %04X", key, *pack); authenticated = true; @@ -492,7 +491,7 @@ MfUltralightConfigPages* mf_ultralight_get_config_pages(MfUltralightData* data) } else if( data->type >= MfUltralightTypeNTAGI2CPlus1K && data->type <= MfUltralightTypeNTAGI2CPlus2K) { - return (MfUltralightConfigPages*)&data->data[0xe3 * 4]; + return (MfUltralightConfigPages*)&data->data[0xe3 * 4]; //-V641 } else { return NULL; } @@ -561,7 +560,7 @@ bool mf_ultralight_read_pages_direct( FURI_LOG_D(TAG, "Failed to read pages %d - %d", start_index, start_index + 3); return false; } - memcpy(data, tx_rx->rx_data, 16); + memcpy(data, tx_rx->rx_data, 16); //-V1086 return true; } @@ -584,7 +583,8 @@ bool mf_ultralight_read_pages( curr_sector_index = tag_sector; } - FURI_LOG_D(TAG, "Reading pages %d - %d", i, i + (valid_pages > 4 ? 4 : valid_pages) - 1); + FURI_LOG_D( + TAG, "Reading pages %zu - %zu", i, i + (valid_pages > 4 ? 4 : valid_pages) - 1U); tx_rx->tx_data[0] = MF_UL_READ_CMD; tx_rx->tx_data[1] = tag_page; tx_rx->tx_bits = 16; @@ -593,9 +593,9 @@ bool mf_ultralight_read_pages( if(!furi_hal_nfc_tx_rx(tx_rx, 50) || tx_rx->rx_bits < 16 * 8) { FURI_LOG_D( TAG, - "Failed to read pages %d - %d", + "Failed to read pages %zu - %zu", i, - i + (valid_pages > 4 ? 4 : valid_pages) - 1); + i + (valid_pages > 4 ? 4 : valid_pages) - 1U); break; } @@ -857,7 +857,7 @@ static void mf_ul_ntag_i2c_fill_cross_area_read( } if(apply) { - while(tx_page_offset < 0 && page_length > 0) { + while(tx_page_offset < 0 && page_length > 0) { //-V614 ++tx_page_offset; ++data_page_offset; --page_length; @@ -987,9 +987,9 @@ static bool mf_ul_check_lock(MfUltralightEmulator* emulator, int16_t write_page) switch(emulator->data.type) { // low byte LSB range, MSB range case MfUltralightTypeNTAG203: - if(write_page >= 16 && write_page <= 27) + if(write_page >= 16 && write_page <= 27) //-V560 shift = (write_page - 16) / 4 + 1; - else if(write_page >= 28 && write_page <= 39) + else if(write_page >= 28 && write_page <= 39) //-V560 shift = (write_page - 28) / 4 + 5; else if(write_page == 41) shift = 12; @@ -1216,7 +1216,7 @@ static void mf_ul_emulate_write( page_buff[0] = new_locks & 0xff; page_buff[1] = new_locks >> 8; page_buff[2] = new_block_locks; - if(emulator->data.type >= MfUltralightTypeUL21 && + if(emulator->data.type >= MfUltralightTypeUL21 && //-V1016 emulator->data.type <= MfUltralightTypeNTAG216) page_buff[3] = MF_UL_TEARING_FLAG_DEFAULT; else diff --git a/lib/one_wire/ibutton/ibutton_key.c b/lib/one_wire/ibutton/ibutton_key.c index 2c0f7fa26..7b7571a29 100644 --- a/lib/one_wire/ibutton/ibutton_key.c +++ b/lib/one_wire/ibutton/ibutton_key.c @@ -62,8 +62,6 @@ const char* ibutton_key_get_string_by_type(iButtonKeyType key_type) { break; default: furi_crash("Invalid iButton type"); - return ""; - break; } } diff --git a/lib/one_wire/ibutton/ibutton_worker_modes.c b/lib/one_wire/ibutton/ibutton_worker_modes.c index b1e5904ca..b284940e7 100644 --- a/lib/one_wire/ibutton/ibutton_worker_modes.c +++ b/lib/one_wire/ibutton/ibutton_worker_modes.c @@ -130,7 +130,6 @@ bool ibutton_worker_read_comparator(iButtonWorker* worker) { ibutton_key_set_data(worker->key_p, worker->key_data, ibutton_key_get_max_size()); result = true; break; - break; default: break; } diff --git a/lib/one_wire/ibutton/ibutton_writer.c b/lib/one_wire/ibutton/ibutton_writer.c index 203c4fc07..84d122491 100644 --- a/lib/one_wire/ibutton/ibutton_writer.c +++ b/lib/one_wire/ibutton/ibutton_writer.c @@ -72,7 +72,7 @@ static bool writer_write_TM2004(iButtonWriter* writer, iButtonKey* key) { writer_write_one_bit(writer, 1, 50000); // read written key byte - answer = onewire_host_read(writer->host); + answer = onewire_host_read(writer->host); //-V519 // check that written and read are same if(ibutton_key_get_data_p(key)[i] != answer) { diff --git a/lib/one_wire/ibutton/protocols/protocol_cyfral.c b/lib/one_wire/ibutton/protocols/protocol_cyfral.c index 51c42824f..0c44c2b45 100644 --- a/lib/one_wire/ibutton/protocols/protocol_cyfral.c +++ b/lib/one_wire/ibutton/protocols/protocol_cyfral.c @@ -270,10 +270,10 @@ static LevelDuration protocol_cyfral_encoder_yield(ProtocolCyfral* proto) { // start word (0b0001) switch(proto->encoder.index) { case 0: - result = level_duration_make(false, CYFRAL_0_LOW); + result = level_duration_make(false, CYFRAL_0_LOW); //-V1037 break; case 1: - result = level_duration_make(true, CYFRAL_0_HI); + result = level_duration_make(true, CYFRAL_0_HI); //-V1037 break; case 2: result = level_duration_make(false, CYFRAL_0_LOW); @@ -341,4 +341,4 @@ const ProtocolBase protocol_cyfral = { .start = (ProtocolEncoderStart)protocol_cyfral_encoder_start, .yield = (ProtocolEncoderYield)protocol_cyfral_encoder_yield, }, -}; \ No newline at end of file +}; diff --git a/lib/one_wire/ibutton/protocols/protocol_metakom.c b/lib/one_wire/ibutton/protocols/protocol_metakom.c index 00f16e455..ff65c6678 100644 --- a/lib/one_wire/ibutton/protocols/protocol_metakom.c +++ b/lib/one_wire/ibutton/protocols/protocol_metakom.c @@ -248,14 +248,14 @@ static LevelDuration protocol_metakom_encoder_yield(ProtocolMetakom* proto) { if(proto->encoder.index == 0) { // sync bit result = level_duration_make(false, METAKOM_PERIOD); - } else if(proto->encoder.index >= 1 && proto->encoder.index <= 6) { + } else if(proto->encoder.index <= 6) { // start word (0b010) switch(proto->encoder.index) { case 1: - result = level_duration_make(true, METAKOM_0_LOW); + result = level_duration_make(true, METAKOM_0_LOW); //-V1037 break; case 2: - result = level_duration_make(false, METAKOM_0_HI); + result = level_duration_make(false, METAKOM_0_HI); //-V1037 break; case 3: result = level_duration_make(true, METAKOM_1_LOW); @@ -317,4 +317,4 @@ const ProtocolBase protocol_metakom = { .start = (ProtocolEncoderStart)protocol_metakom_encoder_start, .yield = (ProtocolEncoderYield)protocol_metakom_encoder_yield, }, -}; \ No newline at end of file +}; diff --git a/lib/one_wire/one_wire_slave.c b/lib/one_wire/one_wire_slave.c index af04cfdab..ad9c34b19 100644 --- a/lib/one_wire/one_wire_slave.c +++ b/lib/one_wire/one_wire_slave.c @@ -41,7 +41,7 @@ uint32_t onewire_slave_wait_while_gpio_is(OneWireSlave* bus, uint32_t time, cons uint32_t time_ticks = time * furi_hal_cortex_instructions_per_microsecond(); uint32_t time_captured; - do { + do { //-V1044 time_captured = DWT->CYCCNT; if(furi_hal_ibutton_pin_get_level() != pin_value) { uint32_t remaining_time = time_ticks - (time_captured - start); @@ -155,8 +155,10 @@ bool onewire_slave_receive_and_process_cmd(OneWireSlave* bus) { uint8_t cmd; onewire_slave_receive(bus, &cmd, 1); - if(bus->error == RESET_IN_PROGRESS) return true; - if(bus->error != NO_ERROR) return false; + if(bus->error == RESET_IN_PROGRESS) + return true; + else if(bus->error != NO_ERROR) + return false; switch(cmd) { case 0xF0: @@ -172,10 +174,8 @@ bool onewire_slave_receive_and_process_cmd(OneWireSlave* bus) { default: // Unknown command bus->error = INCORRECT_ONEWIRE_CMD; + return false; } - - if(bus->error == RESET_IN_PROGRESS) return true; - return (bus->error == NO_ERROR); } bool onewire_slave_bus_start(OneWireSlave* bus) { diff --git a/lib/print/printf_tiny.c b/lib/print/printf_tiny.c index 6e47f6528..54f192a60 100644 --- a/lib/print/printf_tiny.c +++ b/lib/print/printf_tiny.c @@ -541,7 +541,7 @@ static size_t _etoa( exp2 = (int)(expval * 3.321928094887362 + 0.5); const double z = expval * 2.302585092994046 - exp2 * 0.6931471805599453; const double z2 = z * z; - conv.U = ((uint64_t)exp2 + 1023) << 52U; + conv.U = ((uint64_t)exp2 + 1023) << 52U; //-V519 // compute exp(z) using continued fractions, see https://en.wikipedia.org/wiki/Exponential_function#Continued_fractions_for_ex conv.F *= 1 + 2 * z / (2 - z + (z2 / (6 + (z2 / (10 + z2 / 14))))); // correct for rounding errors diff --git a/lib/subghz/blocks/generic.c b/lib/subghz/blocks/generic.c index 1bad5f0a3..94114676d 100644 --- a/lib/subghz/blocks/generic.c +++ b/lib/subghz/blocks/generic.c @@ -71,7 +71,7 @@ bool subghz_block_generic_serialize( uint8_t key_data[sizeof(uint64_t)] = {0}; for(size_t i = 0; i < sizeof(uint64_t); i++) { - key_data[sizeof(uint64_t) - i - 1] = (instance->data >> i * 8) & 0xFF; + key_data[sizeof(uint64_t) - i - 1] = (instance->data >> (i * 8)) & 0xFF; } if(!flipper_format_write_hex(flipper_format, "Key", key_data, sizeof(uint64_t))) { diff --git a/lib/subghz/blocks/math.h b/lib/subghz/blocks/math.h index a4f04271a..87c209f71 100644 --- a/lib/subghz/blocks/math.h +++ b/lib/subghz/blocks/math.h @@ -8,8 +8,7 @@ #define bit_set(value, bit) ((value) |= (1UL << (bit))) #define bit_clear(value, bit) ((value) &= ~(1UL << (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)) -#define abs(x) ((x) > 0 ? (x) : -(x)) +#define DURATION_DIFF(x, y) (((x) < (y)) ? ((y) - (x)) : ((x) - (y))) #ifdef __cplusplus extern "C" { diff --git a/lib/subghz/protocols/bett.c b/lib/subghz/protocols/bett.c index 2dd39af9e..644d80fd8 100644 --- a/lib/subghz/protocols/bett.c +++ b/lib/subghz/protocols/bett.c @@ -242,7 +242,6 @@ void subghz_protocol_decoder_bett_feed(void* context, bool level, uint32_t durat if(!level) { if(DURATION_DIFF(duration, subghz_protocol_bett_const.te_short * 44) < (subghz_protocol_bett_const.te_delta * 15)) { - instance->decoder.parser_step = BETTDecoderStepSaveDuration; if(instance->decoder.decode_count_bit == subghz_protocol_bett_const.min_count_bit_for_found) { instance->generic.data = instance->decoder.decode_data; diff --git a/lib/subghz/protocols/holtek.c b/lib/subghz/protocols/holtek.c index 39e27bbf8..8aaad3b71 100644 --- a/lib/subghz/protocols/holtek.c +++ b/lib/subghz/protocols/holtek.c @@ -240,7 +240,6 @@ void subghz_protocol_decoder_holtek_feed(void* context, bool level, uint32_t dur if(!level) { if(duration >= ((uint32_t)subghz_protocol_holtek_const.te_short * 10 + subghz_protocol_holtek_const.te_delta)) { - instance->decoder.parser_step = HoltekDecoderStepSaveDuration; if(instance->decoder.decode_count_bit == subghz_protocol_holtek_const.min_count_bit_for_found) { if((instance->decoder.decode_data & HOLTEK_HEADER_MASK) == HOLTEK_HEADER) { diff --git a/lib/subghz/protocols/keeloq.c b/lib/subghz/protocols/keeloq.c index eef1d0937..6a9c3468e 100644 --- a/lib/subghz/protocols/keeloq.c +++ b/lib/subghz/protocols/keeloq.c @@ -119,8 +119,8 @@ void subghz_protocol_encoder_keeloq_free(void* context) { */ static bool subghz_protocol_keeloq_gen_data(SubGhzProtocolEncoderKeeloq* instance, uint8_t btn) { instance->generic.cnt++; - uint32_t fix = btn << 28 | instance->generic.serial; - uint32_t decrypt = btn << 28 | + uint32_t fix = (uint32_t)btn << 28 | instance->generic.serial; + uint32_t decrypt = (uint32_t)btn << 28 | (instance->generic.serial & 0x3FF) << 16 | //ToDo in some protocols the discriminator is 0 instance->generic.cnt; @@ -271,7 +271,8 @@ bool subghz_protocol_encoder_keeloq_deserialize(void* context, FlipperFormat* fl subghz_protocol_keeloq_check_remote_controller( &instance->generic, instance->keystore, &instance->manufacture_name); - if(strcmp(instance->manufacture_name, "DoorHan")) { + if(strcmp(instance->manufacture_name, "DoorHan") != 0) { + FURI_LOG_E(TAG, "Wrong manufacturer name"); break; } @@ -287,7 +288,7 @@ bool subghz_protocol_encoder_keeloq_deserialize(void* context, FlipperFormat* fl } uint8_t key_data[sizeof(uint64_t)] = {0}; for(size_t i = 0; i < sizeof(uint64_t); i++) { - key_data[sizeof(uint64_t) - i - 1] = (instance->generic.data >> i * 8) & 0xFF; + key_data[sizeof(uint64_t) - i - 1] = (instance->generic.data >> (i * 8)) & 0xFF; } if(!flipper_format_update_hex(flipper_format, "Key", key_data, sizeof(uint64_t))) { FURI_LOG_E(TAG, "Unable to add Key"); diff --git a/lib/subghz/protocols/kia.c b/lib/subghz/protocols/kia.c index 997f8e1de..a5d9e37ef 100644 --- a/lib/subghz/protocols/kia.c +++ b/lib/subghz/protocols/kia.c @@ -142,7 +142,7 @@ void subghz_protocol_decoder_kia_feed(void* context, bool level, uint32_t durati case KIADecoderStepSaveDuration: if(level) { if(duration >= - (uint32_t)(subghz_protocol_kia_const.te_long + subghz_protocol_kia_const.te_delta * 2)) { + (subghz_protocol_kia_const.te_long + subghz_protocol_kia_const.te_delta * 2UL)) { //Found stop bit instance->decoder.parser_step = KIADecoderStepReset; if(instance->decoder.decode_count_bit == diff --git a/lib/subghz/protocols/megacode.c b/lib/subghz/protocols/megacode.c index 1b871a0c6..05b5b6894 100644 --- a/lib/subghz/protocols/megacode.c +++ b/lib/subghz/protocols/megacode.c @@ -417,7 +417,7 @@ void subghz_protocol_decoder_megacode_get_string(void* context, FuriString* outp output, "%s %dbit\r\n" "Key:0x%06lX\r\n" - "Sn:0x%04lX - %ld\r\n" + "Sn:0x%04lX - %lu\r\n" "Facility:%lX Btn:%X\r\n", instance->generic.protocol_name, instance->generic.data_count_bit, diff --git a/lib/subghz/protocols/nero_radio.c b/lib/subghz/protocols/nero_radio.c index 5fffaa19d..c8126b1e1 100644 --- a/lib/subghz/protocols/nero_radio.c +++ b/lib/subghz/protocols/nero_radio.c @@ -308,7 +308,7 @@ void subghz_protocol_decoder_nero_radio_feed(void* context, bool level, uint32_t } instance->decoder.decode_data = 0; instance->decoder.decode_count_bit = 0; - instance->decoder.parser_step = NeroRadioDecoderStepReset; + instance->decoder.parser_step = NeroRadioDecoderStepReset; //-V1048 break; } else if( (DURATION_DIFF( diff --git a/lib/subghz/protocols/princeton.c b/lib/subghz/protocols/princeton.c index ab1c58765..7fc8f6524 100644 --- a/lib/subghz/protocols/princeton.c +++ b/lib/subghz/protocols/princeton.c @@ -363,7 +363,7 @@ void subghz_protocol_decoder_princeton_get_string(void* context, FuriString* out "Key:0x%08lX\r\n" "Yek:0x%08lX\r\n" "Sn:0x%05lX Btn:%01X\r\n" - "Te:%ldus\r\n", + "Te:%luus\r\n", instance->generic.protocol_name, instance->generic.data_count_bit, (uint32_t)(instance->generic.data & 0xFFFFFF), diff --git a/lib/subghz/protocols/princeton_for_testing.c b/lib/subghz/protocols/princeton_for_testing.c index 0987e0ad6..fa5616020 100644 --- a/lib/subghz/protocols/princeton_for_testing.c +++ b/lib/subghz/protocols/princeton_for_testing.c @@ -94,12 +94,12 @@ void subghz_encoder_princeton_for_testing_print_log(void* context) { ((float)instance->time_high / (instance->time_high + instance->time_low)) * 100; FURI_LOG_I( TAG "Encoder", - "Radio tx_time=%ldus ON=%ldus, OFF=%ldus, DutyCycle=%ld,%ld%%", + "Radio tx_time=%luus ON=%luus, OFF=%luus, DutyCycle=%lu,%lu%%", instance->time_high + instance->time_low, instance->time_high, instance->time_low, (uint32_t)duty_cycle, - (uint32_t)((duty_cycle - (uint32_t)duty_cycle) * 100)); + (uint32_t)((duty_cycle - (uint32_t)duty_cycle) * 100UL)); } LevelDuration subghz_encoder_princeton_for_testing_yield(void* context) { diff --git a/lib/subghz/protocols/scher_khan.c b/lib/subghz/protocols/scher_khan.c index a9a3078e4..955104bcf 100644 --- a/lib/subghz/protocols/scher_khan.c +++ b/lib/subghz/protocols/scher_khan.c @@ -151,8 +151,8 @@ void subghz_protocol_decoder_scher_khan_feed(void* context, bool level, uint32_t break; case ScherKhanDecoderStepSaveDuration: if(level) { - if(duration >= (uint32_t)(subghz_protocol_scher_khan_const.te_long + - subghz_protocol_scher_khan_const.te_delta * 2)) { + if(duration >= (subghz_protocol_scher_khan_const.te_delta * 2UL + + subghz_protocol_scher_khan_const.te_long)) { //Found stop bit instance->decoder.parser_step = ScherKhanDecoderStepReset; if(instance->decoder.decode_count_bit >= diff --git a/lib/subghz/protocols/secplus_v1.c b/lib/subghz/protocols/secplus_v1.c index 7bd0b5b79..75a44a26c 100644 --- a/lib/subghz/protocols/secplus_v1.c +++ b/lib/subghz/protocols/secplus_v1.c @@ -291,7 +291,7 @@ bool subghz_protocol_encoder_secplus_v1_deserialize(void* context, FlipperFormat uint8_t key_data[sizeof(uint64_t)] = {0}; for(size_t i = 0; i < sizeof(uint64_t); i++) { - key_data[sizeof(uint64_t) - i - 1] = (instance->generic.data >> i * 8) & 0xFF; + key_data[sizeof(uint64_t) - i - 1] = (instance->generic.data >> (i * 8)) & 0xFF; } if(!flipper_format_update_hex(flipper_format, "Key", key_data, sizeof(uint64_t))) { FURI_LOG_E(TAG, "Unable to add Key"); @@ -550,7 +550,7 @@ bool subghz_protocol_secplus_v1_check_fixed(uint32_t fixed) { do { if(id1 == 0) return false; - if(!(btn == 0 || btn == 1 || btn == 2)) return false; + if(!(btn == 0 || btn == 1 || btn == 2)) return false; //-V560 } while(false); return true; } @@ -588,7 +588,7 @@ void subghz_protocol_decoder_secplus_v1_get_string(void* context, FuriString* ou if(pin <= 9999) { furi_string_cat_printf(output, " pin:%d", pin); - } else if(10000 <= pin && pin <= 11029) { + } else if(pin <= 11029) { furi_string_cat_printf(output, " pin:enter"); } @@ -618,7 +618,7 @@ void subghz_protocol_decoder_secplus_v1_get_string(void* context, FuriString* ou furi_string_cat_printf(output, " Btn:left\r\n"); } else if(instance->generic.btn == 0) { furi_string_cat_printf(output, " Btn:middle\r\n"); - } else if(instance->generic.btn == 2) { + } else if(instance->generic.btn == 2) { //-V547 furi_string_cat_printf(output, " Btn:right\r\n"); } diff --git a/lib/subghz/protocols/secplus_v2.c b/lib/subghz/protocols/secplus_v2.c index 90cc805a3..7b79892b0 100644 --- a/lib/subghz/protocols/secplus_v2.c +++ b/lib/subghz/protocols/secplus_v2.c @@ -151,7 +151,7 @@ static bool subghz_protocol_secplus_v2_mix_order_decode(uint8_t order, uint16_t case 0x06: // 0b0110 2, 1, 0], case 0x09: // 0b1001 2, 1, 0], p[2] = a; - p[1] = b; + // p[1]: no change p[0] = c; break; case 0x08: // 0b1000 1, 2, 0], @@ -166,20 +166,18 @@ static bool subghz_protocol_secplus_v2_mix_order_decode(uint8_t order, uint16_t p[1] = c; break; case 0x00: // 0b0000 0, 2, 1], - p[0] = a; + // p[0]: no change p[2] = b; p[1] = c; break; case 0x05: // 0b0101 1, 0, 2], p[1] = a; p[0] = b; - p[2] = c; + // p[2]: no change break; case 0x02: // 0b0010 0, 1, 2], case 0x0A: // 0b1010 0, 1, 2], - p[0] = a; - p[1] = b; - p[2] = c; + // no reordering break; default: FURI_LOG_E(TAG, "Order FAIL"); @@ -539,7 +537,7 @@ bool subghz_protocol_encoder_secplus_v2_deserialize(void* context, FlipperFormat //update data for(size_t i = 0; i < sizeof(uint64_t); i++) { - key_data[sizeof(uint64_t) - i - 1] = (instance->generic.data >> i * 8) & 0xFF; + key_data[sizeof(uint64_t) - i - 1] = (instance->generic.data >> (i * 8)) & 0xFF; } if(!flipper_format_update_hex(flipper_format, "Key", key_data, sizeof(uint64_t))) { FURI_LOG_E(TAG, "Unable to add Key"); @@ -547,7 +545,7 @@ bool subghz_protocol_encoder_secplus_v2_deserialize(void* context, FlipperFormat } for(size_t i = 0; i < sizeof(uint64_t); i++) { - key_data[sizeof(uint64_t) - i - 1] = (instance->secplus_packet_1 >> i * 8) & 0xFF; + key_data[sizeof(uint64_t) - i - 1] = (instance->secplus_packet_1 >> (i * 8)) & 0xFF; } if(!flipper_format_update_hex( flipper_format, "Secplus_packet_1", key_data, sizeof(uint64_t))) { @@ -605,7 +603,7 @@ bool subghz_protocol_secplus_v2_create_data( uint8_t key_data[sizeof(uint64_t)] = {0}; for(size_t i = 0; i < sizeof(uint64_t); i++) { - key_data[sizeof(uint64_t) - i - 1] = (instance->secplus_packet_1 >> i * 8) & 0xFF; + key_data[sizeof(uint64_t) - i - 1] = (instance->secplus_packet_1 >> (i * 8)) & 0xFF; } if(res && @@ -691,7 +689,7 @@ void subghz_protocol_decoder_secplus_v2_feed(void* context, bool level, uint32_t subghz_protocol_secplus_v2_const.te_delta) { event = ManchesterEventLongLow; } else if( - duration >= (uint32_t)(subghz_protocol_secplus_v2_const.te_long * 2 + + duration >= (subghz_protocol_secplus_v2_const.te_long * 2UL + subghz_protocol_secplus_v2_const.te_delta)) { if(instance->decoder.decode_count_bit == subghz_protocol_secplus_v2_const.min_count_bit_for_found) { @@ -766,7 +764,7 @@ bool subghz_protocol_decoder_secplus_v2_serialize( uint8_t key_data[sizeof(uint64_t)] = {0}; for(size_t i = 0; i < sizeof(uint64_t); i++) { - key_data[sizeof(uint64_t) - i - 1] = (instance->secplus_packet_1 >> i * 8) & 0xFF; + key_data[sizeof(uint64_t) - i - 1] = (instance->secplus_packet_1 >> (i * 8)) & 0xFF; } if(res && diff --git a/lib/subghz/protocols/smc5326.c b/lib/subghz/protocols/smc5326.c index 889e39f05..9c9b5d4fd 100644 --- a/lib/subghz/protocols/smc5326.c +++ b/lib/subghz/protocols/smc5326.c @@ -372,8 +372,8 @@ void subghz_protocol_decoder_smc5326_get_string(void* context, FuriString* outpu furi_string_cat_printf( output, - "%s %dbit\r\n" - "Key:%07lX Te:%ldus\r\n" + "%s %ubit\r\n" + "Key:%07lX Te:%luus\r\n" " +: " DIP_PATTERN "\r\n" " o: " DIP_PATTERN " ", instance->generic.protocol_name, diff --git a/lib/subghz/subghz_file_encoder_worker.c b/lib/subghz/subghz_file_encoder_worker.c index abc33188f..5c4d36f78 100644 --- a/lib/subghz/subghz_file_encoder_worker.c +++ b/lib/subghz/subghz_file_encoder_worker.c @@ -90,7 +90,7 @@ LevelDuration subghz_file_encoder_worker_get_level_duration(void* context) { level_duration = level_duration_make(false, -duration); } else if(duration > 0) { level_duration = level_duration_make(true, duration); - } else if(duration == 0) { + } else if(duration == 0) { //-V547 level_duration = level_duration_reset(); FURI_LOG_I(TAG, "Stop transmission"); instance->worker_stoping = true; diff --git a/lib/subghz/subghz_keystore.c b/lib/subghz/subghz_keystore.c index e06bd9796..e0b1cf6ca 100644 --- a/lib/subghz/subghz_keystore.c +++ b/lib/subghz/subghz_keystore.c @@ -189,7 +189,7 @@ bool subghz_keystore_load(SubGhzKeystore* instance, const char* file_name) { bool result = false; uint8_t iv[16]; uint32_t version; - SubGhzKeystoreEncryption encryption; + uint32_t encryption; FuriString* filetype; filetype = furi_string_alloc(); @@ -324,9 +324,9 @@ bool subghz_keystore_save(SubGhzKeystore* instance, const char* file_name, uint8 size_t total_keys = SubGhzKeyArray_size(instance->data); result = encrypted_line_count == total_keys; if(result) { - FURI_LOG_I(TAG, "Success. Encrypted: %d of %d", encrypted_line_count, total_keys); + FURI_LOG_I(TAG, "Success. Encrypted: %zu of %zu", encrypted_line_count, total_keys); } else { - FURI_LOG_E(TAG, "Failure. Encrypted: %d of %d", encrypted_line_count, total_keys); + FURI_LOG_E(TAG, "Failure. Encrypted: %zu of %zu", encrypted_line_count, total_keys); } } while(0); flipper_format_free(flipper_format); @@ -349,9 +349,9 @@ bool subghz_keystore_raw_encrypted_save( uint8_t* iv) { bool encrypted = false; uint32_t version; + uint32_t encryption; FuriString* filetype; filetype = furi_string_alloc(); - SubGhzKeystoreEncryption encryption; Storage* storage = furi_record_open(RECORD_STORAGE); @@ -464,7 +464,7 @@ bool subghz_keystore_raw_encrypted_save( } stream_write_cstring(output_stream, encrypted_line); - } while(result); + } while(true); flipper_format_free(output_flipper_format); @@ -488,7 +488,7 @@ bool subghz_keystore_raw_get_data(const char* file_name, size_t offset, uint8_t* bool result = false; uint8_t iv[16]; uint32_t version; - SubGhzKeystoreEncryption encryption; + uint32_t encryption; FuriString* str_temp; str_temp = furi_string_alloc(); diff --git a/lib/subghz/subghz_setting.c b/lib/subghz/subghz_setting.c index c5ec5db75..57e23c38c 100644 --- a/lib/subghz/subghz_setting.c +++ b/lib/subghz/subghz_setting.c @@ -532,9 +532,8 @@ uint8_t* subghz_setting_get_preset_data_by_name(SubGhzSetting* instance, const c uint32_t subghz_setting_get_frequency(SubGhzSetting* instance, size_t idx) { furi_assert(instance); - uint32_t* ret = FrequencyList_get(instance->frequencies, idx); - if(ret) { - return (*ret) & FREQUENCY_MASK; + if(idx < FrequencyList_size(instance->frequencies)) { + return (*FrequencyList_get(instance->frequencies, idx)) & FREQUENCY_MASK; } else { return 0; } @@ -542,9 +541,8 @@ uint32_t subghz_setting_get_frequency(SubGhzSetting* instance, size_t idx) { uint32_t subghz_setting_get_hopper_frequency(SubGhzSetting* instance, size_t idx) { furi_assert(instance); - uint32_t* ret = FrequencyList_get(instance->hopper_frequencies, idx); - if(ret) { - return *ret; + if(idx < FrequencyList_size(instance->frequencies)) { + return *FrequencyList_get(instance->hopper_frequencies, idx); } else { return 0; } diff --git a/lib/toolbox/dir_walk.c b/lib/toolbox/dir_walk.c index b5e2cb52b..e5a3cf32b 100644 --- a/lib/toolbox/dir_walk.c +++ b/lib/toolbox/dir_walk.c @@ -69,8 +69,11 @@ static DirWalkResult if(dir_walk_filter(dir_walk, name, &info)) { if(return_path != NULL) { - furi_string_printf( - return_path, "%s/%s", furi_string_get_cstr(dir_walk->path), name); + furi_string_printf( //-V576 + return_path, + "%s/%s", + furi_string_get_cstr(dir_walk->path), + name); } if(fileinfo != NULL) { diff --git a/lib/toolbox/float_tools.c b/lib/toolbox/float_tools.c new file mode 100644 index 000000000..9c0fe871e --- /dev/null +++ b/lib/toolbox/float_tools.c @@ -0,0 +1,8 @@ +#include "float_tools.h" + +#include +#include + +bool float_is_equal(float a, float b) { + return fabsf(a - b) <= FLT_EPSILON * fmaxf(fabsf(a), fabsf(b)); +} diff --git a/lib/toolbox/float_tools.h b/lib/toolbox/float_tools.h new file mode 100644 index 000000000..0b758e9f5 --- /dev/null +++ b/lib/toolbox/float_tools.h @@ -0,0 +1,19 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/** Compare two floating point numbers + * @param a First number to compare + * @param b Second number to compare + * + * @return bool true if a equals b, false otherwise + */ +bool float_is_equal(float a, float b); + +#ifdef __cplusplus +} +#endif diff --git a/lib/toolbox/hex.c b/lib/toolbox/hex.c index 7b2719b79..25dcb0950 100644 --- a/lib/toolbox/hex.c +++ b/lib/toolbox/hex.c @@ -1,14 +1,14 @@ #include "hex.h" bool hex_char_to_hex_nibble(char c, uint8_t* nibble) { - if((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f')) { - if((c >= '0' && c <= '9')) { - *nibble = c - '0'; - } else if((c >= 'A' && c <= 'F')) { - *nibble = c - 'A' + 10; - } else { - *nibble = c - 'a' + 10; - } + if((c >= '0' && c <= '9')) { + *nibble = c - '0'; + return true; + } else if((c >= 'A' && c <= 'F')) { + *nibble = c - 'A' + 10; + return true; + } else if(c >= 'a' && c <= 'f') { + *nibble = c - 'a' + 10; return true; } else { return false; diff --git a/lib/toolbox/md5.c b/lib/toolbox/md5.c index 3cf7cf05c..a907d52e3 100644 --- a/lib/toolbox/md5.c +++ b/lib/toolbox/md5.c @@ -115,7 +115,7 @@ void md5_process(md5_context* ctx, const unsigned char data[64]) { GET_UINT32_LE(X[14], data, 56); GET_UINT32_LE(X[15], data, 60); -#define S(x, n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) +#define S(x, n) (((x) << (n)) | (((x)&0xFFFFFFFF) >> (32 - (n)))) #define P(a, b, c, d, k, s, t) \ { \ @@ -128,7 +128,7 @@ void md5_process(md5_context* ctx, const unsigned char data[64]) { C = ctx->state[2]; D = ctx->state[3]; -#define F(x, y, z) (z ^ (x & (y ^ z))) +#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) P(A, B, C, D, 0, 7, 0xD76AA478); P(D, A, B, C, 1, 12, 0xE8C7B756); @@ -149,7 +149,7 @@ void md5_process(md5_context* ctx, const unsigned char data[64]) { #undef F -#define F(x, y, z) (y ^ (z & (x ^ y))) +#define F(x, y, z) ((y) ^ ((z) & ((x) ^ (y)))) P(A, B, C, D, 1, 5, 0xF61E2562); P(D, A, B, C, 6, 9, 0xC040B340); @@ -170,7 +170,7 @@ void md5_process(md5_context* ctx, const unsigned char data[64]) { #undef F -#define F(x, y, z) (x ^ y ^ z) +#define F(x, y, z) ((x) ^ (y) ^ (z)) P(A, B, C, D, 5, 4, 0xFFFA3942); P(D, A, B, C, 8, 11, 0x8771F681); @@ -191,7 +191,7 @@ void md5_process(md5_context* ctx, const unsigned char data[64]) { #undef F -#define F(x, y, z) (y ^ (x | ~z)) +#define F(x, y, z) ((y) ^ ((x) | ~(z))) P(A, B, C, D, 0, 6, 0xF4292244); P(D, A, B, C, 7, 10, 0x432AFF97); @@ -295,5 +295,5 @@ void md5(const unsigned char* input, size_t ilen, unsigned char output[16]) { md5_update(&ctx, input, ilen); md5_finish(&ctx, output); - memset(&ctx, 0, sizeof(md5_context)); + memset(&ctx, 0, sizeof(md5_context)); //-V597 } diff --git a/lib/toolbox/sha256.c b/lib/toolbox/sha256.c index ece77955d..ff4984439 100644 --- a/lib/toolbox/sha256.c +++ b/lib/toolbox/sha256.c @@ -62,15 +62,15 @@ static void memcpy_output_bswap32(unsigned char* dst, const uint32_t* p) { } } -#define rotr32(x, n) (((x) >> n) | ((x) << (32 - n))) +#define rotr32(x, n) (((x) >> n) | ((x) << (32 - (n)))) #define ch(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) #define maj(x, y, z) (((x) & (y)) | ((z) & ((x) ^ (y)))) /* round transforms for SHA256 compression functions */ -#define vf(n, i) v[(n - i) & 7] +#define vf(n, i) v[((n) - (i)) & 7] -#define hf(i) (p[i & 15] += g_1(p[(i + 14) & 15]) + p[(i + 9) & 15] + g_0(p[(i + 1) & 15])) +#define hf(i) (p[(i)&15] += g_1(p[((i) + 14) & 15]) + p[((i) + 9) & 15] + g_0(p[((i) + 1) & 15])) #define v_cycle0(i) \ p[i] = __builtin_bswap32(p[i]); \ @@ -176,8 +176,8 @@ void sha256_finish(sha256_context* ctx, unsigned char output[32]) { uint32_t last = (ctx->total[0] & SHA256_MASK); ctx->wbuf[last >> 2] = __builtin_bswap32(ctx->wbuf[last >> 2]); - ctx->wbuf[last >> 2] &= 0xffffff80 << (8 * (~last & 3)); - ctx->wbuf[last >> 2] |= 0x00000080 << (8 * (~last & 3)); + ctx->wbuf[last >> 2] &= 0xffffff80UL << (8 * (~last & 3)); + ctx->wbuf[last >> 2] |= 0x00000080UL << (8 * (~last & 3)); ctx->wbuf[last >> 2] = __builtin_bswap32(ctx->wbuf[last >> 2]); if(last > SHA256_BLOCK_SIZE - 9) { diff --git a/lib/toolbox/stream/stream.c b/lib/toolbox/stream/stream.c index 86d35c959..055bab5bf 100644 --- a/lib/toolbox/stream/stream.c +++ b/lib/toolbox/stream/stream.c @@ -315,8 +315,8 @@ void stream_dump_data(Stream* stream) { size_t size = stream_size(stream); size_t tell = stream_tell(stream); printf("stream %p\r\n", stream); - printf("size = %u\r\n", size); - printf("tell = %u\r\n", tell); + printf("size = %zu\r\n", size); + printf("tell = %zu\r\n", tell); printf("DATA START\r\n"); uint8_t* data = malloc(STREAM_CACHE_SIZE); stream_rewind(stream); diff --git a/lib/toolbox/tar/tar_archive.c b/lib/toolbox/tar/tar_archive.c index e8b447291..fd0d175ea 100644 --- a/lib/toolbox/tar/tar_archive.c +++ b/lib/toolbox/tar/tar_archive.c @@ -236,7 +236,7 @@ static int archive_extract_foreach_cb(mtar_t* tar, const mtar_header_t* header, return 0; } - FURI_LOG_D(TAG, "Extracting %d bytes to '%s'", header->size, header->name); + FURI_LOG_D(TAG, "Extracting %u bytes to '%s'", header->size, header->name); FuriString* converted_fname = furi_string_alloc_set(header->name); if(op_params->converter) { @@ -382,4 +382,4 @@ bool tar_archive_unpack_file( return false; } return archive_extract_current_file(archive, destination); -} \ No newline at end of file +} diff --git a/lib/toolbox/varint.c b/lib/toolbox/varint.c index ee2f5c3af..79777c4ba 100644 --- a/lib/toolbox/varint.c +++ b/lib/toolbox/varint.c @@ -15,7 +15,7 @@ size_t varint_uint32_unpack(uint32_t* value, const uint8_t* input, size_t input_ uint32_t parsed = 0; for(i = 0; i < input_size; i++) { - parsed |= (input[i] & 0x7F) << (7 * i); + parsed |= (input[i] & 0x7FUL) << (7 * i); if(!(input[i] & 0x80)) { break; @@ -73,4 +73,4 @@ size_t varint_int32_length(int32_t value) { } return varint_uint32_length(v); -} \ No newline at end of file +} diff --git a/lib/update_util/dfu_file.c b/lib/update_util/dfu_file.c index d6f31b602..62b139e86 100644 --- a/lib/update_util/dfu_file.c +++ b/lib/update_util/dfu_file.c @@ -35,7 +35,7 @@ uint8_t dfu_file_validate_headers(File* dfuf, const DfuValidationParams* referen return 0; } - if(memcmp(dfu_prefix.szSignature, DFU_SIGNATURE, sizeof(dfu_prefix.szSignature))) { + if(memcmp(dfu_prefix.szSignature, DFU_SIGNATURE, sizeof(dfu_prefix.szSignature)) != 0) { return 0; } diff --git a/lib/update_util/resources/manifest.c b/lib/update_util/resources/manifest.c index 8b6a1b33c..baa7acebd 100644 --- a/lib/update_util/resources/manifest.c +++ b/lib/update_util/resources/manifest.c @@ -98,7 +98,7 @@ ResourceManifestEntry* resource_manifest_reader_next(ResourceManifestReader* res furi_string_right(resource_manifest->linebuf, offs + 1); furi_string_set(resource_manifest->entry.name, resource_manifest->linebuf); - } else if(resource_manifest->entry.type == ResourceManifestEntryTypeDirectory) { + } else if(resource_manifest->entry.type == ResourceManifestEntryTypeDirectory) { //-V547 /* Parse directory entry D: */ diff --git a/lib/update_util/update_operation.c b/lib/update_util/update_operation.c index 3a44605e0..c6a9ccc5f 100644 --- a/lib/update_util/update_operation.c +++ b/lib/update_util/update_operation.c @@ -11,7 +11,7 @@ #define UPDATE_ROOT_DIR EXT_PATH("update") /* Need at least 4 free LFS pages before update */ -#define UPDATE_MIN_INT_FREE_SPACE 2 * 4 * 1024 +#define UPDATE_MIN_INT_FREE_SPACE (2 * 4 * 1024) static const char* update_prepare_result_descr[] = { [UpdatePrepareResultOK] = "OK", @@ -110,7 +110,7 @@ bool update_operation_get_current_package_manifest_path(Storage* storage, FuriSt } static bool update_operation_persist_manifest_path(Storage* storage, const char* manifest_path) { - const uint16_t manifest_path_len = strlen(manifest_path); + const size_t manifest_path_len = strlen(manifest_path); furi_check(manifest_path && manifest_path_len); bool success = false; File* file = storage_file_alloc(storage); diff --git a/scripts/fbt_tools/fbt_debugopts.py b/scripts/fbt_tools/fbt_debugopts.py index 9ff05cb73..f4b021c20 100644 --- a/scripts/fbt_tools/fbt_debugopts.py +++ b/scripts/fbt_tools/fbt_debugopts.py @@ -41,12 +41,10 @@ def generate(env, **kw): "|openocd -c 'gdb_port pipe; log_output ${FBT_DEBUG_DIR}/openocd.log' ${[SINGLEQUOTEFUNC(OPENOCD_OPTS)]}" ], GDBOPTS_BASE=[ - "-ex", - "set pagination off", "-ex", "target extended-remote ${GDBREMOTE}", "-ex", - "set confirm off", + "source ${FBT_DEBUG_DIR}/gdbinit", ], GDBOPTS_BLACKMAGIC=[ "-ex", From a34fbf6976dabd905ad0d88a814dec0c32df7634 Mon Sep 17 00:00:00 2001 From: Max Andreev Date: Mon, 26 Dec 2022 22:33:44 +0300 Subject: [PATCH 13/34] [FL-3056] Prevent merging of PRs if there are warnings from PVS-studio (#2176) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: あく --- .github/workflows/pvs_studio.yml | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/.github/workflows/pvs_studio.yml b/.github/workflows/pvs_studio.yml index c521fbca4..46ee8801d 100644 --- a/.github/workflows/pvs_studio.yml +++ b/.github/workflows/pvs_studio.yml @@ -63,11 +63,20 @@ jobs: -f build/f7-firmware-DC/compile_commands.json \ -o PVS-Studio.log - - name: 'Convert PVS-Studio output to html page' - run: plog-converter -a GA:1,2,3 -t fullhtml PVS-Studio.log -o reports/${DEFAULT_TARGET}-${SUFFIX} + - name: 'Convert PVS-Studio output to html and detect warnings' + id: pvs-warn + run: | + WARNINGS=0 + plog-converter \ + -a GA:1,2,3 \ + -t fullhtml \ + --indicate-warnings \ + PVS-Studio.log \ + -o reports/${DEFAULT_TARGET}-${SUFFIX} || WARNINGS=1 + echo "warnings=${WARNINGS}" >> $GITHUB_OUTPUT - name: 'Upload artifacts to update server' - if: ${{ !github.event.pull_request.head.repo.fork }} + if: ${{ !github.event.pull_request.head.repo.fork && (steps.pvs-warn.outputs.warnings != 0) }} run: | mkdir -p ~/.ssh ssh-keyscan -p ${{ secrets.RSYNC_DEPLOY_PORT }} -H ${{ secrets.RSYNC_DEPLOY_HOST }} > ~/.ssh/known_hosts @@ -79,8 +88,8 @@ jobs: rm ./deploy_key; - name: 'Find Previous Comment' - if: ${{ !github.event.pull_request.head.repo.fork && github.event.pull_request }} - uses: peter-evans/find-comment@v1 + if: ${{ !github.event.pull_request.head.repo.fork && github.event.pull_request && (steps.pvs-warn.outputs.warnings != 0) }} + uses: peter-evans/find-comment@v2 id: fc with: issue-number: ${{ github.event.pull_request.number }} @@ -88,7 +97,7 @@ jobs: body-includes: 'PVS-Studio report for commit' - name: 'Create or update comment' - if: ${{ !github.event.pull_request.head.repo.fork && github.event.pull_request}} + if: ${{ !github.event.pull_request.head.repo.fork && github.event.pull_request && (steps.pvs-warn.outputs.warnings != 0) }} uses: peter-evans/create-or-update-comment@v1 with: comment-id: ${{ steps.fc.outputs.comment-id }} @@ -97,3 +106,10 @@ jobs: **PVS-Studio report for commit `${{steps.names.outputs.commit_sha}}`:** - [Report](https://update.flipperzero.one/builds/firmware-pvs-studio-report/${{steps.names.outputs.branch_name}}/${{steps.names.outputs.default_target}}-${{steps.names.outputs.suffix}}/index.html) edit-mode: replace + + - name: 'Raise exception' + if: ${{ steps.pvs-warn.outputs.warnings != 0 }} + run: | + echo "Please fix all PVS varnings before merge" + exit 1 + From 9192520c7096a9ff673c8bfbdd75abb71e4c7e7c Mon Sep 17 00:00:00 2001 From: Sergey Gavrilov Date: Tue, 27 Dec 2022 05:46:05 +1000 Subject: [PATCH 14/34] Modules: locking view model (#2189) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Popup, dialog_ex: locking model * Desktop: do not use the model where it is not needed Co-authored-by: あく --- applications/services/desktop/views/desktop_view_main.c | 1 - .../services/desktop/views/desktop_view_pin_setup_done.c | 3 +-- applications/services/gui/modules/dialog_ex.c | 2 +- applications/services/gui/modules/popup.c | 2 +- .../views/desktop_settings_view_pin_setup_howto.c | 3 +-- .../views/desktop_settings_view_pin_setup_howto2.c | 3 +-- 6 files changed, 5 insertions(+), 9 deletions(-) diff --git a/applications/services/desktop/views/desktop_view_main.c b/applications/services/desktop/views/desktop_view_main.c index cbf4a20ff..7d956489a 100644 --- a/applications/services/desktop/views/desktop_view_main.c +++ b/applications/services/desktop/views/desktop_view_main.c @@ -102,7 +102,6 @@ DesktopMainView* desktop_main_alloc() { DesktopMainView* main_view = malloc(sizeof(DesktopMainView)); main_view->view = view_alloc(); - view_allocate_model(main_view->view, ViewModelTypeLockFree, 1); view_set_context(main_view->view, main_view); view_set_input_callback(main_view->view, desktop_main_input_callback); diff --git a/applications/services/desktop/views/desktop_view_pin_setup_done.c b/applications/services/desktop/views/desktop_view_pin_setup_done.c index 1d82aeaac..561b12861 100644 --- a/applications/services/desktop/views/desktop_view_pin_setup_done.c +++ b/applications/services/desktop/views/desktop_view_pin_setup_done.c @@ -18,7 +18,7 @@ struct DesktopViewPinSetupDone { static void desktop_view_pin_done_draw(Canvas* canvas, void* model) { furi_assert(canvas); - furi_assert(model); + UNUSED(model); canvas_set_font(canvas, FontPrimary); elements_multiline_text_aligned( @@ -59,7 +59,6 @@ void desktop_view_pin_done_set_callback( DesktopViewPinSetupDone* desktop_view_pin_done_alloc() { DesktopViewPinSetupDone* view = malloc(sizeof(DesktopViewPinSetupDone)); view->view = view_alloc(); - view_allocate_model(view->view, ViewModelTypeLockFree, 1); view_set_context(view->view, view); view_set_draw_callback(view->view, desktop_view_pin_done_draw); view_set_input_callback(view->view, desktop_view_pin_done_input); diff --git a/applications/services/gui/modules/dialog_ex.c b/applications/services/gui/modules/dialog_ex.c index 1cb467232..7c3ef9b45 100644 --- a/applications/services/gui/modules/dialog_ex.c +++ b/applications/services/gui/modules/dialog_ex.c @@ -147,7 +147,7 @@ DialogEx* dialog_ex_alloc() { DialogEx* dialog_ex = malloc(sizeof(DialogEx)); dialog_ex->view = view_alloc(); view_set_context(dialog_ex->view, dialog_ex); - view_allocate_model(dialog_ex->view, ViewModelTypeLockFree, sizeof(DialogExModel)); + view_allocate_model(dialog_ex->view, ViewModelTypeLocking, sizeof(DialogExModel)); view_set_draw_callback(dialog_ex->view, dialog_ex_view_draw_callback); view_set_input_callback(dialog_ex->view, dialog_ex_view_input_callback); with_view_model( diff --git a/applications/services/gui/modules/popup.c b/applications/services/gui/modules/popup.c index 08e8d8c2b..d75abb95f 100644 --- a/applications/services/gui/modules/popup.c +++ b/applications/services/gui/modules/popup.c @@ -117,7 +117,7 @@ Popup* popup_alloc() { popup->timer_enabled = false; view_set_context(popup->view, popup); - view_allocate_model(popup->view, ViewModelTypeLockFree, sizeof(PopupModel)); + view_allocate_model(popup->view, ViewModelTypeLocking, sizeof(PopupModel)); view_set_draw_callback(popup->view, popup_view_draw_callback); view_set_input_callback(popup->view, popup_view_input_callback); view_set_enter_callback(popup->view, popup_start_timer); diff --git a/applications/settings/desktop_settings/views/desktop_settings_view_pin_setup_howto.c b/applications/settings/desktop_settings/views/desktop_settings_view_pin_setup_howto.c index 3831be8c4..26aa7c3e1 100644 --- a/applications/settings/desktop_settings/views/desktop_settings_view_pin_setup_howto.c +++ b/applications/settings/desktop_settings/views/desktop_settings_view_pin_setup_howto.c @@ -17,7 +17,7 @@ struct DesktopSettingsViewPinSetupHowto { static void desktop_settings_view_pin_setup_howto_draw(Canvas* canvas, void* model) { furi_assert(canvas); - furi_assert(model); + UNUSED(model); canvas_draw_icon(canvas, 16, 18, &I_Pin_attention_dpad_29x29); elements_button_right(canvas, "Next"); @@ -57,7 +57,6 @@ void desktop_settings_view_pin_setup_howto_set_callback( DesktopSettingsViewPinSetupHowto* desktop_settings_view_pin_setup_howto_alloc() { DesktopSettingsViewPinSetupHowto* view = malloc(sizeof(DesktopSettingsViewPinSetupHowto)); view->view = view_alloc(); - view_allocate_model(view->view, ViewModelTypeLockFree, 1); view_set_context(view->view, view); view_set_draw_callback(view->view, desktop_settings_view_pin_setup_howto_draw); view_set_input_callback(view->view, desktop_settings_view_pin_setup_howto_input); diff --git a/applications/settings/desktop_settings/views/desktop_settings_view_pin_setup_howto2.c b/applications/settings/desktop_settings/views/desktop_settings_view_pin_setup_howto2.c index ab1fa2383..c28826e62 100644 --- a/applications/settings/desktop_settings/views/desktop_settings_view_pin_setup_howto2.c +++ b/applications/settings/desktop_settings/views/desktop_settings_view_pin_setup_howto2.c @@ -18,7 +18,7 @@ struct DesktopSettingsViewPinSetupHowto2 { static void desktop_settings_view_pin_setup_howto2_draw(Canvas* canvas, void* model) { furi_assert(canvas); - furi_assert(model); + UNUSED(model); canvas_set_font(canvas, FontSecondary); elements_multiline_text_aligned( @@ -79,7 +79,6 @@ void desktop_settings_view_pin_setup_howto2_set_ok_callback( DesktopSettingsViewPinSetupHowto2* desktop_settings_view_pin_setup_howto2_alloc() { DesktopSettingsViewPinSetupHowto2* view = malloc(sizeof(DesktopSettingsViewPinSetupHowto2)); view->view = view_alloc(); - view_allocate_model(view->view, ViewModelTypeLockFree, 1); view_set_context(view->view, view); view_set_draw_callback(view->view, desktop_settings_view_pin_setup_howto2_draw); view_set_input_callback(view->view, desktop_settings_view_pin_setup_howto2_input); From 5992e2d4f282dd40f3c1fd3a2fbd86d2b2b4bd89 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Mon, 26 Dec 2022 23:10:42 +0300 Subject: [PATCH 15/34] Update readme --- ReadMe.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/ReadMe.md b/ReadMe.md index 3b2c3d914..41aca4ed2 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -73,6 +73,17 @@ Also check changelog in releases for latest updates! - Star Line ## Please support development of the project +The majority of this project is developed and maintained by me, @xMasterX. +I'm unemployed because of the war, and the only income I receive is from your donations. +Our team is small and the guys are working on this project as much as they can solely based on the enthusiasm they have for this project and the community. +- @Svaarich - UI design and animations +- @Amec0e - Infrared assets +- Community moderators in Telegram, Discord, and Reddit +- And of course our GitHub community. Your PRs are a very important part of this firmware and open-source development. + +The amount of work done on this project is huge and we need your support, no matter how large or small. Even if you just say, "Thank you Unleashed firmware developers!" somewhere. Doing so will help us continue our work and will help drive us to make the firmware better every time. +Also, regarding our releases, every build has and always will be free and open-source. There will be no paywall releases or closed-source apps within the firmware. As long as I am working on this project it will never happen. +You can support us by using links or addresses below: * Boosty: https://boosty.to/mmxdev * Ko-Fi: https://ko-fi.com/masterx * destream (100 EUR min): https://destream.net/live/MMX/donate From a7fc43d1acb43f7c2a8dd850257ca85cbc3610f9 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Mon, 26 Dec 2022 23:12:45 +0300 Subject: [PATCH 16/34] Update wifi marauder --- .../wifi_marauder_scene_console_output.c | 2 +- .../scenes/wifi_marauder_scene_start.c | 44 ++++++++-- .../scenes/wifi_marauder_scene_text_input.c | 88 ++++++++++++++++++- .../wifi_marauder_app.c | 2 + .../wifi_marauder_app_i.h | 7 +- .../wifi_marauder_custom_event.h | 2 + 6 files changed, 131 insertions(+), 14 deletions(-) diff --git a/applications/plugins/wifi_marauder_companion/scenes/wifi_marauder_scene_console_output.c b/applications/plugins/wifi_marauder_companion/scenes/wifi_marauder_scene_console_output.c index 25ea0abb0..8b9984dbf 100644 --- a/applications/plugins/wifi_marauder_companion/scenes/wifi_marauder_scene_console_output.c +++ b/applications/plugins/wifi_marauder_companion/scenes/wifi_marauder_scene_console_output.c @@ -34,7 +34,7 @@ void wifi_marauder_scene_console_output_on_enter(void* context) { app->text_box_store_strlen = 0; if(0 == strncmp("help", app->selected_tx_string, strlen("help"))) { const char* help_msg = - "Marauder companion v0.2.2\nFor app support/feedback,\nreach out to me:\n@cococode#6011 (discord)\n0xchocolate (github)\n"; + "Marauder companion v0.3.0\nFor app support/feedback,\nreach out to me:\n@cococode#6011 (discord)\n0xchocolate (github)\n"; furi_string_cat_str(app->text_box_store, help_msg); app->text_box_store_strlen += strlen(help_msg); } diff --git a/applications/plugins/wifi_marauder_companion/scenes/wifi_marauder_scene_start.c b/applications/plugins/wifi_marauder_companion/scenes/wifi_marauder_scene_start.c index 029614c5d..df759bd15 100644 --- a/applications/plugins/wifi_marauder_companion/scenes/wifi_marauder_scene_start.c +++ b/applications/plugins/wifi_marauder_companion/scenes/wifi_marauder_scene_start.c @@ -26,7 +26,13 @@ typedef struct { // NUM_MENU_ITEMS defined in wifi_marauder_app_i.h - if you add an entry here, increment it! const WifiMarauderItem items[NUM_MENU_ITEMS] = { {"View Log from", {"start", "end"}, 2, {"", ""}, NO_ARGS, FOCUS_CONSOLE_TOGGLE, NO_TIP}, - {"Scan AP", {""}, 1, {"scanap"}, NO_ARGS, FOCUS_CONSOLE_END, SHOW_STOPSCAN_TIP}, + {"Scan", + {"ap", "station"}, + 2, + {"scanap", "scansta"}, + NO_ARGS, + FOCUS_CONSOLE_END, + SHOW_STOPSCAN_TIP}, {"SSID", {"add rand", "add name", "remove"}, 3, @@ -34,12 +40,24 @@ const WifiMarauderItem items[NUM_MENU_ITEMS] = { INPUT_ARGS, FOCUS_CONSOLE_START, NO_TIP}, - {"List", {"ap", "ssid"}, 2, {"list -a", "list -s"}, NO_ARGS, FOCUS_CONSOLE_START, NO_TIP}, - {"Select", {"ap", "ssid"}, 2, {"select -a", "select -s"}, INPUT_ARGS, FOCUS_CONSOLE_END, NO_TIP}, + {"List", + {"ap", "ssid", "station"}, + 3, + {"list -a", "list -s", "list -c"}, + NO_ARGS, + FOCUS_CONSOLE_START, + NO_TIP}, + {"Select", + {"ap", "ssid", "station"}, + 3, + {"select -a", "select -s", "select -c"}, + INPUT_ARGS, + FOCUS_CONSOLE_END, + NO_TIP}, {"Clear List", - {"ap", "ssid"}, - 2, - {"clearlist -a", "clearlist -s"}, + {"ap", "ssid", "station"}, + 3, + {"clearlist -a", "clearlist -s", "clearlist -c"}, NO_ARGS, FOCUS_CONSOLE_END, NO_TIP}, @@ -50,6 +68,13 @@ const WifiMarauderItem items[NUM_MENU_ITEMS] = { NO_ARGS, FOCUS_CONSOLE_END, SHOW_STOPSCAN_TIP}, + {"Targeted Deauth", + {"station", "manual"}, + 2, + {"attack -t deauth -c", "attack -t deauth -s"}, + TOGGLE_ARGS, + FOCUS_CONSOLE_END, + SHOW_STOPSCAN_TIP}, {"Beacon Spam", {"ap list", "ssid list", "random"}, 3, @@ -87,18 +112,19 @@ const WifiMarauderItem items[NUM_MENU_ITEMS] = { FOCUS_CONSOLE_END, NO_TIP}, {"Settings", - {"display", "restore", "ForcePMKID", "ForceProbe", "SavePCAP", "other"}, - 6, + {"display", "restore", "ForcePMKID", "ForceProbe", "SavePCAP", "EnableLED", "other"}, + 7, {"settings", "settings -r", "settings -s ForcePMKID enable", "settings -s ForceProbe enable", "settings -s SavePCAP enable", + "settings -s EnableLED enable", "settings -s"}, TOGGLE_ARGS, FOCUS_CONSOLE_START, NO_TIP}, - {"Update", {""}, 1, {"update -w"}, NO_ARGS, FOCUS_CONSOLE_END, NO_TIP}, + {"Update", {"ota", "sd"}, 2, {"update -w", "update -s"}, NO_ARGS, FOCUS_CONSOLE_END, NO_TIP}, {"Reboot", {""}, 1, {"reboot"}, NO_ARGS, FOCUS_CONSOLE_END, NO_TIP}, {"Help", {""}, 1, {"help"}, NO_ARGS, FOCUS_CONSOLE_START, SHOW_STOPSCAN_TIP}, }; diff --git a/applications/plugins/wifi_marauder_companion/scenes/wifi_marauder_scene_text_input.c b/applications/plugins/wifi_marauder_companion/scenes/wifi_marauder_scene_text_input.c index 061e9c5fe..ac8b15a2d 100644 --- a/applications/plugins/wifi_marauder_companion/scenes/wifi_marauder_scene_text_input.c +++ b/applications/plugins/wifi_marauder_companion/scenes/wifi_marauder_scene_text_input.c @@ -3,13 +3,34 @@ void wifi_marauder_scene_text_input_callback(void* context) { WifiMarauderApp* app = context; - view_dispatcher_send_custom_event(app->view_dispatcher, WifiMarauderEventStartConsole); + switch(app->special_case_input_step) { + case 0: // most commands + view_dispatcher_send_custom_event(app->view_dispatcher, WifiMarauderEventStartConsole); + break; + case 1: // special case for deauth: save source MAC + view_dispatcher_send_custom_event(app->view_dispatcher, WifiMarauderEventSaveSourceMac); + break; + case 2: // special case for deauth: save destination MAC + view_dispatcher_send_custom_event( + app->view_dispatcher, WifiMarauderEventSaveDestinationMac); + break; + default: + break; + } } void wifi_marauder_scene_text_input_on_enter(void* context) { WifiMarauderApp* app = context; - if(false == app->is_custom_tx_string) { + if(0 == + strncmp("attack -t deauth -s", app->selected_tx_string, strlen("attack -t deauth -s"))) { + // Special case for manual deauth input + app->special_case_input_step = 1; + bzero(app->text_input_store, WIFI_MARAUDER_TEXT_INPUT_STORE_SIZE); + } else if(false == app->is_custom_tx_string) { + // Most commands + app->special_case_input_step = 0; + // Fill text input with selected string so that user can add to it size_t length = strlen(app->selected_tx_string); furi_assert(length < WIFI_MARAUDER_TEXT_INPUT_STORE_SIZE); @@ -25,7 +46,9 @@ void wifi_marauder_scene_text_input_on_enter(void* context) { // Setup view TextInput* text_input = app->text_input; // Add help message to header - if(0 == strncmp("ssid -a -g", app->selected_tx_string, strlen("ssid -a -g"))) { + if(app->special_case_input_step == 1) { + text_input_set_header_text(text_input, "Enter source MAC"); + } else if(0 == strncmp("ssid -a -g", app->selected_tx_string, strlen("ssid -a -g"))) { text_input_set_header_text(text_input, "Enter # SSIDs to generate"); } else if(0 == strncmp("ssid -a -n", app->selected_tx_string, strlen("ssid -a -n"))) { text_input_set_header_text(text_input, "Enter SSID name to add"); @@ -59,6 +82,65 @@ bool wifi_marauder_scene_text_input_on_event(void* context, SceneManagerEvent ev app->selected_tx_string = app->text_input_store; scene_manager_next_scene(app->scene_manager, WifiMarauderAppViewConsoleOutput); consumed = true; + } else if(event.event == WifiMarauderEventSaveSourceMac) { + if(12 != strlen(app->text_input_store)) { + text_input_set_header_text(app->text_input, "MAC must be 12 hex chars!"); + } else { + snprintf( + app->special_case_input_src_addr, + sizeof(app->special_case_input_src_addr), + "%c%c:%c%c:%c%c:%c%c:%c%c:%c%c", + app->text_input_store[0], + app->text_input_store[1], + app->text_input_store[2], + app->text_input_store[3], + app->text_input_store[4], + app->text_input_store[5], + app->text_input_store[6], + app->text_input_store[7], + app->text_input_store[8], + app->text_input_store[9], + app->text_input_store[10], + app->text_input_store[11]); + + // Advance scene to input destination MAC, clear text input + app->special_case_input_step = 2; + bzero(app->text_input_store, WIFI_MARAUDER_TEXT_INPUT_STORE_SIZE); + text_input_set_header_text(app->text_input, "Enter destination MAC"); + } + consumed = true; + } else if(event.event == WifiMarauderEventSaveDestinationMac) { + if(12 != strlen(app->text_input_store)) { + text_input_set_header_text(app->text_input, "MAC must be 12 hex chars!"); + } else { + snprintf( + app->special_case_input_dst_addr, + sizeof(app->special_case_input_dst_addr), + "%c%c:%c%c:%c%c:%c%c:%c%c:%c%c", + app->text_input_store[0], + app->text_input_store[1], + app->text_input_store[2], + app->text_input_store[3], + app->text_input_store[4], + app->text_input_store[5], + app->text_input_store[6], + app->text_input_store[7], + app->text_input_store[8], + app->text_input_store[9], + app->text_input_store[10], + app->text_input_store[11]); + + // Construct command with source and destination MACs + snprintf( + app->text_input_store, + WIFI_MARAUDER_TEXT_INPUT_STORE_SIZE, + "attack -t deauth -s %18s -d %18s", + app->special_case_input_src_addr, + app->special_case_input_dst_addr); + app->selected_tx_string = app->text_input_store; + scene_manager_next_scene(app->scene_manager, WifiMarauderAppViewConsoleOutput); + } + consumed = true; } } diff --git a/applications/plugins/wifi_marauder_companion/wifi_marauder_app.c b/applications/plugins/wifi_marauder_companion/wifi_marauder_app.c index 705473759..1deb4e6f2 100644 --- a/applications/plugins/wifi_marauder_companion/wifi_marauder_app.c +++ b/applications/plugins/wifi_marauder_companion/wifi_marauder_app.c @@ -50,6 +50,8 @@ WifiMarauderApp* wifi_marauder_app_alloc() { app->selected_option_index[i] = 0; } + app->special_case_input_step = 0; + app->text_box = text_box_alloc(); view_dispatcher_add_view( app->view_dispatcher, WifiMarauderAppViewConsoleOutput, text_box_get_view(app->text_box)); diff --git a/applications/plugins/wifi_marauder_companion/wifi_marauder_app_i.h b/applications/plugins/wifi_marauder_companion/wifi_marauder_app_i.h index f571a11a2..4df9e326b 100644 --- a/applications/plugins/wifi_marauder_companion/wifi_marauder_app_i.h +++ b/applications/plugins/wifi_marauder_companion/wifi_marauder_app_i.h @@ -14,7 +14,7 @@ #include #include -#define NUM_MENU_ITEMS (15) +#define NUM_MENU_ITEMS (16) #define WIFI_MARAUDER_TEXT_BOX_STORE_SIZE (4096) #define WIFI_MARAUDER_TEXT_INPUT_STORE_SIZE (512) @@ -41,6 +41,11 @@ struct WifiMarauderApp { bool is_custom_tx_string; bool focus_console_start; bool show_stopscan_tip; + + // For input source and destination MAC in targeted deauth attack + int special_case_input_step; + char special_case_input_src_addr[20]; + char special_case_input_dst_addr[20]; }; // Supported commands: diff --git a/applications/plugins/wifi_marauder_companion/wifi_marauder_custom_event.h b/applications/plugins/wifi_marauder_companion/wifi_marauder_custom_event.h index fe1bff6af..990b457f5 100644 --- a/applications/plugins/wifi_marauder_companion/wifi_marauder_custom_event.h +++ b/applications/plugins/wifi_marauder_companion/wifi_marauder_custom_event.h @@ -4,4 +4,6 @@ typedef enum { WifiMarauderEventRefreshConsoleOutput = 0, WifiMarauderEventStartConsole, WifiMarauderEventStartKeyboard, + WifiMarauderEventSaveSourceMac, + WifiMarauderEventSaveDestinationMac } WifiMarauderCustomEvent; From ac400abede45913c0f3f3f38d41e44c4da141c07 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Mon, 26 Dec 2022 23:15:10 +0300 Subject: [PATCH 17/34] Update UniTemp --- applications/plugins/unitemp/README.md | 2 +- applications/plugins/unitemp/Sensors.c | 2 + applications/plugins/unitemp/Sensors.h | 1 + applications/plugins/unitemp/sensors/SHT30.c | 90 ++++++++++++++++++ applications/plugins/unitemp/sensors/SHT30.h | 70 ++++++++++++++ .../plugins/unitemp/sensors/Sensors.xlsx | Bin 12014 -> 12265 bytes .../plugins/unitemp/views/Widgets_view.c | 2 +- 7 files changed, 165 insertions(+), 2 deletions(-) create mode 100644 applications/plugins/unitemp/sensors/SHT30.c create mode 100644 applications/plugins/unitemp/sensors/SHT30.h diff --git a/applications/plugins/unitemp/README.md b/applications/plugins/unitemp/README.md index c40ed520a..257e8a8ae 100644 --- a/applications/plugins/unitemp/README.md +++ b/applications/plugins/unitemp/README.md @@ -4,6 +4,6 @@ [![GitHub](https://img.shields.io/github/license/quen0n/unitemp-flipperzero)](https://github.com/quen0n/unitemp-flipperzero/blob/dev/LICENSE.md) [Flipper Zero](https://flipperzero.one/) application for reading temperature, humidity and pressure sensors using Onewire, Singlewire, I2C protocols. ## List of supported sensors (supplemented) -![image](https://user-images.githubusercontent.com/10090793/208763931-d15e9883-1016-4add-bd00-14d7842fd82d.png) +![image](https://user-images.githubusercontent.com/10090793/209491886-f4c5ef6e-38b2-45b8-a8e7-4aeca9e155f2.png) ## Installation Copy the contents of the repository to the `applications/plugins/unitemp` folder and build the project. Flash FZ along with resources. [More...](https://github.com/flipperdevices/flipperzero-firmware/blob/dev/documentation/fbt.md) diff --git a/applications/plugins/unitemp/Sensors.c b/applications/plugins/unitemp/Sensors.c index f81daa827..f202794f4 100644 --- a/applications/plugins/unitemp/Sensors.c +++ b/applications/plugins/unitemp/Sensors.c @@ -81,6 +81,8 @@ static const SensorType* sensorTypes[] = { &AM2320_SW, &AM2320_I2C, &AHT10, + &SHT30, + &GXHT30, &LM75, &BMP280, &BME280}; diff --git a/applications/plugins/unitemp/Sensors.h b/applications/plugins/unitemp/Sensors.h index cb98e1783..0643ffb1f 100644 --- a/applications/plugins/unitemp/Sensors.h +++ b/applications/plugins/unitemp/Sensors.h @@ -322,4 +322,5 @@ const GPIO* #include "./sensors/BMx280.h" #include "./sensors/AM2320.h" #include "./sensors/DHT20.h" +#include "./sensors/SHT30.h" #endif diff --git a/applications/plugins/unitemp/sensors/SHT30.c b/applications/plugins/unitemp/sensors/SHT30.c new file mode 100644 index 000000000..700a54dec --- /dev/null +++ b/applications/plugins/unitemp/sensors/SHT30.c @@ -0,0 +1,90 @@ +/* + Unitemp - Universal temperature reader + Copyright (C) 2022 Victor Nikitchuk (https://github.com/quen0n) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +#include "SHT30.h" +#include "../interfaces/I2CSensor.h" + +const SensorType SHT30 = { + .typename = "SHT30", + .altname = "SHT30/31/35", + .interface = &I2C, + .datatype = UT_TEMPERATURE | UT_HUMIDITY, + .pollingInterval = 1000, + .allocator = unitemp_SHT30_I2C_alloc, + .mem_releaser = unitemp_SHT30_I2C_free, + .initializer = unitemp_SHT30_init, + .deinitializer = unitemp_SHT30_I2C_deinit, + .updater = unitemp_SHT30_I2C_update}; +const SensorType GXHT30 = { + .typename = "GXHT30", + .altname = "GXHT30/31/35", + .interface = &I2C, + .datatype = UT_TEMPERATURE | UT_HUMIDITY, + .pollingInterval = 1000, + .allocator = unitemp_SHT30_I2C_alloc, + .mem_releaser = unitemp_SHT30_I2C_free, + .initializer = unitemp_GXHT30_init, + .deinitializer = unitemp_SHT30_I2C_deinit, + .updater = unitemp_SHT30_I2C_update}; + +bool unitemp_SHT30_I2C_alloc(Sensor* sensor, char* args) { + UNUSED(args); + I2CSensor* i2c_sensor = (I2CSensor*)sensor->instance; + + //Адреса на шине I2C (7 бит) + i2c_sensor->minI2CAdr = 0x44 << 1; + i2c_sensor->maxI2CAdr = 0x45 << 1; + return true; +} + +bool unitemp_SHT30_I2C_free(Sensor* sensor) { + //Нечего высвобождать, так как ничего не было выделено + UNUSED(sensor); + return true; +} + +bool unitemp_SHT30_init(Sensor* sensor) { + UNUSED(sensor); + return true; +} + +bool unitemp_GXHT30_init(Sensor* sensor) { + I2CSensor* i2c_sensor = (I2CSensor*)sensor->instance; + //Включение режима автоматического преобразования 2 раза в сек + uint8_t data[2] = {0x22, 0x36}; + if(!unitemp_i2c_writeArray(i2c_sensor, 2, data)) return false; + return true; +} + +bool unitemp_SHT30_I2C_deinit(Sensor* sensor) { + //Нечего деинициализировать + UNUSED(sensor); + return true; +} + +UnitempStatus unitemp_SHT30_I2C_update(Sensor* sensor) { + I2CSensor* i2c_sensor = (I2CSensor*)sensor->instance; + //Получение данных + uint8_t data[6] = {0xE0, 0x00}; + if(!unitemp_i2c_writeArray(i2c_sensor, 2, data)) return UT_SENSORSTATUS_TIMEOUT; + if(!unitemp_i2c_readArray(i2c_sensor, 6, data)) return UT_SENSORSTATUS_TIMEOUT; + + sensor->temp = -45 + 175 * (((uint16_t)(data[0] << 8) | data[1]) / 65535.0f); + sensor->hum = 100 * (((uint16_t)(data[3] << 8) | data[4]) / 65535.0f); + + return UT_SENSORSTATUS_OK; +} diff --git a/applications/plugins/unitemp/sensors/SHT30.h b/applications/plugins/unitemp/sensors/SHT30.h new file mode 100644 index 000000000..93e9d05f2 --- /dev/null +++ b/applications/plugins/unitemp/sensors/SHT30.h @@ -0,0 +1,70 @@ +/* + Unitemp - Universal temperature reader + Copyright (C) 2022 Victor Nikitchuk (https://github.com/quen0n) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +#ifndef UNITEMP_SHT30 +#define UNITEMP_SHT30 + +#include "../unitemp.h" +#include "../Sensors.h" +extern const SensorType SHT30; +extern const SensorType GXHT30; +/** + * @brief Выделение памяти и установка начальных значений датчика SHT30 + * + * @param sensor Указатель на создаваемый датчик + * @return Истина при успехе + */ +bool unitemp_SHT30_I2C_alloc(Sensor* sensor, char* args); + +/** + * @brief Инициализации датчика SHT30 + * + * @param sensor Указатель на датчик + * @return Истина если инициализация упспешная + */ +bool unitemp_SHT30_init(Sensor* sensor); +/** + * @brief Инициализации датчика GXHT30 + * + * @param sensor Указатель на датчик + * @return Истина если инициализация упспешная + */ +bool unitemp_GXHT30_init(Sensor* sensor); + +/** + * @brief Деинициализация датчика + * + * @param sensor Указатель на датчик + */ +bool unitemp_SHT30_I2C_deinit(Sensor* sensor); + +/** + * @brief Обновление значений из датчика + * + * @param sensor Указатель на датчик + * @return Статус обновления + */ +UnitempStatus unitemp_SHT30_I2C_update(Sensor* sensor); + +/** + * @brief Высвободить память датчика + * + * @param sensor Указатель на датчик + */ +bool unitemp_SHT30_I2C_free(Sensor* sensor); + +#endif \ No newline at end of file diff --git a/applications/plugins/unitemp/sensors/Sensors.xlsx b/applications/plugins/unitemp/sensors/Sensors.xlsx index 03522a6434f0cd0c63c2866a4601f8ebb604befc..b139b1b00722c1c505ebb46541ba194caeddd262 100644 GIT binary patch delta 5128 zcmYjV1yCEx)=q;{0wH*y1PdA*iUoIVixmn4io3fs5F82=0>xWsX^XoTxVYQJid&&r zDK4eRiHY-xlS=udXXYDKlacGnJ^ZU!BC{0Pw=yQC4fW+f;jk;KuAxm{A;)%Z|tr0gL zwA6x&y51SDM9e;C_fM_V8t`*+tW=g$h^bBQR zyQooV^9;BDB(Ph$tSIoOy!J<~loPz~z?E-k@HswSuSz>rCrm=1@vB(a&Z+^37dO2{ zmjmEJRzS9{nwT(NLg`HE<<5}e_V8HF2Xs-Ybg5#v#>f+luQ*Efk@<~bMH+6(g-Wf( z*of$u4$lj0wtO?b>jGKh-)Y6#AA5C2G>X+E9zh6BYIh&n?6GYNK-?&I51}5NL zVT@jOD`O5e;f9(YDb8kd*iVumo$v4F$$RIJte&6zr4Ed=1!|2Q4D>~u5d93*dXtvh zDFG&a4+q&U<)gCB%ZnWrAV&n`!F)t$ECZ8y3_Z+u0{upe&wJEaZ5}-9eis5{mP!7} z7F-nZ;9_eIFZD?58la4~le+LuHoBPkAd!ki-tWmrd!eI6&e{))BM8|+U7kdRzPOWE z*ym>%+POO%genp09UfoanzY()SM7w0lWH9t+1knLO#FSE*^8~YF%GlXcTBPEndH&A;_vN$xImG z_?D!wfnP2<_Fb{~saL|Zg=aM#S8czqe($BbpnO16vq7?}GW?X(Z5n5j*V<>?ZWBp+z8*ln1M z4nIW5GBz3h3@R5r6ZWH4s&Rgc->h^coN^6|c343S{Q6U1%vbgF8<2+Qve+z{y9Xj7 zii;a;o}wKt?t{$R-r{Ts7V$*%e|Ez&{)IA&&0f+~vFxAP<9jF4Ay*v!_}io9 z3JU2T3rjb)qR!5mXT>)uC0bh{e@_3B_#vh$i5f0Ha6PfgVk22~O ztQ&c0aJD4nOIR9F3uNmQPu$8z|CFVZeWd(-KXbyg9^NS*ft=AbKJqpD@Lrbs7924D zrk*9i**F%Jq4ETKanMUp^tjn}*k8`xC)UxbUYXYMg|NIgQ$uMa2Tu{MpnJ(o{xY`; zcRE{^KqC4Bk}{&9kd<yK*CO}4=afq7^Y`sp9WuW4Kfx!xA1tm>=tK4%Ab&N{TYqA3#<6vhhn zZrwUpMf9D=_8*|09$BTh``Y%<7#%YqWV?R)7NITsN+3769OR6kADKyZU6Jp9)Xcsg z#m|J<)LdJ=+nltP{1eUoJ+6yrp&Z#`2+vwy_hQI*7xKlw>Y0=O3mO!K_^T%BSyvvR z%Db~I-N6L2OAt_$MeNOSl& zPO0M3BDHU5S}=Avop1thlV&z0?{~5PoY*+Xf3(Q-mMCuE3!MjPG*qX#DL5zu9kL?* zm#nNy+uhk%*M-YkT=dY&m|Oaexw)w^@_KJ~E1lo`ZlM*0Lai(}^n8ce=pkKDwwGg> z%hY@8FRyxRs&D-r#Y$jLvZpoKB-yi4w{iZ4!nD&^q*NI7Ebp*JJ&gn+40F+%AvuT1 z4?wJcIQ3w5!QJ#-jv7azV|tEg;bY{a*E=*{g`y&iWIt^duj}-LTN@-{1w4LbVVQd+ zzMSCMOmEXjZ_`4*87vlO9+$$YXTv2t2{Z80KH(??utPahWSAz$N+>SqG(wZ1PNC%P zo?wsmfoI(vlH@20ClD}9gAPa6T;G5!CHM%?j&wpu}V3 zIFku+2c!jcJLAy!_d1AUlK-_7`?;Q5@k1tlti_fuu!H}Z95viBg3Yp^b4CGIAy$bg zH6|INGbMjN23oQygo{NfeRyIF89A-b;69$=wff5NrpTd%1%xQH>+ZN+5mdOh+40*8 z9QKsu-;L&N(cbIeWKv-f@wZZAyUKz8t%dGtAp9et^1|pT3~ZuIC4CV&|P?d+=+y z=s?O>juY`W`u^0#K5H*&=}Mj-2G{rx6$Flmt-NM7ZRA|IdNCQmNjt$KFcc`*6-b1C z?B$MOZq0bvnz42T*<(Ss0ra)%ZQ4zZ}pAm!?}(nk5}z zr?__D>=gRuEYu>R;W3+P{7{|lFU}!1j>xs+9~3bEdAHO&WsVH$<4IN9rnc_w&{0KO z_tymqFRf@ZO*(a~>H39IHnphTcy~J9iut%B^*E0@*)pgf>%-8Qo89qY0MS6pQ$S=8 zxT?{koxGh(#%I!!X^0akRtXxzaJ~HFe-_nHmbIHEhH*z)6c&0|+`G!pS8}%7JMib?`ES9~a*8TQ0xr&Zw zhYWr1NJmLhbY^~LS&TBxX8-I7IGO}Ukkxq9`e-I)=J~RF=h1e4L9hI44$hO{?5*MW zrUy2+V(gShxfE$d9_{KKTrxIeiqkgvGi#rk7qyKtCJD3oxe|tSGTi@Q`D0!?uNT!;`D8`5RmJ$>0vqxeMc6d z&QEzn%i|DP82WauaEe|B&7Yp?h|8{&x%z3QB!BPiP6~Aa63fGF0Z%Vxf_`>fd&{G& zZV3H^`5Lx$wuBJ~b9>5)zk;DHPjF!wy<1i)0Irp7zdn7OF+_(2JXC!Jc#<~Wov zg$$B$Q+FHk$&=R`qX=;1q-`TVF3ZS-$GF!xA-PxbojT>$t^AN0@N{Aa!bbvja13Sb zvWJd%Hji!nW`RYpUOY}o16y$fL*-{6zlc!wg9O(OCPtNQsIzG2-QL_qv$()08p^jH z0Cyi0Ur}zg1ENVVM}&ildT?6-`H@S<8q6Va;f5re?@IF0L*>V>z|v;9=DO=FY1~bn3!CRj~RE#vPkcrh5y)8EfV&5;{ZcR4|6=H~ zxT#fJ)hq9c9t&oMC1L@SRMm@_(ZvJJ@03qdbw~LVgjY5QkOmTvJxjywbU9J)5WRQ% zU~$(dQI0d*#z3_Jf*TdC_QH~ge#ag$^Rjpe1K}X5*~wCG%a0B3|5|lsCU*3~{T5e| zHYGBB?s<%MCicB4YTXlm9BOnE()TnCb~Y~H4dY!6C^2Jo&8?OQ35CB-stN8}WcI2I zZa0-W5U_(HPxrFaYE$D{!~3&T-UDkWf5|uQi)u9Q6Qc6)uxI)B@8bMvEbzhXhw_0@J=4^hUJQ}5cXU?k(bj^{%A`ImiuF_`Oe z_zRxpis;By2d&h*hc5Ln5`-KmZv>5&ZvEDo z<-oBUKTsY;9EUr|=9ntg6oyMn9_9aRYBOh)Z311|7aGe;P`H%N6Z(7tvt`JvM=Ypx zF5NLe@33o}RK$1=_R6I9bhrSFb!UR2r;IdR7X-jdG~15|AK>Zcy;b9`o|b#IS};OT zNYCmkYhq|?`2ez+;yvL#J?U*`-l4jqE}6O*tQ2Uhv@|QQaxEg9Bj)LOScVuEP3NxY zZc`2Z$;?;n_%^;Iqcc2 zBDK9GH#aewpVLz~!gR3h3}WLu)x&m8Z7%PV;Lit{WrwRjS!cr09o=a*!KO>@u>}vI z2EwS?T$H;3l_n_Gnbl3_OGF+zckTDa_07OgU!fL-L=@TCBeNQyu6zrVc6D(f+r*ov z{Q)5?Nj&-V$*hJO=GLwoe8!nH4I_eOR9jlyZR7?1-*WKk!kbNl96N*rh|ZpxqP+Oc zDmd?BWAgPMi(S4o?QR=B?%zzE-Zy*Od~XSC*tba=D{fW_bfWBN%5rwmsd+T}EEX#c zwykl_##Y(QBu0i~+wALq+M`&Zx{EXK+7r0Nn+Nv!UWq}K>TCLck5fQk^Sxtus_z-z zu7rx$F?Q$ZaH>d&zAoE%l-Mg$&uGz#*$Mq&HACvtO1w{^U}D?^lvgznU=LaNsb~JM z7WGng_i|)gB}Gz3nnZIBZRMtC?o^Jv5&!jSVTbb1te}?Ecw)hc>3JvtikTpYA#qtU zivK)Bwv$gK4?i$rpJ=fpxlNBtNRo8f>9s`Ya=8bER03Uug>%9=%6btDmFN$$8XNE! zHx;ihjch!}Neo3qC4%Bp+6DO8`CdQHP>!@y@CqQ}d1m53NFS<<4(m=r-(AvO-6Xjj zjgx6dh6*BLuEJf$Rfaw(HtfCGf4A-eJ|a*7DKzA|#I{guKzwgy6dNYYw(!-f93(MT zs%~>U43VRl+p2jxPf3u6`|(_G9q1W4n_6kwPy1m_w{qFn=~#t3f^d3nxhw@E)?P|3 z$I2P@mDmm6I}jP^CEyCyxb88Df5@+RMeq;TtZ`sH1md;DAIaF)px8wou)EtkNIjh! z2(wT=qE2x$snXVj?E7K^4u37(3Hlz2)!y~jF6~-l8#%1eV7ol7FInsO_B7JuF3CA( z{p-q~c|(OsxU89KJKud@GcUu>EJD-I555!9JgpYUtoOZ`%kk+!wLVqnM+{AH5tML|5_RtVb^${01e^T05&eH2_N|X&I;?!M+H>k Vz((^)1HW@&d-+)K%MkzI{{w3}bu|D0 delta 4846 zcmY+IbyO7Ex5tMZ9HgYXOJL}_^H~$=CQQ)Q#V;f9 zp8s4q2v2oU%c#=Df!W4(b!dGlXiT{DSVYrRl8}+pL7zBJtOQ~*iaVIDf4=F9u#YTZ zB(=w?5ogvvPgXf!UKo?ft7$P=_U;q_gbb9Ma?U6<@|?#BnY=qm=c`LK7c%M5<91yD zh2feK6=pB`(X!W3Yh;NtC~QzXg{BL!KN)L_;u8+R(X++6uv2`|BJX@=yGF%rWZ}Hs z?u54SZq`8RD!*i6YvLxwGxXRQffE$|%9eQzwDy*UVre<2+vlVrY9~w`T0tDr2%H3- zGNY9C3_&8%;$rv%4OjvBtx-WnOmOB(tGA?*;f%Y{6ND<2b846aLCo1*yF1wqrL5Hh zBMcT8O^3jxJ++wu;+RjBmCSq+3kyj7S#Tquq*eYnPH0#LE@GO&<6(AqnEyT zaw|RZ4wyY(FF&*6*cx#$Q5eBSv(RbXHg9!DF6YnV!oMVPodqdlh4!HbL#p^TB)?pr zJ*yntQ;-tgo!IygaYEkZ7vb5c5@XJ}0v^n6=NGyv(yk&`!Q0$|LITcnVuL){%Wlo%Lz6j5atQ-n9Z4Y>S(WjK5*HG<`q1b4YRfiXaJ1< z5X0wQ)tnI1>PX%k4ph3rRl6U+oxWYL3T}FJ|NC;NNv7*QaxHZZ=>6VdiZJ#$*}_175>Z*H?rVY2f`$5+jJ z&+MZ5TJ<6sx`{{6h%26Fhn;HKc9D^-WMY;*O$TwQ{OS4Sj0|gcDJ}=m^@8Ye&?tc+ zd16$UOJMqY7&9UvCE%yS7|i$AHZ?)r_|bbd6W{Tr*4jHU-y)PtTiYskbfRlH^s}W; z+FrZ+`v+0f!Hx%lAyzY)=zdj?XgKJ~~*+WCtPzn-62WbdX z_}T#hfJ|oO)>ANohLNdCmc+LhY9IxrMiIt~X}LDkRoouY?g9*xjY1SCP^YiX-`=w~ zlp@RW$V-GWG(+pi8KQ*^(%TnE_wJfLOF-U;6mhEZP#fhNmrP9kzHeL5t>~zs5X2{> zvdACI6uA!8Vl=(n-8bUb^HVLn>SaKv1ViBAfpRr&*8PX+`i&_U z3?{aLF*d^d`Ig4*Gt8RfFFeA^?hAa&Nq87U+IMz7hchXU{|=Z_Q4|rr2>!xfFsjaZeFArGN{+oe^Y@so}G`w0V(y zCvyxv*A|n1cr{D82Xs)rADicgou|ztP+=?bc~!}X>Kz?^amWM#%G19oD--f!UmdYQf@FC5`s|nxC;!e z>@Uwisq2$+e5HF6PGTf+k)KE+a~B{9yAJRmv!MIBc_MisK%?>D;80=y8cej2Nn!a+ zR3k^YNvhpcijIL$8RtS&)noEUXEM5+1ScVIaLbMLM|TKZHw6ZXIK*DzV4-F>u?{ln z_d!_6zB0#&a(8tHQY2*d=dh^eY8~{f%o9p~A6)FbM%@R+DZ*L9*KEv-%ov&IoCSiULH;CU}M~|1O_5%n0W|H*pJMT^3kD{iAz6-S6 zrKAnK^rTs<#puwefXzN`EL9#?zT`((^6a3J%d$A+3r`iCY*GVaswi7CfGC z=RFgI66#ShPP%(yN@RUvYwyLFhwq+Q{#?osDICR+n!fRd3xg8L2XX7Kf5sH5Q6GKg6jT)L+kcrqG_xiY;V2n^JR=iiiZj6&@(x#lZEJhAfRDI zZ|g8AI6d(A&>@XX1ego4lFeEQB$;N_vR1`Dbev$~tB^23IV&9^yK&iQ>|(zBY$C6I zW+XnpUU#NwLcTl`0ry~DKSn=P0Rf4|48srjDi-kvSkvjsQg(5}z{BsM)D_hGqBRYN zO)@I=Gb(v;3>mS=#VatCJwg>A@tEk;%DY6iM4(ZeP{sQ!TI&hfXtK2C7)*2t>&;}< zcnVG{unWb2HP}Uw>5~de*v1j%fR#eEN(5QJSChXpSxp3|Dq`S~^&p0;vBKDsmDzY~ zBDif>P?eE?CdDc^5;0RAl>HYV{|D&MxHXykE&$DtnzW?iRe6H(l0wz`p_Y;{{!g;U zg*XMr&_-5DKdfHArupe z{ulaZ_`mh(29j@20P$bY4lkSWU!2fPf{|7Yy=g*y^%`hKZkYP(X3sS6v6jls9n-8F zQTnSGw#Q0+&5CgiYJ0{oWOrBSVTlnWZ{L6q9!!zt)b%RYsVmd^Z&v`H#Zz9XzaqHV zrralgj&Q3Q0}|ho&bd%5O4mKHucMz1D_>KZPZ<7WDQ&z)KAe~s6F$b41`_>}+>-90 zt){M~JQzyikXConODs~Dvt!xrR{)#Vwk-+MFHn^dw1C^gZEe}2V_QgD;03?L8qdl; z+2(Rh#rCsm^oCmrWJ+rVulrU+z5e!@OwWyG3&AJo+*4<{!LJ2OhF?uVzCOKUrT8mG z0lYY`K+`UiU`s$II$cWqv~9R$-tJWD(M!BWD%tCtu{R^l>iIk(JGp+Qzifi%FW@KI z2j#bNTZQrK{qu&g%i-ynZ&EQhN1w0X#_j)Aw4~o(C&)rk(+(fd-&T|ldCqG_0B5G} zVps8?#P3_~pC7c<&u1-R-j@Ayf+jc3_Hu*OVF@+!!yen;F!G-BuG|;|*zbW(=xHN8 zO&U*rO}oebP!UhssM^4l>3UdQv;;I@kWAxXeS|RM&?A>3{aA)YDBdR4QL{ zTMLkHV$fLY`_imJZ&SqZbEMTr&oot`0c%sky^1Fx&gZumXAu)FzK*jD3uncB0Z6C1 zRle$CRvb$`tqNA7-Ce_Vo?Cn&vNWG)k#fWnx{WeDV@Ay3;=ih$VdjafDKs9AAkb!S zA!(H>H^X-X$ zlq@dGRh*MzRcNF8XLU>k1F)*R8#i&-UbgZDUraPnEB1@h4OIejjadOy7JlMGFdqyD(1(K~zo;z-qW~Cv8sa~(Gb8o;hYvrTKCgkUGU6>UG`#EO^QQe*r zE@Dn>-7~wXug2Ze&=YReVp3UGUp0Wq3`PzOt+X2^vl3TcKZG?DbCit`Epc=j=}j4Y z9~wY3aL!+sp4RNn^-=1ftJoEJ$lCD9X;H0hUUH8 zj>>g98Ly>gnoxUwh0o+n6$~2IYX+`2&T${AY7kA|;O)G_JRBkUNq^Qtv#2{M9+Z%B zhaccU@hG@LuM>B@WsaoNPQup)?N>8xvsNS4-RcZ&krTp^_{GcnR=|7bIbc$Y`Fi6? zrySz`gvb@K@Zfnrb=7qEeoh9zbpx}H%(-v& zkMY2|;ClInlU~nn>seK14lho~gG|GMkl3BB>wvbmQut9T@%`7iH{IuX9x6(sj$$#n z0b4+aUJpOIkq>lNd&vZLW0&_k19Yz4%C;k*!K^)-8O1W*NQRyZI`$>-v!jRI@e6kV zvH*hw)Kqz9KJllfD8NHs3xhC=6*9zdQbYle>8?emc>_r0j2AQANW1_Sd|; zdC|5caTD|L=A|j`S<x7Pp` zgJ>~#W>nXih>rTef;o@aoFbi0LNugDV7=f|RYX)X#zuh}%#!Q%q)HSJ`mB;W*4Jw! zo;5?mI0Y4|wb30zz1RNyV?YW0;#v8Yn)n6E$xJof?ABOg$!xTATPj1PHD6VHH$Y;K z)YuN{!~vrgm+E4}JWNFJI%LqVbUcu!sdAT|eCYfjkuJ{}L(bx9wo|M?1p*1zvYu6u zwCajm2V5!ID;-CXnm&xjIJq`k>76DreZyeJ{R!}G!=FhhUVC<1(A>TW{Rq{ahQS1G z9tWoNzvLvuYovN{^}_D=xA-%vMTjqOBrhM_bsaY2D~&XL<;D?}e#CXhJ`K>w#+p-2 z3w-Wcav$WWzRl*7L;a=3cRh)N;;mx`oUdgT2o9|Z&c_9x(S9H0#ZrDx`%W8@X9nb- zr2OVs8&z-EzB!PpG>bONHIMJeZ+B=gSJ`O+q2Q`C%HP`q^}!t5f{&a-XSoidX}c(w zIrLCX(bk+nhpvcQ=fkvJOVl#GM4lDBM7k5OFWKkaP$PT|&#Mk~x>ap^W3zfKe_(_8 zG9SameGQuUG*79Z-tz>yIgECJ&8D&CV^0`X|9LT};EBBB9>Z~>3_GgFW4-@u7UfHW zg9+pJYp>&Y^7PzhP`PRhidU_v@vNfvd+k_-M8! zgqPR;5NfUryk%E;Kjk<-$k$a-`=nM{7v-HihK$#{$ATJMv|^S?Bsm4lVqU}P_YoiX zO!;J9Y!Y{~8=V3Fe&Y=`EGOt#kDzg&eS9Va5dm9t^R-3RbHEUk zqq6#1!r$=5!GTPR4C4FA-{Li1030av`ehv>rBJ;HGduzPN0Coyw07xxcGd!}2S*>p z_v1PO3sRsa>Bai^X4HLM(e&)1{;mcRL?agbvbx<_V=Ov(LuI#Bvoro36|aAaR^Gl8 znQ4X2&|d~!(yr0kc~^282HMbBWdoGE%;}t^UHFjS^Oxak>GenckfyZgo*7?BB_hu! z^-^P1nec~`FZ4;JePd7raj`_dNX?sPv6@Sn%@0Wj#7!X_-N04$TdaRJe9EbW@#O!1 ziIB29T4+e*TOJmXDhNyfzyJ>b_~ZX!_(&+2 zf#zS)002n-BMJbRFd+FD$&hv6=jbn(ksd6pNHpH(=oTzU9$s;pf35%x0EqviH$?x1 Xsk0%&c%{(yIFLQOOxPc}{to^R&Ql4r diff --git a/applications/plugins/unitemp/views/Widgets_view.c b/applications/plugins/unitemp/views/Widgets_view.c index 6d8702ca1..892b31f98 100644 --- a/applications/plugins/unitemp/views/Widgets_view.c +++ b/applications/plugins/unitemp/views/Widgets_view.c @@ -132,7 +132,7 @@ void unitemp_widget_delete_switch(Sensor* sensor) { app->buff, BUFF_SIZE, "\e#I2C addr:\e# 0x%02X", - ((I2CSensor*)current_sensor->instance)->currentI2CAdr); + ((I2CSensor*)current_sensor->instance)->currentI2CAdr >> 1); widget_add_text_box_element( app->widget, 0, 28, 128, 23, AlignLeft, AlignTop, app->buff, false); } From 1243dad8fd8109d7a4c3f1f72664722488ca0bcd Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Mon, 26 Dec 2022 23:21:10 +0300 Subject: [PATCH 18/34] Fix POCSAG Pager UI bug same as subghz and weather station bug with invisible element selected --- applications/plugins/pocsag_pager/views/pocsag_pager_receiver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/applications/plugins/pocsag_pager/views/pocsag_pager_receiver.c b/applications/plugins/pocsag_pager/views/pocsag_pager_receiver.c index d8398cbfe..76545b238 100644 --- a/applications/plugins/pocsag_pager/views/pocsag_pager_receiver.c +++ b/applications/plugins/pocsag_pager/views/pocsag_pager_receiver.c @@ -307,7 +307,7 @@ bool pcsg_view_receiver_input(InputEvent* event, void* context) { pcsg_receiver->view, PCSGReceiverModel * model, { - if(model->idx != model->history_item - 1) model->idx++; + if(model->history_item && model->idx != model->history_item - 1) model->idx++; }, true); } else if(event->key == InputKeyLeft && event->type == InputTypeShort) { From 1c926cf8a2989bfb96d4201e813a80dcbe0eeb63 Mon Sep 17 00:00:00 2001 From: Max Andreev Date: Mon, 26 Dec 2022 23:22:22 +0300 Subject: [PATCH 19/34] Trigger amap from another repo (#2171) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add s3 upload, repository dispatch * Add trigger * Fix map file upload * Debug * Add event file upload to s3 * fix triggering * Fix upload process * fix build.yml Co-authored-by: あく --- .github/workflows/amap_analyse.yml | 103 ---------------------- .github/workflows/build.yml | 39 +++++++-- scripts/amap_mariadb_insert.py | 136 ----------------------------- 3 files changed, 32 insertions(+), 246 deletions(-) delete mode 100644 .github/workflows/amap_analyse.yml delete mode 100755 scripts/amap_mariadb_insert.py diff --git a/.github/workflows/amap_analyse.yml b/.github/workflows/amap_analyse.yml deleted file mode 100644 index 1340e4cde..000000000 --- a/.github/workflows/amap_analyse.yml +++ /dev/null @@ -1,103 +0,0 @@ -name: 'Analyze .map file with Amap' - -on: - push: - branches: - - dev - - "release*" - tags: - - '*' - pull_request: - -env: - TARGETS: f7 - FBT_TOOLCHAIN_PATH: /opt - -jobs: - amap_analyse: - if: ${{ !github.event.pull_request.head.repo.fork }} - runs-on: [self-hosted,FlipperZeroMacShell] - timeout-minutes: 15 - steps: - - name: 'Wait Build workflow' - uses: fountainhead/action-wait-for-check@v1.0.0 - id: wait-for-build - with: - token: ${{ secrets.GITHUB_TOKEN }} - checkName: 'main' - ref: ${{ github.event.pull_request.head.sha || github.sha }} - intervalSeconds: 20 - - - name: 'Check Build workflow status' - if: steps.wait-for-build.outputs.conclusion == 'failure' - run: | - exit 1 - - - name: 'Decontaminate previous build leftovers' - run: | - if [ -d .git ]; then - git submodule status || git checkout "$(git rev-list --max-parents=0 HEAD | tail -n 1)" - fi - - - name: 'Checkout code' - uses: actions/checkout@v3 - with: - fetch-depth: 0 - ref: ${{ github.event.pull_request.head.sha }} - - - name: 'Get commit details' - run: | - if [[ ${{ github.event_name }} == 'pull_request' ]]; then - TYPE="pull" - elif [[ "${{ github.ref }}" == "refs/tags/"* ]]; then - TYPE="tag" - else - TYPE="other" - fi - python3 scripts/get_env.py "--event_file=${{ github.event_path }}" "--type=$TYPE" - - - name: 'Make artifacts directory' - run: | - rm -rf artifacts - mkdir artifacts - - - name: 'Download build artifacts' - run: | - mkdir -p ~/.ssh - ssh-keyscan -p ${{ secrets.RSYNC_DEPLOY_PORT }} -H ${{ secrets.RSYNC_DEPLOY_HOST }} > ~/.ssh/known_hosts - echo "${{ secrets.RSYNC_DEPLOY_KEY }}" > deploy_key; - chmod 600 ./deploy_key; - rsync -avzP \ - -e 'ssh -p ${{ secrets.RSYNC_DEPLOY_PORT }} -i ./deploy_key' \ - ${{ secrets.RSYNC_DEPLOY_USER }}@${{ secrets.RSYNC_DEPLOY_HOST }}:"${{ secrets.RSYNC_DEPLOY_BASE_PATH }}${BRANCH_NAME}/" artifacts/; - rm ./deploy_key; - - - name: 'Make .map file analyze' - run: | - cd artifacts/ - /Applications/amap/Contents/MacOS/amap -f "flipper-z-f7-firmware-${SUFFIX}.elf.map" - - - name: 'Upload report to DB' - run: | - source scripts/toolchain/fbtenv.sh - get_size() - { - SECTION="$1"; - arm-none-eabi-size \ - -A artifacts/flipper-z-f7-firmware-$SUFFIX.elf \ - | grep "^$SECTION" | awk '{print $2}' - } - export BSS_SIZE="$(get_size ".bss")" - export TEXT_SIZE="$(get_size ".text")" - export RODATA_SIZE="$(get_size ".rodata")" - export DATA_SIZE="$(get_size ".data")" - export FREE_FLASH_SIZE="$(get_size ".free_flash")" - python3 -m pip install mariadb==1.1.4 - python3 scripts/amap_mariadb_insert.py \ - ${{ secrets.AMAP_MARIADB_USER }} \ - ${{ secrets.AMAP_MARIADB_PASSWORD }} \ - ${{ secrets.AMAP_MARIADB_HOST }} \ - ${{ secrets.AMAP_MARIADB_PORT }} \ - ${{ secrets.AMAP_MARIADB_DATABASE }} \ - artifacts/flipper-z-f7-firmware-$SUFFIX.elf.map.all - diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2de0e57c3..9ca60aee6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -30,11 +30,6 @@ jobs: fetch-depth: 0 ref: ${{ github.event.pull_request.head.sha }} - - name: 'Make artifacts directory' - run: | - rm -rf artifacts - mkdir artifacts - - name: 'Get commit details' id: names run: | @@ -46,6 +41,15 @@ jobs: TYPE="other" fi python3 scripts/get_env.py "--event_file=${{ github.event_path }}" "--type=$TYPE" + echo random_hash=$(openssl rand -base64 40 | shasum -a 256 | awk '{print $1}') >> $GITHUB_OUTPUT + echo "event_type=$TYPE" >> $GITHUB_OUTPUT + + - name: 'Make artifacts directory' + run: | + rm -rf artifacts + rm -rf map_analyser_files + mkdir artifacts + mkdir map_analyser_files - name: 'Bundle scripts' if: ${{ !github.event.pull_request.head.repo.fork }} @@ -82,9 +86,30 @@ jobs: run: | cp build/core2_firmware.tgz "artifacts/flipper-z-any-core2_firmware-${SUFFIX}.tgz" - - name: 'Copy .map file' + - name: 'Copy map analyser files' run: | - cp build/f7-firmware-*/firmware.elf.map "artifacts/flipper-z-f7-firmware-${SUFFIX}.elf.map" + cp build/f7-firmware-*/firmware.elf.map map_analyser_files/firmware.elf.map + cp build/f7-firmware-*/firmware.elf map_analyser_files/firmware.elf + cp ${{ github.event_path }} map_analyser_files/event.json + + - name: 'Upload map analyser files to storage' + uses: keithweaver/aws-s3-github-action@v1.0.0 + with: + source: map_analyser_files/ + destination: "s3://${{ secrets.MAP_REPORT_AWS_BUCKET }}/${{steps.names.outputs.random_hash}}" + aws_access_key_id: "${{ secrets.MAP_REPORT_AWS_ACCESS_KEY }}" + aws_secret_access_key: "${{ secrets.MAP_REPORT_AWS_SECRET_KEY }}" + aws_region: "${{ secrets.MAP_REPORT_AWS_REGION }}" + flags: --recursive + + - name: 'Trigger map file reporter' + uses: peter-evans/repository-dispatch@v2 + with: + repository: flipperdevices/flipper-map-reporter + token: ${{ secrets.REPOSITORY_DISPATCH_TOKEN }} + event-type: map-file-analyse + client-payload: '{"random_hash": "${{steps.names.outputs.random_hash}}", "event_type": "${{steps.names.outputs.event_type}}"}' + - name: 'Upload artifacts to update server' if: ${{ !github.event.pull_request.head.repo.fork }} diff --git a/scripts/amap_mariadb_insert.py b/scripts/amap_mariadb_insert.py deleted file mode 100755 index 6ff1b3bf0..000000000 --- a/scripts/amap_mariadb_insert.py +++ /dev/null @@ -1,136 +0,0 @@ -#!/usr/bin/env python3 - -from datetime import datetime -import argparse -import mariadb -import sys -import os - - -def parseArgs(): - parser = argparse.ArgumentParser() - parser.add_argument("db_user", help="MariaDB user") - parser.add_argument("db_pass", help="MariaDB password") - parser.add_argument("db_host", help="MariaDB hostname") - parser.add_argument("db_port", type=int, help="MariaDB port") - parser.add_argument("db_name", help="MariaDB database") - parser.add_argument("report_file", help="Report file(.map.all)") - args = parser.parse_args() - return args - - -def mariadbConnect(args): - try: - conn = mariadb.connect( - user=args.db_user, - password=args.db_pass, - host=args.db_host, - port=args.db_port, - database=args.db_name, - ) - except mariadb.Error as e: - print(f"Error connecting to MariaDB: {e}") - sys.exit(1) - return conn - - -def parseEnv(): - outArr = [] - outArr.append(datetime.now().strftime("%Y-%m-%d %H:%M:%S")) - outArr.append(os.getenv("COMMIT_HASH", default=None)) - outArr.append(os.getenv("COMMIT_MSG", default=None)) - outArr.append(os.getenv("BRANCH_NAME", default=None)) - outArr.append(os.getenv("BSS_SIZE", default=None)) - outArr.append(os.getenv("TEXT_SIZE", default=None)) - outArr.append(os.getenv("RODATA_SIZE", default=None)) - outArr.append(os.getenv("DATA_SIZE", default=None)) - outArr.append(os.getenv("FREE_FLASH_SIZE", default=None)) - outArr.append(os.getenv("PULL_ID", default=None)) - outArr.append(os.getenv("PULL_NAME", default=None)) - return outArr - - -def createTables(cur, conn): - headerTable = "CREATE TABLE IF NOT EXISTS `header` ( \ - `id` int(10) unsigned NOT NULL AUTO_INCREMENT, \ - `datetime` datetime NOT NULL, \ - `commit` varchar(40) NOT NULL, \ - `commit_msg` text NOT NULL, \ - `branch_name` text NOT NULL, \ - `bss_size` int(10) unsigned NOT NULL, \ - `text_size` int(10) unsigned NOT NULL, \ - `rodata_size` int(10) unsigned NOT NULL, \ - `data_size` int(10) unsigned NOT NULL, \ - `free_flash_size` int(10) unsigned NOT NULL, \ - `pullrequest_id` int(10) unsigned DEFAULT NULL, \ - `pullrequest_name` text DEFAULT NULL, \ - PRIMARY KEY (`id`), \ - KEY `header_id_index` (`id`) )" - dataTable = "CREATE TABLE IF NOT EXISTS `data` ( \ - `header_id` int(10) unsigned NOT NULL, \ - `id` int(10) unsigned NOT NULL AUTO_INCREMENT, \ - `section` text NOT NULL, \ - `address` text NOT NULL, \ - `size` int(10) unsigned NOT NULL, \ - `name` text NOT NULL, \ - `lib` text NOT NULL, \ - `obj_name` text NOT NULL, \ - PRIMARY KEY (`id`), \ - KEY `data_id_index` (`id`), \ - KEY `data_header_id_index` (`header_id`), \ - CONSTRAINT `data_header_id_foreign` FOREIGN KEY (`header_id`) REFERENCES `header` (`id`) )" - cur.execute(headerTable) - cur.execute(dataTable) - conn.commit() - - -def insertHeader(data, cur, conn): - query = "INSERT INTO `header` ( \ - datetime, commit, commit_msg, branch_name, bss_size, text_size, \ - rodata_size, data_size, free_flash_size, pullrequest_id, pullrequest_name) \ - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" - cur.execute(query, data) - conn.commit() - return cur.lastrowid - - -def parseFile(fileObj, headerID): - arr = [] - fileLines = fileObj.readlines() - for line in fileLines: - lineArr = [] - tempLineArr = line.split("\t") - lineArr.append(headerID) - lineArr.append(tempLineArr[0]) # section - lineArr.append(int(tempLineArr[2], 16)) # address hex - lineArr.append(int(tempLineArr[3])) # size - lineArr.append(tempLineArr[4]) # name - lineArr.append(tempLineArr[5]) # lib - lineArr.append(tempLineArr[6]) # obj_name - arr.append(tuple(lineArr)) - return arr - - -def insertData(data, cur, conn): - query = "INSERT INTO `data` ( \ - header_id, section, address, size, \ - name, lib, obj_name) \ - VALUES (?, ?, ?, ?, ? ,?, ?)" - cur.executemany(query, data) - conn.commit() - - -def main(): - args = parseArgs() - dbConn = mariadbConnect(args) - reportFile = open(args.report_file) - dbCurs = dbConn.cursor() - createTables(dbCurs, dbConn) - headerID = insertHeader(parseEnv(), dbCurs, dbConn) - insertData(parseFile(reportFile, headerID), dbCurs, dbConn) - reportFile.close() - dbCurs.close() - - -if __name__ == "__main__": - main() From 4f05c1816bf9f2e915e00e48150a8b9305392480 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Mon, 26 Dec 2022 23:31:38 +0300 Subject: [PATCH 20/34] Update TOTP --- applications/plugins/totp/cli/cli_helpers.h | 3 + .../plugins/totp/cli/commands/add/add.c | 8 +- .../plugins/totp/cli/commands/delete/delete.c | 11 +- .../plugins/totp/cli/commands/move/move.c | 14 +- .../cli/commands/notification/notification.c | 13 +- .../plugins/totp/cli/commands/pin/pin.c | 25 +- .../totp/cli/commands/timezone/timezone.c | 7 +- .../plugins/totp/services/config/config.c | 595 +++++++++++++----- .../plugins/totp/services/config/config.h | 69 +- .../plugins/totp/services/crypto/crypto.c | 21 +- .../plugins/totp/services/crypto/crypto.h | 3 +- .../plugins/totp/services/hmac/memxor.c | 2 - applications/plugins/totp/totp_app.c | 54 +- applications/plugins/totp/ui/common_dialogs.c | 20 + applications/plugins/totp/ui/common_dialogs.h | 7 + .../add_new_token/totp_scene_add_new_token.c | 7 +- .../scenes/app_settings/totp_app_settings.c | 8 +- .../totp_scene_generate_token.c | 4 +- .../scenes/token_menu/totp_scene_token_menu.c | 6 +- 19 files changed, 620 insertions(+), 257 deletions(-) create mode 100644 applications/plugins/totp/ui/common_dialogs.c create mode 100644 applications/plugins/totp/ui/common_dialogs.h diff --git a/applications/plugins/totp/cli/cli_helpers.h b/applications/plugins/totp/cli/cli_helpers.h index 075822cd6..ae6fe6e0c 100644 --- a/applications/plugins/totp/cli/cli_helpers.h +++ b/applications/plugins/totp/cli/cli_helpers.h @@ -38,6 +38,9 @@ TOTP_CLI_PRINTF( \ "Invalid command arguments. use \"help\" command to get list of available commands") +#define TOTP_CLI_PRINT_ERROR_UPDATING_CONFIG_FILE() \ + TOTP_CLI_PRINTF("An error has occurred during updating config file\r\n") + /** * @brief Checks whether user is authenticated and entered correct PIN. * If user is not authenticated it prompts user to enter correct PIN to authenticate. diff --git a/applications/plugins/totp/cli/commands/add/add.c b/applications/plugins/totp/cli/commands/add/add.c index 90cc0f420..e037546e2 100644 --- a/applications/plugins/totp/cli/commands/add/add.c +++ b/applications/plugins/totp/cli/commands/add/add.c @@ -206,11 +206,13 @@ void totp_cli_command_add_handle(PluginState* plugin_state, FuriString* args, Cl TOTP_LIST_INIT_OR_ADD(plugin_state->tokens_list, token_info, furi_check); plugin_state->tokens_count++; - totp_config_file_save_new_token(token_info); + if(totp_config_file_save_new_token(token_info) == TotpConfigFileUpdateSuccess) { + TOTP_CLI_PRINTF("Token \"%s\" has been successfully added\r\n", token_info->name); + } else { + TOTP_CLI_PRINT_ERROR_UPDATING_CONFIG_FILE(); + } if(load_generate_token_scene) { totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL); } - - TOTP_CLI_PRINTF("Token \"%s\" has been successfully added\r\n", token_info->name); } \ No newline at end of file diff --git a/applications/plugins/totp/cli/commands/delete/delete.c b/applications/plugins/totp/cli/commands/delete/delete.c index 7eddb96bd..046341693 100644 --- a/applications/plugins/totp/cli/commands/delete/delete.c +++ b/applications/plugins/totp/cli/commands/delete/delete.c @@ -93,14 +93,17 @@ void totp_cli_command_delete_handle(PluginState* plugin_state, FuriString* args, plugin_state->tokens_list = list_remove(plugin_state->tokens_list, list_node); plugin_state->tokens_count--; - totp_full_save_config_file(plugin_state); + if(totp_full_save_config_file(plugin_state) == TotpConfigFileUpdateSuccess) { + TOTP_CLI_PRINTF("Token \"%s\" has been successfully deleted\r\n", token_info->name); + } else { + TOTP_CLI_PRINT_ERROR_UPDATING_CONFIG_FILE(); + } + + token_info_free(token_info); if(activate_generate_token_scene) { totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL); } - - TOTP_CLI_PRINTF("Token \"%s\" has been successfully deleted\r\n", token_info->name); - token_info_free(token_info); } else { TOTP_CLI_PRINTF("User not confirmed\r\n"); } diff --git a/applications/plugins/totp/cli/commands/move/move.c b/applications/plugins/totp/cli/commands/move/move.c index 95cb8dcac..9d47134e5 100644 --- a/applications/plugins/totp/cli/commands/move/move.c +++ b/applications/plugins/totp/cli/commands/move/move.c @@ -147,18 +147,18 @@ void totp_cli_command_move_handle(PluginState* plugin_state, FuriString* args, C } if(token_updated) { - totp_full_save_config_file(plugin_state); + if(totp_full_save_config_file(plugin_state) == TotpConfigFileUpdateSuccess) { + TOTP_CLI_PRINTF("Token \"%s\" has been successfully updated\r\n", token_info->name); + } else { + TOTP_CLI_PRINT_ERROR_UPDATING_CONFIG_FILE(); + } + } else { + TOTP_CLI_PRINT_INVALID_ARGUMENTS(); } if(activate_generate_token_scene) { totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL); } - if(token_updated) { - TOTP_CLI_PRINTF("Token \"%s\" has been successfully updated\r\n", token_info->name); - } else { - TOTP_CLI_PRINT_INVALID_ARGUMENTS(); - } - furi_string_free(temp_str); } \ No newline at end of file diff --git a/applications/plugins/totp/cli/commands/notification/notification.c b/applications/plugins/totp/cli/commands/notification/notification.c index 91dd44d4f..5b98a857b 100644 --- a/applications/plugins/totp/cli/commands/notification/notification.c +++ b/applications/plugins/totp/cli/commands/notification/notification.c @@ -86,15 +86,18 @@ void totp_cli_command_notification_handle(PluginState* plugin_state, FuriString* } plugin_state->notification_method = new_method; - totp_config_file_update_notification_method(new_method); + if(totp_config_file_update_notification_method(new_method) == + TotpConfigFileUpdateSuccess) { + TOTP_CLI_PRINTF("Notification method is set to "); + totp_cli_command_notification_print_method(new_method); + cli_nl(); + } else { + TOTP_CLI_PRINT_ERROR_UPDATING_CONFIG_FILE(); + } if(previous_scene != TotpSceneNone) { totp_scene_director_activate_scene(plugin_state, previous_scene, NULL); } - - TOTP_CLI_PRINTF("Notification method is set to "); - totp_cli_command_notification_print_method(new_method); - cli_nl(); } else { TOTP_CLI_PRINTF("Current notification method is "); totp_cli_command_notification_print_method(plugin_state->notification_method); diff --git a/applications/plugins/totp/cli/commands/pin/pin.c b/applications/plugins/totp/cli/commands/pin/pin.c index 045976eef..198324e27 100644 --- a/applications/plugins/totp/cli/commands/pin/pin.c +++ b/applications/plugins/totp/cli/commands/pin/pin.c @@ -134,8 +134,14 @@ void totp_cli_command_pin_handle(PluginState* plugin_state, FuriString* args, Cl plugin_state->crypto_verify_data = NULL; } - totp_crypto_seed_iv( - plugin_state, new_pin_length > 0 ? &new_pin[0] : NULL, new_pin_length); + if(!totp_crypto_seed_iv( + plugin_state, new_pin_length > 0 ? &new_pin[0] : NULL, new_pin_length)) { + memset_s(&new_pin[0], TOTP_IV_SIZE, 0, TOTP_IV_SIZE); + TOTP_CLI_PRINT_ERROR_UPDATING_CONFIG_FILE(); + break; + } + + memset_s(&new_pin[0], TOTP_IV_SIZE, 0, TOTP_IV_SIZE); TOTP_LIST_FOREACH(plugin_state->tokens_list, node, { TokenInfo* token_info = node->data; @@ -152,15 +158,18 @@ void totp_cli_command_pin_handle(PluginState* plugin_state, FuriString* args, Cl free(plain_token); }); - totp_full_save_config_file(plugin_state); - TOTP_CLI_DELETE_LAST_LINE(); - if(do_change) { - TOTP_CLI_PRINTF("PIN has been successfully changed\r\n"); - } else if(do_remove) { - TOTP_CLI_PRINTF("PIN has been successfully removed\r\n"); + if(totp_full_save_config_file(plugin_state) == TotpConfigFileUpdateSuccess) { + if(do_change) { + TOTP_CLI_PRINTF("PIN has been successfully changed\r\n"); + } else if(do_remove) { + TOTP_CLI_PRINTF("PIN has been successfully removed\r\n"); + } + } else { + TOTP_CLI_PRINT_ERROR_UPDATING_CONFIG_FILE(); } + } while(false); if(load_generate_token_scene) { diff --git a/applications/plugins/totp/cli/commands/timezone/timezone.c b/applications/plugins/totp/cli/commands/timezone/timezone.c index 7a17c1ae2..537cf8a4a 100644 --- a/applications/plugins/totp/cli/commands/timezone/timezone.c +++ b/applications/plugins/totp/cli/commands/timezone/timezone.c @@ -33,8 +33,11 @@ void totp_cli_command_timezone_handle(PluginState* plugin_state, FuriString* arg float tz = strtof(furi_string_get_cstr(temp_str), NULL); if(tz >= -12.75f && tz <= 12.75f) { plugin_state->timezone_offset = tz; - totp_config_file_update_timezone_offset(tz); - TOTP_CLI_PRINTF("Timezone is set to %f\r\n", tz); + if(totp_config_file_update_timezone_offset(tz) == TotpConfigFileUpdateSuccess) { + TOTP_CLI_PRINTF("Timezone is set to %f\r\n", tz); + } else { + TOTP_CLI_PRINT_ERROR_UPDATING_CONFIG_FILE(); + } if(plugin_state->current_scene == TotpSceneGenerateToken) { totp_scene_director_activate_scene(plugin_state, TotpSceneNone, NULL); totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL); diff --git a/applications/plugins/totp/services/config/config.c b/applications/plugins/totp/services/config/config.c index ff7e4eb2d..b9f0e9d50 100644 --- a/applications/plugins/totp/services/config/config.c +++ b/applications/plugins/totp/services/config/config.c @@ -6,9 +6,12 @@ #include "../../types/token_info.h" #include "migrations/config_migration_v1_to_v2.h" -#define CONFIG_FILE_DIRECTORY_PATH "/ext/apps/Misc" +#define CONFIG_FILE_DIRECTORY_PATH EXT_PATH("authenticator") #define CONFIG_FILE_PATH CONFIG_FILE_DIRECTORY_PATH "/totp.conf" #define CONFIG_FILE_BACKUP_PATH CONFIG_FILE_PATH ".backup" +#define CONFIG_FILE_TEMP_PATH CONFIG_FILE_PATH ".tmp" +#define CONFIG_FILE_ORIG_PATH CONFIG_FILE_PATH ".orig" +#define CONFIG_FILE_PATH_PREVIOUS EXT_PATH("apps/Misc") "/totp.conf" static char* token_info_get_algo_as_cstr(const TokenInfo* token_info) { switch(token_info->algo) { @@ -35,15 +38,38 @@ static void token_info_set_algo_from_str(TokenInfo* token_info, const FuriString } } -Storage* totp_open_storage() { +/** + * @brief Opens storage record + * @return Storage record + */ +static Storage* totp_open_storage() { return furi_record_open(RECORD_STORAGE); } -void totp_close_storage() { +/** + * @brief Closes storage record + */ +static void totp_close_storage() { furi_record_close(RECORD_STORAGE); } -FlipperFormat* totp_open_config_file(Storage* storage) { +/** + * @brief Closes config file + * @param file config file reference + */ +static void totp_close_config_file(FlipperFormat* file) { + if(file == NULL) return; + flipper_format_file_close(file); + flipper_format_free(file); +} + +/** + * @brief Opens or creates TOTP application standard config file + * @param storage storage record to use + * @param[out] file opened config file + * @return Config file open result + */ +static TotpConfigFileOpenResult totp_open_config_file(Storage* storage, FlipperFormat** file) { FlipperFormat* fff_data_file = flipper_format_file_alloc(storage); if(storage_common_stat(storage, CONFIG_FILE_PATH, NULL) == FSE_OK) { @@ -51,8 +77,28 @@ FlipperFormat* totp_open_config_file(Storage* storage) { if(!flipper_format_file_open_existing(fff_data_file, CONFIG_FILE_PATH)) { FURI_LOG_E(LOGGING_TAG, "Error opening existing file %s", CONFIG_FILE_PATH); totp_close_config_file(fff_data_file); - return NULL; + return TotpConfigFileOpenError; } + } else if(storage_common_stat(storage, CONFIG_FILE_PATH_PREVIOUS, NULL) == FSE_OK) { + FURI_LOG_D(LOGGING_TAG, "Old config file %s found", CONFIG_FILE_PATH_PREVIOUS); + if(storage_common_stat(storage, CONFIG_FILE_DIRECTORY_PATH, NULL) == FSE_NOT_EXIST) { + FURI_LOG_D( + LOGGING_TAG, + "Directory %s doesn't exist. Will create new.", + CONFIG_FILE_DIRECTORY_PATH); + if(!storage_simply_mkdir(storage, CONFIG_FILE_DIRECTORY_PATH)) { + FURI_LOG_E(LOGGING_TAG, "Error creating directory %s", CONFIG_FILE_DIRECTORY_PATH); + totp_close_config_file(fff_data_file); + return TotpConfigFileOpenError; + } + } + if(storage_common_rename(storage, CONFIG_FILE_PATH_PREVIOUS, CONFIG_FILE_PATH) != FSE_OK) { + FURI_LOG_E(LOGGING_TAG, "Error moving config to %s", CONFIG_FILE_PATH); + totp_close_config_file(fff_data_file); + return TotpConfigFileOpenError; + } + FURI_LOG_I(LOGGING_TAG, "Applied config file path migration"); + return totp_open_config_file(storage, file); } else { FURI_LOG_D(LOGGING_TAG, "Config file %s is not found. Will create new.", CONFIG_FILE_PATH); if(storage_common_stat(storage, CONFIG_FILE_DIRECTORY_PATH, NULL) == FSE_NOT_EXIST) { @@ -62,14 +108,14 @@ FlipperFormat* totp_open_config_file(Storage* storage) { CONFIG_FILE_DIRECTORY_PATH); if(!storage_simply_mkdir(storage, CONFIG_FILE_DIRECTORY_PATH)) { FURI_LOG_E(LOGGING_TAG, "Error creating directory %s", CONFIG_FILE_DIRECTORY_PATH); - return NULL; + return TotpConfigFileOpenError; } } if(!flipper_format_file_open_new(fff_data_file, CONFIG_FILE_PATH)) { totp_close_config_file(fff_data_file); FURI_LOG_E(LOGGING_TAG, "Error creating new file %s", CONFIG_FILE_PATH); - return NULL; + return TotpConfigFileOpenError; } flipper_format_write_header_cstr( @@ -134,228 +180,415 @@ FlipperFormat* totp_open_config_file(Storage* storage) { if(!flipper_format_rewind(fff_data_file)) { totp_close_config_file(fff_data_file); FURI_LOG_E(LOGGING_TAG, "Rewind error"); - return NULL; + return TotpConfigFileOpenError; } } - return fff_data_file; + *file = fff_data_file; + return TotpConfigFileOpenSuccess; } -void totp_config_file_save_new_token_i(FlipperFormat* file, const TokenInfo* token_info) { - flipper_format_seek_to_end(file); - flipper_format_write_string_cstr(file, TOTP_CONFIG_KEY_TOKEN_NAME, token_info->name); - bool token_is_valid = token_info->token != NULL && token_info->token_length > 0; - if(!token_is_valid) { - flipper_format_write_comment_cstr(file, "!!! WARNING BEGIN: INVALID TOKEN !!!"); +TotpConfigFileUpdateResult + totp_config_file_save_new_token_i(FlipperFormat* file, const TokenInfo* token_info) { + TotpConfigFileUpdateResult update_result; + do { + if(!flipper_format_seek_to_end(file)) { + update_result = TotpConfigFileUpdateError; + break; + } + + if(!flipper_format_write_string_cstr(file, TOTP_CONFIG_KEY_TOKEN_NAME, token_info->name)) { + update_result = TotpConfigFileUpdateError; + break; + } + + bool token_is_valid = token_info->token != NULL && token_info->token_length > 0; + if(!token_is_valid && + !flipper_format_write_comment_cstr(file, "!!! WARNING BEGIN: INVALID TOKEN !!!")) { + update_result = TotpConfigFileUpdateError; + break; + } + + if(!flipper_format_write_hex( + file, TOTP_CONFIG_KEY_TOKEN_SECRET, token_info->token, token_info->token_length)) { + update_result = TotpConfigFileUpdateError; + break; + } + + if(!token_is_valid && !flipper_format_write_comment_cstr(file, "!!! WARNING END !!!")) { + update_result = TotpConfigFileUpdateError; + break; + } + + if(!flipper_format_write_string_cstr( + file, TOTP_CONFIG_KEY_TOKEN_ALGO, token_info_get_algo_as_cstr(token_info))) { + update_result = TotpConfigFileUpdateError; + break; + } + + uint32_t tmp_uint32 = token_info->digits; + if(!flipper_format_write_uint32(file, TOTP_CONFIG_KEY_TOKEN_DIGITS, &tmp_uint32, 1)) { + update_result = TotpConfigFileUpdateError; + break; + } + + update_result = TotpConfigFileUpdateSuccess; + } while(false); + + return update_result; +} + +TotpConfigFileUpdateResult totp_config_file_save_new_token(const TokenInfo* token_info) { + Storage* cfg_storage = totp_open_storage(); + FlipperFormat* file; + TotpConfigFileUpdateResult update_result; + + if(totp_open_config_file(cfg_storage, &file) == TotpConfigFileOpenSuccess) { + do { + if(totp_config_file_save_new_token_i(file, token_info) != + TotpConfigFileUpdateSuccess) { + update_result = TotpConfigFileUpdateError; + break; + } + + update_result = TotpConfigFileUpdateSuccess; + } while(false); + + totp_close_config_file(file); + } else { + update_result = TotpConfigFileUpdateError; } - flipper_format_write_hex( - file, TOTP_CONFIG_KEY_TOKEN_SECRET, token_info->token, token_info->token_length); - if(!token_is_valid) { - flipper_format_write_comment_cstr(file, "!!! WARNING END !!!"); + + totp_close_storage(); + return update_result; +} + +TotpConfigFileUpdateResult totp_config_file_update_timezone_offset(float new_timezone_offset) { + Storage* cfg_storage = totp_open_storage(); + FlipperFormat* file; + TotpConfigFileUpdateResult update_result; + + if(totp_open_config_file(cfg_storage, &file) == TotpConfigFileOpenSuccess) { + do { + if(!flipper_format_insert_or_update_float( + file, TOTP_CONFIG_KEY_TIMEZONE, &new_timezone_offset, 1)) { + update_result = TotpConfigFileUpdateError; + break; + } + + update_result = TotpConfigFileUpdateSuccess; + } while(false); + + totp_close_config_file(file); + } else { + update_result = TotpConfigFileUpdateError; } - flipper_format_write_string_cstr( - file, TOTP_CONFIG_KEY_TOKEN_ALGO, token_info_get_algo_as_cstr(token_info)); - uint32_t tmp_uint32 = token_info->digits; - flipper_format_write_uint32(file, TOTP_CONFIG_KEY_TOKEN_DIGITS, &tmp_uint32, 1); -} -void totp_config_file_save_new_token(const TokenInfo* token_info) { - Storage* cfg_storage = totp_open_storage(); - FlipperFormat* file = totp_open_config_file(cfg_storage); - - totp_config_file_save_new_token_i(file, token_info); - - totp_close_config_file(file); totp_close_storage(); + return update_result; } -void totp_config_file_update_timezone_offset(float new_timezone_offset) { +TotpConfigFileUpdateResult + totp_config_file_update_notification_method(NotificationMethod new_notification_method) { Storage* cfg_storage = totp_open_storage(); - FlipperFormat* file = totp_open_config_file(cfg_storage); + FlipperFormat* file; + TotpConfigFileUpdateResult update_result; - flipper_format_insert_or_update_float(file, TOTP_CONFIG_KEY_TIMEZONE, &new_timezone_offset, 1); + if(totp_open_config_file(cfg_storage, &file) == TotpConfigFileOpenSuccess) { + do { + uint32_t tmp_uint32 = new_notification_method; + if(!flipper_format_insert_or_update_uint32( + file, TOTP_CONFIG_KEY_NOTIFICATION_METHOD, &tmp_uint32, 1)) { + update_result = TotpConfigFileUpdateError; + break; + } + + update_result = TotpConfigFileUpdateSuccess; + } while(false); + + totp_close_config_file(file); + } else { + update_result = TotpConfigFileUpdateError; + } - totp_close_config_file(file); totp_close_storage(); + return update_result; } -void totp_config_file_update_notification_method(NotificationMethod new_notification_method) { +TotpConfigFileUpdateResult totp_config_file_update_user_settings(const PluginState* plugin_state) { Storage* cfg_storage = totp_open_storage(); - FlipperFormat* file = totp_open_config_file(cfg_storage); + FlipperFormat* file; + TotpConfigFileUpdateResult update_result; + if(totp_open_config_file(cfg_storage, &file) == TotpConfigFileOpenSuccess) { + do { + if(!flipper_format_insert_or_update_float( + file, TOTP_CONFIG_KEY_TIMEZONE, &plugin_state->timezone_offset, 1)) { + update_result = TotpConfigFileUpdateError; + break; + } + uint32_t tmp_uint32 = plugin_state->notification_method; + if(!flipper_format_insert_or_update_uint32( + file, TOTP_CONFIG_KEY_NOTIFICATION_METHOD, &tmp_uint32, 1)) { + update_result = TotpConfigFileUpdateError; + break; + } - uint32_t tmp_uint32 = new_notification_method; - flipper_format_insert_or_update_uint32( - file, TOTP_CONFIG_KEY_NOTIFICATION_METHOD, &tmp_uint32, 1); + update_result = TotpConfigFileUpdateSuccess; + } while(false); + + totp_close_config_file(file); + } else { + update_result = TotpConfigFileUpdateError; + } - totp_close_config_file(file); totp_close_storage(); + return update_result; } -void totp_config_file_update_user_settings(const PluginState* plugin_state) { - Storage* cfg_storage = totp_open_storage(); - FlipperFormat* file = totp_open_config_file(cfg_storage); - - flipper_format_insert_or_update_float( - file, TOTP_CONFIG_KEY_TIMEZONE, &plugin_state->timezone_offset, 1); - uint32_t tmp_uint32 = plugin_state->notification_method; - flipper_format_insert_or_update_uint32( - file, TOTP_CONFIG_KEY_NOTIFICATION_METHOD, &tmp_uint32, 1); - - totp_close_config_file(file); - totp_close_storage(); -} - -void totp_full_save_config_file(const PluginState* const plugin_state) { +TotpConfigFileUpdateResult totp_full_save_config_file(const PluginState* const plugin_state) { Storage* storage = totp_open_storage(); FlipperFormat* fff_data_file = flipper_format_file_alloc(storage); + TotpConfigFileUpdateResult result = TotpConfigFileUpdateSuccess; - flipper_format_file_open_always(fff_data_file, CONFIG_FILE_PATH); - flipper_format_write_header_cstr( - fff_data_file, CONFIG_FILE_HEADER, CONFIG_FILE_ACTUAL_VERSION); - flipper_format_write_hex( - fff_data_file, TOTP_CONFIG_KEY_BASE_IV, &plugin_state->base_iv[0], TOTP_IV_SIZE); - flipper_format_write_hex( - fff_data_file, - TOTP_CONFIG_KEY_CRYPTO_VERIFY, - plugin_state->crypto_verify_data, - plugin_state->crypto_verify_data_length); - flipper_format_write_float( - fff_data_file, TOTP_CONFIG_KEY_TIMEZONE, &plugin_state->timezone_offset, 1); - flipper_format_write_bool(fff_data_file, TOTP_CONFIG_KEY_PINSET, &plugin_state->pin_set, 1); - uint32_t tmp_uint32 = plugin_state->notification_method; - flipper_format_write_uint32( - fff_data_file, TOTP_CONFIG_KEY_NOTIFICATION_METHOD, &tmp_uint32, 1); + do { + if(!flipper_format_file_open_always(fff_data_file, CONFIG_FILE_TEMP_PATH)) { + result = TotpConfigFileUpdateError; + break; + } - TOTP_LIST_FOREACH(plugin_state->tokens_list, node, { - const TokenInfo* token_info = node->data; - totp_config_file_save_new_token_i(fff_data_file, token_info); - }); + if(!flipper_format_write_header_cstr( + fff_data_file, CONFIG_FILE_HEADER, CONFIG_FILE_ACTUAL_VERSION)) { + result = TotpConfigFileUpdateError; + break; + } + + if(!flipper_format_write_hex( + fff_data_file, TOTP_CONFIG_KEY_BASE_IV, &plugin_state->base_iv[0], TOTP_IV_SIZE)) { + result = TotpConfigFileUpdateError; + break; + } + + if(!flipper_format_write_hex( + fff_data_file, + TOTP_CONFIG_KEY_CRYPTO_VERIFY, + plugin_state->crypto_verify_data, + plugin_state->crypto_verify_data_length)) { + result = TotpConfigFileUpdateError; + break; + } + + if(!flipper_format_write_float( + fff_data_file, TOTP_CONFIG_KEY_TIMEZONE, &plugin_state->timezone_offset, 1)) { + result = TotpConfigFileUpdateError; + break; + } + + if(!flipper_format_write_bool( + fff_data_file, TOTP_CONFIG_KEY_PINSET, &plugin_state->pin_set, 1)) { + result = TotpConfigFileUpdateError; + break; + } + uint32_t tmp_uint32 = plugin_state->notification_method; + if(!flipper_format_write_uint32( + fff_data_file, TOTP_CONFIG_KEY_NOTIFICATION_METHOD, &tmp_uint32, 1)) { + result = TotpConfigFileUpdateError; + break; + } + + bool tokens_written = true; + TOTP_LIST_FOREACH(plugin_state->tokens_list, node, { + const TokenInfo* token_info = node->data; + tokens_written = tokens_written && + totp_config_file_save_new_token_i(fff_data_file, token_info) == + TotpConfigFileUpdateSuccess; + }); + + if(!tokens_written) { + result = TotpConfigFileUpdateError; + break; + } + } while(false); totp_close_config_file(fff_data_file); + + if(result == TotpConfigFileUpdateSuccess) { + if(storage_file_exists(storage, CONFIG_FILE_ORIG_PATH)) { + storage_simply_remove(storage, CONFIG_FILE_ORIG_PATH); + } + + if(storage_common_rename(storage, CONFIG_FILE_PATH, CONFIG_FILE_ORIG_PATH) != FSE_OK) { + result = TotpConfigFileUpdateError; + } else if(storage_common_rename(storage, CONFIG_FILE_TEMP_PATH, CONFIG_FILE_PATH) != FSE_OK) { + result = TotpConfigFileUpdateError; + } else if(!storage_simply_remove(storage, CONFIG_FILE_ORIG_PATH)) { + result = TotpConfigFileUpdateError; + } + } + totp_close_storage(); + return result; } -void totp_config_file_load_base(PluginState* const plugin_state) { +TotpConfigFileOpenResult totp_config_file_load_base(PluginState* const plugin_state) { Storage* storage = totp_open_storage(); - FlipperFormat* fff_data_file = totp_open_config_file(storage); + FlipperFormat* fff_data_file; + + TotpConfigFileOpenResult result; + if((result = totp_open_config_file(storage, &fff_data_file)) != TotpConfigFileOpenSuccess) { + totp_close_storage(); + return result; + } plugin_state->timezone_offset = 0; FuriString* temp_str = furi_string_alloc(); - uint32_t file_version; - if(!flipper_format_read_header(fff_data_file, temp_str, &file_version)) { - FURI_LOG_E(LOGGING_TAG, "Missing or incorrect header"); - furi_string_free(temp_str); - return; - } - - if(file_version < CONFIG_FILE_ACTUAL_VERSION) { - FURI_LOG_I( - LOGGING_TAG, - "Obsolete config file version detected. Current version: %" PRIu32 - "; Actual version: %" PRId16, - file_version, - CONFIG_FILE_ACTUAL_VERSION); - totp_close_config_file(fff_data_file); - - if(storage_common_stat(storage, CONFIG_FILE_BACKUP_PATH, NULL) == FSE_OK) { - storage_simply_remove(storage, CONFIG_FILE_BACKUP_PATH); + do { + uint32_t file_version; + if(!flipper_format_read_header(fff_data_file, temp_str, &file_version)) { + FURI_LOG_E(LOGGING_TAG, "Missing or incorrect header"); + result = TotpConfigFileOpenError; + break; } - if(storage_common_copy(storage, CONFIG_FILE_PATH, CONFIG_FILE_BACKUP_PATH) == FSE_OK) { - FURI_LOG_I(LOGGING_TAG, "Took config file backup to %s", CONFIG_FILE_BACKUP_PATH); - fff_data_file = totp_open_config_file(storage); - FlipperFormat* fff_backup_data_file = flipper_format_file_alloc(storage); - flipper_format_file_open_existing(fff_backup_data_file, CONFIG_FILE_BACKUP_PATH); + if(file_version < CONFIG_FILE_ACTUAL_VERSION) { + FURI_LOG_I( + LOGGING_TAG, + "Obsolete config file version detected. Current version: %" PRIu32 + "; Actual version: %" PRId16, + file_version, + CONFIG_FILE_ACTUAL_VERSION); + totp_close_config_file(fff_data_file); - if(file_version == 1) { - if(totp_config_migrate_v1_to_v2(fff_data_file, fff_backup_data_file)) { - FURI_LOG_I(LOGGING_TAG, "Applied migration from v1 to v2"); - } else { - FURI_LOG_W(LOGGING_TAG, "An error occurred during migration from v1 to v2"); - } + if(storage_common_stat(storage, CONFIG_FILE_BACKUP_PATH, NULL) == FSE_OK) { + storage_simply_remove(storage, CONFIG_FILE_BACKUP_PATH); } - flipper_format_file_close(fff_backup_data_file); - flipper_format_free(fff_backup_data_file); - flipper_format_rewind(fff_data_file); - } else { - FURI_LOG_E( - LOGGING_TAG, - "An error occurred during taking backup of %s into %s before migration", - CONFIG_FILE_PATH, - CONFIG_FILE_BACKUP_PATH); + if(storage_common_copy(storage, CONFIG_FILE_PATH, CONFIG_FILE_BACKUP_PATH) == FSE_OK) { + FURI_LOG_I(LOGGING_TAG, "Took config file backup to %s", CONFIG_FILE_BACKUP_PATH); + if(totp_open_config_file(storage, &fff_data_file) != TotpConfigFileOpenSuccess) { + result = TotpConfigFileOpenError; + break; + } + + FlipperFormat* fff_backup_data_file = flipper_format_file_alloc(storage); + if(!flipper_format_file_open_existing( + fff_backup_data_file, CONFIG_FILE_BACKUP_PATH)) { + flipper_format_file_close(fff_backup_data_file); + flipper_format_free(fff_backup_data_file); + result = TotpConfigFileOpenError; + break; + } + + if(file_version == 1) { + if(totp_config_migrate_v1_to_v2(fff_data_file, fff_backup_data_file)) { + FURI_LOG_I(LOGGING_TAG, "Applied migration from v1 to v2"); + } else { + FURI_LOG_W( + LOGGING_TAG, "An error occurred during migration from v1 to v2"); + result = TotpConfigFileOpenError; + break; + } + } + + flipper_format_file_close(fff_backup_data_file); + flipper_format_free(fff_backup_data_file); + flipper_format_rewind(fff_data_file); + } else { + FURI_LOG_E( + LOGGING_TAG, + "An error occurred during taking backup of %s into %s before migration", + CONFIG_FILE_PATH, + CONFIG_FILE_BACKUP_PATH); + result = TotpConfigFileOpenError; + break; + } } - } - if(!flipper_format_read_hex( - fff_data_file, TOTP_CONFIG_KEY_BASE_IV, &plugin_state->base_iv[0], TOTP_IV_SIZE)) { - FURI_LOG_D(LOGGING_TAG, "Missing base IV"); - } - - flipper_format_rewind(fff_data_file); - - uint32_t crypto_size; - if(flipper_format_get_value_count(fff_data_file, TOTP_CONFIG_KEY_CRYPTO_VERIFY, &crypto_size) && - crypto_size > 0) { - plugin_state->crypto_verify_data = malloc(sizeof(uint8_t) * crypto_size); - furi_check(plugin_state->crypto_verify_data != NULL); - plugin_state->crypto_verify_data_length = crypto_size; if(!flipper_format_read_hex( - fff_data_file, - TOTP_CONFIG_KEY_CRYPTO_VERIFY, - plugin_state->crypto_verify_data, - crypto_size)) { - FURI_LOG_D(LOGGING_TAG, "Missing crypto verify token"); - free(plugin_state->crypto_verify_data); + fff_data_file, TOTP_CONFIG_KEY_BASE_IV, &plugin_state->base_iv[0], TOTP_IV_SIZE)) { + FURI_LOG_D(LOGGING_TAG, "Missing base IV"); + } + + if(!flipper_format_rewind(fff_data_file)) { + result = TotpConfigFileOpenError; + break; + } + + uint32_t crypto_size; + if(flipper_format_get_value_count( + fff_data_file, TOTP_CONFIG_KEY_CRYPTO_VERIFY, &crypto_size) && + crypto_size > 0) { + plugin_state->crypto_verify_data = malloc(sizeof(uint8_t) * crypto_size); + furi_check(plugin_state->crypto_verify_data != NULL); + plugin_state->crypto_verify_data_length = crypto_size; + if(!flipper_format_read_hex( + fff_data_file, + TOTP_CONFIG_KEY_CRYPTO_VERIFY, + plugin_state->crypto_verify_data, + crypto_size)) { + FURI_LOG_D(LOGGING_TAG, "Missing crypto verify token"); + free(plugin_state->crypto_verify_data); + plugin_state->crypto_verify_data = NULL; + plugin_state->crypto_verify_data_length = 0; + } + } else { plugin_state->crypto_verify_data = NULL; plugin_state->crypto_verify_data_length = 0; } - } else { - plugin_state->crypto_verify_data = NULL; - plugin_state->crypto_verify_data_length = 0; - } - flipper_format_rewind(fff_data_file); + if(!flipper_format_rewind(fff_data_file)) { + result = TotpConfigFileOpenError; + break; + } - if(!flipper_format_read_float( - fff_data_file, TOTP_CONFIG_KEY_TIMEZONE, &plugin_state->timezone_offset, 1)) { - plugin_state->timezone_offset = 0; - FURI_LOG_D(LOGGING_TAG, "Missing timezone offset information, defaulting to 0"); - } + if(!flipper_format_read_float( + fff_data_file, TOTP_CONFIG_KEY_TIMEZONE, &plugin_state->timezone_offset, 1)) { + plugin_state->timezone_offset = 0; + FURI_LOG_D(LOGGING_TAG, "Missing timezone offset information, defaulting to 0"); + } - flipper_format_rewind(fff_data_file); + if(!flipper_format_rewind(fff_data_file)) { + result = TotpConfigFileOpenError; + break; + } - if(!flipper_format_read_bool( - fff_data_file, TOTP_CONFIG_KEY_PINSET, &plugin_state->pin_set, 1)) { - plugin_state->pin_set = true; - } + if(!flipper_format_read_bool( + fff_data_file, TOTP_CONFIG_KEY_PINSET, &plugin_state->pin_set, 1)) { + plugin_state->pin_set = true; + } - flipper_format_rewind(fff_data_file); + flipper_format_rewind(fff_data_file); - uint32_t tmp_uint32; - if(!flipper_format_read_uint32( - fff_data_file, TOTP_CONFIG_KEY_NOTIFICATION_METHOD, &tmp_uint32, 1)) { - tmp_uint32 = NotificationMethodSound | NotificationMethodVibro; - } + uint32_t tmp_uint32; + if(!flipper_format_read_uint32( + fff_data_file, TOTP_CONFIG_KEY_NOTIFICATION_METHOD, &tmp_uint32, 1)) { + tmp_uint32 = NotificationMethodSound | NotificationMethodVibro; + } - plugin_state->notification_method = tmp_uint32; + plugin_state->notification_method = tmp_uint32; + } while(false); furi_string_free(temp_str); totp_close_config_file(fff_data_file); totp_close_storage(); + return result; } TokenLoadingResult totp_config_file_load_tokens(PluginState* const plugin_state) { Storage* storage = totp_open_storage(); - FlipperFormat* fff_data_file = totp_open_config_file(storage); + FlipperFormat* fff_data_file; + if(totp_open_config_file(storage, &fff_data_file) != TotpConfigFileOpenSuccess) { + totp_close_storage(); + return TokenLoadingResultError; + } FuriString* temp_str = furi_string_alloc(); uint32_t temp_data32; if(!flipper_format_read_header(fff_data_file, temp_str, &temp_data32)) { FURI_LOG_E(LOGGING_TAG, "Missing or incorrect header"); + totp_close_storage(); furi_string_free(temp_str); return TokenLoadingResultError; } @@ -459,8 +692,42 @@ TokenLoadingResult totp_config_file_load_tokens(PluginState* const plugin_state) return result; } -void totp_close_config_file(FlipperFormat* file) { - if(file == NULL) return; - flipper_format_file_close(file); - flipper_format_free(file); -} +TotpConfigFileUpdateResult + totp_config_file_update_crypto_signatures(const PluginState* plugin_state) { + Storage* storage = totp_open_storage(); + FlipperFormat* config_file; + TotpConfigFileUpdateResult update_result; + if(totp_open_config_file(storage, &config_file) == TotpConfigFileOpenSuccess) { + do { + if(!flipper_format_insert_or_update_hex( + config_file, TOTP_CONFIG_KEY_BASE_IV, plugin_state->base_iv, TOTP_IV_SIZE)) { + update_result = TotpConfigFileUpdateError; + break; + } + + if(!flipper_format_insert_or_update_hex( + config_file, + TOTP_CONFIG_KEY_CRYPTO_VERIFY, + plugin_state->crypto_verify_data, + plugin_state->crypto_verify_data_length)) { + update_result = TotpConfigFileUpdateError; + break; + } + + if(!flipper_format_insert_or_update_bool( + config_file, TOTP_CONFIG_KEY_PINSET, &plugin_state->pin_set, 1)) { + update_result = TotpConfigFileUpdateError; + break; + } + + update_result = TotpConfigFileUpdateSuccess; + } while(false); + + totp_close_config_file(config_file); + } else { + update_result = TotpConfigFileUpdateError; + } + + totp_close_storage(); + return update_result; +} \ No newline at end of file diff --git a/applications/plugins/totp/services/config/config.h b/applications/plugins/totp/services/config/config.h index 1eabe3365..bb48105f7 100644 --- a/applications/plugins/totp/services/config/config.h +++ b/applications/plugins/totp/services/config/config.h @@ -7,6 +7,8 @@ #include "constants.h" typedef uint8_t TokenLoadingResult; +typedef uint8_t TotpConfigFileOpenResult; +typedef uint8_t TotpConfigFileUpdateResult; /** * @brief Token loading results @@ -29,40 +31,48 @@ enum TokenLoadingResults { }; /** - * @brief Opens storage record - * @return Storage record + * @brief Config file opening result */ -Storage* totp_open_storage(); +enum TotpConfigFileOpenResults { + /** + * @brief Config file opened successfully + */ + TotpConfigFileOpenSuccess = 0, + + /** + * @brief An error has occurred during opening config file + */ + TotpConfigFileOpenError = 1 +}; /** - * @brief Closes storage record + * @brief Config file updating result */ -void totp_close_storage(); +enum TotpConfigFileUpdateResults { + /** + * @brief Config file updated successfully + */ + TotpConfigFileUpdateSuccess, -/** - * @brief Opens or creates TOTP application standard config file - * @param storage storage record to use - * @return Config file reference - */ -FlipperFormat* totp_open_config_file(Storage* storage); - -/** - * @brief Closes config file - * @param file config file reference - */ -void totp_close_config_file(FlipperFormat* file); + /** + * @brief An error has occurred during updating config file + */ + TotpConfigFileUpdateError +}; /** * @brief Saves all the settings and tokens to an application config file * @param plugin_state application state + * @return Config file update result */ -void totp_full_save_config_file(const PluginState* const plugin_state); +TotpConfigFileUpdateResult totp_full_save_config_file(const PluginState* const plugin_state); /** * @brief Loads basic information from an application config file into application state without loading all the tokens * @param plugin_state application state + * @return Config file open result */ -void totp_config_file_load_base(PluginState* const plugin_state); +TotpConfigFileOpenResult totp_config_file_load_base(PluginState* const plugin_state); /** * @brief Loads tokens from an application config file into application state @@ -74,23 +84,36 @@ TokenLoadingResult totp_config_file_load_tokens(PluginState* const plugin_state) /** * @brief Add new token to the end of the application config file * @param token_info token information to be saved + * @return Config file update result */ -void totp_config_file_save_new_token(const TokenInfo* token_info); +TotpConfigFileUpdateResult totp_config_file_save_new_token(const TokenInfo* token_info); /** * @brief Updates timezone offset in an application config file * @param new_timezone_offset new timezone offset to be set + * @return Config file update result */ -void totp_config_file_update_timezone_offset(float new_timezone_offset); +TotpConfigFileUpdateResult totp_config_file_update_timezone_offset(float new_timezone_offset); /** * @brief Updates notification method in an application config file * @param new_notification_method new notification method to be set + * @return Config file update result */ -void totp_config_file_update_notification_method(NotificationMethod new_notification_method); +TotpConfigFileUpdateResult + totp_config_file_update_notification_method(NotificationMethod new_notification_method); /** * @brief Updates application user settings * @param plugin_state application state + * @return Config file update result */ -void totp_config_file_update_user_settings(const PluginState* plugin_state); \ No newline at end of file +TotpConfigFileUpdateResult totp_config_file_update_user_settings(const PluginState* plugin_state); + +/** + * @brief Updates crypto signatures information + * @param plugin_state application state + * @return Config file update result + */ +TotpConfigFileUpdateResult + totp_config_file_update_crypto_signatures(const PluginState* plugin_state); \ No newline at end of file diff --git a/applications/plugins/totp/services/crypto/crypto.c b/applications/plugins/totp/services/crypto/crypto.c index 794d0b0be..ed4775dfb 100644 --- a/applications/plugins/totp/services/crypto/crypto.c +++ b/applications/plugins/totp/services/crypto/crypto.c @@ -61,7 +61,7 @@ uint8_t* totp_crypto_decrypt( return decrypted_data; } -void totp_crypto_seed_iv(PluginState* plugin_state, const uint8_t* pin, uint8_t pin_length) { +bool totp_crypto_seed_iv(PluginState* plugin_state, const uint8_t* pin, uint8_t pin_length) { if(plugin_state->crypto_verify_data == NULL) { FURI_LOG_D(LOGGING_TAG, "Generating new IV"); furi_hal_random_fill_buf(&plugin_state->base_iv[0], TOTP_IV_SIZE); @@ -94,13 +94,12 @@ void totp_crypto_seed_iv(PluginState* plugin_state, const uint8_t* pin, uint8_t } } + bool result = true; if(plugin_state->crypto_verify_data == NULL) { FURI_LOG_D(LOGGING_TAG, "Generating crypto verify data"); plugin_state->crypto_verify_data = malloc(CRYPTO_VERIFY_KEY_LENGTH); furi_check(plugin_state->crypto_verify_data != NULL); plugin_state->crypto_verify_data_length = CRYPTO_VERIFY_KEY_LENGTH; - Storage* storage = totp_open_storage(); - FlipperFormat* config_file = totp_open_config_file(storage); plugin_state->crypto_verify_data = totp_crypto_encrypt( (uint8_t*)CRYPTO_VERIFY_KEY, @@ -108,19 +107,13 @@ void totp_crypto_seed_iv(PluginState* plugin_state, const uint8_t* pin, uint8_t &plugin_state->iv[0], &plugin_state->crypto_verify_data_length); - flipper_format_insert_or_update_hex( - config_file, TOTP_CONFIG_KEY_BASE_IV, plugin_state->base_iv, TOTP_IV_SIZE); - flipper_format_insert_or_update_hex( - config_file, - TOTP_CONFIG_KEY_CRYPTO_VERIFY, - plugin_state->crypto_verify_data, - CRYPTO_VERIFY_KEY_LENGTH); plugin_state->pin_set = pin != NULL && pin_length > 0; - flipper_format_insert_or_update_bool( - config_file, TOTP_CONFIG_KEY_PINSET, &plugin_state->pin_set, 1); - totp_close_config_file(config_file); - totp_close_storage(); + + result = totp_config_file_update_crypto_signatures(plugin_state) == + TotpConfigFileUpdateSuccess; } + + return result; } bool totp_crypto_verify_key(const PluginState* plugin_state) { diff --git a/applications/plugins/totp/services/crypto/crypto.h b/applications/plugins/totp/services/crypto/crypto.h index d39fe013b..3442b9a6e 100644 --- a/applications/plugins/totp/services/crypto/crypto.h +++ b/applications/plugins/totp/services/crypto/crypto.h @@ -35,8 +35,9 @@ uint8_t* totp_crypto_decrypt( * @param plugin_state application state * @param pin user's PIN * @param pin_length user's PIN length + * @return \c true on success; \c false otherwise */ -void totp_crypto_seed_iv(PluginState* plugin_state, const uint8_t* pin, uint8_t pin_length); +bool totp_crypto_seed_iv(PluginState* plugin_state, const uint8_t* pin, uint8_t pin_length); /** * @brief Verifies whether cryptographic information (certificate + IV) is valid and can be used for encryption and decryption diff --git a/applications/plugins/totp/services/hmac/memxor.c b/applications/plugins/totp/services/hmac/memxor.c index 6824ea33b..ab6026aa3 100644 --- a/applications/plugins/totp/services/hmac/memxor.c +++ b/applications/plugins/totp/services/hmac/memxor.c @@ -18,8 +18,6 @@ /* Written by Simon Josefsson. The interface was inspired by memxor in Niels Möller's Nettle. */ -/* #include */ - #include "memxor.h" void* memxor(void* /*restrict*/ dest, const void* /*restrict*/ src, size_t n) { diff --git a/applications/plugins/totp/totp_app.c b/applications/plugins/totp/totp_app.c index 5a551c4f1..93acf8e4d 100644 --- a/applications/plugins/totp/totp_app.c +++ b/applications/plugins/totp/totp_app.c @@ -15,6 +15,7 @@ #include "types/common.h" #include "ui/scene_director.h" #include "ui/constants.h" +#include "ui/common_dialogs.h" #include "services/crypto/crypto.h" #include "cli/cli.h" @@ -36,17 +37,7 @@ static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queu furi_message_queue_put(event_queue, &event, FuriWaitForever); } -static bool totp_plugin_state_init(PluginState* const plugin_state) { - plugin_state->gui = furi_record_open(RECORD_GUI); - plugin_state->notification_app = furi_record_open(RECORD_NOTIFICATION); - plugin_state->dialogs_app = furi_record_open(RECORD_DIALOGS); - - totp_config_file_load_base(plugin_state); - - totp_cli_register_command_handler(plugin_state); - - totp_scene_director_init_scenes(plugin_state); - +static bool totp_activate_initial_scene(PluginState* const plugin_state) { if(plugin_state->crypto_verify_data == NULL) { DialogMessage* message = dialog_message_alloc(); dialog_message_set_buttons(message, "No", NULL, "Yes"); @@ -63,13 +54,19 @@ static bool totp_plugin_state_init(PluginState* const plugin_state) { if(dialog_result == DialogMessageButtonRight) { totp_scene_director_activate_scene(plugin_state, TotpSceneAuthentication, NULL); } else { - totp_crypto_seed_iv(plugin_state, NULL, 0); + if(!totp_crypto_seed_iv(plugin_state, NULL, 0)) { + totp_dialogs_config_loading_error(plugin_state); + return false; + } totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL); } } else if(plugin_state->pin_set) { totp_scene_director_activate_scene(plugin_state, TotpSceneAuthentication, NULL); } else { - totp_crypto_seed_iv(plugin_state, NULL, 0); + if(!totp_crypto_seed_iv(plugin_state, NULL, 0)) { + totp_dialogs_config_loading_error(plugin_state); + return false; + } if(totp_crypto_verify_key(plugin_state)) { totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL); } else { @@ -94,13 +91,20 @@ static bool totp_plugin_state_init(PluginState* const plugin_state) { return true; } +static bool totp_plugin_state_init(PluginState* const plugin_state) { + plugin_state->gui = furi_record_open(RECORD_GUI); + plugin_state->notification_app = furi_record_open(RECORD_NOTIFICATION); + plugin_state->dialogs_app = furi_record_open(RECORD_DIALOGS); + + if(totp_config_file_load_base(plugin_state) != TotpConfigFileOpenSuccess) { + totp_dialogs_config_loading_error(plugin_state); + return false; + } + + return true; +} + static void totp_plugin_state_free(PluginState* plugin_state) { - totp_cli_unregister_command_handler(); - - totp_scene_director_deactivate_active_scene(plugin_state); - - totp_scene_director_dispose(plugin_state); - furi_record_close(RECORD_GUI); furi_record_close(RECORD_NOTIFICATION); furi_record_close(RECORD_DIALOGS); @@ -139,6 +143,14 @@ int32_t totp_app() { return 255; } + totp_cli_register_command_handler(plugin_state); + totp_scene_director_init_scenes(plugin_state); + if(!totp_activate_initial_scene(plugin_state)) { + FURI_LOG_E(LOGGING_TAG, "An error ocurred during activating initial scene\r\n"); + totp_plugin_state_free(plugin_state); + return 253; + } + // Set system callbacks ViewPort* view_port = view_port_alloc(); view_port_draw_callback_set(view_port, render_callback, &state_mutex); @@ -171,6 +183,10 @@ int32_t totp_app() { release_mutex(&state_mutex, plugin_state_m); } + totp_cli_unregister_command_handler(); + totp_scene_director_deactivate_active_scene(plugin_state); + totp_scene_director_dispose(plugin_state); + view_port_enabled_set(view_port, false); gui_remove_view_port(plugin_state->gui, view_port); view_port_free(view_port); diff --git a/applications/plugins/totp/ui/common_dialogs.c b/applications/plugins/totp/ui/common_dialogs.c new file mode 100644 index 000000000..0a10389e1 --- /dev/null +++ b/applications/plugins/totp/ui/common_dialogs.c @@ -0,0 +1,20 @@ +#include "common_dialogs.h" +#include "constants.h" + +static DialogMessageButton totp_dialogs_common(PluginState* plugin_state, const char* text) { + DialogMessage* message = dialog_message_alloc(); + dialog_message_set_buttons(message, "Exit", NULL, NULL); + dialog_message_set_text( + message, text, SCREEN_WIDTH_CENTER, SCREEN_HEIGHT_CENTER, AlignCenter, AlignCenter); + DialogMessageButton result = dialog_message_show(plugin_state->dialogs_app, message); + dialog_message_free(message); + return result; +} + +DialogMessageButton totp_dialogs_config_loading_error(PluginState* plugin_state) { + return totp_dialogs_common(plugin_state, "An error has occurred\nduring loading config file"); +} + +DialogMessageButton totp_dialogs_config_updating_error(PluginState* plugin_state) { + return totp_dialogs_common(plugin_state, "An error has occurred\nduring updating config file"); +} \ No newline at end of file diff --git a/applications/plugins/totp/ui/common_dialogs.h b/applications/plugins/totp/ui/common_dialogs.h new file mode 100644 index 000000000..187d0e95c --- /dev/null +++ b/applications/plugins/totp/ui/common_dialogs.h @@ -0,0 +1,7 @@ +#pragma once + +#include +#include "../types/plugin_state.h" + +DialogMessageButton totp_dialogs_config_loading_error(PluginState* plugin_state); +DialogMessageButton totp_dialogs_config_updating_error(PluginState* plugin_state); \ No newline at end of file diff --git a/applications/plugins/totp/ui/scenes/add_new_token/totp_scene_add_new_token.c b/applications/plugins/totp/ui/scenes/add_new_token/totp_scene_add_new_token.c index e6351010e..592a12d0f 100644 --- a/applications/plugins/totp/ui/scenes/add_new_token/totp_scene_add_new_token.c +++ b/applications/plugins/totp/ui/scenes/add_new_token/totp_scene_add_new_token.c @@ -7,6 +7,7 @@ #include "../../../lib/list/list.h" #include "../../../services/config/config.h" #include "../../ui_controls.h" +#include "../../common_dialogs.h" #include "../../../lib/roll_value/roll_value.h" #include "../../../types/nullable.h" #include "../generate_token/totp_scene_generate_token.h" @@ -248,7 +249,11 @@ bool totp_scene_add_new_token_handle_event(PluginEvent* const event, PluginState TOTP_LIST_INIT_OR_ADD(plugin_state->tokens_list, tokenInfo, furi_check); plugin_state->tokens_count++; - totp_config_file_save_new_token(tokenInfo); + if(totp_config_file_save_new_token(tokenInfo) != TotpConfigFileUpdateSuccess) { + token_info_free(tokenInfo); + totp_dialogs_config_updating_error(plugin_state); + return false; + } GenerateTokenSceneContext generate_scene_context = { .current_token_index = plugin_state->tokens_count - 1}; diff --git a/applications/plugins/totp/ui/scenes/app_settings/totp_app_settings.c b/applications/plugins/totp/ui/scenes/app_settings/totp_app_settings.c index 5f68c6772..b8936f395 100644 --- a/applications/plugins/totp/ui/scenes/app_settings/totp_app_settings.c +++ b/applications/plugins/totp/ui/scenes/app_settings/totp_app_settings.c @@ -2,6 +2,7 @@ #include #include #include "../../ui_controls.h" +#include "../../common_dialogs.h" #include "../../scene_director.h" #include "../token_menu/totp_scene_token_menu.h" #include "../../constants.h" @@ -202,7 +203,12 @@ bool totp_scene_app_settings_handle_event( NotificationMethodNone) | (scene_state->notification_vibro ? NotificationMethodVibro : NotificationMethodNone); - totp_config_file_update_user_settings(plugin_state); + + if(totp_config_file_update_user_settings(plugin_state) != + TotpConfigFileUpdateSuccess) { + totp_dialogs_config_updating_error(plugin_state); + return false; + } if(!scene_state->current_token_index.is_null) { TokenMenuSceneContext generate_scene_context = { diff --git a/applications/plugins/totp/ui/scenes/generate_token/totp_scene_generate_token.c b/applications/plugins/totp/ui/scenes/generate_token/totp_scene_generate_token.c index c90cc6b23..157a7192f 100644 --- a/applications/plugins/totp/ui/scenes/generate_token/totp_scene_generate_token.c +++ b/applications/plugins/totp/ui/scenes/generate_token/totp_scene_generate_token.c @@ -128,7 +128,7 @@ static void int_token_to_str(uint32_t i_token_code, char* str, TokenDigitsCount str[len] = '\0'; } -TOTP_ALGO get_totp_algo_impl(TokenHashAlgo algo) { +static TOTP_ALGO get_totp_algo_impl(TokenHashAlgo algo) { switch(algo) { case SHA1: return TOTP_ALGO_SHA1; @@ -143,7 +143,7 @@ TOTP_ALGO get_totp_algo_impl(TokenHashAlgo algo) { return NULL; } -void update_totp_params(PluginState* const plugin_state) { +static void update_totp_params(PluginState* const plugin_state) { SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; if(scene_state->current_token_index < plugin_state->tokens_count) { diff --git a/applications/plugins/totp/ui/scenes/token_menu/totp_scene_token_menu.c b/applications/plugins/totp/ui/scenes/token_menu/totp_scene_token_menu.c index dc713f0a8..167762602 100644 --- a/applications/plugins/totp/ui/scenes/token_menu/totp_scene_token_menu.c +++ b/applications/plugins/totp/ui/scenes/token_menu/totp_scene_token_menu.c @@ -2,6 +2,7 @@ #include #include #include "../../ui_controls.h" +#include "../../common_dialogs.h" #include "../../constants.h" #include "../../scene_director.h" #include "../../../services/config/config.h" @@ -156,7 +157,10 @@ bool totp_scene_token_menu_handle_event(const PluginEvent* const event, PluginSt furi_check(tokenInfo != NULL); token_info_free(tokenInfo); - totp_full_save_config_file(plugin_state); + if(totp_full_save_config_file(plugin_state) != TotpConfigFileUpdateSuccess) { + totp_dialogs_config_updating_error(plugin_state); + return false; + } totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL); } break; From 96f6e77fd223478433b5c01293227af24e1c8115 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Tue, 27 Dec 2022 00:20:00 +0300 Subject: [PATCH 21/34] Fix builds --- .drone.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.drone.yml b/.drone.yml index d46354045..defde9435 100644 --- a/.drone.yml +++ b/.drone.yml @@ -244,8 +244,7 @@ steps: from_secret: dep_port command_timeout: 30s script: - - cd web/unleashedflip.com/public_html/fw/dev - - rm -f ./* + - cd web/unleashedflip.com/public_html/fw/dev && rm -f ./* - name: "Upload default to updates srv" image: appleboy/drone-scp From b21618b4ccc5faa1d85238c95d302135bb07b25c Mon Sep 17 00:00:00 2001 From: amec0e <88857687+amec0e@users.noreply.github.com> Date: Mon, 26 Dec 2022 23:02:33 +0000 Subject: [PATCH 22/34] Updated ac.ir last checked --- assets/resources/infrared/assets/ac.ir | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/resources/infrared/assets/ac.ir b/assets/resources/infrared/assets/ac.ir index a326e748c..8cbba0b63 100644 --- a/assets/resources/infrared/assets/ac.ir +++ b/assets/resources/infrared/assets/ac.ir @@ -1,7 +1,7 @@ Filetype: IR library file Version: 1 # Last Updated 20th Dec, 2022 -# Last Checked 21th Dec, 2022 +# Last Checked 26th Dec, 2022 # # POWER_ON name: POWER From 05293ce86001ef3f3ba93d78bda6e31b715f42f0 Mon Sep 17 00:00:00 2001 From: amec0e <88857687+amec0e@users.noreply.github.com> Date: Mon, 26 Dec 2022 23:03:28 +0000 Subject: [PATCH 23/34] Updated audio.ir --- assets/resources/infrared/assets/audio.ir | 46 ++++++++++++++++++++++- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/assets/resources/infrared/assets/audio.ir b/assets/resources/infrared/assets/audio.ir index 90d6e8d05..7a2d60b92 100644 --- a/assets/resources/infrared/assets/audio.ir +++ b/assets/resources/infrared/assets/audio.ir @@ -1,7 +1,7 @@ Filetype: IR library file Version: 1 -# Last Updated 21th Dec, 2022 -# Last Checked 21th Dec, 2022 +# Last Updated 26th Dec, 2022 +# Last Checked 26th Dec, 2022 # name: POWER type: parsed @@ -1817,3 +1817,45 @@ protocol: RC5 address: 10 00 00 00 command: 0F 00 00 00 # +name: POWER +type: parsed +protocol: NEC +address: 00 00 00 00 +command: 02 00 00 00 +# +name: VOL+ +type: parsed +protocol: NEC +address: 00 00 00 00 +command: 0A 00 00 00 +# +name: VOL- +type: parsed +protocol: NEC +address: 00 00 00 00 +command: 0E 00 00 00 +# +name: MUTE +type: parsed +protocol: Kaseikyo +address: A0 02 20 00 +command: 20 03 00 00 +# +name: POWER +type: parsed +protocol: Kaseikyo +address: AC 02 20 00 +command: D1 03 00 00 +# +name: VOL+ +type: parsed +protocol: Kaseikyo +address: A0 02 20 00 +command: 00 02 00 00 +# +name: VOL- +type: parsed +protocol: Kaseikyo +address: A0 02 20 00 +command: 10 02 00 00 +# From 29ba7956c1a8ce3479381a144a52951397cb84aa Mon Sep 17 00:00:00 2001 From: amec0e <88857687+amec0e@users.noreply.github.com> Date: Mon, 26 Dec 2022 23:03:57 +0000 Subject: [PATCH 24/34] Updated fans.ir last checked --- assets/resources/infrared/assets/fans.ir | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/resources/infrared/assets/fans.ir b/assets/resources/infrared/assets/fans.ir index 16b3a477d..8b3310fb6 100644 --- a/assets/resources/infrared/assets/fans.ir +++ b/assets/resources/infrared/assets/fans.ir @@ -1,7 +1,7 @@ Filetype: IR library file Version: 1 # Last Updated 21th Dec, 2022 -# Last Checked 21th Dec, 2022 +# Last Checked 26th Dec, 2022 # name: POWER type: raw From bce32bf893453f9437280567d22d4c6c600354e4 Mon Sep 17 00:00:00 2001 From: amec0e <88857687+amec0e@users.noreply.github.com> Date: Mon, 26 Dec 2022 23:04:38 +0000 Subject: [PATCH 25/34] Updated projectors.ir --- .../resources/infrared/assets/projectors.ir | 53 ++++++++++++++++++- 1 file changed, 51 insertions(+), 2 deletions(-) diff --git a/assets/resources/infrared/assets/projectors.ir b/assets/resources/infrared/assets/projectors.ir index c089a44bd..f30ee402a 100644 --- a/assets/resources/infrared/assets/projectors.ir +++ b/assets/resources/infrared/assets/projectors.ir @@ -1,7 +1,14 @@ Filetype: IR library file Version: 1 -# Last Updated 21th Dec, 2022 -# Last Checked 21th Dec, 2022 +# Last Updated 26th Dec, 2022 +# Last Checked 26th Dec, 2022 +# +# ON +name: POWER +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 310 27591 171 27662 241 27731 307 27575 107 27749 306 27551 130 55520 243 27614 217 55584 129 27743 119 27756 115 27747 163 27712 308 27502 243 27650 217 27732 175 27693 167 27698 166 27689 171 27622 215 27712 133 27658 216 27716 129 27732 162 27698 305 27571 131 27753 310 27570 170 27707 162 27707 175 10960 9194 4518 618 542 618 543 725 434 672 1623 671 1647 646 514 592 568 592 568 592 1702 592 568 592 567 593 1702 592 568 618 1676 618 1676 618 1676 618 543 617 543 617 543 617 1677 617 544 616 544 616 544 616 544 616 1678 616 1678 616 1678 616 544 616 1678 616 1679 615 1678 616 1678 616 40239 9196 2250 617 # name: VOL + type: parsed @@ -591,4 +598,46 @@ type: raw frequency: 38000 duty_cycle: 0.330000 data: 9093 4441 620 507 618 530 594 531 593 1652 595 1653 620 505 620 505 619 506 617 1630 616 508 616 508 616 1632 615 509 615 1631 616 1632 615 1632 615 510 615 509 615 1632 615 509 615 1632 615 510 615 510 614 509 615 1632 614 1633 614 509 615 1633 614 509 615 1632 615 1632 614 1633 614 510 614 510 615 510 615 510 614 510 614 510 615 510 615 510 614 1632 615 1632 614 1632 615 1632 615 1632 615 1632 615 1632 615 1633 614 14439 9088 2192 614 96349 9112 2190 616 +# OFF +name: POWER +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 243 27700 170 27632 246 27694 282 27595 307 27497 241 27696 177 27710 164 27644 245 27629 246 27712 174 27638 211 27736 131 27741 306 27504 214 27727 135 27749 132 27761 126 27744 131 27753 127 27764 121 27767 132 27773 307 27577 131 27706 213 27761 129 27759 128 27770 125 27694 213 27751 307 27578 131 27737 131 27745 304 27575 335 27540 124 27752 132 27749 132 27747 134 27757 134 27758 127 27762 131 27748 131 27750 122 27749 130 27748 125 27772 131 27774 136 27762 135 27686 215 27742 131 27749 132 27756 133 27764 126 24073 9255 4460 672 488 618 541 619 541 619 1675 619 1676 618 542 618 542 618 542 618 1676 618 542 618 543 617 1678 616 568 592 1702 592 1702 592 1703 617 543 617 543 617 1677 617 543 617 1678 615 544 616 544 616 544 616 1678 616 1679 615 544 616 1679 615 545 615 1679 615 1679 615 1679 615 40240 9173 2273 591 +# +name: VOL+ +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 219 27658 217 27663 216 27658 216 27634 216 27642 215 27646 217 27662 217 27637 216 27649 216 27649 218 27656 217 27658 215 27640 214 27636 217 27649 216 27644 218 27635 217 27630 215 27645 216 27631 215 27632 216 27650 216 27628 217 27630 214 27627 217 27623 215 27632 215 27641 216 27634 214 27633 215 27648 215 27648 217 27651 215 27635 216 27629 216 27630 216 2021 9254 4461 618 542 618 542 618 542 618 1675 619 1676 618 541 619 541 619 542 618 1677 617 543 617 543 617 1678 616 568 592 1702 592 1702 618 1676 618 542 618 542 618 543 617 1677 617 543 617 544 616 1678 616 544 616 1678 616 1678 616 1678 616 544 616 1678 616 1678 616 544 616 1678 616 40239 9200 2247 617 99930 110 27739 119 27738 123 27750 126 27738 175 27617 214 27716 203 27604 213 27639 217 27631 214 27722 136 27753 119 27736 175 27618 246 27683 177 27619 245 27685 171 55486 244 27693 158 27635 241 27695 170 27693 129 27717 340 27530 113 27757 106 27751 124 27728 172 27707 126 27666 215 27708 123 27733 123 +# +name: VOL- +type: parsed +protocol: NECext +address: 18 E9 00 00 +command: 49 B6 00 00 +# +name: POWER +type: parsed +protocol: NEC +address: 02 00 00 00 +command: 14 00 00 00 +# +name: VOL+ +type: parsed +protocol: NEC +address: 02 00 00 00 +command: 48 00 00 00 +# +name: VOL- +type: parsed +protocol: NEC +address: 02 00 00 00 +command: 40 00 00 00 +# +name: MUTE +type: parsed +protocol: NEC +address: 02 00 00 00 +command: 18 00 00 00 # From 3ec517bb548ebcea5d088568a98bfacc2ec51360 Mon Sep 17 00:00:00 2001 From: amec0e <88857687+amec0e@users.noreply.github.com> Date: Mon, 26 Dec 2022 23:05:04 +0000 Subject: [PATCH 26/34] Updated tv.ir last checked --- assets/resources/infrared/assets/tv.ir | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/resources/infrared/assets/tv.ir b/assets/resources/infrared/assets/tv.ir index 98cb13007..a4df4d4c4 100755 --- a/assets/resources/infrared/assets/tv.ir +++ b/assets/resources/infrared/assets/tv.ir @@ -1,7 +1,7 @@ Filetype: IR library file Version: 1 # Last Updated 20th Dec, 2022 -# Last Checked 21th Dec, 2022 +# Last Checked 26th Dec, 2022 # name: POWER type: parsed From 4e347b207ca8136b69a76d18c1ab01fec13ca2ee Mon Sep 17 00:00:00 2001 From: Max Andreev Date: Tue, 27 Dec 2022 10:35:57 +0300 Subject: [PATCH 27/34] Fix amap on forks (#2200) --- .github/workflows/build.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9ca60aee6..4f7233e46 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -87,12 +87,14 @@ jobs: cp build/core2_firmware.tgz "artifacts/flipper-z-any-core2_firmware-${SUFFIX}.tgz" - name: 'Copy map analyser files' + if: ${{ !github.event.pull_request.head.repo.fork }} run: | cp build/f7-firmware-*/firmware.elf.map map_analyser_files/firmware.elf.map cp build/f7-firmware-*/firmware.elf map_analyser_files/firmware.elf cp ${{ github.event_path }} map_analyser_files/event.json - name: 'Upload map analyser files to storage' + if: ${{ !github.event.pull_request.head.repo.fork }} uses: keithweaver/aws-s3-github-action@v1.0.0 with: source: map_analyser_files/ @@ -103,6 +105,7 @@ jobs: flags: --recursive - name: 'Trigger map file reporter' + if: ${{ !github.event.pull_request.head.repo.fork }} uses: peter-evans/repository-dispatch@v2 with: repository: flipperdevices/flipper-map-reporter From 8a279758fd9334adbc18dc1dcaca7485e66ed13d Mon Sep 17 00:00:00 2001 From: Daniel Carvallo Date: Tue, 27 Dec 2022 01:55:25 -0600 Subject: [PATCH 28/34] Fix quoted error for macOS bad-usb (#2155) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add stderr redirect to null device * Remove stderr redirect and replace <`> with <'> Co-authored-by: あく --- assets/resources/badusb/demo_macos.txt | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/assets/resources/badusb/demo_macos.txt b/assets/resources/badusb/demo_macos.txt index 6da305905..3c21a4df8 100644 --- a/assets/resources/badusb/demo_macos.txt +++ b/assets/resources/badusb/demo_macos.txt @@ -34,43 +34,43 @@ ENTER STRING _.-------.._ -, ENTER HOME -STRING .-"```"--..,,_/ /`-, -, \ +STRING .-"'''"--..,,_/ /'-, -, \ ENTER HOME -STRING .:" /:/ /'\ \ ,_..., `. | | +STRING .:" /:/ /'\ \ ,_..., '. | | ENTER HOME -STRING / ,----/:/ /`\ _\~`_-"` _; +STRING / ,----/:/ /'\ _\~'_-"' _; ENTER HOME -STRING ' / /`"""'\ \ \.~`_-' ,-"'/ +STRING ' / /'"""'\ \ \.~'_-' ,-"'/ ENTER HOME -STRING | | | 0 | | .-' ,/` / +STRING | | | 0 | | .-' ,/' / ENTER HOME -STRING | ,..\ \ ,.-"` ,/` / +STRING | ,..\ \ ,.-"' ,/' / ENTER HOME -STRING ; : `/`""\` ,/--==,/-----, +STRING ; : '/'""\' ,/--==,/-----, ENTER HOME -STRING | `-...| -.___-Z:_______J...---; +STRING | '-...| -.___-Z:_______J...---; ENTER HOME -STRING : ` _-' +STRING : ' _-' ENTER HOME -STRING _L_ _ ___ ___ ___ ___ ____--"` +STRING _L_ _ ___ ___ ___ ___ ____--"' ENTER HOME -STRING | __|| | |_ _|| _ \| _ \| __|| _ \ +STRING | __|| | |_ _|| _ \| _ \| __|| _ \ ENTER HOME -STRING | _| | |__ | | | _/| _/| _| | / +STRING | _| | |__ | | | _/| _/| _| | / ENTER HOME -STRING |_| |____||___||_| |_| |___||_|_\ +STRING |_| |____||___||_| |_| |___||_|_\ ENTER HOME ENTER From f43b76efc21bd7cb248d7dc14d232fb6b2617a95 Mon Sep 17 00:00:00 2001 From: Nikolay Minaylov Date: Tue, 27 Dec 2022 11:03:56 +0300 Subject: [PATCH 29/34] [FL-3021] USB/BLE HID Remote icon fix (#2179) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: あく --- .../hid_app/assets/Ble_disconnected_15x15.png | Bin 3632 -> 657 bytes applications/plugins/hid_app/hid.c | 14 +++++++++----- .../plugins/hid_app/views/hid_keyboard.c | 9 ++++++++- .../plugins/hid_app/views/hid_keynote.c | 15 +++++++++++---- .../plugins/hid_app/views/hid_media.c | 15 +++++++++++---- .../plugins/hid_app/views/hid_mouse.c | 15 +++++++++++---- .../plugins/hid_app/views/hid_mouse_jiggler.c | 18 ++++++++++++++---- .../plugins/hid_app/views/hid_tiktok.c | 15 +++++++++++---- 8 files changed, 75 insertions(+), 26 deletions(-) diff --git a/applications/plugins/hid_app/assets/Ble_disconnected_15x15.png b/applications/plugins/hid_app/assets/Ble_disconnected_15x15.png index 0858bb93f43d7cfc81e3f6f3b7540bd1a5e17ebf..bd54646d891976d838ecdf1acb1d05ee1f3ba40c 100644 GIT binary patch delta 392 zcmdlWGm&+IvK<3kfKQ0)|2hUBV0ZLc3#5utBRtc5eHpZXYz_t{MneWBAWIR5)!H)| zSb#Jm5PJYI!{kIB1rs36ynvB`8AvmNq!uv274a`%MzBE|T2IA$1C^Cbp3Nma`3;wj zaD;Dwf^&XRs)CuGfu4bq9hZW_ zN&}yC+C4=^_C}p+7pp(c*RPG+WFRMY!+)9eNuJG762JFz%im^jo_*=zKTt?`y85}S Ib4q9e01jJVn*aa+ delta 3367 zcmZ{iXH?T!x5ob&klv(<2os7lAtCe0D?cPPS0dvV^Gdq3PYXPpn{JZt~Xe)c{)^-T4J6iF(Z5dn$3Y=%UF zeaR$G!Yv#C1WwZI@o4*1LEXLC9fU<(_(Kblod65i4v`SfpDHac&dOsRCtffiVB2!m z$cRy-D?g4QDJeWrz*d3dKHE6+lK7LPsHbuFdk*G9o_dcq?tSSyel@1IQn5{|9bj%| z;m9ymu~iG_C`E{!rGAd;Z10#~f*3@wN%;aiEVUlu{zsA^U_T5Fza-Jj{1yNO4zsfW z%~rY1N*7{JxW6H?uYtnvfto3)nieeK{D47l5~2t&Fb0LwvZU>Sd`7^v*WGOqxU2}c z%22-y1L3s&><|#({7_r~l%EQK`EYS4z)J_H7`SquY6M`E0De!4b}e9B5l}L7^fU#k z>wxBd9`+i5g#%Esjf<887()QpE=kEi;9fSsZ@lFQ|Km~>&x-tMud-|4^-@|!5zZ`% ze$0-J5HZ<)GoefT>eyefIR=o{plo5~2vzRS+aCZRKULuD=cw(Yz<#c({(ki&I@b+F z>bG}HClYRMi^t0Y<-P_0Fi!~^JXV0#o)6by3MU>vxwygTb)7x`_FjT#4Y$E7Ab)kz zaohK2cZ>>B>L(_amzKuO+Y!##9>>sQeCv&7$D><+hQSZ_c0a#ekcv=ti7;W@|J?dv z$FlIkzysEMZqr|qO%ChWPYy+gCECrXZuJ;>{zY3}za&&n;c0RDOhfwV}vP%Q=N+rVA}+rd!w#UDfX)q}p2%JX8dmNB9M@ zt6W7SLN=zaT2$T@`pH04wb|AyCe4=%((3S+^g%2w}83%H^ zkC9Ab5z3C<7jH3Tn7^4`Uil zU=Jf|Y;`|zyh7HOXq>-iOnt)s(SriZNfyk{{YZX!UN=#_VC7@E7x!ec9!mFluI1XAD4qv0{d%7)y-x zxM>Oaf|TmnNmdP3hI_WHG7@Pe7B8jWoc*)?oSQN%7GtU)Im(;N2c`0a#39=?qET_&to2Xa=^&b_zPHr8*_CW%v>jTA%tX%;_ke$*Ik<%?A0* zHvh$q#l{XWySs30pn|wJXL-!+2(@w1=$4fhXdzY1RUB*WwjX-x zGcRWO?LVSev#!V%XKshxpXJ|_TaXheQnjpy;jVd?Wn^Yx%1z5{%T3mr)T`EuX+=#& z4NeCUT!x+IGS{dwCivw3Gqe@^3HzC1wqijmUG3c}NSSw`NI?TC;GIwLMpoY2>*0Bp zq~h72rj;KTLZL_KBjS(ZT@wxrQ!R%S(-cSlIrw`uKN4IN+Bx-yEz+gU09lAl$7aso zORXP-KOHgt&6qop&~a^1YLVDM?0728BrPs&VfD>wBZq2dRbM1mq+_XL+1dA@?@8Zi zwpy+(Y)pA2cO`c$cdpL$YT#7`dI|kC&a7tXYLU|hz0oK7s+LnB#^I_+-x&d|UM&^lo}-opAN?IMY-Wok$PG;@yPsb?>X%Hqx5XLf?e`cBIS9 z89TvME=s*B8s`6!%&&b#dp4*4(T0BL`<;wcC>}GwGcc~QNayR7YbVg`bB9gvLil?B zsO`9fc#FthNTwbnSEOU6t7*xcvg_wEA3U^6%dO3AT`!q>zM;NB*od8e{6Y1xT%MDP z|Hrm2TIaXa)7*Mu{-4xRMu19{nsJ95$ zm{p#2y757yxvs0O*QSk>cO!ZZNtHbDI0-%(1d78ig76IS5rz@YzZ~ob-xYtCq^~`N z`(87#ZkU)~Zzy1x99bE;+)^p-)%ANyrTE@TR)1S|Sx8BYju5ZUK&=%MiLxi%RT`s;s1^ul%(ZzzL5MBlC3@t4gbaSPHzP+y5{)3PeL73ES%6VJ^VA3Q z!WaujMN!O`riz1tHM{LU19W$%KnxuoRyd$o+^hCD2 z0(q~oJFqQBhptVJt-IJ@piXnIus>pGB6P4_}s+ zx7T|Ncn*24ewkIwbLPq@%lwkb)f6gr}pHX#E^=4=HXxOh~h<|HxW5oImWs6IS0;e&Tni!=nam3 zn+-lRnfjIckt*CN$b1{!O_*Gb98SY;4J6XiX`x||Kc`)%p3p;9-23Nla+5aS@KEN5 zj7}0(bQ*Q~uWh}iY}HIH^EpyqJLWvszCrv(`365u8@B0ec+`+nRe#O9ej~W)Rfy-_ zsz{zj|IAKP&>w;)qa%4*x-(7N!KA(Sd%JUjGht+zqyFB8i2#|6%0`>U8#@N;h7-t{ z*b#l_pNEt z)>{Im14K8U&T-o;-33!+PrUwov1|Xa_#jOCYP*w&5bVz&NFdSo6bAsfexNVb z-5W;%yW#KzA6<#fhIbNRf`_hzqneeHl`j(KMKBE}N3Up>!oq10e*0hqk7Y zAwpAA$q1%o41>XpP=;z6nuh8~1WXNyQr9##{D(!6+;02 zPgA3CWWpVshcTH%1pifmHsRmRApiBjzgdreH-q~BtmWU8Ku_&J$sV4kX8hgB1YZh) zRB?gJI%X(Cbl{|$D*!U)aSaE_ z@=3SGMTeU!Bb3gGk6#v(Oa$2`r5Ml|8sHDY__tq7B+si-_MYx@gPVb0vjId3kq`WH O;LMDyQB?@n$o~M7G41{U diff --git a/applications/plugins/hid_app/hid.c b/applications/plugins/hid_app/hid.c index 1d2235e08..7f63f0cc6 100644 --- a/applications/plugins/hid_app/hid.c +++ b/applications/plugins/hid_app/hid.c @@ -42,10 +42,12 @@ static void bt_hid_connection_status_changed_callback(BtStatus status, void* con furi_assert(context); Hid* hid = context; bool connected = (status == BtStatusConnected); - if(connected) { - notification_internal_message(hid->notifications, &sequence_set_blue_255); - } else { - notification_internal_message(hid->notifications, &sequence_reset_blue); + if(hid->transport == HidTransportBle) { + if(connected) { + notification_internal_message(hid->notifications, &sequence_set_blue_255); + } else { + notification_internal_message(hid->notifications, &sequence_reset_blue); + } } hid_keynote_set_connected_status(hid->hid_keynote, connected); hid_keyboard_set_connected_status(hid->hid_keyboard, connected); @@ -186,7 +188,9 @@ void hid_free(Hid* app) { furi_assert(app); // Reset notification - notification_internal_message(app->notifications, &sequence_reset_blue); + if(app->transport == HidTransportBle) { + notification_internal_message(app->notifications, &sequence_reset_blue); + } // Free views view_dispatcher_remove_view(app->view_dispatcher, HidViewSubmenu); diff --git a/applications/plugins/hid_app/views/hid_keyboard.c b/applications/plugins/hid_app/views/hid_keyboard.c index 3e3b63284..8b12e8fd1 100644 --- a/applications/plugins/hid_app/views/hid_keyboard.c +++ b/applications/plugins/hid_app/views/hid_keyboard.c @@ -25,6 +25,7 @@ typedef struct { bool back_pressed; bool connected; char key_string[5]; + HidTransport transport; } HidKeyboardModel; typedef struct { @@ -207,7 +208,7 @@ static void hid_keyboard_draw_callback(Canvas* canvas, void* context) { HidKeyboardModel* model = context; // Header - if(!model->connected) { + if((!model->connected) && (model->transport == HidTransportBle)) { canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15); canvas_set_font(canvas, FontPrimary); elements_multiline_text_aligned(canvas, 17, 3, AlignLeft, AlignTop, "Keyboard"); @@ -361,6 +362,12 @@ HidKeyboard* hid_keyboard_alloc(Hid* bt_hid) { view_set_draw_callback(hid_keyboard->view, hid_keyboard_draw_callback); view_set_input_callback(hid_keyboard->view, hid_keyboard_input_callback); + with_view_model( + hid_keyboard->view, + HidKeyboardModel * model, + { model->transport = bt_hid->transport; }, + true); + return hid_keyboard; } diff --git a/applications/plugins/hid_app/views/hid_keynote.c b/applications/plugins/hid_app/views/hid_keynote.c index c95f42780..5e5eeb790 100644 --- a/applications/plugins/hid_app/views/hid_keynote.c +++ b/applications/plugins/hid_app/views/hid_keynote.c @@ -19,6 +19,7 @@ typedef struct { bool ok_pressed; bool back_pressed; bool connected; + HidTransport transport; } HidKeynoteModel; static void hid_keynote_draw_arrow(Canvas* canvas, uint8_t x, uint8_t y, CanvasDirection dir) { @@ -39,11 +40,14 @@ static void hid_keynote_draw_callback(Canvas* canvas, void* context) { HidKeynoteModel* model = context; // Header - if(model->connected) { - canvas_draw_icon(canvas, 0, 0, &I_Ble_connected_15x15); - } else { - canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15); + if(model->transport == HidTransportBle) { + if(model->connected) { + canvas_draw_icon(canvas, 0, 0, &I_Ble_connected_15x15); + } else { + canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15); + } } + canvas_set_font(canvas, FontPrimary); elements_multiline_text_aligned(canvas, 17, 3, AlignLeft, AlignTop, "Keynote"); @@ -186,6 +190,9 @@ HidKeynote* hid_keynote_alloc(Hid* hid) { view_set_draw_callback(hid_keynote->view, hid_keynote_draw_callback); view_set_input_callback(hid_keynote->view, hid_keynote_input_callback); + with_view_model( + hid_keynote->view, HidKeynoteModel * model, { model->transport = hid->transport; }, true); + return hid_keynote; } diff --git a/applications/plugins/hid_app/views/hid_media.c b/applications/plugins/hid_app/views/hid_media.c index 5d764f73a..468529d56 100644 --- a/applications/plugins/hid_app/views/hid_media.c +++ b/applications/plugins/hid_app/views/hid_media.c @@ -21,6 +21,7 @@ typedef struct { bool down_pressed; bool ok_pressed; bool connected; + HidTransport transport; } HidMediaModel; static void hid_media_draw_arrow(Canvas* canvas, uint8_t x, uint8_t y, CanvasDirection dir) { @@ -41,11 +42,14 @@ static void hid_media_draw_callback(Canvas* canvas, void* context) { HidMediaModel* model = context; // Header - if(model->connected) { - canvas_draw_icon(canvas, 0, 0, &I_Ble_connected_15x15); - } else { - canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15); + if(model->transport == HidTransportBle) { + if(model->connected) { + canvas_draw_icon(canvas, 0, 0, &I_Ble_connected_15x15); + } else { + canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15); + } } + canvas_set_font(canvas, FontPrimary); elements_multiline_text_aligned(canvas, 17, 3, AlignLeft, AlignTop, "Media"); canvas_set_font(canvas, FontSecondary); @@ -190,6 +194,9 @@ HidMedia* hid_media_alloc(Hid* hid) { view_set_draw_callback(hid_media->view, hid_media_draw_callback); view_set_input_callback(hid_media->view, hid_media_input_callback); + with_view_model( + hid_media->view, HidMediaModel * model, { model->transport = hid->transport; }, true); + return hid_media; } diff --git a/applications/plugins/hid_app/views/hid_mouse.c b/applications/plugins/hid_app/views/hid_mouse.c index d1d76c15a..30a9d9d06 100644 --- a/applications/plugins/hid_app/views/hid_mouse.c +++ b/applications/plugins/hid_app/views/hid_mouse.c @@ -20,6 +20,7 @@ typedef struct { bool left_mouse_held; bool right_mouse_pressed; bool connected; + HidTransport transport; } HidMouseModel; static void hid_mouse_draw_callback(Canvas* canvas, void* context) { @@ -27,11 +28,14 @@ static void hid_mouse_draw_callback(Canvas* canvas, void* context) { HidMouseModel* model = context; // Header - if(model->connected) { - canvas_draw_icon(canvas, 0, 0, &I_Ble_connected_15x15); - } else { - canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15); + if(model->transport == HidTransportBle) { + if(model->connected) { + canvas_draw_icon(canvas, 0, 0, &I_Ble_connected_15x15); + } else { + canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15); + } } + canvas_set_font(canvas, FontPrimary); elements_multiline_text_aligned(canvas, 17, 3, AlignLeft, AlignTop, "Mouse"); canvas_set_font(canvas, FontSecondary); @@ -198,6 +202,9 @@ HidMouse* hid_mouse_alloc(Hid* hid) { view_set_draw_callback(hid_mouse->view, hid_mouse_draw_callback); view_set_input_callback(hid_mouse->view, hid_mouse_input_callback); + with_view_model( + hid_mouse->view, HidMouseModel * model, { model->transport = hid->transport; }, true); + return hid_mouse; } diff --git a/applications/plugins/hid_app/views/hid_mouse_jiggler.c b/applications/plugins/hid_app/views/hid_mouse_jiggler.c index a2b07c7a1..d8f1f8928 100644 --- a/applications/plugins/hid_app/views/hid_mouse_jiggler.c +++ b/applications/plugins/hid_app/views/hid_mouse_jiggler.c @@ -16,6 +16,7 @@ typedef struct { bool connected; bool running; uint8_t counter; + HidTransport transport; } HidMouseJigglerModel; static void hid_mouse_jiggler_draw_callback(Canvas* canvas, void* context) { @@ -23,11 +24,14 @@ static void hid_mouse_jiggler_draw_callback(Canvas* canvas, void* context) { HidMouseJigglerModel* model = context; // Header - if(model->connected) { - canvas_draw_icon(canvas, 0, 0, &I_Ble_connected_15x15); - } else { - canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15); + if(model->transport == HidTransportBle) { + if(model->connected) { + canvas_draw_icon(canvas, 0, 0, &I_Ble_connected_15x15); + } else { + canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15); + } } + canvas_set_font(canvas, FontPrimary); elements_multiline_text_aligned(canvas, 17, 3, AlignLeft, AlignTop, "Mouse Jiggler"); @@ -120,6 +124,12 @@ HidMouseJiggler* hid_mouse_jiggler_alloc(Hid* hid) { hid_mouse_jiggler->timer = furi_timer_alloc( hid_mouse_jiggler_timer_callback, FuriTimerTypePeriodic, hid_mouse_jiggler); + with_view_model( + hid_mouse_jiggler->view, + HidMouseJigglerModel * model, + { model->transport = hid->transport; }, + true); + return hid_mouse_jiggler; } diff --git a/applications/plugins/hid_app/views/hid_tiktok.c b/applications/plugins/hid_app/views/hid_tiktok.c index 42abf4148..e1f9f4bed 100644 --- a/applications/plugins/hid_app/views/hid_tiktok.c +++ b/applications/plugins/hid_app/views/hid_tiktok.c @@ -19,6 +19,7 @@ typedef struct { bool ok_pressed; bool connected; bool is_cursor_set; + HidTransport transport; } HidTikTokModel; static void hid_tiktok_draw_callback(Canvas* canvas, void* context) { @@ -26,11 +27,14 @@ static void hid_tiktok_draw_callback(Canvas* canvas, void* context) { HidTikTokModel* model = context; // Header - if(model->connected) { - canvas_draw_icon(canvas, 0, 0, &I_Ble_connected_15x15); - } else { - canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15); + if(model->transport == HidTransportBle) { + if(model->connected) { + canvas_draw_icon(canvas, 0, 0, &I_Ble_connected_15x15); + } else { + canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15); + } } + canvas_set_font(canvas, FontPrimary); elements_multiline_text_aligned(canvas, 17, 3, AlignLeft, AlignTop, "TikTok"); canvas_set_font(canvas, FontSecondary); @@ -207,6 +211,9 @@ HidTikTok* hid_tiktok_alloc(Hid* bt_hid) { view_set_draw_callback(hid_tiktok->view, hid_tiktok_draw_callback); view_set_input_callback(hid_tiktok->view, hid_tiktok_input_callback); + with_view_model( + hid_tiktok->view, HidTikTokModel * model, { model->transport = bt_hid->transport; }, true); + return hid_tiktok; } From 1390f10a6fc53aabd128820e563fb98fe6c8079f Mon Sep 17 00:00:00 2001 From: Skorpionm <85568270+Skorpionm@users.noreply.github.com> Date: Tue, 27 Dec 2022 12:29:21 +0400 Subject: [PATCH 30/34] [FL-3068] SubGhz: add Holtek_ht12x protocol (#2187) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * SubGhz: add Holtek_ht12x protocol * SubGhz: add unit_test holtek_ht12x * SubGhz: correct string formatting Co-authored-by: あく --- .../debug/unit_tests/subghz/subghz_test.c | 17 +- assets/unit_tests/subghz/holtek_ht12x.sub | 8 + assets/unit_tests/subghz/holtek_ht12x_raw.sub | 10 + assets/unit_tests/subghz/test_random_raw.sub | 5 + lib/subghz/protocols/holtek_ht12x.c | 400 ++++++++++++++++++ lib/subghz/protocols/holtek_ht12x.h | 107 +++++ lib/subghz/protocols/protocol_items.c | 1 + lib/subghz/protocols/protocol_items.h | 1 + 8 files changed, 548 insertions(+), 1 deletion(-) create mode 100644 assets/unit_tests/subghz/holtek_ht12x.sub create mode 100644 assets/unit_tests/subghz/holtek_ht12x_raw.sub create mode 100644 lib/subghz/protocols/holtek_ht12x.c create mode 100644 lib/subghz/protocols/holtek_ht12x.h diff --git a/applications/debug/unit_tests/subghz/subghz_test.c b/applications/debug/unit_tests/subghz/subghz_test.c index cb89e1f02..1dee1d59e 100644 --- a/applications/debug/unit_tests/subghz/subghz_test.c +++ b/applications/debug/unit_tests/subghz/subghz_test.c @@ -13,7 +13,7 @@ #define CAME_ATOMO_DIR_NAME EXT_PATH("subghz/assets/came_atomo") #define NICE_FLOR_S_DIR_NAME EXT_PATH("subghz/assets/nice_flor_s") #define TEST_RANDOM_DIR_NAME EXT_PATH("unit_tests/subghz/test_random_raw.sub") -#define TEST_RANDOM_COUNT_PARSE 253 +#define TEST_RANDOM_COUNT_PARSE 273 #define TEST_TIMEOUT 10000 static SubGhzEnvironment* environment_handler; @@ -597,6 +597,13 @@ MU_TEST(subghz_decoder_smc5326_test) { "Test decoder " SUBGHZ_PROTOCOL_SMC5326_NAME " error\r\n"); } +MU_TEST(subghz_decoder_holtek_ht12x_test) { + mu_assert( + subghz_decoder_test( + EXT_PATH("unit_tests/subghz/holtek_ht12x_raw.sub"), SUBGHZ_PROTOCOL_HOLTEK_HT12X_NAME), + "Test decoder " SUBGHZ_PROTOCOL_HOLTEK_HT12X_NAME " error\r\n"); +} + //test encoders MU_TEST(subghz_encoder_princeton_test) { mu_assert( @@ -730,6 +737,12 @@ MU_TEST(subghz_encoder_smc5326_test) { "Test encoder " SUBGHZ_PROTOCOL_SMC5326_NAME " error\r\n"); } +MU_TEST(subghz_encoder_holtek_ht12x_test) { + mu_assert( + subghz_encoder_test(EXT_PATH("unit_tests/subghz/holtek_ht12x.sub")), + "Test encoder " SUBGHZ_PROTOCOL_HOLTEK_HT12X_NAME " error\r\n"); +} + MU_TEST(subghz_random_test) { mu_assert(subghz_decode_random_test(TEST_RANDOM_DIR_NAME), "Random test error\r\n"); } @@ -774,6 +787,7 @@ MU_TEST_SUITE(subghz) { MU_RUN_TEST(subghz_decoder_clemsa_test); MU_RUN_TEST(subghz_decoder_ansonic_test); MU_RUN_TEST(subghz_decoder_smc5326_test); + MU_RUN_TEST(subghz_decoder_holtek_ht12x_test); MU_RUN_TEST(subghz_encoder_princeton_test); MU_RUN_TEST(subghz_encoder_came_test); @@ -797,6 +811,7 @@ MU_TEST_SUITE(subghz) { MU_RUN_TEST(subghz_encoder_clemsa_test); MU_RUN_TEST(subghz_encoder_ansonic_test); MU_RUN_TEST(subghz_encoder_smc5326_test); + MU_RUN_TEST(subghz_encoder_holtek_ht12x_test); MU_RUN_TEST(subghz_random_test); subghz_test_deinit(); diff --git a/assets/unit_tests/subghz/holtek_ht12x.sub b/assets/unit_tests/subghz/holtek_ht12x.sub new file mode 100644 index 000000000..09e20b134 --- /dev/null +++ b/assets/unit_tests/subghz/holtek_ht12x.sub @@ -0,0 +1,8 @@ +Filetype: Flipper SubGhz Key File +Version: 1 +Frequency: 433920000 +Preset: FuriHalSubGhzPresetOok650Async +Protocol: Holtek_HT12X +Bit: 12 +Key: 00 00 00 00 00 00 0F FB +TE: 205 diff --git a/assets/unit_tests/subghz/holtek_ht12x_raw.sub b/assets/unit_tests/subghz/holtek_ht12x_raw.sub new file mode 100644 index 000000000..1aeedac38 --- /dev/null +++ b/assets/unit_tests/subghz/holtek_ht12x_raw.sub @@ -0,0 +1,10 @@ +Filetype: Flipper SubGhz RAW File +Version: 1 +Frequency: 433920000 +Preset: FuriHalSubGhzPresetOok650Async +Protocol: RAW +RAW_Data: 97 -264 65 -1890 231 -366 165 -232 99 -166 297 -68 401 -100 97 -100 759 -264 823 -132 919 -98 65 -230 367 -98 1055 -52 51 -104 101 -126 173 -148 151 -100 153 -222 77 -288 53 -280 331 -212 81 -108 246 -156 267 -268 183 -1260 53 -622 51 -468 183 -264 105 -990 77 -421 75 -52 53 -214 185 -504 75 -563 131 -338 165 -82 133 -80 53 -236 231 -208 282 -836 187 -406 81 -102 181 -54 107 -415 81 -54 109 -298 55 -406 323 -136 299 -136 437 -52 133 -294 53 -110 133 -420 333 -402 269 -574 79 -270 163 -594 124 -52 51 -320 79 -324 109 -78 105 -236 79 -292 53 -432 181 -110 187 -268 107 -78 79 -188 79 -78 75 -130 75 -128 103 -628 79 -322 79 -136 81 -196 85 -296 51 -349 159 -325 131 -80 131 -80 402 -110 55 -194 109 -108 53 -108 135 -224 81 -162 57 -228 161 -357 105 -54 103 -347 279 -294 422 -152 51 -104 99 -146 147 -205 77 -216 107 -52 181 -52 107 -158 105 -52 133 -134 139 -418 291 -102 103 -106 105 -584 103 -540 53 -52 153 -208 227 -128 307 -184 105 -328 109 -862 129 -196 55 -244 51 -1501 55 -82 81 -326 79 -500 103 -406 207 -130 75 -126 155 -202 53 -376 135 -158 53 -428 107 -467 167 -138 81 -106 79 -346 157 -84 143 -144 85 -136 53 -308 189 -248 79 -711 109 -592 107 -220 107 -104 77 -583 131 -158 53 -110 135 -191 107 -748 105 -478 77 -398 107 -138 83 -410 127 -477 103 -162 119 -72 103 -442 129 -237 107 -664 175 -74 147 -406 53 -78 127 -178 51 -102 101 -259 125 -202 257 -210 77 -52 77 -130 251 -230 77 -76 77 -178 155 -98 97 -100 153 -54 185 -82 79 -82 135 -398 241 -130 77 -76 311 -210 53 -238 181 -404 241 -352 189 -270 265 -164 215 -998 157 -82 77 -106 51 -54 75 -100 328 -178 103 -224 253 -341 147 -334 446 -76 125 -100 75 -126 173 -690 75 -250 51 -554 81 -300 53 -188 53 -106 265 -1024 105 -646 221 -82 191 -362 75 -234 131 -128 83 -224 55 -240 77 -376 157 -78 187 -358 389 -76 103 -128 199 -513 83 -492 129 -618 123 -52 129 -52 79 -376 101 -688 105 -110 55 -84 179 -152 51 -486 358 -276 99 -74 73 -679 51 -210 113 -196 365 -104 223 -104 53 -430 55 -140 55 -84 153 -202 181 -358 149 -820 103 -80 215 -108 309 -368 105 -538 154 -732 233 -588 53 -253 155 -288 55 -136 55715 -102 407 -100 259 -78 157 -130 206 -52 258 -78 441 -104 77 -80 492 -104 182 -104 79 -155 +RAW_Data: 287 -78 807 -104 1588 -52 2952 -78 1018 -240 341 -262 361 -258 335 -280 309 -100 509 -280 307 -302 307 -6968 321 -290 293 -298 323 -294 289 -314 285 -334 285 -330 257 -330 281 -328 293 -310 281 -124 479 -330 281 -326 267 -6994 295 -324 267 -320 287 -340 259 -332 257 -358 257 -354 257 -328 257 -352 257 -352 255 -150 455 -360 255 -326 255 -7024 253 -352 255 -352 255 -354 267 -326 269 -352 239 -346 261 -362 233 -358 257 -356 255 -152 455 -334 255 -354 255 -7006 267 -342 267 -352 241 -350 263 -342 259 -362 233 -356 257 -356 231 -378 231 -380 231 -150 455 -358 231 -378 229 -7050 229 -378 229 -352 253 -352 239 -372 239 -380 243 -348 235 -368 231 -388 231 -356 233 -176 431 -384 229 -380 231 -7028 239 -368 241 -372 241 -350 239 -372 233 -366 233 -384 231 -358 231 -380 231 -378 231 -176 429 -384 205 -402 205 -7064 213 -380 243 -378 215 -374 233 -368 233 -386 231 -382 205 -382 231 -380 229 -380 231 -176 429 -386 203 -378 231 -7062 229 -378 229 -378 229 -378 229 -378 213 -396 203 -404 203 -404 203 -404 203 -404 203 -198 431 -376 215 -376 239 -7064 235 -364 231 -386 231 -384 205 -408 205 -380 231 -380 231 -380 231 -378 207 -404 205 -200 431 -384 205 -404 205 -7118 205 -408 205 -406 205 -408 205 -408 205 -408 205 -436 179 -440 283 -460 75 -1486 105 -54 103 -784 107 -218 113 -824 125 -2140 85 -583 51 -1291 53 -722 113 -622 107 -1176 51 -52 75 -152 113 -56 111 -784 105 -436 81 -112 85 -272 53 -406 81 -1345 105 -3008 53 -1418 105 -254 107 -874 131 -818 53 -595 77 -130 123 -1088 213 -724 131 -793 99 -428 75 -288 51 -334 101 -1471 81 -274 53 -164 107 -2618 129 -532 55 -366 297 -160 83 -166 184 -208 57 -196 328 -1640 235 -1743 79 -594 51 -76 77 -270 163 -728 51 -408 55 -354 101 -126 153 -184 133 -392 53 -604 77 -804 127 -965 51 -78 103 -668 262 -210 237 -439 75 -340 77 -106 105 -1775 79 -284 51 -3100 157 -433 55 -1355 107 -198 165 -82 79 -770 79 -1587 81 -638 79 -530 103 -703 51 -396 71 -956 151 -248 53 -553 103 -154 75 -806 75 -660 53 -698 127 -1210 53 -3175 79 -608 245 -1590 207 -164 107 -232 51 -1094 99 -695 135 -955 53 -804 217 -587 55 -1452 163 -1232 79 -968 79 -720 81 -1110 129 -1194 105 -1736 79 -386 79 -184 77 -652 75 -2442 103 -555 129 -125 75 -1115 81 -108 135 -980 53 -808 105 -1001 155 -1068 131 -850 99 -268 51 -1106 159 -2408 79 -612 51 -1191 +RAW_Data: 135 -212 77 -2816 137 -980 51 -1921 79 -1554 53 -906 83 -1042 99 -5161 51 -290 75 -558 51 -260 77 -738 99 -2128 105 -1384 53 -108 79 -188 55 -830 77 -5690 109 -2652 51 -1374 53 -2469 79 -2163 203 -152 71 -1459 79 -2741 105 -262 75 -1194 75 -228 153 -210 107 -3236 107 -1500 77 -3562 79 -170 55 -540 53 -1270 51 -304 51 -2071 137 -134 105 -266 101 -834 51 -8117 73 -3292 81 -732 181 -1539 53 -132 109 -1375 77 -132 81 -1061 77 -1620 79 -1373 105 -643 183 -190 53 -620 77 -1633 55 -931 51 -398 135 -924 111 -1122 51 -128 125 -2361 97 -2571 51 -3563 51 -794 77 -844 81 -788 81 -2040 77 -232 77 -1000 131 -322 73 -848 55 -336 107 -1546 81 -602 79 -954 107 -1824 73 -1131 240 -1048 197 -2442 73 -720 127 -78 77 -574 79 -624 101 -5754 103 -1829 149 -719 77 -982 53 -250 53 -634 161 -2201 75 -3483 149 -356 73 -98 123 -176 75 -702 231 -1633 121 -704 53 -1163 51 -1227 73 -368 123 -258 103 -530 279 -628 53 -884 55 -82 101 -102 135 -162 107 -1264 159 -3370 77 -3538 131 -130 81 -2460 129 -588 51 -514 77 -376 53 -616 53 -956 51 -1508 53 -1044 53 -1160 261 -442 53 -640 83 -300 79 -1723 75 -124 125 -532 103 -500 79 -764 53 -1220 279 -458 77 -548 159 -450 223 -718 55 -716 51 -716 203 -732 79 -6974 53 -1086 51 -1794 79 -882 53 -4221 53 -1070 77 -1126 75 -2307 155 -1233 131 -156 111 -1352 51 -478 51 -154 75 -724 51 -635 103 -652 77 -294 75 -268 81 -1046 177 -1778 51 -298 109 -336 77 -80 53 -192 133 -556 99 -394 81 -654 51 -106 79 -1893 55 -240 55 -136 55 -2680 77 -136 81 -164 53 -576 135 -3304 131 -654 103 -788 53 -224 187 -354 79 -1872 81 -290 207 -410 77 -1132 55 -112 57 -512 51 -2736 123 -404 239 -1283 51 -1526 213 -720 133 -354 109 -396 77 -1518 105 -632 53 -164 53 -1090 55 -730 79 -1705 75 -370 75 -378 79 -2022 81 -2480 103 -1108 79 -106 53 -1784 105 -512 219 -669 179 -795 105 -376 105 -514 53 -402 53 -282 83 -554 133 -448 105 -972 79 -490 81 -1184 77 -216 109 -132 51 -164 135 -1570 51 -1329 79 -1218 53 -2450 75 -1246 51 -3825 77 -1114 53 -1718 51 -846 79 -826 165 -306 75 -3821 51 -606 55 -880 107 -56 55 -5505 53 -504 79 -1356 77 -569 51 -2268 149 -358 53 -1979 51 -106 103 -176 221 -508 51 -110 53 -3896 127 -234 79 -1012 79 -84 243 -2860 53 -1010 73 -286 133 -2198 151 -370 129 -1942 101 -154 109 -702 79 -696 51 -302 +RAW_Data: 51 -744 83 -496 79 -672 77 -170 111 -264 103 -472 51 -524 75 -1172 51 -240 51963 -254 333 -278 333 -276 333 -278 305 -302 307 -76 531 -280 331 -276 331 -6938 347 -268 319 -272 319 -292 311 -312 283 -306 309 -304 283 -328 293 -310 281 -326 293 -110 479 -322 295 -322 291 -6964 283 -334 283 -304 283 -328 283 -328 281 -328 255 -354 265 -338 255 -352 255 -352 255 -124 481 -338 277 -328 279 -6984 269 -350 265 -320 287 -340 257 -332 257 -358 255 -356 255 -328 257 -354 257 -352 255 -150 455 -360 229 -376 231 -7040 239 -348 267 -350 239 -346 261 -364 231 -360 257 -356 231 -380 231 -378 231 -352 257 -150 453 -360 229 -378 229 -7032 239 -372 227 -378 227 -380 241 -352 241 -374 233 -366 233 -384 233 -356 231 -380 231 -176 431 -384 229 -354 255 -7030 231 -376 231 -376 229 -378 229 -378 229 -352 255 -352 255 -352 229 -378 229 -378 229 -174 427 -384 229 -376 241 -7040 241 -350 235 -368 233 -388 231 -358 233 -380 231 -380 229 -380 231 -380 229 -380 211 -192 421 -366 227 -380 227 -7068 239 -378 215 -402 209 -394 207 -388 231 -386 231 -384 205 -408 205 -408 205 -408 205 -202 409 -412 207 -1400 105 -1002 51 -9495 53 -250 57 -1093 155 -124 73 -344 75 -2759 83 -468 53 -738 77 -134 53 -1581 51 -106 127 -1209 121 -956 51 -918 83 -276 85 -1696 125 -618 81 -1666 51 -152 101 -1324 107 -54 141 -586 75 -784 55 -1828 51 -4052 81 -480 53 -218 141 -1346 105 -1152 127 -776 53 -426 135 -390 105 -939 81 -887 71 -492 107 -1311 105 -1844 101 -1340 77 -2586 51 -2637 51 -1626 105 -54 53 -1672 151 -2830 57 -3143 51 -1859 79 -929 179 -78 77 -890 73 -894 79 -80 79 -1184 53 -323 53 -1344 79 -636 53 -1808 55 -3048 79 -2287 53 -572 51 -822 51 -608 77 -1772 75 -2521 79 -162 81 -664 163 -110 83 -524 53 -930 53 -1816 79 -1305 51 -816 53 -1358 55 -822 55 -594 81 -2230 55 -234 77 -600 201 -3174 151 -2534 71 -122 51 -1370 81 -3130 127 -236 79 -728 101 -1472 53 -800 127 -528 51 -802 77 -52 99 -3144 77 -6346 51 -1090 81 -588 79 -292 169 -2345 107 -370 187 -1218 81 -296 75 -696 51 -516 77 -2154 75 -558 75 -816 103 -2200 125 -2766 229 -376 151 -3375 79 -1466 53 -535 167 -524 217 -54 131 -3408 51 -54 109 -1886 77 -732 83 -536 99 -3128 103 -168 57 -1852 51 -574 79 -296 155 -844 99 -767 147 -2406 99 -1014 81 -4460 175 -226 195 -454 73 -2236 53 -818 155 -352 83 -752 79 -5083 51 -1716 +RAW_Data: 77 -1925 51 -1760 81 -162 53 -1469 79 -362 53 -471 103 -750 53 -562 127 -238 79 -250 107 -52 53 -210 83 -504 79 -1566 107 -82 79 -968 53 -458 131 -1944 301 -594 79 -382 51 -1196 79 -3963 183 -670 111 -360 105 -1990 53 -1084 79 -658 73 -301 73 -264 75 -1335 79 -1110 81 -1856 159 -3986 75 -1262 53 -1189 53 -158 53 -903 81 -1135 133 -350 107 -178 151 -1096 73 -2734 81 -1280 107 -950 79 -52 53 -5912 53 -1653 111 -1601 79 -742 51 -1104 55 -1254 51 -867 53 -136 109 -813 79 -1082 53 -395 53 -54 109 -504 79 -218 109 -114 57 -1620 157 -3003 79 -656 53 -510 209 -1933 107 -1197 159 -5508 79 -1164 77 -1466 77 -742 101 -124 71 -2049 85 -144 109 -1304 105 -2310 55 -381 83 -114 113 -944 103 -184 83 -558 55 -2064 109 -760 75 -1036 77 -574 51 -134 131 -224 57 -104 53 -440 53 -1262 183 -2454 51 -1966 73 -1950 125 -1095 51 -480 121 -1994 57 -1930 103 -786 79 -2272 105 -3312 51 -746 127 -144 133 -1608 77 -692 51 -1136 53 -164 55 -573 55 -3110 53 -1558 105 -6248 53 -1051 111 -886 105 -2234 103 -106 53 -1256 101 -1446 111 -974 79 -851 81 -136 193 -3392 83 -582 103 -1197 111 -196 55 -906 51 -742 77 -2038 71 -686 53 -1943 51 -134 51 -852 51 -1658 133 -2050 161 -388 77 -326 81 -412 55 -1137 81 -3256 55 -1516 53 -1414 117 -372 51 -1144 199 -3087 51 -430 75 -1856 151 -128 95 -192 398 -1207 77 -280 51 -2716 51 -808 53 -78 77 -1524 109 -54 79 -410 79 -132 53 -770 109 -2066 185 -368 131 -2102 125 -1037 75 -780 127 -128 51 -176 53 -1982 77 -140 111 -1046 109 -3166 169 -1956 77 -4040 79 -2778 73 -204 129 -1546 82945 -150 359 -252 333 -76 533 -280 319 -286 305 -6960 319 -300 323 -270 317 -290 313 -308 283 -306 309 -304 283 -328 291 -310 281 -326 281 -124 481 -334 279 -302 305 -6970 293 -318 301 -304 279 -328 279 -328 277 -330 277 -330 293 -298 295 -320 287 -314 283 -128 489 -334 255 -330 281 -7012 265 -340 265 -344 251 -354 253 -354 269 -322 293 -322 263 -344 259 -336 257 -360 257 -152 457 -358 231 -354 257 -7060 237 -364 255 -354 237 -366 255 -354 255 -354 267 -352 241 -352 265 -348 261 -342 259 -154 439 -388 231 -358 255 -7114 237 -370 235 -394 233 -362 233 -386 233 -386 233 -386 233 -386 231 -388 233 -414 233 -180 441 -392 233 -1832 53 -564 53 -370 289 -867 201 -78 103 -352 213 -586 103 -1226 165 -112 55 -300 105 -975 107 -358 77 -410 55 -1777 51 -973 51 -828 diff --git a/assets/unit_tests/subghz/test_random_raw.sub b/assets/unit_tests/subghz/test_random_raw.sub index 900b26207..be635f04d 100644 --- a/assets/unit_tests/subghz/test_random_raw.sub +++ b/assets/unit_tests/subghz/test_random_raw.sub @@ -168,3 +168,8 @@ RAW_Data: 285 -96 627 -362 53 -84 201 -374 113 -202 115 -202 421 -316 85 -58 139 RAW_Data: 535 -142 57 -58 55 -116 115 -432 85 -172 259 -192 167 -120 117 -72 119 -240 334 -72 71 -267 285 -144 119 -374 85 -88 85 -114 143 -202 229 -58 143 -202 115 -202 171 -86 71 -144 87 -56 173 -373 143 -116 113 -462 169 -80 215 -148 115 -336 85 -230 163 -432 85 -374 639 -174 85 -58 57 -82 295 -352 269 -532 414 -322 95 -287 263 -268 115 -56 259 -76 85 -282 401 -305 516 -114 115 -202 171 -86 451 -110 85 -346 201 -274 149 -202 85 -364 366 -258 57 -114 259 -172 142 -144 85 -116 85 -480 171 -144 57 -352 115 -116 535 -404 315 -202 163 -158 517 -316 215 -98 85 -346 85 -144 87 -86 257 -82 167 -58 85 -116 113 -894 233 -186 77 -266 147 -72 71 -82 57 -86 171 -58 57 -86 201 -364 143 -202 115 -114 85 -88 113 -86 87 -230 57 -76 613 -72 85 -96 209 -346 458 -58 547 -490 201 -315 315 -116 75 -168 359 -335 95 -384 93 -120 71 -312 251 -366 233 -96 189 -240 263 -192 271 -58 115 -58 229 -346 459 -174 113 -144 173 -144 218 -224 57 -116 215 -72 103 -202 513 -210 433 -116 113 -174 650 -273 147 -450 375 -86 115 -172 536 -84 85 -230 85 -58 195 -468 287 -110 551 -214 167 -311 213 -250 85 -58 85 -355 113 -230 115 -144 117 -288 195 -202 57 -376 123 -144 236 -168 553 -284 119 -72 143 -188 161 -120 93 -312 335 -58 55 -260 105 -244 143 -120 381 -268 173 -268 635 -168 453 -318 71 -167 71 -406 191 -172 215 -408 119 -144 93 -120 97 -130 143 -192 308 -122 147 -550 313 -96 139 -162 167 -96 431 -80 83 -112 201 -86 287 -86 229 -116 57 -288 113 -174 143 -116 113 -144 115 -518 57 -230 57 -172 231 -86 113 -314 183 -144 119 -72 165 -446 81 -86 135 -190 143 -96 71 -72 411 -96 143 -120 69 -216 349 -72 95 -96 517 -646 163 -86 113 -116 171 -116 143 -116 113 -287 259 -114 517 -168 141 -116 105 -72 95 -96 311 -118 159 -310 191 -54 143 -258 115 -450 219 -54 339 -372 239 -72 167 -174 113 -58 57 -144 259 -172 143 -336 113 -174 85 -230 83 -668 85 -202 113 -144 57 -116 373 -316 719 -288 115 -58 75 -120 139 -144 229 -144 57 -144 171 -192 391 -202 403 -58 315 -188 259 -56 115 -144 85 -404 57 -58 105 -102 429 -406 81 -172 57 -144 287 -230 287 -220 317 -458 283 -58 113 -86 269 -72 281 -58 85 -202 113 -52 421 -58 229 -480 259 -58 143 -660 155 -638 123 -86 57 -86 143 -346 143 -144 57 -144 RAW_Data: 2442 -312 275 -972 949 -310 941 -322 923 -342 921 -352 923 -334 281 -954 945 -350 279 -958 907 -354 289 -980 909 -352 281 -962 907 -330 311 -964 913 -350 317 -930 933 -344 921 -352 893 -330 311 -954 943 -318 315 -958 909 -324 947 -7854 953 -322 289 -948 939 -354 927 -332 911 -324 943 -344 917 -318 317 -964 905 -344 303 -942 947 -312 319 -960 913 -348 281 -958 941 -322 295 -978 905 -350 279 -962 931 -328 947 -324 939 -346 267 -964 935 -348 283 -938 953 -318 931 -7868 935 -346 269 -968 953 -310 941 -322 921 -330 935 -342 931 -318 311 -962 939 -290 337 -950 909 -352 317 -924 943 -324 313 -938 941 -318 317 -932 939 -344 301 -938 933 -350 921 -322 959 -310 301 -942 933 -352 317 -926 957 -314 919 -7868 943 -314 317 -958 909 -322 951 -344 919 -352 921 -324 937 -326 281 -964 941 -318 317 -930 939 -344 301 -938 933 -352 281 -962 953 -314 317 -922 933 -330 315 -954 943 -318 921 -342 943 -320 291 -980 909 -354 281 -962 943 -296 967 -7836 943 -332 309 -950 935 -318 929 -340 943 -320 921 -344 921 -354 283 -960 943 -296 309 -964 945 -318 279 -964 941 -322 333 -944 939 -314 279 -992 903 -342 319 -932 933 -330 931 -340 929 -348 281 -964 935 -334 281 -970 927 -346 921 -7862 951 -314 319 -922 953 -320 923 -346 921 -320 965 -298 943 -324 313 -942 941 -320 317 -930 941 -344 303 -940 945 -312 321 -940 953 -314 303 -960 933 -348 287 -962 911 -352 917 -350 905 -324 333 -918 971 -322 317 -924 945 -324 937 -7872 919 -324 317 -942 941 -318 933 -330 943 -324 943 -310 951 -318 317 -930 939 -344 301 -938 933 -352 317 -926 953 -314 319 -924 939 -324 331 -950 907 -354 315 -926 945 -324 939 -312 953 -318 317 -930 937 -344 301 -940 947 -348 909 -7864 949 -310 319 -956 915 -350 919 -348 905 -322 963 -296 935 -348 317 -922 951 -322 295 -976 939 -314 281 -996 915 -326 307 -940 959 -310 301 -966 935 -346 285 -958 915 -348 921 -348 903 -354 303 -948 911 -350 315 -926 945 -324 941 -7874 943 -290 319 -942 973 -318 929 -314 937 -328 941 -324 939 -310 303 -962 933 -352 285 -962 949 -314 319 -924 951 -320 293 -948 941 -354 283 -962 943 -294 309 -966 943 -320 931 -328 943 -326 311 -940 939 -320 309 -958 933 -338 943 -7840 933 -352 277 -964 941 -322 923 -344 923 -350 931 -310 955 -320 291 -974 907 -350 281 -958 963 -298 313 -956 945 -314 311 -960 937 -312 311 -966 909 -324 319 -944 941 -354 929 -298 945 -324 315 -940 RAW_Data: 943 -354 281 -964 905 -330 933 -7868 951 -324 315 -938 943 -354 893 -330 943 -324 943 -344 919 -318 317 -962 903 -344 301 -974 903 -350 317 -932 931 -342 269 -972 949 -346 285 -938 955 -310 301 -964 935 -348 921 -320 921 -344 301 -940 935 -350 317 -930 929 -318 937 -7872 939 -344 301 -940 947 -346 917 -322 921 -344 923 -352 927 -334 281 -970 925 -334 277 -982 943 -318 317 -932 931 -344 301 -936 935 -350 281 -960 957 -312 303 -960 935 -346 907 -322 929 -344 301 -942 935 -350 317 -924 955 -312 951 -7858 919 -342 309 -940 949 -348 909 -322 923 -344 923 -352 923 -336 317 -924 945 -312 311 -966 921 -340 317 -924 947 -350 281 -958 941 -322 291 -976 905 -350 279 -960 935 -342 943 -320 919 -330 311 -958 943 -320 315 -932 935 -344 919 -7866 957 -312 303 -964 917 -342 945 -320 923 -344 923 -354 929 -298 315 -956 941 -318 315 -960 911 -324 317 -942 939 -354 281 -964 941 -294 311 -968 943 -318 317 -932 937 -330 931 -350 919 -348 283 -960 917 -350 317 -922 939 -322 965 -7864 921 -324 329 -950 909 -354 923 -336 913 -322 947 -344 919 -354 281 -962 941 -294 311 -960 935 -354 281 -962 939 -294 311 -964 937 -354 281 -964 941 -296 309 -964 939 -318 931 -330 945 -324 315 -940 939 -354 281 -964 909 -344 921 -7862 963 -304 307 -976 933 -320 929 -328 941 -324 939 -348 915 -320 317 -930 939 -344 301 -940 965 -320 319 -926 953 -312 303 -960 933 -312 321 -960 913 -348 319 -924 943 -320 959 -310 921 -354 319 -924 943 -324 311 -938 941 -318 957 -7862 943 -318 317 -932 933 -344 925 -352 897 -332 943 -324 943 -346 267 -966 951 -310 321 -960 911 -350 281 -958 949 -320 291 -978 937 -316 279 -964 949 -326 309 -944 943 -314 959 -318 933 -336 317 -934 933 -344 267 -964 937 -350 905 -7896 943 -318 319 -926 955 -314 919 -350 935 -324 941 -294 967 -312 303 -962 933 -348 285 -960 917 -348 317 -922 941 -322 329 -950 907 -354 315 -926 943 -326 313 -940 941 -352 893 -332 949 -324 315 -938 941 -352 283 -962 943 -310 925 -7890 931 -344 269 -968 949 -310 943 -320 923 -350 937 -310 955 -318 317 -930 935 -344 301 -942 947 -346 285 -958 915 -346 317 -924 951 -322 295 -982 905 -352 317 -924 945 -324 941 -346 917 -318 317 -962 905 -330 311 -956 937 -352 897 -7878 939 -354 283 -960 941 -294 965 -312 953 -318 385 -201512 165 -198 265 -526 229 -298 755 -164 61687 -17310 131 -1056 99 -296 195 -296 65 -66 1617 +RAW_Data: 77 -76 131 -244 81 -210 55 -1428 53 -344 53 -238 51 -448 51 -804 125 -1490 51 -452 79 -1816 51 -176 197 -700 133 -563 51 -386 79 -474 109 -626 55 -266 103 -616 283 -1932 51 -1034 51 -2809 75 -244 83 -5339 77 -260 105 -839 107 -1806 53 -1408 81 -810 135 -488 187 -1469 73 -2596 75 -74 51 -726 113 -136 83 -406 55 -194 133 -606 55 -1018 55 -1774 51 -1954 75 -910 51 -944 137 -1337 51 -1606 101 -566 75 -584 51 -1470 133 -242 159 -2798 51 -1568 97 -100 71 -556 77 -1234 53 -320 53 -274 68337 -252 333 -278 333 -74 533 -280 307 -276 331 -6948 347 -262 329 -278 329 -278 329 -278 303 -304 303 -302 303 -304 303 -278 329 -278 329 -74 533 -294 325 -270 317 -6944 335 -282 309 -304 309 -304 281 -328 293 -310 281 -326 281 -326 281 -326 279 -302 305 -100 503 -306 305 -302 293 -6992 295 -294 291 -314 285 -336 283 -334 257 -328 283 -328 291 -310 281 -328 279 -328 279 -124 479 -332 279 -328 255 -7012 295 -324 271 -330 267 -346 261 -342 259 -334 257 -358 255 -356 257 -354 231 -354 255 -152 453 -356 257 -352 255 -7024 255 -352 257 -352 255 -354 255 -326 257 -352 255 -352 255 -354 255 -352 253 -352 255 -150 453 -356 255 -354 253 -7030 255 -352 267 -344 251 -354 253 -354 253 -354 267 -322 267 -350 261 -344 257 -364 231 -154 459 -360 257 -354 231 -7062 231 -380 231 -380 231 -352 257 -352 257 -352 257 -352 257 -352 257 -352 255 -354 231 -174 457 -360 229 -378 229 -7084 239 -364 239 -366 229 -380 229 -378 229 -380 229 -378 255 -354 255 -354 255 -352 255 -150 457 -364 253 -354 255 -9542 101 -3126 53 -814 109 -406 51 -162 109 -2219 183 -496 103 -1369 81 -603 99 -2172 79 -1103 75 -676 77 -560 103 -378 51 -654 95 -888 155 -1322 111 -1626 53 -182 51 -166 83 -52 181 -182 71 -2132 77 -2839 103 -4022 79 -362 81 -466 75 -970 203 -998 51 -2085 51 -1853 99 -328 75 -346 55 -1949 79 -2648 79 -434 75 -6757 51 -1920 109 -306 51 -612 101 -996 77 -764 81 -790 125 -1489 99 -430 77 -4142 165 -372 101 -198 71 -1688 51 -1636 99 -434 81 -794 135 -1973 79 -188 109 -2678 81 -196 109 -2099 51 -504 77 -1854 51 -910 107 -948 75 -122 131 -78 79 -1781 103 -3344 111 -406 79 -184 51 -408 103 -54 79 -1474 127 -1789 213 -683 131 -348 161 -5237 53 -2675 101 -52 105 -474 103 -1336 99 -3548 105 -1724 161 -2180 107 -2514 97 -3784 51 -910 77 -505 71 -494 131 -1154 79 -2295 75 -350 161 -274 81 -222 +RAW_Data: 107 -1501 77 -1518 53 -704 113 -390 107 -650 73 -932 51 -3641 169 -704 187 -574 79 -332 51 -3765 51 -1042 75 -1413 103 -2163 75 -218 73 -4118 73 -716 51 -1720 51 -176 145 -817 79 -602 55 -1270 53 -2290 81 -346 79 -1840 53 -596 97 -1135 155 -1672 157 -1150 53 -52 101 -2753 153 -1546 158 -698 79 -2962 215 -490 161 -766 51 -2170 55 -811 51 -694 51 -1461 103 -2590 149 -3785 130 -54 103 -1108 103 -3978 51 -1626 81 -1825 109 -452 129 -1000 79 -1651 157 -276 53 -104 81 -2440 81 -1780 53 -1554 51 -512 131 -2508 99 -176 73 -914 51 -76 81 -202 111 -690 109 -790 109 -584 53 -244 79 -706 73 -550 129 -142 127 -546 77 -296 53 -874 105 -2623 51 -1004 77 -3131 79 -552 81 -2008 187 -1168 55 -1173 51 -2146 99 -700 51 -1580 101 -252 75 -474 77 -569 73 -5817 77 -614 77 -712 149 -228 73 -562 201 -274 127 -648 77 -578 75 -1810 109 -2106 171 -5996 81 -366 159 -274 55 -1228 77 -3386 53 -106 81 -1024 133 -2331 53 -2636 53 -780 149 -842 79 -2288 53 -2807 107 -1410 51 -620 75 -428 71 -272 75 -1140 103 -4912 55 -2261 53 -716 53 -3093 109 -502 111 -1492 53 -4317 51 -500 83 -338 129 -698 105 -1565 103 -1874 105 -344 77 -546 79 -2826 105 -260 75 -616 103 -1254 113 -2687 77 -977 73 -246 97 -1054 109 -4681 67101 -252 357 -252 333 -276 333 -252 355 -254 333 -276 331 -6932 347 -272 353 -242 343 -268 339 -286 309 -282 309 -306 307 -304 283 -328 281 -328 281 -102 505 -308 291 -314 279 -6996 281 -326 279 -328 277 -328 277 -328 279 -328 277 -328 279 -328 279 -328 277 -330 277 -124 483 -322 297 -298 293 -6972 283 -336 281 -332 257 -330 281 -328 283 -328 281 -330 265 -338 255 -352 253 -352 255 -150 455 -336 279 -328 279 -6992 295 -322 265 -348 261 -342 259 -334 259 -356 257 -356 255 -330 257 -354 257 -352 255 -152 455 -358 239 -368 253 -7026 243 -352 243 -350 265 -344 261 -362 231 -358 255 -356 257 -354 231 -380 229 -354 255 -150 455 -360 231 -376 231 -7050 229 -378 229 -378 229 -378 229 -378 229 -378 229 -378 229 -352 255 -352 253 -352 255 -150 455 -362 229 -378 227 -7050 253 -354 229 -378 229 -378 229 -378 227 -378 229 -378 229 -378 229 -378 229 -376 229 -174 431 -374 243 -378 241 -7032 261 -370 233 -362 233 -384 233 -356 233 -380 231 -380 231 -380 231 -380 231 -378 231 -176 431 -384 231 -380 211 -7114 231 -384 231 -384 205 -408 207 -408 207 -408 231 -384 231 -412 207 -412 181 -530 77 -1144 +RAW_Data: 79 -4798 53 -918 83 -4847 51 -755 103 -732 81 -388 55 -1026 77 -1506 101 -242 107 -469 51 -2026 79 -686 77 -348 51 -104 131 -860 129 -148 73 -446 75 -440 97 -306 99 -600 51 -626 105 -1350 95 -674 83 -230 119 -1714 135 -396 155 -1111 109 -652 111 -482 51 -506 55 -1715 103 -968 207 -1156 81 -164 57 -404 99 -508 205 -126 75 -1417 51 -186 77 -588 53 -54 103 -2854 73 -1010 53 -800 51 -2494 53 -106 105 -52 51 -104 79 -1116 51 -654 103 -220 77 -162 71 -5385 137 -2232 79 -1159 79 -250 57 -108 79 -164 107 -1660 79 -3927 129 -992 73 -1913 51 -1430 51 -1498 55 -514 103 -586 81 -386 53 -2402 175 -1994 85 -3431 53 -3209 99 -372 79 -78 53 -1338 75 -682 97 -680 51 -206 101 -1708 101 -452 131 -1397 161 -2272 53 -456 77 -1413 193 -270 109 -466 53 -2432 77 -222 189 -474 107 -774 171 -192 79 -1327 75 -2141 51 -908 135 -3866 75 -804 129 -468 101 -1040 79 -1470 55 -869 77 -1448 105 -160 55 -1916 240 -588 79 -1587 53 -922 79 -2292 181 -1448 51 -552 77 -2189 75 -2545 77 -384 300 -2478 101 -1092 73 -558 79 -132 105 -884 103 -1177 109 -880 79 -2431 109 -1006 105 -468 53 -1378 235 -684 75 -285 73 -604 129 -528 77 -1582 51 -1240 105 -2750 75 -252 51 -1024 95 -1891 51 -864 107 -326 83 -887 159 -1058 163 -322 105 -722 83 -388 81 -936 155 -880 55 -220 83 -2123 135 -2100 73 -1926 103 -1633 149 -526 51 -324 51 -1538 103 -164 137 -964 81 -152 111 -781 225 -655 53 -2888 105 -151 131 -454 53 -4109 77 -1052 53 -178 163 -910 51 -733 207 -2070 53 -474 79 -54 53 -818 51 -1228 53 -2262 79 -788 79 -480 73 -2747 83 -316 183 -1880 105 -862 53 -662 53 -2287 153 -1630 51 -817 243 -806 55 -510 51 -1389 75 -986 135 -498 109 -532 131 -5521 99 -2948 209 -764 75 -1168 75 -886 83 -2065 53 -710 51 -596 77 -374 73 -628 99 -732 51 -202 73 -632 53 -222 55 -511 79 -4884 53 -1826 81 -1266 107 -356 55 -110 113 -280 83 -756 169 -252 81 -1854 51 -1556 157 -258 75 -748 53 -1438 291 -244 71 -1092 77 -1220 229 -1055 181 -1182 71 -1284 77 -864 79 -138 53 -160 53 -952 81 -80 127 -1272 51 -590 103 -502 77 -634 101 -74 51 -224 101 -912 77 -562 51 -164 83 -396 105 -4643 111 -3293 133 -1395 107 -3047 137 -2353 53 -298 83 -54 81 -80 53 -162 83 -392 105 -606 107 -787 53 -928 51 -2800 161 -1146 51 -182 103 -536 103 -994 81 -2044 83 -732 133 -1881 133 -2160 75 -178 +RAW_Data: 75 -1694 101 -122 73 -864 51 -250 129 -406 77 -630 77 -610 101 -781 125 -128 51 -5075 77 -1992 83 -1272 176 -2100 53 -2044 53 -1234 79 -1704 157 -519 99 -2374 101 -100 103 -202 51 -360 77 -1962 103 -2153 77 -1820 191 -164 167 -1320 77 -1718 127 -1374 81 -1047 53 -54 79 -632 53 -656 51 -128 81 -216 51 -755 79 -2692 103 -1478 125 -452 51 -896 157 -3679 135 -632 105 -134 55 -112 77 -588 79 -188 55 -1118 79 -1152 51 -1950 109 -1858 103 -1104 81 -580 131 -226 255 -2932 77 -1536 51 -1044 159 -2135 67667 -252 333 -278 333 -276 333 -74 533 -280 307 -276 345 -6930 331 -276 329 -278 329 -278 327 -278 349 -270 325 -270 317 -290 313 -308 283 -306 309 -100 509 -306 283 -328 281 -6972 307 -302 281 -326 281 -326 281 -328 279 -328 281 -326 279 -328 279 -326 281 -328 279 -124 481 -308 281 -326 279 -6998 281 -326 279 -328 279 -328 277 -330 277 -328 279 -328 279 -328 277 -304 303 -302 303 -100 503 -306 295 -322 293 -6968 287 -342 259 -336 283 -332 257 -356 255 -328 283 -328 257 -352 257 -352 257 -352 255 -150 455 -334 281 -326 281 -6996 265 -342 253 -354 253 -354 253 -354 253 -354 267 -326 269 -350 263 -342 257 -336 259 -152 459 -360 257 -354 231 -7038 267 -338 255 -352 253 -354 253 -354 239 -354 269 -352 239 -372 233 -366 233 -358 257 -154 457 -360 231 -378 231 -7050 231 -380 231 -378 231 -380 231 -378 231 -354 255 -352 257 -352 255 -354 231 -378 229 -176 453 -358 229 -378 231 -7076 231 -378 231 -380 231 -380 229 -354 255 -354 257 -352 257 -352 257 -352 257 -354 255 -150 455 -358 265 -364 229 -4941 101 -1058 153 -670 157 -532 124 -1396 133 -82 165 -162 153 -258 207 -156 131 -1582 85 -714 53 -774 103 -396 274 -110 131 -1965 55 -402 159 -1026 79 -590 77 -3531 57 -500 51 -4770 109 -722 77 -186 53 -298 79 -502 165 -808 77 -438 53 -382 101 -1914 75 -504 77 -1969 135 -5517 99 -576 51 -608 243 -684 53 -2058 315 -1384 79 -1079 77 -232 79 -212 155 -1500 137 -258 75 -975 204 -752 83 -2542 51 -484 103 -78 77 -210 53 -922 157 -1900 107 -2173 83 -384 101 -80 128 -814 183 -978 127 -772 105 -2073 51 -708 53 -300 83 -739 237 -884 131 -3412 157 -1752 81 -164 83 -3373 53 -1406 105 -3809 79 -432 51 -724 77 -548 53 -1955 79 -807 81 -2096 103 -490 105 -1196 109 -108 79 -394 71 -1159 129 -126 143 -340 107 -556 81 -2390 135 -106 133 -690 133 -4347 189 -290 51 -110 53 -78 103 -1101 51 -1362 +RAW_Data: 83 -320 81 -4648 101 -3726 173 -1418 85 -348 53 -2994 79 -1390 51 -1656 107 -764 53 -134 79 -1619 131 -932 55 -2810 107 -3218 79 -765 107 -654 103 -1498 77 -228 51 -134 247 -1526 51 -3903 103 -1495 179 -282 77 -392 53 -1756 105 -368 111 -486 51 -298 53 -216 113 -358 51 -266 187 -1059 81 -780 105 -238 51 -482 53 -791 109 -2169 77 -5304 53 -398 79 -650 51 -54 51 -1789 73 -198 101 -1580 101 -746 97 -4518 53 -744 51 -1064 101 -928 111 -392 185 -869 103 -320 133 -704 81 -244 53 -1628 75 -634 79 -666 183 -1276 83 -218 107 -1163 55 -1276 127 -1144 73 -1400 81 -266 77 -568 129 -806 121 -1420 103 -848 77 -982 103 -2132 81 -1610 101 -1218 55 -2208 75 -2735 53 -921 53 -724 51 -472 83 -3164 185 -400 77 -812 81 -306 215 -2167 53 -130 53 -272 81 -400 79 -1272 81 -418 51 -1381 73 -340 101 -2169 81 -2330 137 -2698 99 -2340 99 -126 51 -1714 55 -488 81 -3500 51 -404 77 -1422 77 -856 215 -80 51 -2308 53 -134 77 -2036 75 -5175 129 -946 239 -638 53 -244 55 -564 105 -826 71 -1632 77 -106 129 -246 135 -366 79 -724 79 -1535 57 -1085 113 -1320 79 -3111 127 -1578 75 -324 75 -102 173 -364 79 -1374 53 -1508 107 -622 51 -526 109 -584 187 -2648 51 -106 79 -380 103 -604 51 -1244 73 -5766 107 -1934 177 -702 51 -1277 53 -1643 79 -1446 81 -4098 75 -574 103 -432 189 -1436 107 -454 79 -132 105 -136 81 -112 113 -942 239 -1238 79 -952 157 -340 51 -314 191 -456 53 -3368 101 -150 99 -464 51 -718 73 -770 101 -150 73 -2132 75 -557 77 -680 81 -3512 151 -760 75 -332 75 -1212 131 -1468 79 -1955 101 -541 75 -344 79 -2146 53 -2299 97 -720 79 -2518 79 -3807 51 -1272 75 -352 77 -52 75 -586 53 -1142 79 -82 81 -2400 157 -324 81 -268 103 -1154 81 -1175 79 -1191 51 -1074 53 -2566 137 -854 75 -1497 51 -4533 51 -2290 51 -344 77 -348 55 -1182 77 -897 135 -874 51 -1064 51 -208 55 -140 55 -1334 133 -1238 157 -1669 113 -2128 75 -848 85 -510 83590 -126 333 -280 331 -252 331 -6946 331 -276 331 -276 329 -278 329 -276 331 -276 331 -276 331 -276 347 -238 351 -254 353 -268 323 -270 345 -6924 335 -282 307 -304 307 -304 281 -304 307 -302 307 -302 305 -302 307 -302 305 -302 281 -124 507 -282 305 -302 305 -6984 279 -328 277 -328 279 -328 277 -330 277 -304 303 -302 305 -302 305 -302 303 -304 303 -100 507 -314 295 -298 293 -6986 283 -334 281 -306 283 -328 283 -328 281 -328 283 -328 255 -352 diff --git a/lib/subghz/protocols/holtek_ht12x.c b/lib/subghz/protocols/holtek_ht12x.c new file mode 100644 index 000000000..169387ded --- /dev/null +++ b/lib/subghz/protocols/holtek_ht12x.c @@ -0,0 +1,400 @@ +#include "holtek_ht12x.h" + +#include "../blocks/const.h" +#include "../blocks/decoder.h" +#include "../blocks/encoder.h" +#include "../blocks/generic.h" +#include "../blocks/math.h" + +/* + * Help + * https://www.holtek.com/documents/10179/116711/HT12A_Ev130.pdf + * + */ + +#define TAG "SubGhzProtocolHoltek_HT12X" + +#define DIP_PATTERN "%c%c%c%c%c%c%c%c" +#define CNT_TO_DIP(dip) \ + (dip & 0x0080 ? '0' : '1'), (dip & 0x0040 ? '0' : '1'), (dip & 0x0020 ? '0' : '1'), \ + (dip & 0x0010 ? '0' : '1'), (dip & 0x0008 ? '0' : '1'), (dip & 0x0004 ? '0' : '1'), \ + (dip & 0x0002 ? '0' : '1'), (dip & 0x0001 ? '0' : '1') + +static const SubGhzBlockConst subghz_protocol_holtek_th12x_const = { + .te_short = 320, + .te_long = 640, + .te_delta = 200, + .min_count_bit_for_found = 12, +}; + +struct SubGhzProtocolDecoderHoltek_HT12X { + SubGhzProtocolDecoderBase base; + + SubGhzBlockDecoder decoder; + SubGhzBlockGeneric generic; + + uint32_t te; + uint32_t last_data; +}; + +struct SubGhzProtocolEncoderHoltek_HT12X { + SubGhzProtocolEncoderBase base; + + SubGhzProtocolBlockEncoder encoder; + SubGhzBlockGeneric generic; + + uint32_t te; +}; + +typedef enum { + Holtek_HT12XDecoderStepReset = 0, + Holtek_HT12XDecoderStepFoundStartBit, + Holtek_HT12XDecoderStepSaveDuration, + Holtek_HT12XDecoderStepCheckDuration, +} Holtek_HT12XDecoderStep; + +const SubGhzProtocolDecoder subghz_protocol_holtek_th12x_decoder = { + .alloc = subghz_protocol_decoder_holtek_th12x_alloc, + .free = subghz_protocol_decoder_holtek_th12x_free, + + .feed = subghz_protocol_decoder_holtek_th12x_feed, + .reset = subghz_protocol_decoder_holtek_th12x_reset, + + .get_hash_data = subghz_protocol_decoder_holtek_th12x_get_hash_data, + .serialize = subghz_protocol_decoder_holtek_th12x_serialize, + .deserialize = subghz_protocol_decoder_holtek_th12x_deserialize, + .get_string = subghz_protocol_decoder_holtek_th12x_get_string, +}; + +const SubGhzProtocolEncoder subghz_protocol_holtek_th12x_encoder = { + .alloc = subghz_protocol_encoder_holtek_th12x_alloc, + .free = subghz_protocol_encoder_holtek_th12x_free, + + .deserialize = subghz_protocol_encoder_holtek_th12x_deserialize, + .stop = subghz_protocol_encoder_holtek_th12x_stop, + .yield = subghz_protocol_encoder_holtek_th12x_yield, +}; + +const SubGhzProtocol subghz_protocol_holtek_th12x = { + .name = SUBGHZ_PROTOCOL_HOLTEK_HT12X_NAME, + .type = SubGhzProtocolTypeStatic, + .flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_868 | SubGhzProtocolFlag_315 | + SubGhzProtocolFlag_AM | SubGhzProtocolFlag_FM | SubGhzProtocolFlag_Decodable | + SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save | SubGhzProtocolFlag_Send, + + .decoder = &subghz_protocol_holtek_th12x_decoder, + .encoder = &subghz_protocol_holtek_th12x_encoder, +}; + +void* subghz_protocol_encoder_holtek_th12x_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); + SubGhzProtocolEncoderHoltek_HT12X* instance = + malloc(sizeof(SubGhzProtocolEncoderHoltek_HT12X)); + + instance->base.protocol = &subghz_protocol_holtek_th12x; + instance->generic.protocol_name = instance->base.protocol->name; + + instance->encoder.repeat = 10; + instance->encoder.size_upload = 128; + instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); + instance->encoder.is_running = false; + return instance; +} + +void subghz_protocol_encoder_holtek_th12x_free(void* context) { + furi_assert(context); + SubGhzProtocolEncoderHoltek_HT12X* instance = context; + free(instance->encoder.upload); + free(instance); +} + +/** + * Generating an upload from data. + * @param instance Pointer to a SubGhzProtocolEncoderHoltek_HT12X instance + * @return true On success + */ +static bool + subghz_protocol_encoder_holtek_th12x_get_upload(SubGhzProtocolEncoderHoltek_HT12X* instance) { + furi_assert(instance); + + size_t index = 0; + size_t size_upload = (instance->generic.data_count_bit * 2) + 2; + if(size_upload > instance->encoder.size_upload) { + FURI_LOG_E(TAG, "Size upload exceeds allocated encoder buffer."); + return false; + } else { + instance->encoder.size_upload = size_upload; + } + + //Send header + instance->encoder.upload[index++] = level_duration_make(false, (uint32_t)instance->te * 36); + //Send start bit + instance->encoder.upload[index++] = level_duration_make(true, (uint32_t)instance->te); + //Send key data + for(uint8_t i = instance->generic.data_count_bit; i > 0; i--) { + if(bit_read(instance->generic.data, i - 1)) { + //send bit 1 + instance->encoder.upload[index++] = + level_duration_make(false, (uint32_t)instance->te * 2); + instance->encoder.upload[index++] = level_duration_make(true, (uint32_t)instance->te); + } else { + //send bit 0 + instance->encoder.upload[index++] = level_duration_make(false, (uint32_t)instance->te); + instance->encoder.upload[index++] = + level_duration_make(true, (uint32_t)instance->te * 2); + } + } + return true; +} + +bool subghz_protocol_encoder_holtek_th12x_deserialize(void* context, FlipperFormat* flipper_format) { + furi_assert(context); + SubGhzProtocolEncoderHoltek_HT12X* instance = context; + bool res = false; + do { + if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + FURI_LOG_E(TAG, "Deserialize error"); + break; + } + if(!flipper_format_rewind(flipper_format)) { + FURI_LOG_E(TAG, "Rewind error"); + break; + } + if(!flipper_format_read_uint32(flipper_format, "TE", (uint32_t*)&instance->te, 1)) { + FURI_LOG_E(TAG, "Missing TE"); + break; + } + if(instance->generic.data_count_bit != + subghz_protocol_holtek_th12x_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } + //optional parameter parameter + flipper_format_read_uint32( + flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); + + if(!subghz_protocol_encoder_holtek_th12x_get_upload(instance)) break; + instance->encoder.is_running = true; + + res = true; + } while(false); + + return res; +} + +void subghz_protocol_encoder_holtek_th12x_stop(void* context) { + SubGhzProtocolEncoderHoltek_HT12X* instance = context; + instance->encoder.is_running = false; +} + +LevelDuration subghz_protocol_encoder_holtek_th12x_yield(void* context) { + SubGhzProtocolEncoderHoltek_HT12X* instance = context; + + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; + return level_duration_reset(); + } + + LevelDuration ret = instance->encoder.upload[instance->encoder.front]; + + if(++instance->encoder.front == instance->encoder.size_upload) { + instance->encoder.repeat--; + instance->encoder.front = 0; + } + + return ret; +} + +void* subghz_protocol_decoder_holtek_th12x_alloc(SubGhzEnvironment* environment) { + UNUSED(environment); + SubGhzProtocolDecoderHoltek_HT12X* instance = + malloc(sizeof(SubGhzProtocolDecoderHoltek_HT12X)); + instance->base.protocol = &subghz_protocol_holtek_th12x; + instance->generic.protocol_name = instance->base.protocol->name; + return instance; +} + +void subghz_protocol_decoder_holtek_th12x_free(void* context) { + furi_assert(context); + SubGhzProtocolDecoderHoltek_HT12X* instance = context; + free(instance); +} + +void subghz_protocol_decoder_holtek_th12x_reset(void* context) { + furi_assert(context); + SubGhzProtocolDecoderHoltek_HT12X* instance = context; + instance->decoder.parser_step = Holtek_HT12XDecoderStepReset; +} + +void subghz_protocol_decoder_holtek_th12x_feed(void* context, bool level, uint32_t duration) { + furi_assert(context); + SubGhzProtocolDecoderHoltek_HT12X* instance = context; + + switch(instance->decoder.parser_step) { + case Holtek_HT12XDecoderStepReset: + if((!level) && (DURATION_DIFF(duration, subghz_protocol_holtek_th12x_const.te_short * 36) < + subghz_protocol_holtek_th12x_const.te_delta * 36)) { + //Found Preambula + instance->decoder.parser_step = Holtek_HT12XDecoderStepFoundStartBit; + } + break; + case Holtek_HT12XDecoderStepFoundStartBit: + if((level) && (DURATION_DIFF(duration, subghz_protocol_holtek_th12x_const.te_short) < + subghz_protocol_holtek_th12x_const.te_delta)) { + //Found StartBit + instance->decoder.parser_step = Holtek_HT12XDecoderStepSaveDuration; + instance->decoder.decode_data = 0; + instance->decoder.decode_count_bit = 0; + instance->te = duration; + } else { + instance->decoder.parser_step = Holtek_HT12XDecoderStepReset; + } + break; + case Holtek_HT12XDecoderStepSaveDuration: + //save duration + if(!level) { + if(duration >= ((uint32_t)subghz_protocol_holtek_th12x_const.te_short * 10 + + subghz_protocol_holtek_th12x_const.te_delta)) { + if(instance->decoder.decode_count_bit == + subghz_protocol_holtek_th12x_const.min_count_bit_for_found) { + if((instance->last_data == instance->decoder.decode_data) && + instance->last_data) { + instance->te /= (instance->decoder.decode_count_bit * 3 + 1); + + instance->generic.data = instance->decoder.decode_data; + instance->generic.data_count_bit = instance->decoder.decode_count_bit; + + if(instance->base.callback) + instance->base.callback(&instance->base, instance->base.context); + } + instance->last_data = instance->decoder.decode_data; + } + instance->decoder.decode_data = 0; + instance->decoder.decode_count_bit = 0; + instance->te = 0; + instance->decoder.parser_step = Holtek_HT12XDecoderStepFoundStartBit; + break; + } else { + instance->decoder.te_last = duration; + instance->te += duration; + instance->decoder.parser_step = Holtek_HT12XDecoderStepCheckDuration; + } + } else { + instance->decoder.parser_step = Holtek_HT12XDecoderStepReset; + } + break; + case Holtek_HT12XDecoderStepCheckDuration: + if(level) { + instance->te += duration; + if((DURATION_DIFF( + instance->decoder.te_last, subghz_protocol_holtek_th12x_const.te_long) < + subghz_protocol_holtek_th12x_const.te_delta * 2) && + (DURATION_DIFF(duration, subghz_protocol_holtek_th12x_const.te_short) < + subghz_protocol_holtek_th12x_const.te_delta)) { + subghz_protocol_blocks_add_bit(&instance->decoder, 1); + instance->decoder.parser_step = Holtek_HT12XDecoderStepSaveDuration; + } else if( + (DURATION_DIFF( + instance->decoder.te_last, subghz_protocol_holtek_th12x_const.te_short) < + subghz_protocol_holtek_th12x_const.te_delta) && + (DURATION_DIFF(duration, subghz_protocol_holtek_th12x_const.te_long) < + subghz_protocol_holtek_th12x_const.te_delta * 2)) { + subghz_protocol_blocks_add_bit(&instance->decoder, 0); + instance->decoder.parser_step = Holtek_HT12XDecoderStepSaveDuration; + } else { + instance->decoder.parser_step = Holtek_HT12XDecoderStepReset; + } + } else { + instance->decoder.parser_step = Holtek_HT12XDecoderStepReset; + } + break; + } +} + +/** + * Analysis of received data + * @param instance Pointer to a SubGhzBlockGeneric* instance + */ +static void subghz_protocol_holtek_th12x_check_remote_controller(SubGhzBlockGeneric* instance) { + instance->btn = instance->data & 0x0F; + instance->cnt = (instance->data >> 4) & 0xFF; +} + +uint8_t subghz_protocol_decoder_holtek_th12x_get_hash_data(void* context) { + furi_assert(context); + SubGhzProtocolDecoderHoltek_HT12X* instance = context; + return subghz_protocol_blocks_get_hash_data( + &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); +} + +bool subghz_protocol_decoder_holtek_th12x_serialize( + void* context, + FlipperFormat* flipper_format, + SubGhzRadioPreset* preset) { + furi_assert(context); + SubGhzProtocolDecoderHoltek_HT12X* instance = context; + bool res = subghz_block_generic_serialize(&instance->generic, flipper_format, preset); + if(res && !flipper_format_write_uint32(flipper_format, "TE", &instance->te, 1)) { + FURI_LOG_E(TAG, "Unable to add TE"); + res = false; + } + return res; +} + +bool subghz_protocol_decoder_holtek_th12x_deserialize(void* context, FlipperFormat* flipper_format) { + furi_assert(context); + SubGhzProtocolDecoderHoltek_HT12X* instance = context; + bool ret = false; + do { + if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + break; + } + if(instance->generic.data_count_bit != + subghz_protocol_holtek_th12x_const.min_count_bit_for_found) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + break; + } + if(!flipper_format_rewind(flipper_format)) { + FURI_LOG_E(TAG, "Rewind error"); + break; + } + if(!flipper_format_read_uint32(flipper_format, "TE", (uint32_t*)&instance->te, 1)) { + FURI_LOG_E(TAG, "Missing TE"); + break; + } + ret = true; + } while(false); + return ret; +} + +static void subghz_protocol_holtek_th12x_event_serialize(uint8_t event, FuriString* output) { + furi_string_cat_printf( + output, + "%s%s%s%s\r\n", + (((event >> 3) & 0x1) == 0x0 ? "B1 " : ""), + (((event >> 2) & 0x1) == 0x0 ? "B2 " : ""), + (((event >> 1) & 0x1) == 0x0 ? "B3 " : ""), + (((event >> 0) & 0x1) == 0x0 ? "B4 " : "")); +} + +void subghz_protocol_decoder_holtek_th12x_get_string(void* context, FuriString* output) { + furi_assert(context); + SubGhzProtocolDecoderHoltek_HT12X* instance = context; + subghz_protocol_holtek_th12x_check_remote_controller(&instance->generic); + + furi_string_cat_printf( + output, + "%s %db\r\n" + "Key:0x%03lX\r\n" + "Btn: ", + instance->generic.protocol_name, + instance->generic.data_count_bit, + (uint32_t)(instance->generic.data & 0xFFF)); + subghz_protocol_holtek_th12x_event_serialize(instance->generic.btn, output); + furi_string_cat_printf( + output, + "DIP:" DIP_PATTERN "\r\n" + "Te:%luus\r\n", + CNT_TO_DIP(instance->generic.cnt), + instance->te); +} diff --git a/lib/subghz/protocols/holtek_ht12x.h b/lib/subghz/protocols/holtek_ht12x.h new file mode 100644 index 000000000..7b5c31dd7 --- /dev/null +++ b/lib/subghz/protocols/holtek_ht12x.h @@ -0,0 +1,107 @@ +#pragma once + +#include "base.h" + +#define SUBGHZ_PROTOCOL_HOLTEK_HT12X_NAME "Holtek_HT12X" + +typedef struct SubGhzProtocolDecoderHoltek_HT12X SubGhzProtocolDecoderHoltek_HT12X; +typedef struct SubGhzProtocolEncoderHoltek_HT12X SubGhzProtocolEncoderHoltek_HT12X; + +extern const SubGhzProtocolDecoder subghz_protocol_holtek_th12x_decoder; +extern const SubGhzProtocolEncoder subghz_protocol_holtek_th12x_encoder; +extern const SubGhzProtocol subghz_protocol_holtek_th12x; + +/** + * Allocate SubGhzProtocolEncoderHoltek_HT12X. + * @param environment Pointer to a SubGhzEnvironment instance + * @return SubGhzProtocolEncoderHoltek_HT12X* pointer to a SubGhzProtocolEncoderHoltek_HT12X instance + */ +void* subghz_protocol_encoder_holtek_th12x_alloc(SubGhzEnvironment* environment); + +/** + * Free SubGhzProtocolEncoderHoltek_HT12X. + * @param context Pointer to a SubGhzProtocolEncoderHoltek_HT12X instance + */ +void subghz_protocol_encoder_holtek_th12x_free(void* context); + +/** + * Deserialize and generating an upload to send. + * @param context Pointer to a SubGhzProtocolEncoderHoltek_HT12X instance + * @param flipper_format Pointer to a FlipperFormat instance + * @return true On success + */ +bool subghz_protocol_encoder_holtek_th12x_deserialize(void* context, FlipperFormat* flipper_format); + +/** + * Forced transmission stop. + * @param context Pointer to a SubGhzProtocolEncoderHoltek_HT12X instance + */ +void subghz_protocol_encoder_holtek_th12x_stop(void* context); + +/** + * Getting the level and duration of the upload to be loaded into DMA. + * @param context Pointer to a SubGhzProtocolEncoderHoltek_HT12X instance + * @return LevelDuration + */ +LevelDuration subghz_protocol_encoder_holtek_th12x_yield(void* context); + +/** + * Allocate SubGhzProtocolDecoderHoltek_HT12X. + * @param environment Pointer to a SubGhzEnvironment instance + * @return SubGhzProtocolDecoderHoltek_HT12X* pointer to a SubGhzProtocolDecoderHoltek_HT12X instance + */ +void* subghz_protocol_decoder_holtek_th12x_alloc(SubGhzEnvironment* environment); + +/** + * Free SubGhzProtocolDecoderHoltek_HT12X. + * @param context Pointer to a SubGhzProtocolDecoderHoltek_HT12X instance + */ +void subghz_protocol_decoder_holtek_th12x_free(void* context); + +/** + * Reset decoder SubGhzProtocolDecoderHoltek_HT12X. + * @param context Pointer to a SubGhzProtocolDecoderHoltek_HT12X instance + */ +void subghz_protocol_decoder_holtek_th12x_reset(void* context); + +/** + * Parse a raw sequence of levels and durations received from the air. + * @param context Pointer to a SubGhzProtocolDecoderHoltek_HT12X instance + * @param level Signal level true-high false-low + * @param duration Duration of this level in, us + */ +void subghz_protocol_decoder_holtek_th12x_feed(void* context, bool level, uint32_t duration); + +/** + * Getting the hash sum of the last randomly received parcel. + * @param context Pointer to a SubGhzProtocolDecoderHoltek_HT12X instance + * @return hash Hash sum + */ +uint8_t subghz_protocol_decoder_holtek_th12x_get_hash_data(void* context); + +/** + * Serialize data SubGhzProtocolDecoderHoltek_HT12X. + * @param context Pointer to a SubGhzProtocolDecoderHoltek_HT12X instance + * @param flipper_format Pointer to a FlipperFormat instance + * @param preset The modulation on which the signal was received, SubGhzRadioPreset + * @return true On success + */ +bool subghz_protocol_decoder_holtek_th12x_serialize( + void* context, + FlipperFormat* flipper_format, + SubGhzRadioPreset* preset); + +/** + * Deserialize data SubGhzProtocolDecoderHoltek_HT12X. + * @param context Pointer to a SubGhzProtocolDecoderHoltek_HT12X instance + * @param flipper_format Pointer to a FlipperFormat instance + * @return true On success + */ +bool subghz_protocol_decoder_holtek_th12x_deserialize(void* context, FlipperFormat* flipper_format); + +/** + * Getting a textual representation of the received data. + * @param context Pointer to a SubGhzProtocolDecoderHoltek_HT12X instance + * @param output Resulting text + */ +void subghz_protocol_decoder_holtek_th12x_get_string(void* context, FuriString* output); diff --git a/lib/subghz/protocols/protocol_items.c b/lib/subghz/protocols/protocol_items.c index ed46f5c97..2022e9c47 100644 --- a/lib/subghz/protocols/protocol_items.c +++ b/lib/subghz/protocols/protocol_items.c @@ -13,6 +13,7 @@ const SubGhzProtocol* subghz_protocol_registry_items[] = { &subghz_protocol_bett, &subghz_protocol_doitrand, &subghz_protocol_phoenix_v2, &subghz_protocol_honeywell_wdb, &subghz_protocol_magellan, &subghz_protocol_intertechno_v3, &subghz_protocol_clemsa, &subghz_protocol_ansonic, &subghz_protocol_smc5326, + &subghz_protocol_holtek_th12x, }; const SubGhzProtocolRegistry subghz_protocol_registry = { diff --git a/lib/subghz/protocols/protocol_items.h b/lib/subghz/protocols/protocol_items.h index 9f4467394..998fb56b3 100644 --- a/lib/subghz/protocols/protocol_items.h +++ b/lib/subghz/protocols/protocol_items.h @@ -37,5 +37,6 @@ #include "clemsa.h" #include "ansonic.h" #include "smc5326.h" +#include "holtek_ht12x.h" extern const SubGhzProtocolRegistry subghz_protocol_registry; From 08eb666f7b45cc9d160c4ea2a36d6a12f00281f2 Mon Sep 17 00:00:00 2001 From: Nikolay Minaylov Date: Tue, 27 Dec 2022 11:39:04 +0300 Subject: [PATCH 31/34] [FL-3000] File browser: Empty folder label (#2188) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: あく --- applications/services/gui/modules/file_browser.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/applications/services/gui/modules/file_browser.c b/applications/services/gui/modules/file_browser.c index d21a48b54..e03a032c1 100644 --- a/applications/services/gui/modules/file_browser.c +++ b/applications/services/gui/modules/file_browser.c @@ -544,6 +544,18 @@ static void browser_draw_list(Canvas* canvas, FileBrowserModel* model) { model->item_cnt); } + uint32_t folder_item_cnt = (model->is_root) ? (model->item_cnt) : (model->item_cnt - 1); + if(folder_item_cnt == 0) { + canvas_set_color(canvas, ColorBlack); + canvas_draw_str_aligned( + canvas, + canvas_width(canvas) / 2, + canvas_height(canvas) / 2, + AlignCenter, + AlignCenter, + ""); + } + furi_string_free(filename); } From ded7e727d03342ade0acf9c32ec42d5d8eda2d63 Mon Sep 17 00:00:00 2001 From: Astra <93453568+Astrrra@users.noreply.github.com> Date: Tue, 27 Dec 2022 11:14:03 +0200 Subject: [PATCH 32/34] [FL-3060] New MFC Bruteforce animation (#2190) * Change the wording in the headers * Add support for text in the progress bar * New MFC key bruteforce screen * Typo fix * nfc: rename Flipper Dict to System Dict * elements: fix types * Display the correct key attack sector Co-authored-by: gornekich Co-authored-by: Aleksandr Kutuzov --- .../main/nfc/scenes/nfc_scene_extra_actions.c | 2 +- .../scenes/nfc_scene_mf_classic_dict_attack.c | 19 +++++-- .../nfc/scenes/nfc_scene_mf_classic_keys.c | 8 +-- applications/main/nfc/scenes/nfc_scene_read.c | 2 +- applications/main/nfc/views/dict_attack.c | 50 ++++++++++++++++--- applications/main/nfc/views/dict_attack.h | 4 ++ applications/services/gui/canvas.h | 1 + applications/services/gui/elements.c | 25 ++++++++++ applications/services/gui/elements.h | 17 +++++++ firmware/targets/f7/api_symbols.csv | 5 +- lib/nfc/helpers/mf_classic_dict.c | 4 +- lib/nfc/helpers/mf_classic_dict.h | 2 +- lib/nfc/nfc_device.h | 3 +- lib/nfc/nfc_worker.c | 8 +++ lib/nfc/nfc_worker.h | 3 ++ 15 files changed, 130 insertions(+), 23 deletions(-) diff --git a/applications/main/nfc/scenes/nfc_scene_extra_actions.c b/applications/main/nfc/scenes/nfc_scene_extra_actions.c index fc6021d73..717e8efc4 100644 --- a/applications/main/nfc/scenes/nfc_scene_extra_actions.c +++ b/applications/main/nfc/scenes/nfc_scene_extra_actions.c @@ -43,7 +43,7 @@ bool nfc_scene_extra_actions_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { if(event.event == SubmenuIndexMfClassicKeys) { - if(mf_classic_dict_check_presence(MfClassicDictTypeFlipper)) { + if(mf_classic_dict_check_presence(MfClassicDictTypeSystem)) { scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicKeys); } else { scene_manager_next_scene(nfc->scene_manager, NfcSceneDictNotFound); diff --git a/applications/main/nfc/scenes/nfc_scene_mf_classic_dict_attack.c b/applications/main/nfc/scenes/nfc_scene_mf_classic_dict_attack.c index acb5b783c..b82bf5521 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_classic_dict_attack.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_classic_dict_attack.c @@ -53,10 +53,10 @@ static void nfc_scene_mf_classic_dict_attack_prepare_view(Nfc* nfc, DictAttackSt // Setup view if(state == DictAttackStateUserDictInProgress) { worker_state = NfcWorkerStateMfClassicDictAttack; - dict_attack_set_header(nfc->dict_attack, "Mf Classic User Dict."); + dict_attack_set_header(nfc->dict_attack, "MF Classic User Dictionary"); dict = mf_classic_dict_alloc(MfClassicDictTypeUser); - // If failed to load user dictionary - try flipper dictionary + // If failed to load user dictionary - try the system dictionary if(!dict) { FURI_LOG_E(TAG, "User dictionary not found"); state = DictAttackStateFlipperDictInProgress; @@ -64,11 +64,11 @@ static void nfc_scene_mf_classic_dict_attack_prepare_view(Nfc* nfc, DictAttackSt } if(state == DictAttackStateFlipperDictInProgress) { worker_state = NfcWorkerStateMfClassicDictAttack; - dict_attack_set_header(nfc->dict_attack, "Mf Classic Flipper Dict."); - dict = mf_classic_dict_alloc(MfClassicDictTypeFlipper); + dict_attack_set_header(nfc->dict_attack, "MF Classic System Dictionary"); + dict = mf_classic_dict_alloc(MfClassicDictTypeSystem); if(!dict) { FURI_LOG_E(TAG, "Flipper dictionary not found"); - // Pass through to let worker handle the failure + // Pass through to let the worker handle the failure } } // Free previous dictionary @@ -153,6 +153,15 @@ bool nfc_scene_mf_classic_dict_attack_on_event(void* context, SceneManagerEvent nfc_worker_stop(nfc->worker); consumed = true; } + } else if(event.event == NfcWorkerEventKeyAttackStart) { + dict_attack_set_key_attack( + nfc->dict_attack, + true, + nfc->dev->dev_data.mf_classic_dict_attack_data.current_sector); + } else if(event.event == NfcWorkerEventKeyAttackStop) { + dict_attack_set_key_attack(nfc->dict_attack, false, 0); + } else if(event.event == NfcWorkerEventKeyAttackNextSector) { + dict_attack_inc_key_attack_current_sector(nfc->dict_attack); } } else if(event.type == SceneManagerEventTypeBack) { scene_manager_next_scene(nfc->scene_manager, NfcSceneExitConfirm); diff --git a/applications/main/nfc/scenes/nfc_scene_mf_classic_keys.c b/applications/main/nfc/scenes/nfc_scene_mf_classic_keys.c index dee9553d4..8a7dc2c18 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_classic_keys.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_classic_keys.c @@ -12,7 +12,7 @@ void nfc_scene_mf_classic_keys_on_enter(void* context) { // Load flipper dict keys total uint32_t flipper_dict_keys_total = 0; - MfClassicDict* dict = mf_classic_dict_alloc(MfClassicDictTypeFlipper); + MfClassicDict* dict = mf_classic_dict_alloc(MfClassicDictTypeSystem); if(dict) { flipper_dict_keys_total = mf_classic_dict_get_total_keys(dict); mf_classic_dict_free(dict); @@ -26,11 +26,11 @@ void nfc_scene_mf_classic_keys_on_enter(void* context) { } widget_add_string_element( - nfc->widget, 0, 0, AlignLeft, AlignTop, FontPrimary, "Mifare Classic Keys"); + nfc->widget, 0, 0, AlignLeft, AlignTop, FontPrimary, "MIFARE Classic Keys"); char temp_str[32]; - snprintf(temp_str, sizeof(temp_str), "Flipper list: %lu", flipper_dict_keys_total); + snprintf(temp_str, sizeof(temp_str), "System dict: %lu", flipper_dict_keys_total); widget_add_string_element(nfc->widget, 0, 20, AlignLeft, AlignTop, FontSecondary, temp_str); - snprintf(temp_str, sizeof(temp_str), "User list: %lu", user_dict_keys_total); + snprintf(temp_str, sizeof(temp_str), "User dict: %lu", user_dict_keys_total); widget_add_string_element(nfc->widget, 0, 32, AlignLeft, AlignTop, FontSecondary, temp_str); widget_add_button_element( nfc->widget, GuiButtonTypeCenter, "Add", nfc_scene_mf_classic_keys_widget_callback, nfc); diff --git a/applications/main/nfc/scenes/nfc_scene_read.c b/applications/main/nfc/scenes/nfc_scene_read.c index 2607cbd8f..4252883b2 100644 --- a/applications/main/nfc/scenes/nfc_scene_read.c +++ b/applications/main/nfc/scenes/nfc_scene_read.c @@ -91,7 +91,7 @@ bool nfc_scene_read_on_event(void* context, SceneManagerEvent event) { DOLPHIN_DEED(DolphinDeedNfcReadSuccess); consumed = true; } else if(event.event == NfcWorkerEventReadMfClassicDictAttackRequired) { - if(mf_classic_dict_check_presence(MfClassicDictTypeFlipper)) { + if(mf_classic_dict_check_presence(MfClassicDictTypeSystem)) { scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicDictAttack); } else { scene_manager_next_scene(nfc->scene_manager, NfcSceneDictNotFound); diff --git a/applications/main/nfc/views/dict_attack.c b/applications/main/nfc/views/dict_attack.c index c5f55ae76..5ae204a06 100644 --- a/applications/main/nfc/views/dict_attack.c +++ b/applications/main/nfc/views/dict_attack.c @@ -24,6 +24,8 @@ typedef struct { uint8_t keys_found; uint16_t dict_keys_total; uint16_t dict_keys_current; + bool is_key_attack; + uint8_t key_attack_current_sector; } DictAttackViewModel; static void dict_attack_draw_callback(Canvas* canvas, void* model) { @@ -36,10 +38,19 @@ static void dict_attack_draw_callback(Canvas* canvas, void* model) { canvas, 64, 23, AlignCenter, AlignTop, "Make sure the tag is\npositioned correctly."); } else if(m->state == DictAttackStateRead) { char draw_str[32] = {}; - canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned( - canvas, 64, 2, AlignCenter, AlignTop, furi_string_get_cstr(m->header)); canvas_set_font(canvas, FontSecondary); + canvas_draw_str_aligned( + canvas, 64, 0, AlignCenter, AlignTop, furi_string_get_cstr(m->header)); + if(m->is_key_attack) { + snprintf( + draw_str, + sizeof(draw_str), + "Reuse key check for sector: %d", + m->key_attack_current_sector); + } else { + snprintf(draw_str, sizeof(draw_str), "Unlocking sector: %d", m->sector_current); + } + canvas_draw_str_aligned(canvas, 0, 10, AlignLeft, AlignTop, draw_str); float dict_progress = m->dict_keys_total == 0 ? 0 : (float)(m->dict_keys_current) / (float)(m->dict_keys_total); @@ -49,13 +60,14 @@ static void dict_attack_draw_callback(Canvas* canvas, void* model) { if(progress > 1.0) { progress = 1.0; } - elements_progress_bar(canvas, 5, 15, 120, progress); + snprintf(draw_str, sizeof(draw_str), "%d/%d", m->dict_keys_current, m->dict_keys_total); + elements_progress_bar_with_text(canvas, 0, 20, 128, dict_progress, draw_str); canvas_set_font(canvas, FontSecondary); snprintf(draw_str, sizeof(draw_str), "Keys found: %d/%d", m->keys_found, m->keys_total); - canvas_draw_str_aligned(canvas, 1, 28, AlignLeft, AlignTop, draw_str); + canvas_draw_str_aligned(canvas, 0, 33, AlignLeft, AlignTop, draw_str); snprintf( draw_str, sizeof(draw_str), "Sectors Read: %d/%d", m->sectors_read, m->sectors_total); - canvas_draw_str_aligned(canvas, 1, 40, AlignLeft, AlignTop, draw_str); + canvas_draw_str_aligned(canvas, 0, 43, AlignLeft, AlignTop, draw_str); } elements_button_center(canvas, "Skip"); } @@ -113,6 +125,7 @@ void dict_attack_reset(DictAttack* dict_attack) { model->keys_found = 0; model->dict_keys_total = 0; model->dict_keys_current = 0; + model->is_key_attack = false; furi_string_reset(model->header); }, false); @@ -235,3 +248,28 @@ void dict_attack_inc_current_dict_key(DictAttack* dict_attack, uint16_t keys_tri }, true); } + +void dict_attack_set_key_attack(DictAttack* dict_attack, bool is_key_attack, uint8_t sector) { + furi_assert(dict_attack); + with_view_model( + dict_attack->view, + DictAttackViewModel * model, + { + model->is_key_attack = is_key_attack; + model->key_attack_current_sector = sector; + }, + true); +} + +void dict_attack_inc_key_attack_current_sector(DictAttack* dict_attack) { + furi_assert(dict_attack); + with_view_model( + dict_attack->view, + DictAttackViewModel * model, + { + if(model->key_attack_current_sector < model->sectors_total) { + model->key_attack_current_sector++; + } + }, + true); +} diff --git a/applications/main/nfc/views/dict_attack.h b/applications/main/nfc/views/dict_attack.h index 684f17f06..2839534a7 100644 --- a/applications/main/nfc/views/dict_attack.h +++ b/applications/main/nfc/views/dict_attack.h @@ -38,3 +38,7 @@ void dict_attack_inc_keys_found(DictAttack* dict_attack); void dict_attack_set_total_dict_keys(DictAttack* dict_attack, uint16_t dict_keys_total); void dict_attack_inc_current_dict_key(DictAttack* dict_attack, uint16_t keys_tried); + +void dict_attack_set_key_attack(DictAttack* dict_attack, bool is_key_attack, uint8_t sector); + +void dict_attack_inc_key_attack_current_sector(DictAttack* dict_attack); \ No newline at end of file diff --git a/applications/services/gui/canvas.h b/applications/services/gui/canvas.h index a3df5adc7..c4eb8649f 100644 --- a/applications/services/gui/canvas.h +++ b/applications/services/gui/canvas.h @@ -17,6 +17,7 @@ extern "C" { typedef enum { ColorWhite = 0x00, ColorBlack = 0x01, + ColorXOR = 0x02, } Color; /** Fonts enumeration */ diff --git a/applications/services/gui/elements.c b/applications/services/gui/elements.c index cd4c105ae..e22889bf9 100644 --- a/applications/services/gui/elements.c +++ b/applications/services/gui/elements.c @@ -41,6 +41,31 @@ void elements_progress_bar(Canvas* canvas, uint8_t x, uint8_t y, uint8_t width, canvas_draw_box(canvas, x + 1, y + 1, progress_length, height - 2); } +void elements_progress_bar_with_text( + Canvas* canvas, + uint8_t x, + uint8_t y, + uint8_t width, + float progress, + const char* text) { + furi_assert(canvas); + furi_assert((progress >= 0.0f) && (progress <= 1.0f)); + uint8_t height = 11; + + uint8_t progress_length = roundf(progress * (width - 2)); + + canvas_set_color(canvas, ColorWhite); + canvas_draw_box(canvas, x + 1, y + 1, width - 2, height - 2); + canvas_set_color(canvas, ColorBlack); + canvas_draw_rframe(canvas, x, y, width, height, 3); + + canvas_draw_box(canvas, x + 1, y + 1, progress_length, height - 2); + + canvas_set_color(canvas, ColorXOR); + canvas_set_font(canvas, FontSecondary); + canvas_draw_str_aligned(canvas, x + width / 2, y + 2, AlignCenter, AlignTop, text); +} + void elements_scrollbar_pos( Canvas* canvas, uint8_t x, diff --git a/applications/services/gui/elements.h b/applications/services/gui/elements.h index 162f0d410..485335131 100644 --- a/applications/services/gui/elements.h +++ b/applications/services/gui/elements.h @@ -31,6 +31,23 @@ extern "C" { */ void elements_progress_bar(Canvas* canvas, uint8_t x, uint8_t y, uint8_t width, float progress); +/** Draw progress bar with text. + * + * @param canvas Canvas instance + * @param x progress bar position on X axis + * @param y progress bar position on Y axis + * @param width progress bar width + * @param progress progress (0.0 - 1.0) + * @param text text to draw + */ +void elements_progress_bar_with_text( + Canvas* canvas, + uint8_t x, + uint8_t y, + uint8_t width, + float progress, + const char* text); + /** Draw scrollbar on canvas at specific position. * * @param canvas Canvas instance diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 8503a838a..72d44b501 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,11.2,, +Version,+,11.3,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -562,8 +562,8 @@ Function,+,ble_glue_wait_for_c2_start,_Bool,int32_t Function,-,bsearch,void*,"const void*, const void*, size_t, size_t, __compar_fn_t" Function,+,bt_disconnect,void,Bt* Function,+,bt_forget_bonded_devices,void,Bt* -Function,+,bt_keys_storage_set_storage_path,void,"Bt*, const char*" Function,+,bt_keys_storage_set_default_path,void,Bt* +Function,+,bt_keys_storage_set_storage_path,void,"Bt*, const char*" Function,+,bt_set_profile,_Bool,"Bt*, BtProfile" Function,+,bt_set_status_changed_callback,void,"Bt*, BtStatusChangedCallback, void*" Function,+,buffered_file_stream_alloc,Stream*,Storage* @@ -754,6 +754,7 @@ Function,+,elements_multiline_text,void,"Canvas*, uint8_t, uint8_t, const char*" Function,+,elements_multiline_text_aligned,void,"Canvas*, uint8_t, uint8_t, Align, Align, const char*" Function,+,elements_multiline_text_framed,void,"Canvas*, uint8_t, uint8_t, const char*" Function,+,elements_progress_bar,void,"Canvas*, uint8_t, uint8_t, uint8_t, float" +Function,+,elements_progress_bar_with_text,void,"Canvas*, uint8_t, uint8_t, uint8_t, float, const char*" Function,+,elements_scrollable_text_line,void,"Canvas*, uint8_t, uint8_t, uint8_t, FuriString*, size_t, _Bool" Function,+,elements_scrollbar,void,"Canvas*, uint16_t, uint16_t" Function,+,elements_scrollbar_pos,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint16_t, uint16_t" diff --git a/lib/nfc/helpers/mf_classic_dict.c b/lib/nfc/helpers/mf_classic_dict.c index 98076479f..93098d409 100644 --- a/lib/nfc/helpers/mf_classic_dict.c +++ b/lib/nfc/helpers/mf_classic_dict.c @@ -20,7 +20,7 @@ bool mf_classic_dict_check_presence(MfClassicDictType dict_type) { Storage* storage = furi_record_open(RECORD_STORAGE); bool dict_present = false; - if(dict_type == MfClassicDictTypeFlipper) { + if(dict_type == MfClassicDictTypeSystem) { dict_present = storage_common_stat(storage, MF_CLASSIC_DICT_FLIPPER_PATH, NULL) == FSE_OK; } else if(dict_type == MfClassicDictTypeUser) { dict_present = storage_common_stat(storage, MF_CLASSIC_DICT_USER_PATH, NULL) == FSE_OK; @@ -42,7 +42,7 @@ MfClassicDict* mf_classic_dict_alloc(MfClassicDictType dict_type) { bool dict_loaded = false; do { - if(dict_type == MfClassicDictTypeFlipper) { + if(dict_type == MfClassicDictTypeSystem) { if(!buffered_file_stream_open( dict->stream, MF_CLASSIC_DICT_FLIPPER_PATH, diff --git a/lib/nfc/helpers/mf_classic_dict.h b/lib/nfc/helpers/mf_classic_dict.h index 5b0ee312a..3b2d560ad 100644 --- a/lib/nfc/helpers/mf_classic_dict.h +++ b/lib/nfc/helpers/mf_classic_dict.h @@ -8,7 +8,7 @@ typedef enum { MfClassicDictTypeUser, - MfClassicDictTypeFlipper, + MfClassicDictTypeSystem, MfClassicDictTypeUnitTest, } MfClassicDictType; diff --git a/lib/nfc/nfc_device.h b/lib/nfc/nfc_device.h index 55ee4ac4c..8b2e6e5ba 100644 --- a/lib/nfc/nfc_device.h +++ b/lib/nfc/nfc_device.h @@ -18,7 +18,7 @@ extern "C" { #define NFC_DEV_NAME_MAX_LEN 22 #define NFC_READER_DATA_MAX_SIZE 64 -#define NFC_DICT_KEY_BATCH_SIZE 50 +#define NFC_DICT_KEY_BATCH_SIZE 10 #define NFC_APP_EXTENSION ".nfc" #define NFC_APP_SHADOW_EXTENSION ".shd" @@ -48,6 +48,7 @@ typedef struct { typedef struct { MfClassicDict* dict; + uint8_t current_sector; } NfcMfClassicDictAttackData; typedef enum { diff --git a/lib/nfc/nfc_worker.c b/lib/nfc/nfc_worker.c index 0ffe1d07b..4a66593cb 100644 --- a/lib/nfc/nfc_worker.c +++ b/lib/nfc/nfc_worker.c @@ -573,17 +573,24 @@ static void nfc_worker_mf_classic_key_attack( FuriHalNfcTxRxContext* tx_rx, uint16_t start_sector) { furi_assert(nfc_worker); + furi_assert(nfc_worker->callback); bool card_found_notified = true; bool card_removed_notified = false; MfClassicData* data = &nfc_worker->dev_data->mf_classic_data; + NfcMfClassicDictAttackData* dict_attack_data = + &nfc_worker->dev_data->mf_classic_dict_attack_data; uint32_t total_sectors = mf_classic_get_total_sectors_num(data->type); furi_assert(start_sector < total_sectors); + nfc_worker->callback(NfcWorkerEventKeyAttackStart, nfc_worker->context); + // Check every sector's A and B keys with the given key for(size_t i = start_sector; i < total_sectors; i++) { + nfc_worker->callback(NfcWorkerEventKeyAttackNextSector, nfc_worker->context); + dict_attack_data->current_sector = i; furi_hal_nfc_sleep(); if(furi_hal_nfc_activate_nfca(200, NULL)) { furi_hal_nfc_sleep(); @@ -632,6 +639,7 @@ static void nfc_worker_mf_classic_key_attack( } if(nfc_worker->state != NfcWorkerStateMfClassicDictAttack) break; } + nfc_worker->callback(NfcWorkerEventKeyAttackStop, nfc_worker->context); } void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker) { diff --git a/lib/nfc/nfc_worker.h b/lib/nfc/nfc_worker.h index fdcaa72fd..ce542828a 100644 --- a/lib/nfc/nfc_worker.h +++ b/lib/nfc/nfc_worker.h @@ -55,6 +55,9 @@ typedef enum { NfcWorkerEventNewDictKeyBatch, NfcWorkerEventFoundKeyA, NfcWorkerEventFoundKeyB, + NfcWorkerEventKeyAttackStart, + NfcWorkerEventKeyAttackStop, + NfcWorkerEventKeyAttackNextSector, // Write Mifare Classic events NfcWorkerEventWrongCard, From 727f043747ad337a035ea946733e42be7fd166cb Mon Sep 17 00:00:00 2001 From: Sergey Gavrilov Date: Tue, 27 Dec 2022 22:59:36 +1000 Subject: [PATCH 33/34] OpenOCD scripts (#2101) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Scripts: option bytes check * Scripts: option bytes set * Scripts: openocd config * Scripts: increased readability, process IPCCBR option byte * Scripts: split dap_ob.py * Updater: process IPCCBR option byte * Scripts: move chip-related functions to chip definition * Scripts: freeze CPU registers * Scripts: flash programming routine * ob.py * otp.py * otp: handle errors correctly * downgrade to python 3.9 * correct type hinting * Scripts: fix path to ob.data Co-authored-by: あく --- firmware/targets/f7/furi_hal/furi_hal_flash.c | 2 +- scripts/flipper/utils/openocd.py | 173 +++++++++ scripts/flipper/utils/programmer.py | 31 ++ scripts/flipper/utils/programmer_openocd.py | 281 ++++++++++++++ scripts/flipper/utils/register.py | 95 +++++ scripts/flipper/utils/stm32wb55.py | 352 ++++++++++++++++++ scripts/ob.py | 92 +++-- scripts/otp.py | 75 ++-- 8 files changed, 1035 insertions(+), 66 deletions(-) create mode 100644 scripts/flipper/utils/openocd.py create mode 100644 scripts/flipper/utils/programmer.py create mode 100644 scripts/flipper/utils/programmer_openocd.py create mode 100644 scripts/flipper/utils/register.py create mode 100644 scripts/flipper/utils/stm32wb55.py diff --git a/firmware/targets/f7/furi_hal/furi_hal_flash.c b/firmware/targets/f7/furi_hal/furi_hal_flash.c index e49cd5f29..fc021d969 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_flash.c +++ b/firmware/targets/f7/furi_hal/furi_hal_flash.c @@ -488,7 +488,7 @@ static const FuriHalFlashObMapping furi_hal_flash_ob_reg_map[FURI_HAL_FLASH_OB_T OB_REG_DEF(FuriHalFlashObInvalid, (NULL)), OB_REG_DEF(FuriHalFlashObInvalid, (NULL)), - OB_REG_DEF(FuriHalFlashObRegisterIPCCMail, (NULL)), + OB_REG_DEF(FuriHalFlashObRegisterIPCCMail, (&FLASH->IPCCBR)), OB_REG_DEF(FuriHalFlashObRegisterSecureFlash, (NULL)), OB_REG_DEF(FuriHalFlashObRegisterC2Opts, (NULL)), }; diff --git a/scripts/flipper/utils/openocd.py b/scripts/flipper/utils/openocd.py new file mode 100644 index 000000000..1309055b8 --- /dev/null +++ b/scripts/flipper/utils/openocd.py @@ -0,0 +1,173 @@ +import socket +import subprocess +import logging + + +class OpenOCD: + """OpenOCD cli wrapper""" + + COMMAND_TOKEN = "\x1a" + + def __init__(self, config: dict = {}) -> None: + assert isinstance(config, dict) + + # Params base + self.params = [] + + self.gdb_port = 3333 + self.telnet_port = 4444 + self.tcl_port = 6666 + + # Port + if port_base := config.get("port_base", None): + self.gdb_port = port_base + self.tcl_port = port_base + 1 + self.telnet_port = port_base + 2 + + self._add_command(f"gdb_port {self.gdb_port}") + self._add_command(f"tcl_port {self.tcl_port}") + self._add_command(f"telnet_port {self.telnet_port}") + + # Config files + + if interface := config.get("interface", None): + pass + else: + interface = "interface/stlink.cfg" + + if target := config.get("target", None): + pass + else: + target = "target/stm32wbx.cfg" + + self._add_file(interface) + self._add_file(target) + + # Programmer settings + if serial := config.get("serial", None): + self._add_command(f"{serial}") + + # Other params + if "params" in config: + self.params += config["params"] + + # logging + self.logger = logging.getLogger() + + def _add_command(self, command: str): + self.params.append("-c") + self.params.append(command) + + def _add_file(self, file: str): + self.params.append("-f") + self.params.append(file) + + def start(self, args: list[str] = []): + """Start OpenOCD process""" + + params = ["openocd", *self.params, *args] + self.logger.debug(f"_execute: {params}") + self.process = subprocess.Popen( + params, stderr=subprocess.PIPE, stdout=subprocess.PIPE + ) + + self._wait_for_openocd_tcl() + + self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.socket.connect(("127.0.0.1", self.tcl_port)) + + def _wait_for_openocd_tcl(self): + """Wait for OpenOCD to start""" + # TODO: timeout + while True: + stderr = self.process.stderr + if not stderr: + break + line = stderr.readline() + if not line: + break + line = line.decode("utf-8").strip() + self.logger.debug(f"OpenOCD: {line}") + if "Listening on port" in line and "for tcl connections" in line: + break + + def stop(self): + self.send_tcl("exit") + self.send_tcl("shutdown") + self.socket.close() + try: + self.process.wait(timeout=10) + except subprocess.TimeoutExpired as e: + self.process.kill() + self.logger.error("Failed to stop OpenOCD") + self.logger.exception(e) + self.postmortem() + + def send_tcl(self, cmd) -> str: + """Send a command string to TCL RPC. Return the result that was read.""" + + try: + data = (cmd + OpenOCD.COMMAND_TOKEN).encode("utf-8") + self.logger.debug(f"<- {data}") + + self.socket.send(data) + except Exception as e: + self.logger.error("Failed to send command to OpenOCD") + self.logger.exception(e) + self.postmortem() + raise + + try: + data = self._recv() + return data + except Exception as e: + self.logger.error("Failed to receive response from OpenOCD") + self.logger.exception(e) + self.postmortem() + raise + + def _recv(self): + """Read from the stream until the token (\x1a) was received.""" + # TODO: timeout + data = bytes() + while True: + chunk = self.socket.recv(4096) + data += chunk + if bytes(OpenOCD.COMMAND_TOKEN, encoding="utf-8") in chunk: + break + + self.logger.debug(f"-> {data}") + + data = data.decode("utf-8").strip() + data = data[:-1] # strip trailing \x1a + + return data + + def postmortem(self) -> None: + """Postmortem analysis of the OpenOCD process""" + stdout, stderr = self.process.communicate() + + log = self.logger.error + if self.process.returncode == 0: + log = self.logger.debug + log("OpenOCD exited normally") + else: + log("OpenOCD exited with error") + + log(f"Exit code: {self.process.returncode}") + for line in stdout.decode("utf-8").splitlines(): + log(f"Stdout: {line}") + + for line in stderr.decode("utf-8").splitlines(): + log(f"Stderr: {line}") + + def read_32(self, addr: int) -> int: + """Read 32-bit value from memory""" + data = self.send_tcl(f"mdw {addr}").strip() + data = data.split(": ")[-1] + data = int(data, 16) + return data + + def write_32(self, addr: int, value: int) -> None: + """Write 32-bit value to memory""" + self.send_tcl(f"mww {addr} {value}") diff --git a/scripts/flipper/utils/programmer.py b/scripts/flipper/utils/programmer.py new file mode 100644 index 000000000..84452d154 --- /dev/null +++ b/scripts/flipper/utils/programmer.py @@ -0,0 +1,31 @@ +from abc import ABC, abstractmethod +from enum import Enum + + +class Programmer(ABC): + def __init__(self): + pass + + class RunMode(Enum): + Run = "run" + Stop = "stop" + + @abstractmethod + def reset(self, mode: RunMode = RunMode.Run) -> bool: + pass + + @abstractmethod + def flash(self, address: int, file_path: str, verify: bool = True) -> bool: + pass + + @abstractmethod + def option_bytes_validate(self, file_path: str) -> bool: + pass + + @abstractmethod + def option_bytes_set(self, file_path: str) -> bool: + pass + + @abstractmethod + def otp_write(self, address: int, file_path: str) -> bool: + pass diff --git a/scripts/flipper/utils/programmer_openocd.py b/scripts/flipper/utils/programmer_openocd.py new file mode 100644 index 000000000..b33406103 --- /dev/null +++ b/scripts/flipper/utils/programmer_openocd.py @@ -0,0 +1,281 @@ +import logging +import os +import typing + +from flipper.utils.programmer import Programmer +from flipper.utils.openocd import OpenOCD +from flipper.utils.stm32wb55 import STM32WB55 +from flipper.assets.obdata import OptionBytesData + + +class OpenOCDProgrammer(Programmer): + def __init__( + self, + interface: str = "interface/cmsis-dap.cfg", + port_base: typing.Union[int, None] = None, + serial: typing.Union[str, None] = None, + ): + super().__init__() + + config = {} + + config["interface"] = interface + config["target"] = "target/stm32wbx.cfg" + + if not serial is None: + if interface == "interface/cmsis-dap.cfg": + config["serial"] = f"cmsis_dap_serial {serial}" + elif "stlink" in interface: + config["serial"] = f"stlink_serial {serial}" + + if not port_base is None: + config["port_base"] = port_base + + self.openocd = OpenOCD(config) + self.logger = logging.getLogger() + + def reset(self, mode: Programmer.RunMode = Programmer.RunMode.Run) -> bool: + stm32 = STM32WB55() + if mode == Programmer.RunMode.Run: + stm32.reset(self.openocd, stm32.RunMode.Run) + elif mode == Programmer.RunMode.Stop: + stm32.reset(self.openocd, stm32.RunMode.Init) + else: + raise Exception("Unknown mode") + + return True + + def flash(self, address: int, file_path: str, verify: bool = True) -> bool: + if not os.path.exists(file_path): + raise Exception(f"File {file_path} not found") + + self.openocd.start() + self.openocd.send_tcl(f"init") + self.openocd.send_tcl( + f"program {file_path} 0x{address:08x}{' verify' if verify else ''} reset exit" + ) + self.openocd.stop() + + return True + + def _ob_print_diff_table(self, ob_reference: bytes, ob_read: bytes, print_fn): + print_fn( + f'{"Reference": <20} {"Device": <20} {"Diff Reference": <20} {"Diff Device": <20}' + ) + + # Split into 8 byte, word + word + for i in range(0, len(ob_reference), 8): + ref = ob_reference[i : i + 8] + read = ob_read[i : i + 8] + + diff_str1 = "" + diff_str2 = "" + for j in range(0, len(ref.hex()), 2): + byte_str_1 = ref.hex()[j : j + 2] + byte_str_2 = read.hex()[j : j + 2] + + if byte_str_1 == byte_str_2: + diff_str1 += "__" + diff_str2 += "__" + else: + diff_str1 += byte_str_1 + diff_str2 += byte_str_2 + + print_fn( + f"{ref.hex(): <20} {read.hex(): <20} {diff_str1: <20} {diff_str2: <20}" + ) + + def option_bytes_validate(self, file_path: str) -> bool: + # Registers + stm32 = STM32WB55() + + # OpenOCD + self.openocd.start() + stm32.reset(self.openocd, stm32.RunMode.Init) + + # Generate Option Bytes data + ob_data = OptionBytesData(file_path) + ob_values = ob_data.gen_values().export() + ob_reference = ob_values.reference + ob_compare_mask = ob_values.compare_mask + ob_length = len(ob_reference) + ob_words = int(ob_length / 4) + + # Read Option Bytes + ob_read = bytes() + for i in range(ob_words): + addr = stm32.OPTION_BYTE_BASE + i * 4 + value = self.openocd.read_32(addr) + ob_read += value.to_bytes(4, "little") + + # Compare Option Bytes with reference by mask + ob_compare = bytes() + for i in range(ob_length): + ob_compare += bytes([ob_read[i] & ob_compare_mask[i]]) + + # Compare Option Bytes + return_code = False + + if ob_reference == ob_compare: + self.logger.info("Option Bytes are valid") + return_code = True + else: + self.logger.error("Option Bytes are invalid") + self._ob_print_diff_table(ob_reference, ob_compare, self.logger.error) + + # Stop OpenOCD + stm32.reset(self.openocd, stm32.RunMode.Run) + self.openocd.stop() + + return return_code + + def _unpack_u32(self, data: bytes, offset: int): + return int.from_bytes(data[offset : offset + 4], "little") + + def option_bytes_set(self, file_path: str) -> bool: + # Registers + stm32 = STM32WB55() + + # OpenOCD + self.openocd.start() + stm32.reset(self.openocd, stm32.RunMode.Init) + + # Generate Option Bytes data + ob_data = OptionBytesData(file_path) + ob_values = ob_data.gen_values().export() + ob_reference_bytes = ob_values.reference + ob_compare_mask_bytes = ob_values.compare_mask + ob_write_mask_bytes = ob_values.write_mask + ob_length = len(ob_reference_bytes) + ob_dwords = int(ob_length / 8) + + # Clear flash errors + stm32.clear_flash_errors(self.openocd) + + # Unlock Flash and Option Bytes + stm32.flash_unlock(self.openocd) + stm32.option_bytes_unlock(self.openocd) + + ob_need_to_apply = False + + for i in range(ob_dwords): + device_addr = stm32.OPTION_BYTE_BASE + i * 8 + device_value = self.openocd.read_32(device_addr) + ob_write_mask = self._unpack_u32(ob_write_mask_bytes, i * 8) + ob_compare_mask = self._unpack_u32(ob_compare_mask_bytes, i * 8) + ob_value_ref = self._unpack_u32(ob_reference_bytes, i * 8) + ob_value_masked = device_value & ob_compare_mask + + need_patch = ((ob_value_masked ^ ob_value_ref) & ob_write_mask) != 0 + if need_patch: + ob_need_to_apply = True + + self.logger.info( + f"Need to patch: {device_addr:08X}: {ob_value_masked:08X} != {ob_value_ref:08X}, REG[{i}]" + ) + + # Check if this option byte (dword) is mapped to a register + device_reg_addr = stm32.option_bytes_id_to_address(i) + + # Construct new value for the OB register + ob_value = device_value & (~ob_write_mask) + ob_value |= ob_value_ref & ob_write_mask + + self.logger.info(f"Writing {ob_value:08X} to {device_reg_addr:08X}") + self.openocd.write_32(device_reg_addr, ob_value) + + if ob_need_to_apply: + stm32.option_bytes_apply(self.openocd) + else: + self.logger.info(f"Option Bytes are already correct") + + # Load Option Bytes + # That will reset and also lock the Option Bytes and the Flash + stm32.option_bytes_load(self.openocd) + + # Stop OpenOCD + stm32.reset(self.openocd, stm32.RunMode.Run) + self.openocd.stop() + + return True + + def otp_write(self, address: int, file_path: str) -> bool: + # Open file, check that it aligned to 8 bytes + with open(file_path, "rb") as f: + data = f.read() + if len(data) % 8 != 0: + self.logger.error(f"File {file_path} is not aligned to 8 bytes") + return False + + # Check that address is aligned to 8 bytes + if address % 8 != 0: + self.logger.error(f"Address {address} is not aligned to 8 bytes") + return False + + # Get size of data + data_size = len(data) + + # Check that data size is aligned to 8 bytes + if data_size % 8 != 0: + self.logger.error(f"Data size {data_size} is not aligned to 8 bytes") + return False + + self.logger.debug(f"Writing {data_size} bytes to OTP at {address:08X}") + self.logger.debug(f"Data: {data.hex().upper()}") + + # Start OpenOCD + oocd = self.openocd + oocd.start() + + # Registers + stm32 = STM32WB55() + + try: + # Check that OTP is empty for the given address + # Also check that data is already written + already_written = True + for i in range(0, data_size, 4): + file_word = int.from_bytes(data[i : i + 4], "little") + device_word = oocd.read_32(address + i) + if device_word != 0xFFFFFFFF and device_word != file_word: + self.logger.error( + f"OTP memory at {address + i:08X} is not empty: {device_word:08X}" + ) + raise Exception("OTP memory is not empty") + + if device_word != file_word: + already_written = False + + if already_written: + self.logger.info(f"OTP memory is already written with the given data") + return True + + self.reset(self.RunMode.Stop) + stm32.clear_flash_errors(oocd) + + # Write OTP memory by 8 bytes + for i in range(0, data_size, 8): + word_1 = int.from_bytes(data[i : i + 4], "little") + word_2 = int.from_bytes(data[i + 4 : i + 8], "little") + self.logger.debug( + f"Writing {word_1:08X} {word_2:08X} to {address + i:08X}" + ) + stm32.write_flash_64(oocd, address + i, word_1, word_2) + + # Validate OTP memory + validation_result = True + + for i in range(0, data_size, 4): + file_word = int.from_bytes(data[i : i + 4], "little") + device_word = oocd.read_32(address + i) + if file_word != device_word: + self.logger.error( + f"Validation failed: {file_word:08X} != {device_word:08X} at {address + i:08X}" + ) + validation_result = False + finally: + # Stop OpenOCD + stm32.reset(oocd, stm32.RunMode.Run) + oocd.stop() + + return validation_result diff --git a/scripts/flipper/utils/register.py b/scripts/flipper/utils/register.py new file mode 100644 index 000000000..26d66730c --- /dev/null +++ b/scripts/flipper/utils/register.py @@ -0,0 +1,95 @@ +from dataclasses import dataclass +from flipper.utils.openocd import OpenOCD + + +@dataclass +class RegisterBitDefinition: + name: str + offset: int + size: int + value: int = 0 + + +class Register32: + def __init__(self, address: int, definition_list: list[RegisterBitDefinition]): + self.__dict__["names"] = [definition.name for definition in definition_list] + self.names = [definition.name for definition in definition_list] # typecheck + self.address = address + self.definition_list = definition_list + + # Validate that the definitions are not overlapping + for i in range(len(definition_list)): + for j in range(i + 1, len(definition_list)): + if self._is_overlapping(definition_list[i], definition_list[j]): + raise ValueError("Register definitions are overlapping") + + self.freezed = True + + def _is_overlapping( + self, a: RegisterBitDefinition, b: RegisterBitDefinition + ) -> bool: + if a.offset + a.size <= b.offset: + return False + if b.offset + b.size <= a.offset: + return False + return True + + def _get_definition(self, name: str) -> RegisterBitDefinition: + for definition in self.definition_list: + if definition.name == name: + return definition + raise ValueError(f"Register definition '{name}' not found") + + def get_definition_list(self) -> list[RegisterBitDefinition]: + return self.definition_list + + def get_address(self) -> int: + return self.address + + def set_reg_value(self, name: str, value: int): + definition = self._get_definition(name) + if value > (1 << definition.size) - 1: + raise ValueError( + f"Value {value} is too large for register definition '{name}'" + ) + definition.value = value + + def get_reg_value(self, name: str) -> int: + definition = self._get_definition(name) + return definition.value + + def __getattr__(self, attr): + if str(attr) in self.names: + return self.get_reg_value(str(attr)) + else: + return self.__dict__[attr] + + def __setattr__(self, attr, value): + if str(attr) in self.names: + self.set_reg_value(str(attr), value) + else: + if attr in self.__dict__ or "freezed" not in self.__dict__: + self.__dict__[attr] = value + else: + raise AttributeError(f"Attribute '{attr}' not found") + + def __dir__(self): + return self.names + + def set(self, value: int): + for definition in self.definition_list: + definition.value = (value >> definition.offset) & ( + (1 << definition.size) - 1 + ) + + def get(self) -> int: + value = 0 + for definition in self.definition_list: + value |= definition.value << definition.offset + return value + + def load(self, openocd: OpenOCD): + self.set(openocd.read_32(self.address)) + + def store(self, openocd: OpenOCD): + openocd.write_32(self.address, self.get()) diff --git a/scripts/flipper/utils/stm32wb55.py b/scripts/flipper/utils/stm32wb55.py new file mode 100644 index 000000000..910b0d7d6 --- /dev/null +++ b/scripts/flipper/utils/stm32wb55.py @@ -0,0 +1,352 @@ +import logging +from enum import Enum + +from flipper.utils.openocd import OpenOCD +from flipper.utils.register import Register32, RegisterBitDefinition + + +class STM32WB55: + # Address of OTP memory in flash + OTP_BASE = 0x1FFF7000 + + # Address of Option byte in flash + OPTION_BYTE_BASE = 0x1FFF8000 + + # Flash base address + FLASH_BASE = 0x58004000 + + # Flash unlock register + FLASH_KEYR = FLASH_BASE + 0x08 + + # Option byte unlock register + FLASH_OPTKEYR = FLASH_BASE + 0x0C + + # Flash unlock keys + FLASH_UNLOCK_KEY1 = 0x45670123 + FLASH_UNLOCK_KEY2 = 0xCDEF89AB + + # Option byte unlock keys + FLASH_UNLOCK_OPTKEY1 = 0x08192A3B + FLASH_UNLOCK_OPTKEY2 = 0x4C5D6E7F + + # Flash control register + FLASH_CR = Register32( + FLASH_BASE + 0x14, + [ + RegisterBitDefinition("PG", 0, 1), + RegisterBitDefinition("PER", 1, 1), + RegisterBitDefinition("MER", 2, 1), + RegisterBitDefinition("PNB", 3, 8), + RegisterBitDefinition("_", 11, 5), + RegisterBitDefinition("STRT", 16, 1), + RegisterBitDefinition("OPT_STRT", 17, 1), + RegisterBitDefinition("FSTPG", 18, 1), + RegisterBitDefinition("_", 19, 5), + RegisterBitDefinition("EOPIE", 24, 1), + RegisterBitDefinition("ERRIE", 25, 1), + RegisterBitDefinition("RD_ERRIE", 26, 1), + RegisterBitDefinition("OBL_LAUNCH", 27, 1), + RegisterBitDefinition("_", 28, 2), + RegisterBitDefinition("OPT_LOCK", 30, 1), + RegisterBitDefinition("LOCK", 31, 1), + ], + ) + + # Flash status register + FLASH_SR = Register32( + FLASH_BASE + 0x10, + [ + RegisterBitDefinition("EOP", 0, 1), + RegisterBitDefinition("OP_ERR", 1, 1), + RegisterBitDefinition("_", 2, 1), + RegisterBitDefinition("PROG_ERR", 3, 1), + RegisterBitDefinition("WRP_ERR", 4, 1), + RegisterBitDefinition("PGA_ERR", 5, 1), + RegisterBitDefinition("SIZE_ERR", 6, 1), + RegisterBitDefinition("PGS_ERR", 7, 1), + RegisterBitDefinition("MISS_ERR", 8, 1), + RegisterBitDefinition("FAST_ERR", 9, 1), + RegisterBitDefinition("_", 10, 3), + RegisterBitDefinition("OPTNV", 13, 1), + RegisterBitDefinition("RD_ERR", 14, 1), + RegisterBitDefinition("OPTV_ERR", 15, 1), + RegisterBitDefinition("BSY", 16, 1), + RegisterBitDefinition("_", 17, 1), + RegisterBitDefinition("CFGBSY", 18, 1), + RegisterBitDefinition("PESD", 19, 1), + RegisterBitDefinition("_", 20, 12), + ], + ) + + # Option byte registers + FLASH_OPTR = FLASH_BASE + 0x20 + FLASH_PCROP1ASR = FLASH_BASE + 0x24 + FLASH_PCROP1AER = FLASH_BASE + 0x28 + FLASH_WRP1AR = FLASH_BASE + 0x2C + FLASH_WRP1BR = FLASH_BASE + 0x30 + FLASH_PCROP1BSR = FLASH_BASE + 0x34 + FLASH_PCROP1BER = FLASH_BASE + 0x38 + FLASH_IPCCBR = FLASH_BASE + 0x3C + + # Map option byte dword index to register address + OPTION_BYTE_MAP_TO_REGS = { + 0: FLASH_OPTR, + 1: FLASH_PCROP1ASR, + 2: FLASH_PCROP1AER, + 3: FLASH_WRP1AR, + 4: FLASH_WRP1BR, + 5: FLASH_PCROP1BSR, + 6: FLASH_PCROP1BER, + 7: None, # Invalid Options + 8: None, # Invalid Options + 9: None, # Invalid Options + 10: None, # Invalid Options + 11: None, # Invalid Options + 12: None, # Invalid Options + 13: FLASH_IPCCBR, + 14: None, # Secure Flash + 15: None, # Core 2 Options + } + + def __init__(self): + self.logger = logging.getLogger("STM32WB55") + + class RunMode(Enum): + Init = "init" + Run = "run" + Halt = "halt" + + def reset(self, oocd: OpenOCD, mode: RunMode): + self.logger.debug("Resetting device") + oocd.send_tcl(f"reset {mode.value}") + + def clear_flash_errors(self, oocd: OpenOCD): + # Errata 2.2.9: Flash OPTVERR flag is always set after system reset + # And also clear all other flash error flags + self.logger.debug(f"Resetting flash errors") + self.FLASH_SR.load(oocd) + self.FLASH_SR.OP_ERR = 1 + self.FLASH_SR.PROG_ERR = 1 + self.FLASH_SR.WRP_ERR = 1 + self.FLASH_SR.PGA_ERR = 1 + self.FLASH_SR.SIZE_ERR = 1 + self.FLASH_SR.PGS_ERR = 1 + self.FLASH_SR.MISS_ERR = 1 + self.FLASH_SR.FAST_ERR = 1 + self.FLASH_SR.RD_ERR = 1 + self.FLASH_SR.OPTV_ERR = 1 + self.FLASH_SR.store(oocd) + + def flash_unlock(self, oocd: OpenOCD): + # Check if flash is already unlocked + self.FLASH_CR.load(oocd) + if self.FLASH_CR.LOCK == 0: + self.logger.debug("Flash is already unlocked") + return + + # Unlock flash + self.logger.debug("Unlocking Flash") + oocd.write_32(self.FLASH_KEYR, self.FLASH_UNLOCK_KEY1) + oocd.write_32(self.FLASH_KEYR, self.FLASH_UNLOCK_KEY2) + + # Check if flash is unlocked + self.FLASH_CR.load(oocd) + if self.FLASH_CR.LOCK == 0: + self.logger.debug("Flash unlocked") + else: + self.logger.error("Flash unlock failed") + raise Exception("Flash unlock failed") + + def option_bytes_unlock(self, oocd: OpenOCD): + # Check if options is already unlocked + self.FLASH_CR.load(oocd) + if self.FLASH_CR.OPT_LOCK == 0: + self.logger.debug("Options is already unlocked") + return + + # Unlock options + self.logger.debug("Unlocking Options") + oocd.write_32(self.FLASH_OPTKEYR, self.FLASH_UNLOCK_OPTKEY1) + oocd.write_32(self.FLASH_OPTKEYR, self.FLASH_UNLOCK_OPTKEY2) + + # Check if options is unlocked + self.FLASH_CR.load(oocd) + if self.FLASH_CR.OPT_LOCK == 0: + self.logger.debug("Options unlocked") + else: + self.logger.error("Options unlock failed") + raise Exception("Options unlock failed") + + def option_bytes_lock(self, oocd: OpenOCD): + # Check if options is already locked + self.FLASH_CR.load(oocd) + if self.FLASH_CR.OPT_LOCK == 1: + self.logger.debug("Options is already locked") + return + + # Lock options + self.logger.debug("Locking Options") + self.FLASH_CR.OPT_LOCK = 1 + self.FLASH_CR.store(oocd) + + # Check if options is locked + self.FLASH_CR.load(oocd) + if self.FLASH_CR.OPT_LOCK == 1: + self.logger.debug("Options locked") + else: + self.logger.error("Options lock failed") + raise Exception("Options lock failed") + + def flash_lock(self, oocd: OpenOCD): + # Check if flash is already locked + self.FLASH_CR.load(oocd) + if self.FLASH_CR.LOCK == 1: + self.logger.debug("Flash is already locked") + return + + # Lock flash + self.logger.debug("Locking Flash") + self.FLASH_CR.LOCK = 1 + self.FLASH_CR.store(oocd) + + # Check if flash is locked + self.FLASH_CR.load(oocd) + if self.FLASH_CR.LOCK == 1: + self.logger.debug("Flash locked") + else: + self.logger.error("Flash lock failed") + raise Exception("Flash lock failed") + + def option_bytes_apply(self, oocd: OpenOCD): + self.logger.debug(f"Applying Option Bytes") + + self.FLASH_CR.load(oocd) + self.FLASH_CR.OPT_STRT = 1 + self.FLASH_CR.store(oocd) + + # Wait for Option Bytes to be applied + self.flash_wait_for_operation(oocd) + + def option_bytes_load(self, oocd: OpenOCD): + self.logger.debug(f"Loading Option Bytes") + self.FLASH_CR.load(oocd) + self.FLASH_CR.OBL_LAUNCH = 1 + self.FLASH_CR.store(oocd) + + def option_bytes_id_to_address(self, id: int) -> int: + # Check if this option byte (dword) is mapped to a register + device_reg_addr = self.OPTION_BYTE_MAP_TO_REGS.get(id, None) + if device_reg_addr is None: + raise Exception(f"Option Byte {id} is not mapped to a register") + + return device_reg_addr + + def flash_wait_for_operation(self, oocd: OpenOCD): + # Wait for flash operation to complete + # TODO: timeout + while True: + self.FLASH_SR.load(oocd) + if self.FLASH_SR.BSY == 0: + break + + def flash_dump_status_register(self, oocd: OpenOCD): + self.FLASH_SR.load(oocd) + self.logger.info(f"FLASH_SR: {self.FLASH_SR.get():08x}") + if self.FLASH_SR.EOP: + self.logger.info(" End of operation") + if self.FLASH_SR.OP_ERR: + self.logger.error(" Operation error") + if self.FLASH_SR.PROG_ERR: + self.logger.error(" Programming error") + if self.FLASH_SR.WRP_ERR: + self.logger.error(" Write protection error") + if self.FLASH_SR.PGA_ERR: + self.logger.error(" Programming alignment error") + if self.FLASH_SR.SIZE_ERR: + self.logger.error(" Size error") + if self.FLASH_SR.PGS_ERR: + self.logger.error(" Programming sequence error") + if self.FLASH_SR.MISS_ERR: + self.logger.error(" Fast programming data miss error") + if self.FLASH_SR.FAST_ERR: + self.logger.error(" Fast programming error") + if self.FLASH_SR.OPTNV: + self.logger.info(" User option OPTVAL indication") + if self.FLASH_SR.RD_ERR: + self.logger.info(" PCROP read error") + if self.FLASH_SR.OPTV_ERR: + self.logger.info(" Option and Engineering bits loading validity error") + if self.FLASH_SR.BSY: + self.logger.info(" Busy") + if self.FLASH_SR.CFGBSY: + self.logger.info(" Programming or erase configuration busy") + if self.FLASH_SR.PESD: + self.logger.info(" Programming / erase operation suspended.") + + def write_flash_64(self, oocd: OpenOCD, address: int, word_1: int, word_2: int): + self.logger.debug(f"Writing flash at address {address:08x}") + + if address % 8 != 0: + self.logger.error("Address must be aligned to 8 bytes") + raise Exception("Address must be aligned to 8 bytes") + + if word_1 == oocd.read_32(address) and word_2 == oocd.read_32(address + 4): + self.logger.debug("Data is already programmed") + return + + self.flash_unlock(oocd) + + # Check that no flash main memory operation is ongoing by checking the BSY bit + self.FLASH_SR.load(oocd) + if self.FLASH_SR.BSY: + self.logger.error("Flash is busy") + self.flash_dump_status_register(oocd) + raise Exception("Flash is busy") + + # Enable end of operation interrupts and error interrupts + self.FLASH_CR.load(oocd) + self.FLASH_CR.EOPIE = 1 + self.FLASH_CR.ERRIE = 1 + self.FLASH_CR.store(oocd) + + # Check that flash memory program and erase operations are allowed + if self.FLASH_SR.PESD: + self.logger.error("Flash operations are not allowed") + self.flash_dump_status_register(oocd) + raise Exception("Flash operations are not allowed") + + # Check and clear all error programming flags due to a previous programming. + self.clear_flash_errors(oocd) + + # Set the PG bit in the Flash memory control register (FLASH_CR) + self.FLASH_CR.load(oocd) + self.FLASH_CR.PG = 1 + self.FLASH_CR.store(oocd) + + # Perform the data write operation at the desired memory address, only double word (64 bits) can be programmed. + # Write the first word + oocd.send_tcl(f"mww 0x{address:08x} 0x{word_1:08x}") + # Write the second word + oocd.send_tcl(f"mww 0x{(address + 4):08x} 0x{word_2:08x}") + + # Wait for the BSY bit to be cleared + self.flash_wait_for_operation(oocd) + + # Check that EOP flag is set in the FLASH_SR register + self.FLASH_SR.load(oocd) + if not self.FLASH_SR.EOP: + self.logger.error("Flash operation failed") + self.flash_dump_status_register(oocd) + raise Exception("Flash operation failed") + + # Clear the EOP flag + self.FLASH_SR.load(oocd) + self.FLASH_SR.EOP = 1 + self.FLASH_SR.store(oocd) + + # Clear the PG bit in the FLASH_CR register + self.FLASH_CR.load(oocd) + self.FLASH_CR.PG = 0 + self.FLASH_CR.store(oocd) + + self.flash_lock(oocd) diff --git a/scripts/ob.py b/scripts/ob.py index 722549d69..178fe16a7 100755 --- a/scripts/ob.py +++ b/scripts/ob.py @@ -1,69 +1,79 @@ #!/usr/bin/env python3 -import logging -import argparse -import subprocess -import sys -import os +from os import path from flipper.app import App -from flipper.cube import CubeProgrammer +from flipper.utils.programmer_openocd import OpenOCDProgrammer class Main(App): def init(self): + # Subparsers self.subparsers = self.parser.add_subparsers(help="sub-command help") + + # Check command self.parser_check = self.subparsers.add_parser( "check", help="Check Option Bytes" ) - self._addArgsSWD(self.parser_check) + self._add_args(self.parser_check) self.parser_check.set_defaults(func=self.check) + # Set command self.parser_set = self.subparsers.add_parser("set", help="Set Option Bytes") - self._addArgsSWD(self.parser_set) + self._add_args(self.parser_set) self.parser_set.set_defaults(func=self.set) - # OB - self.ob = {} - def _addArgsSWD(self, parser): + def _add_args(self, parser): parser.add_argument( - "--port", type=str, help="Port to connect: swd or usb1", default="swd" + "--port-base", type=int, help="OpenOCD port base", default=3333 + ) + parser.add_argument( + "--interface", + type=str, + help="OpenOCD interface", + default="interface/cmsis-dap.cfg", + ) + parser.add_argument( + "--serial", type=str, help="OpenOCD interface serial number" + ) + parser.add_argument( + "--ob-path", + type=str, + help="Option bytes file", + default=path.join(path.dirname(__file__), "ob.data"), ) - parser.add_argument("--serial", type=str, help="ST-Link Serial Number") - - def _getCubeParams(self): - return { - "port": self.args.port, - "serial": self.args.serial, - } - - def before(self): - self.logger.info(f"Loading Option Bytes data") - file_path = os.path.join(os.path.dirname(sys.argv[0]), "ob.data") - with open(file_path, "r") as file: - for line in file.readlines(): - k, v, o = line.split(":") - self.ob[k.strip()] = v.strip(), o.strip() def check(self): self.logger.info(f"Checking Option Bytes") - cp = CubeProgrammer(self._getCubeParams()) - if cp.checkOptionBytes(self.ob): - self.logger.info(f"OB Check OK") - return 0 - else: - self.logger.error(f"OB Check FAIL") - return 255 + + # OpenOCD + openocd = OpenOCDProgrammer( + self.args.interface, + self.args.port_base, + self.args.serial, + ) + + return_code = 1 + if openocd.option_bytes_validate(self.args.ob_path): + return_code = 0 + + return return_code def set(self): self.logger.info(f"Setting Option Bytes") - cp = CubeProgrammer(self._getCubeParams()) - if cp.setOptionBytes(self.ob): - self.logger.info(f"OB Set OK") - return 0 - else: - self.logger.error(f"OB Set FAIL") - return 255 + + # OpenOCD + openocd = OpenOCDProgrammer( + self.args.interface, + self.args.port_base, + self.args.serial, + ) + + return_code = 1 + if openocd.option_bytes_set(self.args.ob_path): + return_code = 0 + + return return_code if __name__ == "__main__": diff --git a/scripts/otp.py b/scripts/otp.py index 48056fd2a..3bfe30d2d 100755 --- a/scripts/otp.py +++ b/scripts/otp.py @@ -35,6 +35,7 @@ OTP_DISPLAYS = { from flipper.app import App from flipper.cube import CubeProgrammer +from flipper.utils.programmer_openocd import OpenOCDProgrammer class Main(App): @@ -53,21 +54,21 @@ class Main(App): self.parser_flash_first = self.subparsers.add_parser( "flash_first", help="Flash first block of OTP to device" ) - self._addArgsSWD(self.parser_flash_first) + self._addArgsOpenOCD(self.parser_flash_first) self._addFirstArgs(self.parser_flash_first) self.parser_flash_first.set_defaults(func=self.flash_first) # Flash Second self.parser_flash_second = self.subparsers.add_parser( "flash_second", help="Flash second block of OTP to device" ) - self._addArgsSWD(self.parser_flash_second) + self._addArgsOpenOCD(self.parser_flash_second) self._addSecondArgs(self.parser_flash_second) self.parser_flash_second.set_defaults(func=self.flash_second) # Flash All self.parser_flash_all = self.subparsers.add_parser( "flash_all", help="Flash OTP to device" ) - self._addArgsSWD(self.parser_flash_all) + self._addArgsOpenOCD(self.parser_flash_all) self._addFirstArgs(self.parser_flash_all) self._addSecondArgs(self.parser_flash_all) self.parser_flash_all.set_defaults(func=self.flash_all) @@ -75,17 +76,19 @@ class Main(App): self.logger = logging.getLogger() self.timestamp = datetime.datetime.now().timestamp() - def _addArgsSWD(self, parser): + def _addArgsOpenOCD(self, parser): parser.add_argument( - "--port", type=str, help="Port to connect: swd or usb1", default="swd" + "--port-base", type=int, help="OpenOCD port base", default=3333 + ) + parser.add_argument( + "--interface", + type=str, + help="OpenOCD interface", + default="interface/cmsis-dap.cfg", + ) + parser.add_argument( + "--serial", type=str, help="OpenOCD interface serial number" ) - parser.add_argument("--serial", type=str, help="ST-Link Serial Number") - - def _getCubeParams(self): - return { - "port": self.args.port, - "serial": self.args.serial, - } def _addFirstArgs(self, parser): parser.add_argument("--version", type=int, help="Version", required=True) @@ -173,14 +176,22 @@ class Main(App): file.write(self._packFirst()) self.logger.info(f"Flashing OTP") - cp = CubeProgrammer(self._getCubeParams()) - cp.flashBin("0x1FFF7000", filename) - cp.resetTarget() + + openocd = OpenOCDProgrammer( + self.args.interface, + self.args.port_base, + self.args.serial, + ) + + if not openocd.otp_write(0x1FFF7000, filename): + raise Exception("Failed to flash OTP") + self.logger.info(f"Flashed Successfully") - os.remove(filename) except Exception as e: self.logger.exception(e) return 1 + finally: + os.remove(filename) return 0 @@ -197,14 +208,22 @@ class Main(App): file.write(self._packSecond()) self.logger.info(f"Flashing OTP") - cp = CubeProgrammer(self._getCubeParams()) - cp.flashBin("0x1FFF7010", filename) - cp.resetTarget() + + openocd = OpenOCDProgrammer( + self.args.interface, + self.args.port_base, + self.args.serial, + ) + + if not openocd.otp_write(0x1FFF7010, filename): + raise Exception("Failed to flash OTP") + self.logger.info(f"Flashed Successfully") - os.remove(filename) except Exception as e: self.logger.exception(e) return 1 + finally: + os.remove(filename) return 0 @@ -223,14 +242,22 @@ class Main(App): file.write(self._packSecond()) self.logger.info(f"Flashing OTP") - cp = CubeProgrammer(self._getCubeParams()) - cp.flashBin("0x1FFF7000", filename) - cp.resetTarget() + + openocd = OpenOCDProgrammer( + self.args.interface, + self.args.port_base, + self.args.serial, + ) + + if not openocd.otp_write(0x1FFF7000, filename): + raise Exception("Failed to flash OTP") + self.logger.info(f"Flashed Successfully") - os.remove(filename) except Exception as e: self.logger.exception(e) return 1 + finally: + os.remove(filename) return 0 From 5db923833162213f7d0082b466aa02ac6c44694c Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Tue, 27 Dec 2022 16:09:23 +0300 Subject: [PATCH 34/34] Update API --- firmware/targets/f7/api_symbols.csv | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 85667673b..e495f66e9 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -2686,6 +2686,14 @@ Function,-,subghz_protocol_decoder_holtek_get_hash_data,uint8_t,void* Function,-,subghz_protocol_decoder_holtek_get_string,void,"void*, FuriString*" Function,-,subghz_protocol_decoder_holtek_reset,void,void* Function,-,subghz_protocol_decoder_holtek_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" +Function,-,subghz_protocol_decoder_holtek_th12x_alloc,void*,SubGhzEnvironment* +Function,-,subghz_protocol_decoder_holtek_th12x_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_decoder_holtek_th12x_feed,void,"void*, _Bool, uint32_t" +Function,-,subghz_protocol_decoder_holtek_th12x_free,void,void* +Function,-,subghz_protocol_decoder_holtek_th12x_get_hash_data,uint8_t,void* +Function,-,subghz_protocol_decoder_holtek_th12x_get_string,void,"void*, FuriString*" +Function,-,subghz_protocol_decoder_holtek_th12x_reset,void,void* +Function,-,subghz_protocol_decoder_holtek_th12x_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" Function,-,subghz_protocol_decoder_honeywell_wdb_alloc,void*,SubGhzEnvironment* Function,-,subghz_protocol_decoder_honeywell_wdb_deserialize,_Bool,"void*, FlipperFormat*" Function,-,subghz_protocol_decoder_honeywell_wdb_feed,void,"void*, _Bool, uint32_t" @@ -2944,6 +2952,11 @@ Function,-,subghz_protocol_encoder_holtek_alloc,void*,SubGhzEnvironment* Function,-,subghz_protocol_encoder_holtek_deserialize,_Bool,"void*, FlipperFormat*" Function,-,subghz_protocol_encoder_holtek_free,void,void* Function,-,subghz_protocol_encoder_holtek_stop,void,void* +Function,-,subghz_protocol_encoder_holtek_th12x_alloc,void*,SubGhzEnvironment* +Function,-,subghz_protocol_encoder_holtek_th12x_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_encoder_holtek_th12x_free,void,void* +Function,-,subghz_protocol_encoder_holtek_th12x_stop,void,void* +Function,-,subghz_protocol_encoder_holtek_th12x_yield,LevelDuration,void* Function,-,subghz_protocol_encoder_holtek_yield,LevelDuration,void* Function,-,subghz_protocol_encoder_honeywell_wdb_alloc,void*,SubGhzEnvironment* Function,-,subghz_protocol_encoder_honeywell_wdb_deserialize,_Bool,"void*, FlipperFormat*" @@ -4797,6 +4810,9 @@ Variable,-,subghz_protocol_gate_tx_encoder,const SubGhzProtocolEncoder, Variable,-,subghz_protocol_holtek,const SubGhzProtocol, Variable,-,subghz_protocol_holtek_decoder,const SubGhzProtocolDecoder, Variable,-,subghz_protocol_holtek_encoder,const SubGhzProtocolEncoder, +Variable,-,subghz_protocol_holtek_th12x,const SubGhzProtocol, +Variable,-,subghz_protocol_holtek_th12x_decoder,const SubGhzProtocolDecoder, +Variable,-,subghz_protocol_holtek_th12x_encoder,const SubGhzProtocolEncoder, Variable,-,subghz_protocol_honeywell_wdb,const SubGhzProtocol, Variable,-,subghz_protocol_honeywell_wdb_decoder,const SubGhzProtocolDecoder, Variable,-,subghz_protocol_honeywell_wdb_encoder,const SubGhzProtocolEncoder,