MX 2 лет назад
Родитель
Сommit
339c77aac7
100 измененных файлов с 0 добавлено и 12282 удалено
  1. 0 15
      non_catalog_apps/blackjack/application.fam
  2. BIN
      non_catalog_apps/blackjack/assets/blackjack.png
  3. BIN
      non_catalog_apps/blackjack/assets/card_graphics.png
  4. BIN
      non_catalog_apps/blackjack/assets/endscreen.png
  5. 0 633
      non_catalog_apps/blackjack/blackjack.c
  6. BIN
      non_catalog_apps/blackjack/blackjack_10px.png
  7. 0 353
      non_catalog_apps/blackjack/common/card.c
  8. 0 192
      non_catalog_apps/blackjack/common/card.h
  9. 0 53
      non_catalog_apps/blackjack/common/dml.c
  10. 0 116
      non_catalog_apps/blackjack/common/dml.h
  11. 0 103
      non_catalog_apps/blackjack/common/menu.c
  12. 0 77
      non_catalog_apps/blackjack/common/menu.h
  13. 0 69
      non_catalog_apps/blackjack/common/queue.c
  14. 0 70
      non_catalog_apps/blackjack/common/queue.h
  15. 0 257
      non_catalog_apps/blackjack/common/ui.c
  16. 0 105
      non_catalog_apps/blackjack/common/ui.h
  17. 0 77
      non_catalog_apps/blackjack/defines.h
  18. 0 186
      non_catalog_apps/blackjack/ui.c
  19. 0 18
      non_catalog_apps/blackjack/ui.h
  20. 0 123
      non_catalog_apps/blackjack/util.c
  21. 0 7
      non_catalog_apps/blackjack/util.h
  22. 0 7
      non_catalog_apps/esp8266_deauth/FlipperZeroWiFiDeauthModuleDefines.h
  23. 0 14
      non_catalog_apps/esp8266_deauth/application.fam
  24. 0 543
      non_catalog_apps/esp8266_deauth/esp8266_deauth.c
  25. BIN
      non_catalog_apps/esp8266_deauth/wifi_10px.png
  26. 0 674
      non_catalog_apps/gps_nmea_uart/LICENSE
  27. 0 40
      non_catalog_apps/gps_nmea_uart/README.md
  28. 0 14
      non_catalog_apps/gps_nmea_uart/application.fam
  29. 0 190
      non_catalog_apps/gps_nmea_uart/gps.c
  30. BIN
      non_catalog_apps/gps_nmea_uart/gps_10px.png
  31. 0 217
      non_catalog_apps/gps_nmea_uart/gps_uart.c
  32. 0 46
      non_catalog_apps/gps_nmea_uart/gps_uart.h
  33. 0 640
      non_catalog_apps/gps_nmea_uart/minmea.c
  34. 0 295
      non_catalog_apps/gps_nmea_uart/minmea.h
  35. BIN
      non_catalog_apps/gps_nmea_uart/ui.png
  36. BIN
      non_catalog_apps/gps_nmea_uart/wiring.png
  37. 0 16
      non_catalog_apps/hc_sr04/application.fam
  38. BIN
      non_catalog_apps/hc_sr04/dist_sensor10px.png
  39. 0 275
      non_catalog_apps/hc_sr04/hc_sr04.c
  40. 0 21
      non_catalog_apps/lightmeter/LICENSE
  41. 0 21
      non_catalog_apps/lightmeter/README.md
  42. 0 26
      non_catalog_apps/lightmeter/application.fam
  43. 0 30
      non_catalog_apps/lightmeter/gui/scenes/config/lightmeter_scene.c
  44. 0 29
      non_catalog_apps/lightmeter/gui/scenes/config/lightmeter_scene.h
  45. 0 4
      non_catalog_apps/lightmeter/gui/scenes/config/lightmeter_scene_config.h
  46. 0 71
      non_catalog_apps/lightmeter/gui/scenes/lightmeter_scene_about.c
  47. 0 216
      non_catalog_apps/lightmeter/gui/scenes/lightmeter_scene_config.c
  48. 0 34
      non_catalog_apps/lightmeter/gui/scenes/lightmeter_scene_help.c
  49. 0 43
      non_catalog_apps/lightmeter/gui/scenes/lightmeter_scene_main.c
  50. 0 470
      non_catalog_apps/lightmeter/gui/views/main_view.c
  51. 0 78
      non_catalog_apps/lightmeter/gui/views/main_view.h
  52. BIN
      non_catalog_apps/lightmeter/icons/T_10x14.png
  53. BIN
      non_catalog_apps/lightmeter/icons/f_10x14.png
  54. 0 150
      non_catalog_apps/lightmeter/lib/BH1750/BH1750.c
  55. 0 110
      non_catalog_apps/lightmeter/lib/BH1750/BH1750.h
  56. 0 21
      non_catalog_apps/lightmeter/lib/BH1750/LICENSE
  57. 0 2
      non_catalog_apps/lightmeter/lib/BH1750/README.md
  58. BIN
      non_catalog_apps/lightmeter/lib/BH1750/docs/BH1750.pdf
  59. 0 161
      non_catalog_apps/lightmeter/lightmeter.c
  60. 0 58
      non_catalog_apps/lightmeter/lightmeter.h
  61. BIN
      non_catalog_apps/lightmeter/lightmeter.png
  62. 0 108
      non_catalog_apps/lightmeter/lightmeter_config.h
  63. 0 43
      non_catalog_apps/lightmeter/lightmeter_helper.c
  64. 0 11
      non_catalog_apps/lightmeter/lightmeter_helper.h
  65. 0 26
      non_catalog_apps/mousejacker/application.fam
  66. BIN
      non_catalog_apps/mousejacker/images/badusb_10px.png
  67. BIN
      non_catalog_apps/mousejacker/images/sub1_10px.png
  68. 0 520
      non_catalog_apps/mousejacker/lib/nrf24/nrf24.c
  69. 0 366
      non_catalog_apps/mousejacker/lib/nrf24/nrf24.h
  70. BIN
      non_catalog_apps/mousejacker/mouse_10px.png
  71. 0 398
      non_catalog_apps/mousejacker/mousejacker.c
  72. 0 460
      non_catalog_apps/mousejacker/mousejacker_ducky.c
  73. 0 45
      non_catalog_apps/mousejacker/mousejacker_ducky.h
  74. 0 22
      non_catalog_apps/nrfsniff/application.fam
  75. 0 520
      non_catalog_apps/nrfsniff/lib/nrf24/nrf24.c
  76. 0 366
      non_catalog_apps/nrfsniff/lib/nrf24/nrf24.h
  77. 0 456
      non_catalog_apps/nrfsniff/nrfsniff.c
  78. BIN
      non_catalog_apps/nrfsniff/nrfsniff_10px.png
  79. 0 674
      non_catalog_apps/unitemp/LICENSE.md
  80. 0 24
      non_catalog_apps/unitemp/README.md
  81. 0 653
      non_catalog_apps/unitemp/Sensors.c
  82. 0 339
      non_catalog_apps/unitemp/Sensors.h
  83. 0 19
      non_catalog_apps/unitemp/application.fam
  84. 0 3
      non_catalog_apps/unitemp/assets/README.MD
  85. BIN
      non_catalog_apps/unitemp/assets/co2_11x14.png
  86. BIN
      non_catalog_apps/unitemp/assets/flipper_happy_2_60x38.png
  87. BIN
      non_catalog_apps/unitemp/assets/flipper_happy_60x38.png
  88. BIN
      non_catalog_apps/unitemp/assets/flipper_sad_60x38.png
  89. BIN
      non_catalog_apps/unitemp/assets/heat_index_11x14.png
  90. BIN
      non_catalog_apps/unitemp/assets/hum_9x15.png
  91. BIN
      non_catalog_apps/unitemp/assets/in_hg_15x15.png
  92. BIN
      non_catalog_apps/unitemp/assets/mm_hg_15x15.png
  93. BIN
      non_catalog_apps/unitemp/assets/pressure_7x13.png
  94. BIN
      non_catalog_apps/unitemp/assets/repo_qr_50x50.png
  95. BIN
      non_catalog_apps/unitemp/assets/sherlok_53x45.png
  96. BIN
      non_catalog_apps/unitemp/assets/temp_C_11x14.png
  97. BIN
      non_catalog_apps/unitemp/assets/temp_F_11x14.png
  98. BIN
      non_catalog_apps/unitemp/icon.png
  99. 0 131
      non_catalog_apps/unitemp/interfaces/I2CSensor.c
  100. 0 128
      non_catalog_apps/unitemp/interfaces/I2CSensor.h

+ 0 - 15
non_catalog_apps/blackjack/application.fam

@@ -1,15 +0,0 @@
-App(
-    appid="blackjack",
-    name="Blackjack",
-    apptype=FlipperAppType.EXTERNAL,
-    entry_point="blackjack_app",
-    requires=["gui","storage","canvas"],
-    stack_size=2 * 1024,
-    order=30,
-    fap_icon="blackjack_10px.png",
-    fap_category="Games",
-    fap_icon_assets="assets",
-    fap_author="@teeebor",
-    fap_version="1.0",
-    fap_description="Blackjack Game",
-)

BIN
non_catalog_apps/blackjack/assets/blackjack.png


BIN
non_catalog_apps/blackjack/assets/card_graphics.png


BIN
non_catalog_apps/blackjack/assets/endscreen.png


+ 0 - 633
non_catalog_apps/blackjack/blackjack.c

@@ -1,633 +0,0 @@
-
-#include <gui/gui.h>
-#include <stdlib.h>
-#include <dolphin/dolphin.h>
-#include <dialogs/dialogs.h>
-#include <gui/canvas_i.h>
-
-#include <math.h>
-#include "util.h"
-#include "defines.h"
-#include "common/card.h"
-#include "common/dml.h"
-#include "common/queue.h"
-#include "util.h"
-#include "ui.h"
-
-#include "blackjack_icons.h"
-
-#define DEALER_MAX 17
-
-void start_round(GameState* game_state);
-
-void init(GameState* game_state);
-
-static void draw_ui(Canvas* const canvas, const GameState* game_state) {
-    draw_money(canvas, game_state->player_score);
-
-    draw_score(canvas, true, hand_count(game_state->player_cards, game_state->player_card_count));
-
-    if(!game_state->queue_state.running && game_state->state == GameStatePlay) {
-        render_menu(game_state->menu, canvas, 2, 47);
-    }
-}
-
-static void render_callback(Canvas* const canvas, void* ctx) {
-    furi_assert(ctx);
-    const GameState* game_state = ctx;
-    furi_mutex_acquire(game_state->mutex, FuriWaitForever);
-
-    canvas_set_color(canvas, ColorBlack);
-    canvas_draw_frame(canvas, 0, 0, 128, 64);
-
-    if(game_state->state == GameStateStart) {
-        canvas_draw_icon(canvas, 0, 0, &I_blackjack);
-    }
-    if(game_state->state == GameStateGameOver) {
-        canvas_draw_icon(canvas, 0, 0, &I_endscreen);
-    }
-
-    if(game_state->state == GameStatePlay || game_state->state == GameStateDealer) {
-        if(game_state->state == GameStatePlay)
-            draw_player_scene(canvas, game_state);
-        else
-            draw_dealer_scene(canvas, game_state);
-        render_queue(&(game_state->queue_state), game_state, canvas);
-        draw_ui(canvas, game_state);
-    } else if(game_state->state == GameStateSettings) {
-        settings_page(canvas, game_state);
-    }
-
-    furi_mutex_release(game_state->mutex);
-}
-
-//region card draw
-Card draw_card(GameState* game_state) {
-    Card c = game_state->deck.cards[game_state->deck.index];
-    game_state->deck.index++;
-    return c;
-}
-
-void drawPlayerCard(void* ctx) {
-    GameState* game_state = ctx;
-    Card c = draw_card(game_state);
-    game_state->player_cards[game_state->player_card_count] = c;
-    game_state->player_card_count++;
-    if(game_state->player_score < game_state->settings.round_price || game_state->doubled) {
-        set_menu_state(game_state->menu, 0, false);
-    }
-}
-
-void drawDealerCard(void* ctx) {
-    GameState* game_state = ctx;
-    Card c = draw_card(game_state);
-    game_state->dealer_cards[game_state->dealer_card_count] = c;
-    game_state->dealer_card_count++;
-}
-//endregion
-
-//region queue callbacks
-void to_lose_state(const void* ctx, Canvas* const canvas) {
-    const GameState* game_state = ctx;
-    if(game_state->settings.message_duration == 0) return;
-    popup_frame(canvas);
-    elements_multiline_text_aligned(canvas, 64, 22, AlignCenter, AlignCenter, "You lost");
-}
-
-void to_bust_state(const void* ctx, Canvas* const canvas) {
-    const GameState* game_state = ctx;
-    if(game_state->settings.message_duration == 0) return;
-    popup_frame(canvas);
-    elements_multiline_text_aligned(canvas, 64, 22, AlignCenter, AlignCenter, "Busted!");
-}
-
-void to_draw_state(const void* ctx, Canvas* const canvas) {
-    const GameState* game_state = ctx;
-    if(game_state->settings.message_duration == 0) return;
-    popup_frame(canvas);
-    elements_multiline_text_aligned(canvas, 64, 22, AlignCenter, AlignCenter, "Draw");
-}
-
-void to_dealer_turn(const void* ctx, Canvas* const canvas) {
-    const GameState* game_state = ctx;
-    if(game_state->settings.message_duration == 0) return;
-    popup_frame(canvas);
-    elements_multiline_text_aligned(canvas, 64, 22, AlignCenter, AlignCenter, "Dealers turn");
-}
-
-void to_win_state(const void* ctx, Canvas* const canvas) {
-    const GameState* game_state = ctx;
-    if(game_state->settings.message_duration == 0) return;
-    popup_frame(canvas);
-    elements_multiline_text_aligned(canvas, 64, 22, AlignCenter, AlignCenter, "You win");
-}
-
-void to_start(const void* ctx, Canvas* const canvas) {
-    const GameState* game_state = ctx;
-    if(game_state->settings.message_duration == 0) return;
-    popup_frame(canvas);
-    elements_multiline_text_aligned(canvas, 64, 22, AlignCenter, AlignCenter, "Round started");
-}
-
-void before_start(void* ctx) {
-    GameState* game_state = ctx;
-    game_state->dealer_card_count = 0;
-    game_state->player_card_count = 0;
-}
-
-void start(void* ctx) {
-    GameState* game_state = ctx;
-    start_round(game_state);
-}
-
-void draw(void* ctx) {
-    GameState* game_state = ctx;
-    game_state->player_score += game_state->bet;
-    game_state->bet = 0;
-    enqueue(
-        &(game_state->queue_state),
-        game_state,
-        start,
-        before_start,
-        to_start,
-        game_state->settings.message_duration);
-}
-
-void game_over(void* ctx) {
-    GameState* game_state = ctx;
-    game_state->state = GameStateGameOver;
-}
-
-void lose(void* ctx) {
-    GameState* game_state = ctx;
-    game_state->state = GameStatePlay;
-    game_state->bet = 0;
-    if(game_state->player_score >= game_state->settings.round_price) {
-        enqueue(
-            &(game_state->queue_state),
-            game_state,
-            start,
-            before_start,
-            to_start,
-            game_state->settings.message_duration);
-    } else {
-        enqueue(&(game_state->queue_state), game_state, game_over, NULL, NULL, 0);
-    }
-}
-
-void win(void* ctx) {
-    GameState* game_state = ctx;
-    game_state->state = GameStatePlay;
-    game_state->player_score += game_state->bet * 2;
-    game_state->bet = 0;
-    enqueue(
-        &(game_state->queue_state),
-        game_state,
-        start,
-        before_start,
-        to_start,
-        game_state->settings.message_duration);
-}
-
-void dealerTurn(void* ctx) {
-    GameState* game_state = ctx;
-    game_state->state = GameStateDealer;
-}
-
-float animationTime(const GameState* game_state) {
-    return (float)(furi_get_tick() - game_state->queue_state.start) /
-           (float)(game_state->settings.animation_duration);
-}
-
-void dealer_card_animation(const void* ctx, Canvas* const canvas) {
-    const GameState* game_state = ctx;
-    float t = animationTime(game_state);
-
-    Card animatingCard = game_state->deck.cards[game_state->deck.index];
-    if(game_state->dealer_card_count > 1) {
-        Vector end = card_pos_at_index(game_state->dealer_card_count);
-        draw_card_animation(animatingCard, (Vector){0, 64}, (Vector){0, 32}, end, t, true, canvas);
-    } else {
-        draw_card_animation(
-            animatingCard,
-            (Vector){32, -CARD_HEIGHT},
-            (Vector){64, 32},
-            (Vector){2, 2},
-            t,
-            false,
-            canvas);
-    }
-}
-
-void dealer_back_card_animation(const void* ctx, Canvas* const canvas) {
-    const GameState* game_state = ctx;
-    float t = animationTime(game_state);
-
-    Vector currentPos =
-        quadratic_2d((Vector){32, -CARD_HEIGHT}, (Vector){64, 32}, (Vector){13, 5}, t);
-    draw_card_back_at(currentPos.x, currentPos.y, canvas);
-}
-
-void player_card_animation(const void* ctx, Canvas* const canvas) {
-    const GameState* game_state = ctx;
-    float t = animationTime(game_state);
-
-    Card animatingCard = game_state->deck.cards[game_state->deck.index];
-    Vector end = card_pos_at_index(game_state->player_card_count);
-
-    draw_card_animation(
-        animatingCard, (Vector){32, -CARD_HEIGHT}, (Vector){0, 32}, end, t, true, canvas);
-}
-//endregion
-
-void player_tick(GameState* game_state) {
-    uint8_t score = hand_count(game_state->player_cards, game_state->player_card_count);
-    if((game_state->doubled && score <= 21) || score == 21) {
-        enqueue(
-            &(game_state->queue_state),
-            game_state,
-            dealerTurn,
-            NULL,
-            to_dealer_turn,
-            game_state->settings.message_duration);
-    } else if(score > 21) {
-        enqueue(
-            &(game_state->queue_state),
-            game_state,
-            lose,
-            NULL,
-            to_bust_state,
-            game_state->settings.message_duration);
-    } else {
-        if(game_state->selectDirection == DirectionUp ||
-           game_state->selectDirection == DirectionDown) {
-            move_menu(game_state->menu, game_state->selectDirection == DirectionUp ? -1 : 1);
-        }
-
-        if(game_state->selectDirection == Select) {
-            activate_menu(game_state->menu, game_state);
-        }
-    }
-}
-
-void dealer_tick(GameState* game_state) {
-    uint8_t dealer_score = hand_count(game_state->dealer_cards, game_state->dealer_card_count);
-    uint8_t player_score = hand_count(game_state->player_cards, game_state->player_card_count);
-
-    if(dealer_score >= DEALER_MAX) {
-        if(dealer_score > 21 || dealer_score < player_score) {
-            dolphin_deed(DolphinDeedPluginGameWin);
-            enqueue(
-                &(game_state->queue_state),
-                game_state,
-                win,
-                NULL,
-                to_win_state,
-                game_state->settings.message_duration);
-        } else if(dealer_score > player_score) {
-            enqueue(
-                &(game_state->queue_state),
-                game_state,
-                lose,
-                NULL,
-                to_lose_state,
-                game_state->settings.message_duration);
-        } else if(dealer_score == player_score) {
-            enqueue(
-                &(game_state->queue_state),
-                game_state,
-                draw,
-                NULL,
-                to_draw_state,
-                game_state->settings.message_duration);
-        }
-    } else {
-        enqueue(
-            &(game_state->queue_state),
-            game_state,
-            drawDealerCard,
-            NULL,
-            dealer_card_animation,
-            game_state->settings.animation_duration);
-    }
-}
-
-void settings_tick(GameState* game_state) {
-    if(game_state->selectDirection == DirectionDown && game_state->selectedMenu < 4) {
-        game_state->selectedMenu++;
-    }
-    if(game_state->selectDirection == DirectionUp && game_state->selectedMenu > 0) {
-        game_state->selectedMenu--;
-    }
-
-    if(game_state->selectDirection == DirectionLeft ||
-       game_state->selectDirection == DirectionRight) {
-        int nextScore = 0;
-        switch(game_state->selectedMenu) {
-        case 0:
-            nextScore = game_state->settings.starting_money;
-            if(game_state->selectDirection == DirectionLeft)
-                nextScore -= 10;
-            else
-                nextScore += 10;
-            if(nextScore >= (int)game_state->settings.round_price && nextScore < 400)
-                game_state->settings.starting_money = nextScore;
-            break;
-        case 1:
-            nextScore = game_state->settings.round_price;
-            if(game_state->selectDirection == DirectionLeft)
-                nextScore -= 10;
-            else
-                nextScore += 10;
-            if(nextScore >= 5 && nextScore <= (int)game_state->settings.starting_money)
-                game_state->settings.round_price = nextScore;
-            break;
-        case 2:
-            nextScore = game_state->settings.animation_duration;
-            if(game_state->selectDirection == DirectionLeft)
-                nextScore -= 100;
-            else
-                nextScore += 100;
-            if(nextScore >= 0 && nextScore < 2000)
-                game_state->settings.animation_duration = nextScore;
-            break;
-        case 3:
-            nextScore = game_state->settings.message_duration;
-            if(game_state->selectDirection == DirectionLeft)
-                nextScore -= 100;
-            else
-                nextScore += 100;
-            if(nextScore >= 0 && nextScore < 2000)
-                game_state->settings.message_duration = nextScore;
-            break;
-        case 4:
-            game_state->settings.sound_effects = !game_state->settings.sound_effects;
-        default:
-            break;
-        }
-    }
-}
-
-void tick(GameState* game_state) {
-    game_state->last_tick = furi_get_tick();
-    bool queue_ran = run_queue(&(game_state->queue_state), game_state);
-
-    switch(game_state->state) {
-    case GameStateGameOver:
-    case GameStateStart:
-        if(game_state->selectDirection == Select)
-            init(game_state);
-        else if(game_state->selectDirection == DirectionRight) {
-            game_state->selectedMenu = 0;
-            game_state->state = GameStateSettings;
-        }
-        break;
-    case GameStatePlay:
-        if(!game_state->started) {
-            game_state->selectedMenu = 0;
-            game_state->started = true;
-            enqueue(
-                &(game_state->queue_state),
-                game_state,
-                drawDealerCard,
-                NULL,
-                dealer_back_card_animation,
-                game_state->settings.animation_duration);
-            enqueue(
-                &(game_state->queue_state),
-                game_state,
-                drawPlayerCard,
-                NULL,
-                player_card_animation,
-                game_state->settings.animation_duration);
-            enqueue(
-                &(game_state->queue_state),
-                game_state,
-                drawDealerCard,
-                NULL,
-                dealer_card_animation,
-                game_state->settings.animation_duration);
-            enqueue(
-                &(game_state->queue_state),
-                game_state,
-                drawPlayerCard,
-                NULL,
-                player_card_animation,
-                game_state->settings.animation_duration);
-        }
-        if(!queue_ran) player_tick(game_state);
-        break;
-    case GameStateDealer:
-        if(!queue_ran) dealer_tick(game_state);
-        break;
-    case GameStateSettings:
-        settings_tick(game_state);
-        break;
-    default:
-        break;
-    }
-
-    game_state->selectDirection = None;
-}
-
-void start_round(GameState* game_state) {
-    game_state->menu->current_menu = 1;
-    game_state->player_card_count = 0;
-    game_state->dealer_card_count = 0;
-    set_menu_state(game_state->menu, 0, true);
-    game_state->menu->enabled = true;
-    game_state->started = false;
-    game_state->doubled = false;
-    game_state->queue_state.running = true;
-    shuffle_deck(&(game_state->deck));
-    game_state->doubled = false;
-    game_state->bet = game_state->settings.round_price;
-    if(game_state->player_score < game_state->settings.round_price) {
-        game_state->state = GameStateGameOver;
-    } else {
-        game_state->player_score -= game_state->settings.round_price;
-    }
-    game_state->state = GameStatePlay;
-}
-
-void init(GameState* game_state) {
-    set_menu_state(game_state->menu, 0, true);
-    game_state->menu->enabled = true;
-    game_state->menu->current_menu = 1;
-    game_state->settings = load_settings();
-    game_state->last_tick = 0;
-    game_state->processing = true;
-    game_state->selectedMenu = 0;
-    game_state->player_score = game_state->settings.starting_money;
-    generate_deck(&(game_state->deck), 6);
-    start_round(game_state);
-}
-
-static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) {
-    furi_assert(event_queue);
-    AppEvent event = {.type = EventTypeKey, .input = *input_event};
-    furi_message_queue_put(event_queue, &event, FuriWaitForever);
-}
-
-static void update_timer_callback(FuriMessageQueue* event_queue) {
-    furi_assert(event_queue);
-    AppEvent event = {.type = EventTypeTick};
-    furi_message_queue_put(event_queue, &event, 0);
-}
-
-void doubleAction(void* state) {
-    GameState* game_state = state;
-    if(!game_state->doubled && game_state->player_score >= game_state->settings.round_price) {
-        game_state->player_score -= game_state->settings.round_price;
-        game_state->bet += game_state->settings.round_price;
-        game_state->doubled = true;
-        enqueue(
-            &(game_state->queue_state),
-            game_state,
-            drawPlayerCard,
-            NULL,
-            player_card_animation,
-            game_state->settings.animation_duration);
-        game_state->player_cards[game_state->player_card_count] =
-            game_state->deck.cards[game_state->deck.index];
-        uint8_t score = hand_count(game_state->player_cards, game_state->player_card_count + 1);
-        if(score > 21) {
-            enqueue(
-                &(game_state->queue_state),
-                game_state,
-                lose,
-                NULL,
-                to_bust_state,
-                game_state->settings.message_duration);
-        } else {
-            enqueue(
-                &(game_state->queue_state),
-                game_state,
-                dealerTurn,
-                NULL,
-                to_dealer_turn,
-                game_state->settings.message_duration);
-        }
-        set_menu_state(game_state->menu, 0, false);
-    }
-}
-
-void hitAction(void* state) {
-    GameState* game_state = state;
-    enqueue(
-        &(game_state->queue_state),
-        game_state,
-        drawPlayerCard,
-        NULL,
-        player_card_animation,
-        game_state->settings.animation_duration);
-}
-void stayAction(void* state) {
-    GameState* game_state = state;
-    enqueue(
-        &(game_state->queue_state),
-        game_state,
-        dealerTurn,
-        NULL,
-        to_dealer_turn,
-        game_state->settings.message_duration);
-}
-
-int32_t blackjack_app(void* p) {
-    UNUSED(p);
-
-    int32_t return_code = 0;
-
-    FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(AppEvent));
-
-    GameState* game_state = malloc(sizeof(GameState));
-    game_state->menu = malloc(sizeof(Menu));
-    game_state->menu->menu_width = 40;
-    init(game_state);
-    add_menu(game_state->menu, "Double", doubleAction);
-    add_menu(game_state->menu, "Hit", hitAction);
-    add_menu(game_state->menu, "Stay", stayAction);
-    set_card_graphics(&I_card_graphics);
-
-    game_state->state = GameStateStart;
-
-    game_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
-    if(!game_state->mutex) {
-        FURI_LOG_E(APP_NAME, "cannot create mutex\r\n");
-        return_code = 255;
-        goto free_and_exit;
-    }
-
-    ViewPort* view_port = view_port_alloc();
-    view_port_draw_callback_set(view_port, render_callback, game_state);
-    view_port_input_callback_set(view_port, input_callback, event_queue);
-
-    FuriTimer* timer = furi_timer_alloc(update_timer_callback, FuriTimerTypePeriodic, event_queue);
-    furi_timer_start(timer, furi_kernel_get_tick_frequency() / 25);
-
-    Gui* gui = furi_record_open(RECORD_GUI);
-    gui_add_view_port(gui, view_port, GuiLayerFullscreen);
-
-    AppEvent event;
-
-    // Call dolphin deed on game start
-    dolphin_deed(DolphinDeedPluginGameStart);
-
-    for(bool processing = true; processing;) {
-        FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);
-        furi_mutex_acquire(game_state->mutex, FuriWaitForever);
-        if(event_status == FuriStatusOk) {
-            if(event.type == EventTypeKey) {
-                if(event.input.type == InputTypePress) {
-                    switch(event.input.key) {
-                    case InputKeyUp:
-                        game_state->selectDirection = DirectionUp;
-                        break;
-                    case InputKeyDown:
-                        game_state->selectDirection = DirectionDown;
-                        break;
-                    case InputKeyRight:
-                        game_state->selectDirection = DirectionRight;
-                        break;
-                    case InputKeyLeft:
-                        game_state->selectDirection = DirectionLeft;
-                        break;
-                    case InputKeyBack:
-                        if(game_state->state == GameStateSettings) {
-                            game_state->state = GameStateStart;
-                            save_settings(game_state->settings);
-                        } else
-                            processing = false;
-                        break;
-                    case InputKeyOk:
-                        game_state->selectDirection = Select;
-                        break;
-                    default:
-                        break;
-                    }
-                }
-            } else if(event.type == EventTypeTick) {
-                tick(game_state);
-                processing = game_state->processing;
-            }
-        }
-        view_port_update(view_port);
-        furi_mutex_release(game_state->mutex);
-    }
-
-    furi_timer_free(timer);
-    view_port_enabled_set(view_port, false);
-    gui_remove_view_port(gui, view_port);
-    furi_record_close(RECORD_GUI);
-    view_port_free(view_port);
-    furi_mutex_free(game_state->mutex);
-
-free_and_exit:
-    free(game_state->deck.cards);
-    free_menu(game_state->menu);
-    queue_clear(&(game_state->queue_state));
-    free(game_state);
-    furi_message_queue_free(event_queue);
-
-    return return_code;
-}

BIN
non_catalog_apps/blackjack/blackjack_10px.png


+ 0 - 353
non_catalog_apps/blackjack/common/card.c

@@ -1,353 +0,0 @@
-#include "card.h"
-#include "dml.h"
-#include "ui.h"
-
-#define CARD_DRAW_X_START 108
-#define CARD_DRAW_Y_START 38
-#define CARD_DRAW_X_SPACE 10
-#define CARD_DRAW_Y_SPACE 8
-#define CARD_DRAW_X_OFFSET 4
-#define CARD_DRAW_FIRST_ROW_LENGTH 7
-
-uint8_t pips[4][3] = {
-    {21, 10, 7}, //spades
-    {7, 10, 7}, //hearts
-    {0, 10, 7}, //diamonds
-    {14, 10, 7}, //clubs
-};
-uint8_t letters[13][3] = {
-    {0, 0, 5},
-    {5, 0, 5},
-    {10, 0, 5},
-    {15, 0, 5},
-    {20, 0, 5},
-    {25, 0, 5},
-    {30, 0, 5},
-    {0, 5, 5},
-    {5, 5, 5},
-    {10, 5, 5},
-    {15, 5, 5},
-    {20, 5, 5},
-    {25, 5, 5},
-};
-
-//region Player card positions
-uint8_t playerCardPositions[22][4] = {
-    //first row
-    {108, 38},
-    {98, 38},
-    {88, 38},
-    {78, 38},
-    {68, 38},
-    {58, 38},
-    {48, 38},
-    {38, 38},
-    //second row
-    {104, 26},
-    {94, 26},
-    {84, 26},
-    {74, 26},
-    {64, 26},
-    {54, 26},
-    {44, 26},
-    //third row
-    {99, 14},
-    {89, 14},
-    {79, 14},
-    {69, 14},
-    {59, 14},
-    {49, 14},
-};
-//endregion
-Icon* card_graphics = NULL;
-
-void set_card_graphics(const Icon* graphics) {
-    card_graphics = (Icon*)graphics;
-}
-
-void draw_card_at_colored(
-    int8_t pos_x,
-    int8_t pos_y,
-    uint8_t pip,
-    uint8_t character,
-    bool inverted,
-    Canvas* const canvas) {
-    DrawMode primary = inverted ? Black : White;
-    DrawMode secondary = inverted ? White : Black;
-    draw_rounded_box(canvas, pos_x, pos_y, CARD_WIDTH, CARD_HEIGHT, primary);
-    draw_rounded_box_frame(canvas, pos_x, pos_y, CARD_WIDTH, CARD_HEIGHT, Black);
-
-    uint8_t* drawInfo = pips[pip];
-    uint8_t px = drawInfo[0], py = drawInfo[1], s = drawInfo[2];
-
-    uint8_t left = pos_x + 2;
-    uint8_t right = (pos_x + CARD_WIDTH - s - 2);
-    uint8_t top = pos_y + 2;
-    uint8_t bottom = (pos_y + CARD_HEIGHT - s - 2);
-
-    draw_icon_clip(canvas, card_graphics, right, top, px, py, s, s, secondary);
-    draw_icon_clip_flipped(canvas, card_graphics, left, bottom, px, py, s, s, secondary);
-
-    drawInfo = letters[character];
-    px = drawInfo[0], py = drawInfo[1], s = drawInfo[2];
-    left = pos_x + 2;
-    right = (pos_x + CARD_WIDTH - s - 2);
-    top = pos_y + 2;
-    bottom = (pos_y + CARD_HEIGHT - s - 2);
-
-    draw_icon_clip(canvas, card_graphics, left, top + 1, px, py, s, s, secondary);
-    draw_icon_clip_flipped(canvas, card_graphics, right, bottom - 1, px, py, s, s, secondary);
-}
-
-void draw_card_at(int8_t pos_x, int8_t pos_y, uint8_t pip, uint8_t character, Canvas* const canvas) {
-    draw_card_at_colored(pos_x, pos_y, pip, character, false, canvas);
-}
-
-void draw_deck(const Card* cards, uint8_t count, Canvas* const canvas) {
-    for(int i = count - 1; i >= 0; i--) {
-        draw_card_at(
-            playerCardPositions[i][0],
-            playerCardPositions[i][1],
-            cards[i].pip,
-            cards[i].character,
-            canvas);
-    }
-}
-
-Vector card_pos_at_index(uint8_t index) {
-    return (Vector){playerCardPositions[index][0], playerCardPositions[index][1]};
-}
-
-void draw_card_back_at(int8_t pos_x, int8_t pos_y, Canvas* const canvas) {
-    draw_rounded_box(canvas, pos_x, pos_y, CARD_WIDTH, CARD_HEIGHT, White);
-    draw_rounded_box_frame(canvas, pos_x, pos_y, CARD_WIDTH, CARD_HEIGHT, Black);
-
-    draw_icon_clip(canvas, card_graphics, pos_x + 1, pos_y + 1, 35, 0, 15, 21, Black);
-}
-
-void generate_deck(Deck* deck_ptr, uint8_t deck_count) {
-    uint16_t counter = 0;
-    if(deck_ptr->cards != NULL) {
-        free(deck_ptr->cards);
-    }
-
-    deck_ptr->deck_count = deck_count;
-    deck_ptr->card_count = deck_count * 52;
-    deck_ptr->cards = malloc(sizeof(Card) * deck_ptr->card_count);
-
-    for(uint8_t deck = 0; deck < deck_count; deck++) {
-        for(uint8_t pip = 0; pip < 4; pip++) {
-            for(uint8_t label = 0; label < 13; label++) {
-                deck_ptr->cards[counter] = (Card){pip, label, false, false};
-                counter++;
-            }
-        }
-    }
-}
-
-void shuffle_deck(Deck* deck_ptr) {
-    srand(DWT->CYCCNT);
-    deck_ptr->index = 0;
-    int max = deck_ptr->deck_count * 52;
-    for(int i = 0; i < max; i++) {
-        int r = i + (rand() % (max - i));
-        Card tmp = deck_ptr->cards[i];
-        deck_ptr->cards[i] = deck_ptr->cards[r];
-        deck_ptr->cards[r] = tmp;
-    }
-}
-
-uint8_t hand_count(const Card* cards, uint8_t count) {
-    uint8_t aceCount = 0;
-    uint8_t score = 0;
-
-    for(uint8_t i = 0; i < count; i++) {
-        if(cards[i].character == 12)
-            aceCount++;
-        else {
-            if(cards[i].character > 8)
-                score += 10;
-            else
-                score += cards[i].character + 2;
-        }
-    }
-
-    for(uint8_t i = 0; i < aceCount; i++) {
-        if((score + 11 + (aceCount - 1)) <= 21)
-            score += 11;
-        else
-            score++;
-    }
-
-    return score;
-}
-
-void draw_card_animation(
-    Card animatingCard,
-    Vector from,
-    Vector control,
-    Vector to,
-    float t,
-    bool extra_margin,
-    Canvas* const canvas) {
-    float time = t;
-    if(extra_margin) {
-        time += 0.2;
-    }
-
-    Vector currentPos = quadratic_2d(from, control, to, time);
-    if(t > 1) {
-        draw_card_at(
-            currentPos.x, currentPos.y, animatingCard.pip, animatingCard.character, canvas);
-    } else {
-        if(t < 0.5)
-            draw_card_back_at(currentPos.x, currentPos.y, canvas);
-        else
-            draw_card_at(
-                currentPos.x, currentPos.y, animatingCard.pip, animatingCard.character, canvas);
-    }
-}
-
-void init_hand(Hand* hand_ptr, uint8_t count) {
-    hand_ptr->cards = malloc(sizeof(Card) * count);
-    hand_ptr->index = 0;
-    hand_ptr->max = count;
-}
-
-void free_hand(Hand* hand_ptr) {
-    FURI_LOG_D("CARD", "Freeing hand");
-    free(hand_ptr->cards);
-}
-
-void add_to_hand(Hand* hand_ptr, Card card) {
-    FURI_LOG_D("CARD", "Adding to hand");
-    if(hand_ptr->index < hand_ptr->max) {
-        hand_ptr->cards[hand_ptr->index] = card;
-        hand_ptr->index++;
-    }
-}
-
-void draw_card_space(int16_t pos_x, int16_t pos_y, bool highlighted, Canvas* const canvas) {
-    if(highlighted) {
-        draw_rounded_box_frame(canvas, pos_x, pos_y, CARD_WIDTH, CARD_HEIGHT, Black);
-        draw_rounded_box_frame(
-            canvas, pos_x + 2, pos_y + 2, CARD_WIDTH - 4, CARD_HEIGHT - 4, White);
-    } else {
-        draw_rounded_box(canvas, pos_x, pos_y, CARD_WIDTH, CARD_HEIGHT, Black);
-        draw_rounded_box_frame(
-            canvas, pos_x + 2, pos_y + 2, CARD_WIDTH - 4, CARD_HEIGHT - 4, White);
-    }
-}
-
-int first_non_flipped_card(Hand hand) {
-    for(int i = 0; i < hand.index; i++) {
-        if(!hand.cards[i].flipped) {
-            return i;
-        }
-    }
-    return hand.index;
-}
-
-void draw_hand_column(
-    Hand hand,
-    int16_t pos_x,
-    int16_t pos_y,
-    int8_t highlight,
-    Canvas* const canvas) {
-    if(hand.index == 0) {
-        draw_card_space(pos_x, pos_y, highlight > 0, canvas);
-        if(highlight == 0)
-            draw_rounded_box(canvas, pos_x, pos_y, CARD_WIDTH, CARD_HEIGHT, Inverse);
-        return;
-    }
-
-    int loopEnd = hand.index;
-    int hStart = max(loopEnd - 4, 0);
-    int pos = 0;
-    int first = first_non_flipped_card(hand);
-    bool wastop = false;
-    if(first >= 0 && first <= hStart && highlight != first) {
-        if(first > 0) {
-            draw_card_back_at(pos_x, pos_y + pos, canvas);
-            pos += 4;
-            hStart++;
-            wastop = true;
-        }
-        draw_card_at_colored(
-            pos_x, pos_y + pos, hand.cards[first].pip, hand.cards[first].character, false, canvas);
-        pos += 8;
-        hStart++;
-    }
-    if(hStart > highlight && highlight >= 0) {
-        if(!wastop && first > 0) {
-            draw_card_back_at(pos_x, pos_y + pos, canvas);
-            pos += 4;
-            hStart++;
-        }
-        draw_card_at_colored(
-            pos_x,
-            pos_y + pos,
-            hand.cards[highlight].pip,
-            hand.cards[highlight].character,
-            true,
-            canvas);
-        pos += 8;
-        hStart++;
-    }
-    for(int i = hStart; i < loopEnd; i++, pos += 4) {
-        if(hand.cards[i].flipped) {
-            draw_card_back_at(pos_x, pos_y + pos, canvas);
-            if(i == highlight)
-                draw_rounded_box(
-                    canvas, pos_x + 1, pos_y + pos + 1, CARD_WIDTH - 2, CARD_HEIGHT - 2, Inverse);
-        } else {
-            draw_card_at_colored(
-                pos_x,
-                pos_y + pos,
-                hand.cards[i].pip,
-                hand.cards[i].character,
-                (i == highlight),
-                canvas);
-            if(i == highlight || i == first) pos += 4;
-        }
-    }
-}
-
-Card remove_from_deck(uint16_t index, Deck* deck) {
-    FURI_LOG_D("CARD", "Removing from deck");
-    Card result = {0, 0, true, false};
-    if(deck->card_count > 0) {
-        deck->card_count--;
-        for(int i = 0, curr_index = 0; i <= deck->card_count; i++) {
-            if(i != index) {
-                deck->cards[curr_index] = deck->cards[i];
-                curr_index++;
-            } else {
-                result = deck->cards[i];
-            }
-        }
-        if(deck->index >= 0) {
-            deck->index--;
-        }
-    }
-    return result;
-}
-
-void extract_hand_region(Hand* hand, Hand* to, uint8_t start_index) {
-    FURI_LOG_D("CARD", "Extracting hand region");
-    if(start_index >= hand->index) return;
-
-    for(uint8_t i = start_index; i < hand->index; i++) {
-        add_to_hand(to, hand->cards[i]);
-    }
-    hand->index = start_index;
-}
-
-void add_hand_region(Hand* to, Hand* from) {
-    FURI_LOG_D("CARD", "Adding hand region");
-    if((to->index + from->index) <= to->max) {
-        for(int i = 0; i < from->index; i++) {
-            add_to_hand(to, from->cards[i]);
-        }
-    }
-}

+ 0 - 192
non_catalog_apps/blackjack/common/card.h

@@ -1,192 +0,0 @@
-#pragma once
-
-#include <gui/gui.h>
-#include <math.h>
-#include <stdlib.h>
-#include "dml.h"
-
-#define CARD_HEIGHT 23
-#define CARD_HALF_HEIGHT 11
-#define CARD_WIDTH 17
-#define CARD_HALF_WIDTH 8
-
-//region types
-typedef struct {
-    uint8_t pip; //Pip index 0:spades, 1:hearths, 2:diamonds, 3:clubs
-    uint8_t character; //Card letter [0-12], 0 means 2, 12 is Ace
-    bool disabled;
-    bool flipped;
-} Card;
-
-typedef struct {
-    uint8_t deck_count; //Number of decks used
-    Card* cards; //Cards in the deck
-    int card_count;
-    int index; //Card index (to know where we at in the deck)
-} Deck;
-
-typedef struct {
-    Card* cards; //Cards in the deck
-    uint8_t index; //Current index
-    uint8_t max; //How many cards we want to store
-} Hand;
-//endregion
-
-void set_card_graphics(const Icon* graphics);
-
-/**
- * Gets card coordinates at the index (range: 0-20).
- *
- * @param index Index to check 0-20
- * @return      Position of the card
- */
-Vector card_pos_at_index(uint8_t index);
-
-/**
- * Draws card at a given coordinate (top-left corner)
- *
- * @param pos_x         X position
- * @param pos_y         Y position
- * @param pip           Pip index 0:spades, 1:hearths, 2:diamonds, 3:clubs
- * @param character     Letter [0-12] 0 is 2, 12 is A
- * @param canvas        Pointer to Flipper's canvas object
- */
-void draw_card_at(int8_t pos_x, int8_t pos_y, uint8_t pip, uint8_t character, Canvas* const canvas);
-
-/**
- * Draws card at a given coordinate (top-left corner)
- *
- * @param pos_x         X position
- * @param pos_y         Y position
- * @param pip           Pip index 0:spades, 1:hearths, 2:diamonds, 3:clubs
- * @param character     Letter [0-12] 0 is 2, 12 is A
- * @param inverted      Invert colors
- * @param canvas        Pointer to Flipper's canvas object
- */
-void draw_card_at_colored(
-    int8_t pos_x,
-    int8_t pos_y,
-    uint8_t pip,
-    uint8_t character,
-    bool inverted,
-    Canvas* const canvas);
-
-/**
- * Draws 'count' cards at the bottom right corner
- *
- * @param cards     List of cards
- * @param count     Count of cards
- * @param canvas    Pointer to Flipper's canvas object
- */
-void draw_deck(const Card* cards, uint8_t count, Canvas* const canvas);
-
-/**
- * Draws card back at a given coordinate (top-left corner)
- *
- * @param pos_x     X coordinate
- * @param pos_y     Y coordinate
- * @param canvas    Pointer to Flipper's canvas object
- */
-void draw_card_back_at(int8_t pos_x, int8_t pos_y, Canvas* const canvas);
-
-/**
- * Generates the deck
- *
- * @param deck_ptr      Pointer to the deck
- * @param deck_count    Number of decks
- */
-void generate_deck(Deck* deck_ptr, uint8_t deck_count);
-
-/**
- * Shuffles the deck
- *
- * @param deck_ptr Pointer to the deck
- */
-void shuffle_deck(Deck* deck_ptr);
-
-/**
- * Calculates the hand count for blackjack
- *
- * @param cards     List of cards
- * @param count     Count of cards
- * @return          Hand value
- */
-uint8_t hand_count(const Card* cards, uint8_t count);
-
-/**
- * Draws card animation
- *
- * @param animatingCard Card to animate
- * @param from          Starting position
- * @param control       Quadratic lerp control point
- * @param to            End point
- * @param t             Current time (0-1)
- * @param extra_margin  Use extra margin at the end (arrives 0.2 unit before the end so it can stay there a bit)
- * @param canvas        Pointer to Flipper's canvas object
- */
-void draw_card_animation(
-    Card animatingCard,
-    Vector from,
-    Vector control,
-    Vector to,
-    float t,
-    bool extra_margin,
-    Canvas* const canvas);
-
-/**
- * Init hand pointer
- * @param hand_ptr   Pointer to hand
- * @param count      Number of cards we want to store
- */
-void init_hand(Hand* hand_ptr, uint8_t count);
-
-/**
- * Free hand resources
- * @param hand_ptr  Pointer to hand
- */
-void free_hand(Hand* hand_ptr);
-
-/**
- * Add card to hand
- * @param hand_ptr  Pointer to hand
- * @param card      Card to add
- */
-void add_to_hand(Hand* hand_ptr, Card card);
-
-/**
- * Draw card placement position at coordinate
- * @param pos_x     X coordinate
- * @param pos_y     Y coordinate
- * @param highlighted   Apply highlight effect
- * @param canvas    Canvas object
- */
-void draw_card_space(int16_t pos_x, int16_t pos_y, bool highlighted, Canvas* const canvas);
-
-/**
- * Draws a column of card, displaying the last [max_cards] cards on the list
- * @param hand              Hand object
- * @param pos_x             X coordinate to draw
- * @param pos_y             Y coordinate to draw
- * @param highlight         Index to highlight, negative means no highlight
- * @param canvas            Canvas object
- */
-void draw_hand_column(
-    Hand hand,
-    int16_t pos_x,
-    int16_t pos_y,
-    int8_t highlight,
-    Canvas* const canvas);
-
-/**
- * Removes a card from the deck (Be aware, if you remove the first item, the deck index will be at -1 so you have to handle that)
- * @param index Index to remove
- * @param deck  Deck reference
- * @return      The removed card
- */
-Card remove_from_deck(uint16_t index, Deck* deck);
-
-int first_non_flipped_card(Hand hand);
-
-void extract_hand_region(Hand* hand, Hand* to, uint8_t start_index);
-
-void add_hand_region(Hand* to, Hand* from);

+ 0 - 53
non_catalog_apps/blackjack/common/dml.c

@@ -1,53 +0,0 @@
-#include "dml.h"
-#include <math.h>
-
-float lerp(float v0, float v1, float t) {
-    if(t > 1) return v1;
-    return (1 - t) * v0 + t * v1;
-}
-
-Vector lerp_2d(Vector start, Vector end, float t) {
-    return (Vector){
-        lerp(start.x, end.x, t),
-        lerp(start.y, end.y, t),
-    };
-}
-
-Vector quadratic_2d(Vector start, Vector control, Vector end, float t) {
-    return lerp_2d(lerp_2d(start, control, t), lerp_2d(control, end, t), t);
-}
-
-Vector vector_add(Vector a, Vector b) {
-    return (Vector){a.x + b.x, a.y + b.y};
-}
-
-Vector vector_sub(Vector a, Vector b) {
-    return (Vector){a.x - b.x, a.y - b.y};
-}
-
-Vector vector_mul_components(Vector a, Vector b) {
-    return (Vector){a.x * b.x, a.y * b.y};
-}
-
-Vector vector_div_components(Vector a, Vector b) {
-    return (Vector){a.x / b.x, a.y / b.y};
-}
-
-Vector vector_normalized(Vector a) {
-    float length = vector_magnitude(a);
-    return (Vector){a.x / length, a.y / length};
-}
-
-float vector_magnitude(Vector a) {
-    return sqrt(a.x * a.x + a.y * a.y);
-}
-
-float vector_distance(Vector a, Vector b) {
-    return vector_magnitude(vector_sub(a, b));
-}
-
-float vector_dot(Vector a, Vector b) {
-    Vector _a = vector_normalized(a);
-    Vector _b = vector_normalized(b);
-    return _a.x * _b.x + _a.y * _b.y;
-}

+ 0 - 116
non_catalog_apps/blackjack/common/dml.h

@@ -1,116 +0,0 @@
-//
-// Doofy's Math library
-//
-
-#pragma once
-
-typedef struct {
-    float x;
-    float y;
-} Vector;
-
-#define min(a, b) ((a) < (b) ? (a) : (b))
-#define max(a, b) ((a) > (b) ? (a) : (b))
-#define abs(x) ((x) > 0 ? (x) : -(x))
-
-/**
- * Lerp function
- *
- * @param v0    Start value
- * @param v1    End value
- * @param t     Time (0-1 range)
- * @return      Point between v0-v1 at a given time
- */
-float lerp(float v0, float v1, float t);
-
-/**
- * 2D lerp function
- *
- * @param start Start vector
- * @param end   End vector
- * @param t     Time (0-1 range)
- * @return      2d Vector between start and end at time
- */
-Vector lerp_2d(Vector start, Vector end, float t);
-
-/**
- * Quadratic lerp function
- *
- * @param start     Start vector
- * @param control   Control point
- * @param end       End vector
- * @param t         Time (0-1 range)
- * @return          2d Vector at time
- */
-Vector quadratic_2d(Vector start, Vector control, Vector end, float t);
-
-/**
- * Add vector components together
- *
- * @param a     First vector
- * @param b     Second vector
- * @return      Resulting vector
- */
-Vector vector_add(Vector a, Vector b);
-
-/**
- * Subtract vector components together
- *
- * @param a First vector
- * @param b Second vector
- * @return  Resulting vector
- */
-Vector vector_sub(Vector a, Vector b);
-
-/**
- * Multiplying vector components together
- *
- * @param a First vector
- * @param b Second vector
- * @return  Resulting vector
- */
-Vector vector_mul_components(Vector a, Vector b);
-
-/**
- * Dividing vector components
- *
- * @param a First vector
- * @param b Second vector
- * @return  Resulting vector
- */
-Vector vector_div_components(Vector a, Vector b);
-
-/**
- * Calculating Vector length
- *
- * @param a Direction vector
- * @return  Length of the vector
- */
-float vector_magnitude(Vector a);
-
-/**
- * Get a normalized vector (length of 1)
- *
- * @param a Direction vector
- * @return  Normalized vector
- */
-Vector vector_normalized(Vector a);
-
-/**
- * Calculate two vector's distance
- *
- * @param a First vector
- * @param b Second vector
- * @return  Distance between vectors
- */
-float vector_distance(Vector a, Vector b);
-
-/**
- * Calculate the dot product of the vectors.
- * No need to normalize, it will do it
- *
- * @param a First vector
- * @param b Second vector
- * @return  value from -1 to 1
- */
-float vector_dot(Vector a, Vector b);

+ 0 - 103
non_catalog_apps/blackjack/common/menu.c

@@ -1,103 +0,0 @@
-#include "menu.h"
-
-void add_menu(Menu* menu, const char* name, void (*callback)(void*)) {
-    MenuItem* items = menu->items;
-
-    menu->items = malloc(sizeof(MenuItem) * (menu->menu_count + 1));
-    for(uint8_t i = 0; i < menu->menu_count; i++) {
-        menu->items[i] = items[i];
-    }
-    free(items);
-
-    menu->items[menu->menu_count] = (MenuItem){name, true, callback};
-    menu->menu_count++;
-}
-
-void free_menu(Menu* menu) {
-    free(menu->items);
-    free(menu);
-}
-
-void set_menu_state(Menu* menu, uint8_t index, bool state) {
-    if(menu->menu_count > index) {
-        menu->items[index].enabled = state;
-    }
-    if(!state && menu->current_menu == index) move_menu(menu, 1);
-}
-
-void move_menu(Menu* menu, int8_t direction) {
-    if(!menu->enabled) return;
-    int max = menu->menu_count;
-    for(int8_t i = 0; i < max; i++) {
-        FURI_LOG_D(
-            "MENU",
-            "Iteration %i, current %i, direction %i, state %i",
-            i,
-            menu->current_menu,
-            direction,
-            menu->items[menu->current_menu].enabled ? 1 : 0);
-        if(direction < 0 && menu->current_menu == 0) {
-            menu->current_menu = menu->menu_count - 1;
-        } else {
-            menu->current_menu = (menu->current_menu + direction) % menu->menu_count;
-        }
-        FURI_LOG_D(
-            "MENU",
-            "After process current %i, direction %i, state %i",
-            menu->current_menu,
-            direction,
-            menu->items[menu->current_menu].enabled ? 1 : 0);
-        if(menu->items[menu->current_menu].enabled) {
-            FURI_LOG_D("MENU", "Next menu %i", menu->current_menu);
-            return;
-        }
-    }
-    FURI_LOG_D("MENU", "Not found, setting false");
-    menu->enabled = false;
-}
-
-void activate_menu(Menu* menu, void* state) {
-    if(!menu->enabled) return;
-    menu->items[menu->current_menu].callback(state);
-}
-
-void render_menu(Menu* menu, Canvas* canvas, uint8_t pos_x, uint8_t pos_y) {
-    if(!menu->enabled) return;
-    canvas_set_color(canvas, ColorWhite);
-    canvas_draw_rbox(canvas, pos_x, pos_y, menu->menu_width + 2, 10, 2);
-
-    uint8_t w = pos_x + menu->menu_width;
-    uint8_t h = pos_y + 10;
-    uint8_t p1x = pos_x + 2;
-    uint8_t p2x = pos_x + menu->menu_width - 2;
-    uint8_t p1y = pos_y + 2;
-    uint8_t p2y = pos_y + 8;
-
-    canvas_set_color(canvas, ColorBlack);
-    canvas_draw_line(canvas, p1x, pos_y, p2x, pos_y);
-    canvas_draw_line(canvas, p1x, h, p2x, h);
-    canvas_draw_line(canvas, pos_x, p1y, pos_x, p2y);
-    canvas_draw_line(canvas, w, p1y, w, p2y);
-    canvas_draw_dot(canvas, pos_x + 1, pos_y + 1);
-    canvas_draw_dot(canvas, w - 1, pos_y + 1);
-    canvas_draw_dot(canvas, w - 1, h - 1);
-    canvas_draw_dot(canvas, pos_x + 1, h - 1);
-
-    //    canvas_draw_rbox(canvas, pos_x, pos_y, menu->menu_width + 2, 10, 2);
-    canvas_set_font(canvas, FontSecondary);
-    canvas_draw_str_aligned(
-        canvas,
-        pos_x + menu->menu_width / 2,
-        pos_y + 6,
-        AlignCenter,
-        AlignCenter,
-        menu->items[menu->current_menu].name);
-    //9*5
-    int center = pos_x + menu->menu_width / 2;
-    for(uint8_t i = 0; i < 4; i++) {
-        for(int8_t j = -i; j <= i; j++) {
-            canvas_draw_dot(canvas, center + j, pos_y - 4 + i);
-            canvas_draw_dot(canvas, center + j, pos_y + 14 - i);
-        }
-    }
-}

+ 0 - 77
non_catalog_apps/blackjack/common/menu.h

@@ -1,77 +0,0 @@
-#pragma once
-
-#include <furi.h>
-#include <gui/gui.h>
-
-typedef struct {
-    const char* name; //Name of the menu
-    bool enabled; //Is the menu item enabled (it will not render, you cannot select it)
-
-    void (*callback)(
-        void* state); //Callback for when the activate_menu is called while this menu is selected
-} MenuItem;
-
-typedef struct {
-    MenuItem* items; //list of menu items
-    uint8_t menu_count; //count of menu items (do not change)
-    uint8_t current_menu; //currently selected menu item
-    uint8_t menu_width; //width of the menu
-    bool enabled; //is the menu enabled (it will not render and accept events when disabled)
-} Menu;
-
-/**
- * Cleans up the pointers used by the menu
- *
- * @param menu Pointer of the menu to clean up
- */
-void free_menu(Menu* menu);
-
-/**
- * Add a new menu item
- *
- * @param menu      Pointer of the menu
- * @param name      Name of the menu item
- * @param callback  Callback called on activation
- */
-void add_menu(Menu* menu, const char* name, void (*callback)(void*));
-
-/**
- * Setting menu item to be enabled/disabled
- *
- * @param menu  Pointer of the menu
- * @param index Menu index to set
- * @param state Enabled (true), Disabled(false)
- */
-void set_menu_state(Menu* menu, uint8_t index, bool state);
-
-/**
- * Moves selection up or down
- *
- * @param menu      Pointer of the menu
- * @param direction Direction to move -1 down, 1 up
- */
-void move_menu(Menu* menu, int8_t direction);
-
-/**
- * Triggers the current menu callback
- *
- * @param menu  Pointer of the menu
- * @param state Usually your application state
- */
-void activate_menu(Menu* menu, void* state);
-
-/**
- * Renders the menu at a coordinate (call it in your render function).
- *
- * Keep in mind that Flipper has a 128x64 pixel screen resolution and the coordinate
- * you give is the menu's rectangle top-left corner (arrows not included).
- * The rectangle height is 10 px, the arrows have a 4 pixel height. Space needed is 18px.
- * The width of the menu can be configured in the menu object.
- *
- *
- * @param menu      Pointer of the menu
- * @param canvas    Flippers Canvas pointer
- * @param pos_x     X position to draw
- * @param pos_y     Y position to draw
- */
-void render_menu(Menu* menu, Canvas* canvas, uint8_t pos_x, uint8_t pos_y);

+ 0 - 69
non_catalog_apps/blackjack/common/queue.c

@@ -1,69 +0,0 @@
-#include "queue.h"
-
-void render_queue(const QueueState* queue_state, const void* app_state, Canvas* const canvas) {
-    if(queue_state->current != NULL && queue_state->current->render != NULL)
-        ((QueueItem*)queue_state->current)->render(app_state, canvas);
-}
-
-bool run_queue(QueueState* queue_state, void* app_state) {
-    if(queue_state->current != NULL) {
-        queue_state->running = true;
-        if((furi_get_tick() - queue_state->start) >= queue_state->current->duration)
-            dequeue(queue_state, app_state);
-
-        return true;
-    }
-    return false;
-}
-
-void dequeue(QueueState* queue_state, void* app_state) {
-    ((QueueItem*)queue_state->current)->callback(app_state);
-    QueueItem* f = queue_state->current;
-    queue_state->current = f->next;
-    free(f);
-    if(queue_state->current != NULL) {
-        if(queue_state->current->start != NULL) queue_state->current->start(app_state);
-        queue_state->start = furi_get_tick();
-    } else {
-        queue_state->running = false;
-    }
-}
-
-void queue_clear(QueueState* queue_state) {
-    queue_state->running = false;
-    QueueItem* curr = queue_state->current;
-    while(curr != NULL) {
-        QueueItem* f = curr;
-        curr = curr->next;
-        free(f);
-    }
-}
-
-void enqueue(
-    QueueState* queue_state,
-    void* app_state,
-    void (*done)(void* state),
-    void (*start)(void* state),
-    void (*render)(const void* state, Canvas* const canvas),
-    uint32_t duration) {
-    QueueItem* next;
-    if(queue_state->current == NULL) {
-        queue_state->start = furi_get_tick();
-        queue_state->current = malloc(sizeof(QueueItem));
-        next = queue_state->current;
-        if(next->start != NULL) next->start(app_state);
-
-    } else {
-        next = queue_state->current;
-        while(next->next != NULL) {
-            next = (QueueItem*)(next->next);
-        }
-        next->next = malloc(sizeof(QueueItem));
-        next = next->next;
-    }
-    next->callback = done;
-    next->render = render;
-    next->start = start;
-    next->duration = duration;
-    next->next = NULL;
-}

+ 0 - 70
non_catalog_apps/blackjack/common/queue.h

@@ -1,70 +0,0 @@
-#pragma once
-
-#include <gui/gui.h>
-#include <furi.h>
-
-typedef struct {
-    void (*callback)(void* state); //Callback for when the item is dequeued
-    void (*render)(
-        const void* state,
-        Canvas* const canvas); //Callback for the rendering loop while this item is running
-    void (*start)(void* state); //Callback when this item is started running
-    void* next; //Pointer to the next item
-    uint32_t duration; //duration of the item
-} QueueItem;
-
-typedef struct {
-    unsigned int start; //current queue item start time
-    QueueItem* current; //current queue item
-    bool running; //is the queue running
-} QueueState;
-
-/**
- * Enqueue a new item.
- *
- * @param queue_state   The queue state pointer
- * @param app_state     Your app state
- * @param done          Callback for dequeue event
- * @param start         Callback for when the item is activated
- * @param render        Callback to render loop if needed
- * @param duration      Length of the item
- */
-void enqueue(
-    QueueState* queue_state,
-    void* app_state,
-    void (*done)(void* state),
-    void (*start)(void* state),
-    void (*render)(const void* state, Canvas* const canvas),
-    uint32_t duration);
-/**
- * Clears all queue items
- *
- * @param queue_state   The queue state pointer
- */
-void queue_clear(QueueState* queue_state);
-
-/**
- * Dequeues the active queue item. Usually you don't need to call it directly.
- *
- * @param queue_state   The queue state pointer
- * @param app_state     Your application state
- */
-void dequeue(QueueState* queue_state, void* app_state);
-
-/**
- * Runs the queue logic (place it in your tick function)
- *
- * @param queue_state   The queue state pointer
- * @param app_state     Your application state
- * @return              FALSE when there is nothing to run, TRUE otherwise
- */
-bool run_queue(QueueState* queue_state, void* app_state);
-
-/**
- * Calls the currently active queue items render callback (if there is any)
- *
- * @param queue_state   The queue state pointer
- * @param app_state     Your application state
- * @param canvas        Pointer to Flipper's canvas object
- */
-void render_queue(const QueueState* queue_state, const void* app_state, Canvas* const canvas);

+ 0 - 257
non_catalog_apps/blackjack/common/ui.c

@@ -1,257 +0,0 @@
-#include "ui.h"
-#include <gui/canvas_i.h>
-#include <u8g2_glue.h>
-#include <gui/icon_animation_i.h>
-#include <gui/icon.h>
-#include <gui/icon_i.h>
-#include <furi_hal.h>
-
-TileMap* tileMap;
-uint8_t tileMapCount = 0;
-
-void ui_cleanup() {
-    if(tileMap != NULL) {
-        for(uint8_t i = 0; i < tileMapCount; i++) {
-            if(tileMap[i].data != NULL) free(tileMap[i].data);
-        }
-        free(tileMap);
-    }
-}
-
-void add_new_tilemap(uint8_t* data, unsigned long iconId) {
-    TileMap* old = tileMap;
-    tileMapCount++;
-    tileMap = malloc(sizeof(TileMap) * tileMapCount);
-    if(tileMapCount > 1) {
-        for(uint8_t i = 0; i < tileMapCount; i++) tileMap[i] = old[i];
-    }
-    tileMap[tileMapCount - 1] = (TileMap){data, iconId};
-}
-
-uint8_t* get_tilemap(unsigned long icon_id) {
-    for(uint8_t i = 0; i < tileMapCount; i++) {
-        if(tileMap[i].iconId == icon_id) return tileMap[i].data;
-    }
-
-    return NULL;
-}
-
-uint32_t pixel_index(uint8_t x, uint8_t y) {
-    return y * SCREEN_WIDTH + x;
-}
-
-bool in_screen(int16_t x, int16_t y) {
-    return x >= 0 && x < SCREEN_WIDTH && y >= 0 && y < SCREEN_HEIGHT;
-}
-
-unsigned flipBit(uint8_t x, uint8_t bit) {
-    return x ^ (1 << bit);
-}
-
-unsigned setBit(uint8_t x, uint8_t bit) {
-    return x | (1 << bit);
-}
-
-unsigned unsetBit(uint8_t x, uint8_t bit) {
-    return x & ~(1 << bit);
-}
-
-bool test_pixel(uint8_t* data, uint8_t x, uint8_t y, uint8_t w) {
-    uint8_t current_bit = (y % 8);
-    uint8_t current_row = ((y - current_bit) / 8);
-    uint8_t current_value = data[current_row * w + x];
-    return current_value & (1 << current_bit);
-}
-
-uint8_t* get_buffer(Canvas* const canvas) {
-    return canvas->fb.tile_buf_ptr;
-    //  return canvas_get_buffer(canvas);
-}
-uint8_t* make_buffer() {
-    return malloc(sizeof(uint8_t) * 8 * 128);
-}
-void clone_buffer(uint8_t* canvas, uint8_t* data) {
-    for(int i = 0; i < 1024; i++) {
-        data[i] = canvas[i];
-    }
-}
-
-bool read_pixel(Canvas* const canvas, int16_t x, int16_t y) {
-    if(in_screen(x, y)) {
-        return test_pixel(get_buffer(canvas), x, y, SCREEN_WIDTH);
-    }
-    return false;
-}
-
-void set_pixel(Canvas* const canvas, int16_t x, int16_t y, DrawMode draw_mode) {
-    if(in_screen(x, y)) {
-        uint8_t current_bit = (y % 8);
-        uint8_t current_row = ((y - current_bit) / 8);
-        uint32_t i = pixel_index(x, current_row);
-        uint8_t* buffer = get_buffer(canvas);
-
-        uint8_t current_value = buffer[i];
-        if(draw_mode == Inverse) {
-            buffer[i] = flipBit(current_value, current_bit);
-        } else {
-            if(draw_mode == White) {
-                buffer[i] = unsetBit(current_value, current_bit);
-            } else {
-                buffer[i] = setBit(current_value, current_bit);
-            }
-        }
-    }
-}
-
-void draw_line(
-    Canvas* const canvas,
-    int16_t x1,
-    int16_t y1,
-    int16_t x2,
-    int16_t y2,
-    DrawMode draw_mode) {
-    for(int16_t x = x2; x >= x1; x--) {
-        for(int16_t y = y2; y >= y1; y--) {
-            set_pixel(canvas, x, y, draw_mode);
-        }
-    }
-}
-
-void draw_rounded_box_frame(
-    Canvas* const canvas,
-    int16_t x,
-    int16_t y,
-    uint8_t w,
-    uint8_t h,
-    DrawMode draw_mode) {
-    int16_t xMinCorner = x + 1;
-    int16_t xMax = x + w - 1;
-    int16_t xMaxCorner = x + w - 2;
-    int16_t yMinCorner = y + 1;
-    int16_t yMax = y + h - 1;
-    int16_t yMaxCorner = y + h - 2;
-    draw_line(canvas, xMinCorner, y, xMaxCorner, y, draw_mode);
-    draw_line(canvas, xMinCorner, yMax, xMaxCorner, yMax, draw_mode);
-    draw_line(canvas, x, yMinCorner, x, yMaxCorner, draw_mode);
-    draw_line(canvas, xMax, yMinCorner, xMax, yMaxCorner, draw_mode);
-}
-
-void draw_rounded_box(
-    Canvas* const canvas,
-    int16_t x,
-    int16_t y,
-    uint8_t w,
-    uint8_t h,
-    DrawMode draw_mode) {
-    for(int16_t o = w - 2; o >= 1; o--) {
-        for(int16_t p = h - 2; p >= 1; p--) {
-            set_pixel(canvas, x + o, y + p, draw_mode);
-        }
-    }
-    draw_rounded_box_frame(canvas, x, y, w, h, draw_mode);
-}
-
-void invert_shape(Canvas* const canvas, uint8_t* data, int16_t x, int16_t y, uint8_t w, uint8_t h) {
-    draw_pixels(canvas, data, x, y, w, h, Inverse);
-}
-
-void draw_pixels(
-    Canvas* const canvas,
-    uint8_t* data,
-    int16_t x,
-    int16_t y,
-    uint8_t w,
-    uint8_t h,
-    DrawMode drawMode) {
-    for(int8_t o = 0; o < w; o++) {
-        for(int8_t p = 0; p < h; p++) {
-            if(in_screen(o + x, p + y) && data[p * w + o] == 1)
-                set_pixel(canvas, o + x, p + y, drawMode);
-        }
-    }
-}
-
-void draw_rectangle(
-    Canvas* const canvas,
-    int16_t x,
-    int16_t y,
-    uint8_t w,
-    uint8_t h,
-    DrawMode drawMode) {
-    for(int8_t o = 0; o < w; o++) {
-        for(int8_t p = 0; p < h; p++) {
-            if(in_screen(o + x, p + y)) {
-                set_pixel(canvas, o + x, p + y, drawMode);
-            }
-        }
-    }
-}
-
-void invert_rectangle(Canvas* const canvas, int16_t x, int16_t y, uint8_t w, uint8_t h) {
-    draw_rectangle(canvas, x, y, w, h, Inverse);
-}
-
-uint8_t* image_data(Canvas* const canvas, const Icon* icon) {
-    uint8_t* data = malloc(sizeof(uint8_t) * 8 * 128);
-    uint8_t* screen = canvas->fb.tile_buf_ptr;
-    canvas->fb.tile_buf_ptr = data;
-    canvas_draw_icon(canvas, 0, 0, icon);
-    canvas->fb.tile_buf_ptr = screen;
-    return data;
-}
-
-uint8_t* getOrAddIconData(Canvas* const canvas, const Icon* icon) {
-    uint8_t* icon_data = get_tilemap((unsigned long)icon);
-    if(icon_data == NULL) {
-        icon_data = image_data(canvas, icon);
-        add_new_tilemap(icon_data, (unsigned long)icon);
-    }
-    return icon_data;
-}
-
-void draw_icon_clip(
-    Canvas* const canvas,
-    const Icon* icon,
-    int16_t x,
-    int16_t y,
-    uint8_t left,
-    uint8_t top,
-    uint8_t w,
-    uint8_t h,
-    DrawMode drawMode) {
-    uint8_t* icon_data = getOrAddIconData(canvas, icon);
-
-    for(int i = 0; i < w; i++) {
-        for(int j = 0; j < h; j++) {
-            bool on = test_pixel(icon_data, left + i, top + j, SCREEN_WIDTH);
-            if(drawMode == Filled) {
-                set_pixel(canvas, x + i, y + j, on ? Black : White);
-            } else if(on)
-                set_pixel(canvas, x + i, y + j, drawMode);
-        }
-    }
-}
-
-void draw_icon_clip_flipped(
-    Canvas* const canvas,
-    const Icon* icon,
-    int16_t x,
-    int16_t y,
-    uint8_t left,
-    uint8_t top,
-    uint8_t w,
-    uint8_t h,
-    DrawMode drawMode) {
-    uint8_t* icon_data = getOrAddIconData(canvas, icon);
-
-    for(int i = 0; i < w; i++) {
-        for(int j = 0; j < h; j++) {
-            bool on = test_pixel(icon_data, left + i, top + j, SCREEN_WIDTH);
-
-            if(drawMode == Filled) {
-                set_pixel(canvas, x + w - i - 1, y + h - j - 1, on ? Black : White);
-            } else if(on)
-                set_pixel(canvas, x + w - i - 1, y + h - j - 1, drawMode);
-        }
-    }
-}

+ 0 - 105
non_catalog_apps/blackjack/common/ui.h

@@ -1,105 +0,0 @@
-#pragma once
-
-#include <furi.h>
-#include <gui/canvas.h>
-
-#define SCREEN_WIDTH 128
-#define SCREEN_HEIGHT 64
-
-typedef enum {
-    Black,
-    White,
-    Inverse,
-    Filled //Currently only for Icon clip drawing
-} DrawMode;
-
-// size is the screen size
-
-typedef struct {
-    uint8_t* data;
-    unsigned long iconId;
-} TileMap;
-
-bool test_pixel(uint8_t* data, uint8_t x, uint8_t y, uint8_t w);
-
-uint8_t* image_data(Canvas* const canvas, const Icon* icon);
-
-uint32_t pixel_index(uint8_t x, uint8_t y);
-
-void draw_icon_clip(
-    Canvas* const canvas,
-    const Icon* icon,
-    int16_t x,
-    int16_t y,
-    uint8_t left,
-    uint8_t top,
-    uint8_t w,
-    uint8_t h,
-    DrawMode drawMode);
-
-void draw_icon_clip_flipped(
-    Canvas* const canvas,
-    const Icon* icon,
-    int16_t x,
-    int16_t y,
-    uint8_t left,
-    uint8_t top,
-    uint8_t w,
-    uint8_t h,
-    DrawMode drawMode);
-
-void draw_rounded_box(
-    Canvas* const canvas,
-    int16_t x,
-    int16_t y,
-    uint8_t w,
-    uint8_t h,
-    DrawMode drawMode);
-
-void draw_rounded_box_frame(
-    Canvas* const canvas,
-    int16_t x,
-    int16_t y,
-    uint8_t w,
-    uint8_t h,
-    DrawMode drawMode);
-
-void draw_rectangle(
-    Canvas* const canvas,
-    int16_t x,
-    int16_t y,
-    uint8_t w,
-    uint8_t h,
-    DrawMode drawMode);
-
-void invert_rectangle(Canvas* const canvas, int16_t x, int16_t y, uint8_t w, uint8_t h);
-
-void invert_shape(Canvas* const canvas, uint8_t* data, int16_t x, int16_t y, uint8_t w, uint8_t h);
-
-void draw_pixels(
-    Canvas* const canvas,
-    uint8_t* data,
-    int16_t x,
-    int16_t y,
-    uint8_t w,
-    uint8_t h,
-    DrawMode drawMode);
-
-bool read_pixel(Canvas* const canvas, int16_t x, int16_t y);
-
-void set_pixel(Canvas* const canvas, int16_t x, int16_t y, DrawMode draw_mode);
-
-void draw_line(
-    Canvas* const canvas,
-    int16_t x1,
-    int16_t y1,
-    int16_t x2,
-    int16_t y2,
-    DrawMode draw_mode);
-
-bool in_screen(int16_t x, int16_t y);
-
-void ui_cleanup();
-uint8_t* get_buffer(Canvas* const canvas);
-uint8_t* make_buffer();
-void clone_buffer(uint8_t* canvas, uint8_t* data);

+ 0 - 77
non_catalog_apps/blackjack/defines.h

@@ -1,77 +0,0 @@
-#pragma once
-
-#include <furi.h>
-#include <input/input.h>
-#include <gui/elements.h>
-#include <flipper_format/flipper_format.h>
-#include <flipper_format/flipper_format_i.h>
-#include "common/card.h"
-#include "common/queue.h"
-#include "common/menu.h"
-
-#define APP_NAME "Blackjack"
-
-#define CONF_ANIMATION_DURATION "AnimationDuration"
-#define CONF_MESSAGE_DURATION "MessageDuration"
-#define CONF_STARTING_MONEY "StartingMoney"
-#define CONF_ROUND_PRICE "RoundPrice"
-#define CONF_SOUND_EFFECTS "SoundEffects"
-
-typedef enum {
-    EventTypeTick,
-    EventTypeKey,
-} EventType;
-
-typedef struct {
-    uint32_t animation_duration;
-    uint32_t message_duration;
-    uint32_t starting_money;
-    uint32_t round_price;
-    bool sound_effects;
-} Settings;
-
-typedef struct {
-    EventType type;
-    InputEvent input;
-} AppEvent;
-
-typedef enum {
-    GameStateGameOver,
-    GameStateStart,
-    GameStatePlay,
-    GameStateSettings,
-    GameStateDealer,
-} PlayState;
-
-typedef enum {
-    DirectionUp,
-    DirectionDown,
-    DirectionRight,
-    DirectionLeft,
-    Select,
-    Back,
-    None
-} Direction;
-
-typedef struct {
-    FuriMutex* mutex;
-    Card player_cards[21];
-    Card dealer_cards[21];
-    uint8_t player_card_count;
-    uint8_t dealer_card_count;
-
-    Direction selectDirection;
-    Settings settings;
-
-    uint32_t player_score;
-    uint32_t bet;
-    uint8_t selectedMenu;
-    bool doubled;
-    bool started;
-    bool processing;
-    Deck deck;
-    PlayState state;
-    QueueState queue_state;
-    Menu* menu;
-    unsigned int last_tick;
-} GameState;

+ 0 - 186
non_catalog_apps/blackjack/ui.c

@@ -1,186 +0,0 @@
-#include <math.h>
-#include <notification/notification_messages.h>
-
-#include "ui.h"
-
-#define LINE_HEIGHT 16
-#define ITEM_PADDING 4
-
-const char MoneyMul[4] = {'K', 'B', 'T', 'S'};
-
-void draw_player_scene(Canvas* const canvas, const GameState* game_state) {
-    int max_card = game_state->player_card_count;
-
-    if(max_card > 0) draw_deck((game_state->player_cards), max_card, canvas);
-
-    if(game_state->dealer_card_count > 0) draw_card_back_at(13, 5, canvas);
-
-    max_card = game_state->dealer_card_count;
-    if(max_card > 1) {
-        draw_card_at(
-            2, 2, game_state->dealer_cards[1].pip, game_state->dealer_cards[1].character, canvas);
-    }
-}
-
-void draw_dealer_scene(Canvas* const canvas, const GameState* game_state) {
-    uint8_t max_card = game_state->dealer_card_count;
-    draw_deck((game_state->dealer_cards), max_card, canvas);
-}
-
-void popup_frame(Canvas* const canvas) {
-    canvas_set_color(canvas, ColorWhite);
-    canvas_draw_box(canvas, 32, 15, 66, 13);
-    canvas_set_color(canvas, ColorBlack);
-    canvas_draw_frame(canvas, 32, 15, 66, 13);
-    canvas_set_font(canvas, FontSecondary);
-}
-
-void draw_play_menu(Canvas* const canvas, const GameState* game_state) {
-    const char* menus[3] = {"Double", "Hit", "Stay"};
-    for(uint8_t m = 0; m < 3; m++) {
-        if(m == 0 &&
-           (game_state->doubled || game_state->player_score < game_state->settings.round_price))
-            continue;
-        int y = m * 13 + 25;
-        canvas_set_color(canvas, ColorBlack);
-
-        if(game_state->selectedMenu == m) {
-            canvas_set_color(canvas, ColorBlack);
-            canvas_draw_box(canvas, 1, y, 31, 12);
-        } else {
-            canvas_set_color(canvas, ColorWhite);
-            canvas_draw_box(canvas, 1, y, 31, 12);
-            canvas_set_color(canvas, ColorBlack);
-            canvas_draw_frame(canvas, 1, y, 31, 12);
-        }
-
-        if(game_state->selectedMenu == m)
-            canvas_set_color(canvas, ColorWhite);
-        else
-            canvas_set_color(canvas, ColorBlack);
-        canvas_draw_str_aligned(canvas, 16, y + 6, AlignCenter, AlignCenter, menus[m]);
-    }
-}
-
-void draw_screen(Canvas* const canvas, const bool* points) {
-    for(uint8_t x = 0; x < 128; x++) {
-        for(uint8_t y = 0; y < 64; y++) {
-            if(points[y * 128 + x]) canvas_draw_dot(canvas, x, y);
-        }
-    }
-}
-
-void draw_score(Canvas* const canvas, bool top, uint8_t amount) {
-    char drawChar[20];
-    snprintf(drawChar, sizeof(drawChar), "Player score: %i", amount);
-    if(top)
-        canvas_draw_str_aligned(canvas, 64, 2, AlignCenter, AlignTop, drawChar);
-    else
-        canvas_draw_str_aligned(canvas, 64, 62, AlignCenter, AlignBottom, drawChar);
-}
-
-void draw_money(Canvas* const canvas, uint32_t score) {
-    canvas_set_font(canvas, FontSecondary);
-    char drawChar[11];
-    uint32_t currAmount = score;
-    if(currAmount < 1000) {
-        snprintf(drawChar, sizeof(drawChar), "$%lu", currAmount);
-    } else {
-        char c = 'K';
-        for(uint8_t i = 0; i < 4; i++) {
-            currAmount = currAmount / 1000;
-            if(currAmount < 1000) {
-                c = MoneyMul[i];
-                break;
-            }
-        }
-
-        snprintf(drawChar, sizeof(drawChar), "$%lu %c", currAmount, c);
-    }
-    canvas_draw_str_aligned(canvas, 126, 2, AlignRight, AlignTop, drawChar);
-}
-
-void draw_menu(
-    Canvas* const canvas,
-    const char* text,
-    const char* value,
-    int8_t y,
-    bool left_caret,
-    bool right_caret,
-    bool selected) {
-    UNUSED(selected);
-    if(y < 0 || y >= 64) return;
-
-    if(selected) {
-        canvas_set_color(canvas, ColorBlack);
-        canvas_draw_box(canvas, 0, y, 122, LINE_HEIGHT);
-        canvas_set_color(canvas, ColorWhite);
-    }
-
-    canvas_draw_str_aligned(canvas, 4, y + ITEM_PADDING, AlignLeft, AlignTop, text);
-    if(left_caret) canvas_draw_str_aligned(canvas, 80, y + ITEM_PADDING, AlignLeft, AlignTop, "<");
-    canvas_draw_str_aligned(canvas, 100, y + ITEM_PADDING, AlignCenter, AlignTop, value);
-    if(right_caret)
-        canvas_draw_str_aligned(canvas, 120, y + ITEM_PADDING, AlignRight, AlignTop, ">");
-
-    canvas_set_color(canvas, ColorBlack);
-}
-
-void settings_page(Canvas* const canvas, const GameState* gameState) {
-    char drawChar[10];
-    int startY = 0;
-    if(LINE_HEIGHT * (gameState->selectedMenu + 1) >= 64) {
-        startY -= (LINE_HEIGHT * (gameState->selectedMenu + 1)) - 64;
-    }
-
-    int scrollHeight = round(64 / 6.0) + ITEM_PADDING * 2;
-    int scrollPos = 64 / (6.0 / (gameState->selectedMenu + 1)) - ITEM_PADDING * 2;
-
-    canvas_set_color(canvas, ColorBlack);
-    canvas_draw_box(canvas, 123, scrollPos, 4, scrollHeight);
-    canvas_draw_box(canvas, 125, 0, 1, 64);
-
-    snprintf(drawChar, sizeof(drawChar), "%li", gameState->settings.starting_money);
-    draw_menu(
-        canvas,
-        "Start money",
-        drawChar,
-        0 * LINE_HEIGHT + startY,
-        gameState->settings.starting_money > gameState->settings.round_price,
-        gameState->settings.starting_money < 400,
-        gameState->selectedMenu == 0);
-    snprintf(drawChar, sizeof(drawChar), "%li", gameState->settings.round_price);
-    draw_menu(
-        canvas,
-        "Round price",
-        drawChar,
-        1 * LINE_HEIGHT + startY,
-        gameState->settings.round_price > 10,
-        gameState->settings.round_price < gameState->settings.starting_money,
-        gameState->selectedMenu == 1);
-
-    snprintf(drawChar, sizeof(drawChar), "%li", gameState->settings.animation_duration);
-    draw_menu(
-        canvas,
-        "Anim. length",
-        drawChar,
-        2 * LINE_HEIGHT + startY,
-        gameState->settings.animation_duration > 0,
-        gameState->settings.animation_duration < 2000,
-        gameState->selectedMenu == 2);
-    snprintf(drawChar, sizeof(drawChar), "%li", gameState->settings.message_duration);
-    draw_menu(
-        canvas,
-        "Popup time",
-        drawChar,
-        3 * LINE_HEIGHT + startY,
-        gameState->settings.message_duration > 0,
-        gameState->settings.message_duration < 2000,
-        gameState->selectedMenu == 3);
-    //    draw_menu(canvas, "Sound", gameState->settings.sound_effects ? "Yes" : "No",
-    //              5 * LINE_HEIGHT + startY,
-    //              true,
-    //              true,
-    //              gameState->selectedMenu == 5
-    //    );
-}

+ 0 - 18
non_catalog_apps/blackjack/ui.h

@@ -1,18 +0,0 @@
-#pragma once
-
-#include "defines.h"
-#include <gui/gui.h>
-
-void draw_player_scene(Canvas* const canvas, const GameState* game_state);
-
-void draw_dealer_scene(Canvas* const canvas, const GameState* game_state);
-
-void draw_play_menu(Canvas* const canvas, const GameState* game_state);
-
-void draw_score(Canvas* const canvas, bool top, uint8_t amount);
-
-void draw_money(Canvas* const canvas, uint32_t score);
-void settings_page(Canvas* const canvas, const GameState* gameState);
-
-void popup_frame(Canvas* const canvas);
-void draw_screen(Canvas* const canvas, const bool* points);

+ 0 - 123
non_catalog_apps/blackjack/util.c

@@ -1,123 +0,0 @@
-#include <storage/storage.h>
-#include "util.h"
-
-const char* CONFIG_FILE_PATH = EXT_PATH(".blackjack.settings");
-
-void save_settings(Settings settings) {
-    Storage* storage = furi_record_open(RECORD_STORAGE);
-    FlipperFormat* file = flipper_format_file_alloc(storage);
-    FURI_LOG_D(APP_NAME, "Saving config");
-    if(flipper_format_file_open_existing(file, CONFIG_FILE_PATH)) {
-        FURI_LOG_D(
-            APP_NAME, "Saving %s: %ld", CONF_ANIMATION_DURATION, settings.animation_duration);
-        flipper_format_update_uint32(
-            file, CONF_ANIMATION_DURATION, &(settings.animation_duration), 1);
-
-        FURI_LOG_D(APP_NAME, "Saving %s: %ld", CONF_MESSAGE_DURATION, settings.message_duration);
-        flipper_format_update_uint32(file, CONF_MESSAGE_DURATION, &(settings.message_duration), 1);
-
-        FURI_LOG_D(APP_NAME, "Saving %s: %ld", CONF_STARTING_MONEY, settings.starting_money);
-        flipper_format_update_uint32(file, CONF_STARTING_MONEY, &(settings.starting_money), 1);
-
-        FURI_LOG_D(APP_NAME, "Saving %s: %ld", CONF_ROUND_PRICE, settings.round_price);
-        flipper_format_update_uint32(file, CONF_ROUND_PRICE, &(settings.round_price), 1);
-
-        FURI_LOG_D(APP_NAME, "Saving %s: %i", CONF_SOUND_EFFECTS, settings.sound_effects ? 1 : 0);
-        flipper_format_update_bool(file, CONF_SOUND_EFFECTS, &(settings.sound_effects), 1);
-        FURI_LOG_D(APP_NAME, "Config saved");
-    } else {
-        FURI_LOG_E(APP_NAME, "Save error");
-    }
-    flipper_format_file_close(file);
-    flipper_format_free(file);
-    furi_record_close(RECORD_STORAGE);
-}
-
-void save_settings_file(FlipperFormat* file, Settings* settings) {
-    flipper_format_write_header_cstr(file, CONFIG_FILE_HEADER, CONFIG_FILE_VERSION);
-    flipper_format_write_comment_cstr(file, "Card animation duration in ms");
-    flipper_format_write_uint32(file, CONF_ANIMATION_DURATION, &(settings->animation_duration), 1);
-    flipper_format_write_comment_cstr(file, "Popup message duration in ms");
-    flipper_format_write_uint32(file, CONF_MESSAGE_DURATION, &(settings->message_duration), 1);
-    flipper_format_write_comment_cstr(file, "Player's starting money");
-    flipper_format_write_uint32(file, CONF_STARTING_MONEY, &(settings->starting_money), 1);
-    flipper_format_write_comment_cstr(file, "Round price");
-    flipper_format_write_uint32(file, CONF_ROUND_PRICE, &(settings->round_price), 1);
-    flipper_format_write_comment_cstr(file, "Enable sound effects");
-    flipper_format_write_bool(file, CONF_SOUND_EFFECTS, &(settings->sound_effects), 1);
-}
-
-Settings load_settings() {
-    Settings settings;
-
-    FURI_LOG_D(APP_NAME, "Loading default settings");
-    settings.animation_duration = 800;
-    settings.message_duration = 1500;
-    settings.starting_money = 200;
-    settings.round_price = 10;
-    settings.sound_effects = true;
-
-    FURI_LOG_D(APP_NAME, "Opening storage");
-    Storage* storage = furi_record_open(RECORD_STORAGE);
-    FURI_LOG_D(APP_NAME, "Allocating file");
-    FlipperFormat* file = flipper_format_file_alloc(storage);
-
-    FURI_LOG_D(APP_NAME, "Allocating string");
-    FuriString* string_value;
-    string_value = furi_string_alloc();
-
-    if(storage_common_stat(storage, CONFIG_FILE_PATH, NULL) != FSE_OK) {
-        FURI_LOG_D(APP_NAME, "Config file %s not found, creating new one...", CONFIG_FILE_PATH);
-        if(!flipper_format_file_open_new(file, CONFIG_FILE_PATH)) {
-            FURI_LOG_E(APP_NAME, "Error creating new file %s", CONFIG_FILE_PATH);
-            flipper_format_file_close(file);
-        } else {
-            save_settings_file(file, &settings);
-        }
-    } else {
-        if(!flipper_format_file_open_existing(file, CONFIG_FILE_PATH)) {
-            FURI_LOG_E(APP_NAME, "Error opening existing file %s", CONFIG_FILE_PATH);
-            flipper_format_file_close(file);
-        } else {
-            uint32_t value;
-            bool valueBool;
-            FURI_LOG_D(APP_NAME, "Checking version");
-            if(!flipper_format_read_header(file, string_value, &value)) {
-                FURI_LOG_E(APP_NAME, "Config file mismatch");
-            } else {
-                FURI_LOG_D(APP_NAME, "Loading %s", CONF_ANIMATION_DURATION);
-                if(flipper_format_read_uint32(file, CONF_ANIMATION_DURATION, &value, 1)) {
-                    settings.animation_duration = value;
-                    FURI_LOG_D(APP_NAME, "Loaded %s: %ld", CONF_ANIMATION_DURATION, value);
-                }
-                FURI_LOG_D(APP_NAME, "Loading %s", CONF_MESSAGE_DURATION);
-                if(flipper_format_read_uint32(file, CONF_MESSAGE_DURATION, &value, 1)) {
-                    settings.message_duration = value;
-                    FURI_LOG_D(APP_NAME, "Loaded %s: %ld", CONF_MESSAGE_DURATION, value);
-                }
-                FURI_LOG_D(APP_NAME, "Loading %s", CONF_STARTING_MONEY);
-                if(flipper_format_read_uint32(file, CONF_STARTING_MONEY, &value, 1)) {
-                    settings.starting_money = value;
-                    FURI_LOG_D(APP_NAME, "Loaded %s: %ld", CONF_STARTING_MONEY, value);
-                }
-                FURI_LOG_D(APP_NAME, "Loading %s", CONF_ROUND_PRICE);
-                if(flipper_format_read_uint32(file, CONF_ROUND_PRICE, &value, 1)) {
-                    settings.round_price = value;
-                    FURI_LOG_D(APP_NAME, "Loaded %s: %ld", CONF_ROUND_PRICE, value);
-                }
-                FURI_LOG_D(APP_NAME, "Loading %s", CONF_SOUND_EFFECTS);
-                if(flipper_format_read_bool(file, CONF_SOUND_EFFECTS, &valueBool, 1)) {
-                    settings.sound_effects = valueBool;
-                    FURI_LOG_D(APP_NAME, "Loaded %s: %i", CONF_ROUND_PRICE, valueBool ? 1 : 0);
-                }
-            }
-            flipper_format_file_close(file);
-        }
-    }
-
-    furi_string_free(string_value);
-    //        flipper_format_file_close(file);
-    flipper_format_free(file);
-    furi_record_close(RECORD_STORAGE);
-    return settings;
-}

+ 0 - 7
non_catalog_apps/blackjack/util.h

@@ -1,7 +0,0 @@
-#pragma once
-#include "defines.h"
-#define CONFIG_FILE_HEADER "Blackjack config file"
-#define CONFIG_FILE_VERSION 1
-
-void save_settings(Settings settings);
-Settings load_settings();

+ 0 - 7
non_catalog_apps/esp8266_deauth/FlipperZeroWiFiDeauthModuleDefines.h

@@ -1,7 +0,0 @@
-#define WIFI_MODULE_INIT_VERSION "WFDM_0.1"
-
-#define MODULE_CONTEXT_INITIALIZATION WIFI_MODULE_INIT_VERSION
-
-#define FLIPPERZERO_SERIAL_BAUD 230400
-
-#define NA 0

+ 0 - 14
non_catalog_apps/esp8266_deauth/application.fam

@@ -1,14 +0,0 @@
-App(
-    appid="esp8266_deauther",
-    name="[ESP8266] Deauther",
-    apptype=FlipperAppType.EXTERNAL,
-    entry_point="esp8266_deauth_app",
-    requires=["gui"],
-    stack_size=2 * 1024,
-    order=100,
-    fap_icon="wifi_10px.png",
-    fap_category="GPIO",
-    fap_author="@SequoiaSan & @xMasterX",
-    fap_version="1.0",
-    fap_description="DSTIKE Deauther module interface, based on ESP8266",
-)

+ 0 - 543
non_catalog_apps/esp8266_deauth/esp8266_deauth.c

@@ -1,543 +0,0 @@
-#include <furi.h>
-#include <furi_hal_console.h>
-#include <furi_hal_gpio.h>
-#include <furi_hal_power.h>
-#include <furi_hal_uart.h>
-#include <gui/canvas_i.h>
-#include <gui/gui.h>
-#include <input/input.h>
-//#include <math.h>
-//#include <notification/notification.h>
-//#include <notification/notification_messages.h>
-//#include <stdlib.h>
-
-#include "FlipperZeroWiFiDeauthModuleDefines.h"
-
-#define DEAUTH_APP_DEBUG 0
-
-#if DEAUTH_APP_DEBUG
-#define APP_NAME_TAG "WiFi_Deauther"
-#define DEAUTH_APP_LOG_I(format, ...) FURI_LOG_I(APP_NAME_TAG, format, ##__VA_ARGS__)
-#define DEAUTH_APP_LOG_D(format, ...) FURI_LOG_D(APP_NAME_TAG, format, ##__VA_ARGS__)
-#define DEAUTH_APP_LOG_E(format, ...) FURI_LOG_E(APP_NAME_TAG, format, ##__VA_ARGS__)
-#else
-#define DEAUTH_APP_LOG_I(format, ...)
-#define DEAUTH_APP_LOG_D(format, ...)
-#define DEAUTH_APP_LOG_E(format, ...)
-#endif // WIFI_APP_DEBUG
-
-#define DISABLE_CONSOLE !DEAUTH_APP_DEBUG
-#define ENABLE_MODULE_POWER 1
-#define ENABLE_MODULE_DETECTION 1
-
-typedef enum EEventType // app internally defined event types
-{ EventTypeKey // flipper input.h type
-} EEventType;
-
-typedef struct SPluginEvent {
-    EEventType m_type;
-    InputEvent m_input;
-} SPluginEvent;
-
-typedef enum EAppContext {
-    Undefined,
-    WaitingForModule,
-    Initializing,
-    ModuleActive,
-} EAppContext;
-
-typedef enum EWorkerEventFlags {
-    WorkerEventReserved = (1 << 0), // Reserved for StreamBuffer internal event
-    WorkerEventStop = (1 << 1),
-    WorkerEventRx = (1 << 2),
-} EWorkerEventFlags;
-
-typedef struct SGpioButtons {
-    GpioPin const* pinButtonUp;
-    GpioPin const* pinButtonDown;
-    GpioPin const* pinButtonOK;
-    GpioPin const* pinButtonBack;
-} SGpioButtons;
-
-typedef struct SWiFiDeauthApp {
-    FuriMutex* mutex;
-    Gui* m_gui;
-    FuriThread* m_worker_thread;
-    //NotificationApp* m_notification;
-    FuriStreamBuffer* m_rx_stream;
-    SGpioButtons m_GpioButtons;
-
-    bool m_wifiDeauthModuleInitialized;
-    bool m_wifiDeauthModuleAttached;
-
-    EAppContext m_context;
-
-    uint8_t m_backBuffer[128 * 8 * 8];
-    //uint8_t m_renderBuffer[128 * 8 * 8];
-
-    uint8_t* m_backBufferPtr;
-    //uint8_t* m_m_renderBufferPtr;
-
-    //uint8_t* m_originalBuffer;
-    //uint8_t** m_originalBufferLocation;
-    size_t m_canvasSize;
-
-    bool m_needUpdateGUI;
-} SWiFiDeauthApp;
-
-/////// INIT STATE ///////
-static void esp8266_deauth_app_init(SWiFiDeauthApp* const app) {
-    app->m_context = Undefined;
-
-    app->m_canvasSize = 128 * 8 * 8;
-    memset(app->m_backBuffer, DEAUTH_APP_DEBUG ? 0xFF : 0x00, app->m_canvasSize);
-    //memset(app->m_renderBuffer, DEAUTH_APP_DEBUG ? 0xFF : 0x00, app->m_canvasSize);
-
-    //app->m_originalBuffer = NULL;
-    //app->m_originalBufferLocation = NULL;
-
-    //app->m_m_renderBufferPtr = app->m_renderBuffer;
-    app->m_backBufferPtr = app->m_backBuffer;
-
-    app->m_GpioButtons.pinButtonUp = &gpio_ext_pc3;
-    app->m_GpioButtons.pinButtonDown = &gpio_ext_pb2;
-    app->m_GpioButtons.pinButtonOK = &gpio_ext_pb3;
-    app->m_GpioButtons.pinButtonBack = &gpio_ext_pa4;
-
-    app->m_needUpdateGUI = false;
-
-#if ENABLE_MODULE_POWER
-    app->m_wifiDeauthModuleInitialized = false;
-#else
-    app->m_wifiDeauthModuleInitialized = true;
-#endif // ENABLE_MODULE_POWER
-
-#if ENABLE_MODULE_DETECTION
-    app->m_wifiDeauthModuleAttached = false;
-#else
-    app->m_wifiDeauthModuleAttached = true;
-#endif
-}
-
-static void esp8266_deauth_module_render_callback(Canvas* const canvas, void* ctx) {
-    furi_assert(ctx);
-    SWiFiDeauthApp* app = ctx;
-    furi_mutex_acquire(app->mutex, FuriWaitForever);
-
-    //if(app->m_needUpdateGUI)
-    //{
-    //    app->m_needUpdateGUI = false;
-
-    //    //app->m_canvasSize = canvas_get_buffer_size(canvas);
-    //    //app->m_originalBuffer = canvas_get_buffer(canvas);
-    //    //app->m_originalBufferLocation = &u8g2_GetBufferPtr(&canvas->fb);
-    //    //u8g2_GetBufferPtr(&canvas->fb) = app->m_m_renderBufferPtr;
-    //}
-
-    //uint8_t* exchangeBuffers = app->m_m_renderBufferPtr;
-    //app->m_m_renderBufferPtr = app->m_backBufferPtr;
-    //app->m_backBufferPtr = exchangeBuffers;
-
-    //if(app->m_needUpdateGUI)
-    //{
-    //    //memcpy(app->m_renderBuffer, app->m_backBuffer, app->m_canvasSize);
-    //    app->m_needUpdateGUI = false;
-    //}
-
-    switch(app->m_context) {
-    case Undefined: {
-        canvas_clear(canvas);
-        canvas_set_font(canvas, FontPrimary);
-
-        const char* strInitializing = "Something wrong";
-        canvas_draw_str(
-            canvas,
-            (128 / 2) - (canvas_string_width(canvas, strInitializing) / 2),
-            (64 / 2) /* - (canvas_current_font_height(canvas) / 2)*/,
-            strInitializing);
-    } break;
-    case WaitingForModule:
-#if ENABLE_MODULE_DETECTION
-        furi_assert(!app->m_wifiDeauthModuleAttached);
-        if(!app->m_wifiDeauthModuleAttached) {
-            canvas_clear(canvas);
-            canvas_set_font(canvas, FontSecondary);
-
-            const char* strInitializing = "Attach WiFi Deauther module";
-            canvas_draw_str(
-                canvas,
-                (128 / 2) - (canvas_string_width(canvas, strInitializing) / 2),
-                (64 / 2) /* - (canvas_current_font_height(canvas) / 2)*/,
-                strInitializing);
-        }
-#endif
-        break;
-    case Initializing:
-#if ENABLE_MODULE_POWER
-    {
-        furi_assert(!app->m_wifiDeauthModuleInitialized);
-        if(!app->m_wifiDeauthModuleInitialized) {
-            canvas_set_font(canvas, FontPrimary);
-
-            const char* strInitializing = "Initializing...";
-            canvas_draw_str(
-                canvas,
-                (128 / 2) - (canvas_string_width(canvas, strInitializing) / 2),
-                (64 / 2) - (canvas_current_font_height(canvas) / 2),
-                strInitializing);
-        }
-    }
-#endif // ENABLE_MODULE_POWER
-    break;
-    case ModuleActive: {
-        uint8_t* buffer = canvas->fb.tile_buf_ptr;
-        app->m_canvasSize = gui_get_framebuffer_size(app->m_gui);
-        memcpy(buffer, app->m_backBuffer, app->m_canvasSize);
-    } break;
-    default:
-        break;
-    }
-
-    furi_mutex_release(app->mutex);
-}
-
-static void
-    esp8266_deauth_module_input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) {
-    furi_assert(event_queue);
-
-    SPluginEvent event = {.m_type = EventTypeKey, .m_input = *input_event};
-    furi_message_queue_put(event_queue, &event, FuriWaitForever);
-}
-
-static void uart_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) {
-    furi_assert(context);
-
-    SWiFiDeauthApp* app = context;
-
-    DEAUTH_APP_LOG_I("uart_echo_on_irq_cb");
-
-    if(ev == UartIrqEventRXNE) {
-        DEAUTH_APP_LOG_I("ev == UartIrqEventRXNE");
-        furi_stream_buffer_send(app->m_rx_stream, &data, 1, 0);
-        furi_thread_flags_set(furi_thread_get_id(app->m_worker_thread), WorkerEventRx);
-    }
-}
-
-static int32_t uart_worker(void* context) {
-    furi_assert(context);
-    DEAUTH_APP_LOG_I("[UART] Worker thread init");
-
-    SWiFiDeauthApp* app = context;
-    furi_mutex_acquire(app->mutex, FuriWaitForever);
-    if(app == NULL) {
-        return 1;
-    }
-
-    FuriStreamBuffer* rx_stream = app->m_rx_stream;
-
-    furi_mutex_release(app->mutex);
-
-#if ENABLE_MODULE_POWER
-    bool initialized = false;
-
-    FuriString* receivedString;
-    receivedString = furi_string_alloc();
-#endif // ENABLE_MODULE_POWER
-
-    while(true) {
-        uint32_t events = furi_thread_flags_wait(
-            WorkerEventStop | WorkerEventRx, FuriFlagWaitAny, FuriWaitForever);
-        furi_check((events & FuriFlagError) == 0);
-
-        if(events & WorkerEventStop) break;
-        if(events & WorkerEventRx) {
-            DEAUTH_APP_LOG_I("[UART] Received data");
-            SWiFiDeauthApp* app = context;
-            furi_mutex_acquire(app->mutex, FuriWaitForever);
-            if(app == NULL) {
-                return 1;
-            }
-
-            size_t dataReceivedLength = 0;
-            int index = 0;
-            do {
-                const uint8_t dataBufferSize = 64;
-                uint8_t dataBuffer[dataBufferSize];
-                dataReceivedLength =
-                    furi_stream_buffer_receive(rx_stream, dataBuffer, dataBufferSize, 25);
-                if(dataReceivedLength > 0) {
-#if ENABLE_MODULE_POWER
-                    if(!initialized) {
-                        if(!(dataReceivedLength > strlen(MODULE_CONTEXT_INITIALIZATION))) {
-                            DEAUTH_APP_LOG_I("[UART] Found possible init candidate");
-                            for(uint16_t i = 0; i < dataReceivedLength; i++) {
-                                furi_string_push_back(receivedString, dataBuffer[i]);
-                            }
-                        }
-                    } else
-#endif // ENABLE_MODULE_POWER
-                    {
-                        DEAUTH_APP_LOG_I("[UART] Data copied to backbuffer");
-                        memcpy(app->m_backBuffer + index, dataBuffer, dataReceivedLength);
-                        index += dataReceivedLength;
-                        app->m_needUpdateGUI = true;
-                    }
-                }
-
-            } while(dataReceivedLength > 0);
-
-#if ENABLE_MODULE_POWER
-            if(!app->m_wifiDeauthModuleInitialized) {
-                if(furi_string_cmp_str(receivedString, MODULE_CONTEXT_INITIALIZATION) == 0) {
-                    DEAUTH_APP_LOG_I("[UART] Initialized");
-                    initialized = true;
-                    app->m_wifiDeauthModuleInitialized = true;
-                    app->m_context = ModuleActive;
-                    furi_string_free(receivedString);
-                } else {
-                    DEAUTH_APP_LOG_I("[UART] Not an initialization command");
-                    furi_string_reset(receivedString);
-                }
-            }
-#endif // ENABLE_MODULE_POWER
-
-            furi_mutex_release(app->mutex);
-        }
-    }
-
-    return 0;
-}
-
-int32_t esp8266_deauth_app(void* p) {
-    UNUSED(p);
-
-    DEAUTH_APP_LOG_I("Init");
-
-    // FuriTimer* timer = furi_timer_alloc(blink_test_update, FuriTimerTypePeriodic, event_queue);
-    // furi_timer_start(timer, furi_kernel_get_tick_frequency());
-
-    FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(SPluginEvent));
-
-    SWiFiDeauthApp* app = malloc(sizeof(SWiFiDeauthApp));
-
-    esp8266_deauth_app_init(app);
-
-    furi_hal_gpio_init_simple(app->m_GpioButtons.pinButtonUp, GpioModeOutputPushPull);
-    furi_hal_gpio_init_simple(app->m_GpioButtons.pinButtonDown, GpioModeOutputPushPull);
-    furi_hal_gpio_init_simple(app->m_GpioButtons.pinButtonOK, GpioModeOutputPushPull);
-    furi_hal_gpio_init_simple(app->m_GpioButtons.pinButtonBack, GpioModeOutputPushPull);
-
-    furi_hal_gpio_write(app->m_GpioButtons.pinButtonUp, true);
-    furi_hal_gpio_write(app->m_GpioButtons.pinButtonDown, true);
-    furi_hal_gpio_write(app->m_GpioButtons.pinButtonOK, true);
-    furi_hal_gpio_write(
-        app->m_GpioButtons.pinButtonBack, false); // GPIO15 - Boot fails if pulled HIGH
-
-#if ENABLE_MODULE_DETECTION
-    furi_hal_gpio_init(
-        &gpio_ext_pc0,
-        GpioModeInput,
-        GpioPullUp,
-        GpioSpeedLow); // Connect to the Flipper's ground just to be sure
-    //furi_hal_gpio_add_int_callback(pinD0, input_isr_d0, this);
-    app->m_context = WaitingForModule;
-#else
-#if ENABLE_MODULE_POWER
-    app->m_context = Initializing;
-    uint8_t attempts = 0;
-    while(!furi_hal_power_is_otg_enabled() && attempts++ < 5) {
-        furi_hal_power_enable_otg();
-        furi_delay_ms(10);
-    }
-    furi_delay_ms(200);
-#else
-    app->m_context = ModuleActive;
-#endif
-#endif // ENABLE_MODULE_DETECTION
-
-    app->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
-    if(!app->mutex) {
-        DEAUTH_APP_LOG_E("cannot create mutex\r\n");
-        free(app);
-        return 255;
-    }
-
-    DEAUTH_APP_LOG_I("Mutex created");
-
-    //app->m_notification = furi_record_open(RECORD_NOTIFICATION);
-
-    ViewPort* view_port = view_port_alloc();
-    view_port_draw_callback_set(view_port, esp8266_deauth_module_render_callback, app);
-    view_port_input_callback_set(view_port, esp8266_deauth_module_input_callback, event_queue);
-
-    // Open GUI and register view_port
-    app->m_gui = furi_record_open(RECORD_GUI);
-    gui_add_view_port(app->m_gui, view_port, GuiLayerFullscreen);
-
-    //notification_message(app->notification, &sequence_set_only_blue_255);
-
-    app->m_rx_stream = furi_stream_buffer_alloc(1 * 1024, 1);
-
-    app->m_worker_thread = furi_thread_alloc();
-    furi_thread_set_name(app->m_worker_thread, "WiFiDeauthModuleUARTWorker");
-    furi_thread_set_stack_size(app->m_worker_thread, 1 * 1024);
-    furi_thread_set_context(app->m_worker_thread, app);
-    furi_thread_set_callback(app->m_worker_thread, uart_worker);
-    furi_thread_start(app->m_worker_thread);
-    DEAUTH_APP_LOG_I("UART thread allocated");
-
-    // Enable uart listener
-#if DISABLE_CONSOLE
-    furi_hal_console_disable();
-#endif
-    furi_hal_uart_set_br(FuriHalUartIdUSART1, FLIPPERZERO_SERIAL_BAUD);
-    furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, uart_on_irq_cb, app);
-    DEAUTH_APP_LOG_I("UART Listener created");
-
-    SPluginEvent event;
-    for(bool processing = true; processing;) {
-        FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);
-        furi_mutex_acquire(app->mutex, FuriWaitForever);
-
-#if ENABLE_MODULE_DETECTION
-        if(!app->m_wifiDeauthModuleAttached) {
-            if(furi_hal_gpio_read(&gpio_ext_pc0) == false) {
-                DEAUTH_APP_LOG_I("Module Attached");
-                app->m_wifiDeauthModuleAttached = true;
-#if ENABLE_MODULE_POWER
-                app->m_context = Initializing;
-                uint8_t attempts2 = 0;
-                while(!furi_hal_power_is_otg_enabled() && attempts2++ < 3) {
-                    furi_hal_power_enable_otg();
-                    furi_delay_ms(10);
-                }
-#else
-                app->m_context = ModuleActive;
-#endif
-            }
-        }
-#endif // ENABLE_MODULE_DETECTION
-
-        if(event_status == FuriStatusOk) {
-            if(event.m_type == EventTypeKey) {
-                if(app->m_wifiDeauthModuleInitialized) {
-                    if(app->m_context == ModuleActive) {
-                        switch(event.m_input.key) {
-                        case InputKeyUp:
-                            if(event.m_input.type == InputTypePress) {
-                                DEAUTH_APP_LOG_I("Up Press");
-                                furi_hal_gpio_write(app->m_GpioButtons.pinButtonUp, false);
-                            } else if(event.m_input.type == InputTypeRelease) {
-                                DEAUTH_APP_LOG_I("Up Release");
-                                furi_hal_gpio_write(app->m_GpioButtons.pinButtonUp, true);
-                            }
-                            break;
-                        case InputKeyDown:
-                            if(event.m_input.type == InputTypePress) {
-                                DEAUTH_APP_LOG_I("Down Press");
-                                furi_hal_gpio_write(app->m_GpioButtons.pinButtonDown, false);
-                            } else if(event.m_input.type == InputTypeRelease) {
-                                DEAUTH_APP_LOG_I("Down Release");
-                                furi_hal_gpio_write(app->m_GpioButtons.pinButtonDown, true);
-                            }
-                            break;
-                        case InputKeyOk:
-                            if(event.m_input.type == InputTypePress) {
-                                DEAUTH_APP_LOG_I("OK Press");
-                                furi_hal_gpio_write(app->m_GpioButtons.pinButtonOK, false);
-                            } else if(event.m_input.type == InputTypeRelease) {
-                                DEAUTH_APP_LOG_I("OK Release");
-                                furi_hal_gpio_write(app->m_GpioButtons.pinButtonOK, true);
-                            }
-                            break;
-                        case InputKeyBack:
-                            if(event.m_input.type == InputTypePress) {
-                                DEAUTH_APP_LOG_I("Back Press");
-                                furi_hal_gpio_write(app->m_GpioButtons.pinButtonBack, false);
-                            } else if(event.m_input.type == InputTypeRelease) {
-                                DEAUTH_APP_LOG_I("Back Release");
-                                furi_hal_gpio_write(app->m_GpioButtons.pinButtonBack, true);
-                            } else if(event.m_input.type == InputTypeLong) {
-                                DEAUTH_APP_LOG_I("Back Long");
-                                processing = false;
-                            }
-                            break;
-                        default:
-                            break;
-                        }
-                    }
-                } else {
-                    if(event.m_input.key == InputKeyBack) {
-                        if(event.m_input.type == InputTypeShort ||
-                           event.m_input.type == InputTypeLong) {
-                            processing = false;
-                        }
-                    }
-                }
-            }
-        }
-
-#if ENABLE_MODULE_DETECTION
-        if(app->m_wifiDeauthModuleAttached && furi_hal_gpio_read(&gpio_ext_pc0) == true) {
-            DEAUTH_APP_LOG_D("Module Disconnected - Exit");
-            processing = false;
-            app->m_wifiDeauthModuleAttached = false;
-            app->m_wifiDeauthModuleInitialized = false;
-        }
-#endif
-
-        view_port_update(view_port);
-        furi_mutex_release(app->mutex);
-    }
-
-    DEAUTH_APP_LOG_I("Start exit app");
-
-    furi_thread_flags_set(furi_thread_get_id(app->m_worker_thread), WorkerEventStop);
-    furi_thread_join(app->m_worker_thread);
-    furi_thread_free(app->m_worker_thread);
-
-    DEAUTH_APP_LOG_I("Thread Deleted");
-
-    // Reset GPIO pins to default state
-    furi_hal_gpio_init(&gpio_ext_pc0, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
-    furi_hal_gpio_init(&gpio_ext_pc3, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
-    furi_hal_gpio_init(&gpio_ext_pb2, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
-    furi_hal_gpio_init(&gpio_ext_pb3, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
-    furi_hal_gpio_init(&gpio_ext_pa4, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
-
-#if DISABLE_CONSOLE
-    furi_hal_console_enable();
-#endif
-
-    //*app->m_originalBufferLocation = app->m_originalBuffer;
-
-    view_port_enabled_set(view_port, false);
-
-    gui_remove_view_port(app->m_gui, view_port);
-
-    // Close gui record
-    furi_record_close(RECORD_GUI);
-    //furi_record_close(RECORD_NOTIFICATION);
-    app->m_gui = NULL;
-
-    view_port_free(view_port);
-
-    furi_message_queue_free(event_queue);
-
-    furi_stream_buffer_free(app->m_rx_stream);
-
-    furi_mutex_free(app->mutex);
-
-    // Free rest
-    free(app);
-
-    DEAUTH_APP_LOG_I("App freed");
-
-#if ENABLE_MODULE_POWER
-    if(furi_hal_power_is_otg_enabled()) {
-        furi_hal_power_disable_otg();
-    }
-#endif
-
-    return 0;
-}

BIN
non_catalog_apps/esp8266_deauth/wifi_10px.png


+ 0 - 674
non_catalog_apps/gps_nmea_uart/LICENSE

@@ -1,674 +0,0 @@
-                    GNU GENERAL PUBLIC LICENSE
-                       Version 3, 29 June 2007
-
- Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-                            Preamble
-
-  The GNU General Public License is a free, copyleft license for
-software and other kinds of works.
-
-  The licenses for most software and other practical works are designed
-to take away your freedom to share and change the works.  By contrast,
-the GNU General Public License is intended to guarantee your freedom to
-share and change all versions of a program--to make sure it remains free
-software for all its users.  We, the Free Software Foundation, use the
-GNU General Public License for most of our software; it applies also to
-any other work released this way by its authors.  You can apply it to
-your programs, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-them if you wish), that you receive source code or can get it if you
-want it, that you can change the software or use pieces of it in new
-free programs, and that you know you can do these things.
-
-  To protect your rights, we need to prevent others from denying you
-these rights or asking you to surrender the rights.  Therefore, you have
-certain responsibilities if you distribute copies of the software, or if
-you modify it: responsibilities to respect the freedom of others.
-
-  For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must pass on to the recipients the same
-freedoms that you received.  You must make sure that they, too, receive
-or can get the source code.  And you must show them these terms so they
-know their rights.
-
-  Developers that use the GNU GPL protect your rights with two steps:
-(1) assert copyright on the software, and (2) offer you this License
-giving you legal permission to copy, distribute and/or modify it.
-
-  For the developers' and authors' protection, the GPL clearly explains
-that there is no warranty for this free software.  For both users' and
-authors' sake, the GPL requires that modified versions be marked as
-changed, so that their problems will not be attributed erroneously to
-authors of previous versions.
-
-  Some devices are designed to deny users access to install or run
-modified versions of the software inside them, although the manufacturer
-can do so.  This is fundamentally incompatible with the aim of
-protecting users' freedom to change the software.  The systematic
-pattern of such abuse occurs in the area of products for individuals to
-use, which is precisely where it is most unacceptable.  Therefore, we
-have designed this version of the GPL to prohibit the practice for those
-products.  If such problems arise substantially in other domains, we
-stand ready to extend this provision to those domains in future versions
-of the GPL, as needed to protect the freedom of users.
-
-  Finally, every program is threatened constantly by software patents.
-States should not allow patents to restrict development and use of
-software on general-purpose computers, but in those that do, we wish to
-avoid the special danger that patents applied to a free program could
-make it effectively proprietary.  To prevent this, the GPL assures that
-patents cannot be used to render the program non-free.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.
-
-                       TERMS AND CONDITIONS
-
-  0. Definitions.
-
-  "This License" refers to version 3 of the GNU General Public License.
-
-  "Copyright" also means copyright-like laws that apply to other kinds of
-works, such as semiconductor masks.
-
-  "The Program" refers to any copyrightable work licensed under this
-License.  Each licensee is addressed as "you".  "Licensees" and
-"recipients" may be individuals or organizations.
-
-  To "modify" a work means to copy from or adapt all or part of the work
-in a fashion requiring copyright permission, other than the making of an
-exact copy.  The resulting work is called a "modified version" of the
-earlier work or a work "based on" the earlier work.
-
-  A "covered work" means either the unmodified Program or a work based
-on the Program.
-
-  To "propagate" a work means to do anything with it that, without
-permission, would make you directly or secondarily liable for
-infringement under applicable copyright law, except executing it on a
-computer or modifying a private copy.  Propagation includes copying,
-distribution (with or without modification), making available to the
-public, and in some countries other activities as well.
-
-  To "convey" a work means any kind of propagation that enables other
-parties to make or receive copies.  Mere interaction with a user through
-a computer network, with no transfer of a copy, is not conveying.
-
-  An interactive user interface displays "Appropriate Legal Notices"
-to the extent that it includes a convenient and prominently visible
-feature that (1) displays an appropriate copyright notice, and (2)
-tells the user that there is no warranty for the work (except to the
-extent that warranties are provided), that licensees may convey the
-work under this License, and how to view a copy of this License.  If
-the interface presents a list of user commands or options, such as a
-menu, a prominent item in the list meets this criterion.
-
-  1. Source Code.
-
-  The "source code" for a work means the preferred form of the work
-for making modifications to it.  "Object code" means any non-source
-form of a work.
-
-  A "Standard Interface" means an interface that either is an official
-standard defined by a recognized standards body, or, in the case of
-interfaces specified for a particular programming language, one that
-is widely used among developers working in that language.
-
-  The "System Libraries" of an executable work include anything, other
-than the work as a whole, that (a) is included in the normal form of
-packaging a Major Component, but which is not part of that Major
-Component, and (b) serves only to enable use of the work with that
-Major Component, or to implement a Standard Interface for which an
-implementation is available to the public in source code form.  A
-"Major Component", in this context, means a major essential component
-(kernel, window system, and so on) of the specific operating system
-(if any) on which the executable work runs, or a compiler used to
-produce the work, or an object code interpreter used to run it.
-
-  The "Corresponding Source" for a work in object code form means all
-the source code needed to generate, install, and (for an executable
-work) run the object code and to modify the work, including scripts to
-control those activities.  However, it does not include the work's
-System Libraries, or general-purpose tools or generally available free
-programs which are used unmodified in performing those activities but
-which are not part of the work.  For example, Corresponding Source
-includes interface definition files associated with source files for
-the work, and the source code for shared libraries and dynamically
-linked subprograms that the work is specifically designed to require,
-such as by intimate data communication or control flow between those
-subprograms and other parts of the work.
-
-  The Corresponding Source need not include anything that users
-can regenerate automatically from other parts of the Corresponding
-Source.
-
-  The Corresponding Source for a work in source code form is that
-same work.
-
-  2. Basic Permissions.
-
-  All rights granted under this License are granted for the term of
-copyright on the Program, and are irrevocable provided the stated
-conditions are met.  This License explicitly affirms your unlimited
-permission to run the unmodified Program.  The output from running a
-covered work is covered by this License only if the output, given its
-content, constitutes a covered work.  This License acknowledges your
-rights of fair use or other equivalent, as provided by copyright law.
-
-  You may make, run and propagate covered works that you do not
-convey, without conditions so long as your license otherwise remains
-in force.  You may convey covered works to others for the sole purpose
-of having them make modifications exclusively for you, or provide you
-with facilities for running those works, provided that you comply with
-the terms of this License in conveying all material for which you do
-not control copyright.  Those thus making or running the covered works
-for you must do so exclusively on your behalf, under your direction
-and control, on terms that prohibit them from making any copies of
-your copyrighted material outside their relationship with you.
-
-  Conveying under any other circumstances is permitted solely under
-the conditions stated below.  Sublicensing is not allowed; section 10
-makes it unnecessary.
-
-  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
-
-  No covered work shall be deemed part of an effective technological
-measure under any applicable law fulfilling obligations under article
-11 of the WIPO copyright treaty adopted on 20 December 1996, or
-similar laws prohibiting or restricting circumvention of such
-measures.
-
-  When you convey a covered work, you waive any legal power to forbid
-circumvention of technological measures to the extent such circumvention
-is effected by exercising rights under this License with respect to
-the covered work, and you disclaim any intention to limit operation or
-modification of the work as a means of enforcing, against the work's
-users, your or third parties' legal rights to forbid circumvention of
-technological measures.
-
-  4. Conveying Verbatim Copies.
-
-  You may convey verbatim copies of the Program's source code as you
-receive it, in any medium, provided that you conspicuously and
-appropriately publish on each copy an appropriate copyright notice;
-keep intact all notices stating that this License and any
-non-permissive terms added in accord with section 7 apply to the code;
-keep intact all notices of the absence of any warranty; and give all
-recipients a copy of this License along with the Program.
-
-  You may charge any price or no price for each copy that you convey,
-and you may offer support or warranty protection for a fee.
-
-  5. Conveying Modified Source Versions.
-
-  You may convey a work based on the Program, or the modifications to
-produce it from the Program, in the form of source code under the
-terms of section 4, provided that you also meet all of these conditions:
-
-    a) The work must carry prominent notices stating that you modified
-    it, and giving a relevant date.
-
-    b) The work must carry prominent notices stating that it is
-    released under this License and any conditions added under section
-    7.  This requirement modifies the requirement in section 4 to
-    "keep intact all notices".
-
-    c) You must license the entire work, as a whole, under this
-    License to anyone who comes into possession of a copy.  This
-    License will therefore apply, along with any applicable section 7
-    additional terms, to the whole of the work, and all its parts,
-    regardless of how they are packaged.  This License gives no
-    permission to license the work in any other way, but it does not
-    invalidate such permission if you have separately received it.
-
-    d) If the work has interactive user interfaces, each must display
-    Appropriate Legal Notices; however, if the Program has interactive
-    interfaces that do not display Appropriate Legal Notices, your
-    work need not make them do so.
-
-  A compilation of a covered work with other separate and independent
-works, which are not by their nature extensions of the covered work,
-and which are not combined with it such as to form a larger program,
-in or on a volume of a storage or distribution medium, is called an
-"aggregate" if the compilation and its resulting copyright are not
-used to limit the access or legal rights of the compilation's users
-beyond what the individual works permit.  Inclusion of a covered work
-in an aggregate does not cause this License to apply to the other
-parts of the aggregate.
-
-  6. Conveying Non-Source Forms.
-
-  You may convey a covered work in object code form under the terms
-of sections 4 and 5, provided that you also convey the
-machine-readable Corresponding Source under the terms of this License,
-in one of these ways:
-
-    a) Convey the object code in, or embodied in, a physical product
-    (including a physical distribution medium), accompanied by the
-    Corresponding Source fixed on a durable physical medium
-    customarily used for software interchange.
-
-    b) Convey the object code in, or embodied in, a physical product
-    (including a physical distribution medium), accompanied by a
-    written offer, valid for at least three years and valid for as
-    long as you offer spare parts or customer support for that product
-    model, to give anyone who possesses the object code either (1) a
-    copy of the Corresponding Source for all the software in the
-    product that is covered by this License, on a durable physical
-    medium customarily used for software interchange, for a price no
-    more than your reasonable cost of physically performing this
-    conveying of source, or (2) access to copy the
-    Corresponding Source from a network server at no charge.
-
-    c) Convey individual copies of the object code with a copy of the
-    written offer to provide the Corresponding Source.  This
-    alternative is allowed only occasionally and noncommercially, and
-    only if you received the object code with such an offer, in accord
-    with subsection 6b.
-
-    d) Convey the object code by offering access from a designated
-    place (gratis or for a charge), and offer equivalent access to the
-    Corresponding Source in the same way through the same place at no
-    further charge.  You need not require recipients to copy the
-    Corresponding Source along with the object code.  If the place to
-    copy the object code is a network server, the Corresponding Source
-    may be on a different server (operated by you or a third party)
-    that supports equivalent copying facilities, provided you maintain
-    clear directions next to the object code saying where to find the
-    Corresponding Source.  Regardless of what server hosts the
-    Corresponding Source, you remain obligated to ensure that it is
-    available for as long as needed to satisfy these requirements.
-
-    e) Convey the object code using peer-to-peer transmission, provided
-    you inform other peers where the object code and Corresponding
-    Source of the work are being offered to the general public at no
-    charge under subsection 6d.
-
-  A separable portion of the object code, whose source code is excluded
-from the Corresponding Source as a System Library, need not be
-included in conveying the object code work.
-
-  A "User Product" is either (1) a "consumer product", which means any
-tangible personal property which is normally used for personal, family,
-or household purposes, or (2) anything designed or sold for incorporation
-into a dwelling.  In determining whether a product is a consumer product,
-doubtful cases shall be resolved in favor of coverage.  For a particular
-product received by a particular user, "normally used" refers to a
-typical or common use of that class of product, regardless of the status
-of the particular user or of the way in which the particular user
-actually uses, or expects or is expected to use, the product.  A product
-is a consumer product regardless of whether the product has substantial
-commercial, industrial or non-consumer uses, unless such uses represent
-the only significant mode of use of the product.
-
-  "Installation Information" for a User Product means any methods,
-procedures, authorization keys, or other information required to install
-and execute modified versions of a covered work in that User Product from
-a modified version of its Corresponding Source.  The information must
-suffice to ensure that the continued functioning of the modified object
-code is in no case prevented or interfered with solely because
-modification has been made.
-
-  If you convey an object code work under this section in, or with, or
-specifically for use in, a User Product, and the conveying occurs as
-part of a transaction in which the right of possession and use of the
-User Product is transferred to the recipient in perpetuity or for a
-fixed term (regardless of how the transaction is characterized), the
-Corresponding Source conveyed under this section must be accompanied
-by the Installation Information.  But this requirement does not apply
-if neither you nor any third party retains the ability to install
-modified object code on the User Product (for example, the work has
-been installed in ROM).
-
-  The requirement to provide Installation Information does not include a
-requirement to continue to provide support service, warranty, or updates
-for a work that has been modified or installed by the recipient, or for
-the User Product in which it has been modified or installed.  Access to a
-network may be denied when the modification itself materially and
-adversely affects the operation of the network or violates the rules and
-protocols for communication across the network.
-
-  Corresponding Source conveyed, and Installation Information provided,
-in accord with this section must be in a format that is publicly
-documented (and with an implementation available to the public in
-source code form), and must require no special password or key for
-unpacking, reading or copying.
-
-  7. Additional Terms.
-
-  "Additional permissions" are terms that supplement the terms of this
-License by making exceptions from one or more of its conditions.
-Additional permissions that are applicable to the entire Program shall
-be treated as though they were included in this License, to the extent
-that they are valid under applicable law.  If additional permissions
-apply only to part of the Program, that part may be used separately
-under those permissions, but the entire Program remains governed by
-this License without regard to the additional permissions.
-
-  When you convey a copy of a covered work, you may at your option
-remove any additional permissions from that copy, or from any part of
-it.  (Additional permissions may be written to require their own
-removal in certain cases when you modify the work.)  You may place
-additional permissions on material, added by you to a covered work,
-for which you have or can give appropriate copyright permission.
-
-  Notwithstanding any other provision of this License, for material you
-add to a covered work, you may (if authorized by the copyright holders of
-that material) supplement the terms of this License with terms:
-
-    a) Disclaiming warranty or limiting liability differently from the
-    terms of sections 15 and 16 of this License; or
-
-    b) Requiring preservation of specified reasonable legal notices or
-    author attributions in that material or in the Appropriate Legal
-    Notices displayed by works containing it; or
-
-    c) Prohibiting misrepresentation of the origin of that material, or
-    requiring that modified versions of such material be marked in
-    reasonable ways as different from the original version; or
-
-    d) Limiting the use for publicity purposes of names of licensors or
-    authors of the material; or
-
-    e) Declining to grant rights under trademark law for use of some
-    trade names, trademarks, or service marks; or
-
-    f) Requiring indemnification of licensors and authors of that
-    material by anyone who conveys the material (or modified versions of
-    it) with contractual assumptions of liability to the recipient, for
-    any liability that these contractual assumptions directly impose on
-    those licensors and authors.
-
-  All other non-permissive additional terms are considered "further
-restrictions" within the meaning of section 10.  If the Program as you
-received it, or any part of it, contains a notice stating that it is
-governed by this License along with a term that is a further
-restriction, you may remove that term.  If a license document contains
-a further restriction but permits relicensing or conveying under this
-License, you may add to a covered work material governed by the terms
-of that license document, provided that the further restriction does
-not survive such relicensing or conveying.
-
-  If you add terms to a covered work in accord with this section, you
-must place, in the relevant source files, a statement of the
-additional terms that apply to those files, or a notice indicating
-where to find the applicable terms.
-
-  Additional terms, permissive or non-permissive, may be stated in the
-form of a separately written license, or stated as exceptions;
-the above requirements apply either way.
-
-  8. Termination.
-
-  You may not propagate or modify a covered work except as expressly
-provided under this License.  Any attempt otherwise to propagate or
-modify it is void, and will automatically terminate your rights under
-this License (including any patent licenses granted under the third
-paragraph of section 11).
-
-  However, if you cease all violation of this License, then your
-license from a particular copyright holder is reinstated (a)
-provisionally, unless and until the copyright holder explicitly and
-finally terminates your license, and (b) permanently, if the copyright
-holder fails to notify you of the violation by some reasonable means
-prior to 60 days after the cessation.
-
-  Moreover, your license from a particular copyright holder is
-reinstated permanently if the copyright holder notifies you of the
-violation by some reasonable means, this is the first time you have
-received notice of violation of this License (for any work) from that
-copyright holder, and you cure the violation prior to 30 days after
-your receipt of the notice.
-
-  Termination of your rights under this section does not terminate the
-licenses of parties who have received copies or rights from you under
-this License.  If your rights have been terminated and not permanently
-reinstated, you do not qualify to receive new licenses for the same
-material under section 10.
-
-  9. Acceptance Not Required for Having Copies.
-
-  You are not required to accept this License in order to receive or
-run a copy of the Program.  Ancillary propagation of a covered work
-occurring solely as a consequence of using peer-to-peer transmission
-to receive a copy likewise does not require acceptance.  However,
-nothing other than this License grants you permission to propagate or
-modify any covered work.  These actions infringe copyright if you do
-not accept this License.  Therefore, by modifying or propagating a
-covered work, you indicate your acceptance of this License to do so.
-
-  10. Automatic Licensing of Downstream Recipients.
-
-  Each time you convey a covered work, the recipient automatically
-receives a license from the original licensors, to run, modify and
-propagate that work, subject to this License.  You are not responsible
-for enforcing compliance by third parties with this License.
-
-  An "entity transaction" is a transaction transferring control of an
-organization, or substantially all assets of one, or subdividing an
-organization, or merging organizations.  If propagation of a covered
-work results from an entity transaction, each party to that
-transaction who receives a copy of the work also receives whatever
-licenses to the work the party's predecessor in interest had or could
-give under the previous paragraph, plus a right to possession of the
-Corresponding Source of the work from the predecessor in interest, if
-the predecessor has it or can get it with reasonable efforts.
-
-  You may not impose any further restrictions on the exercise of the
-rights granted or affirmed under this License.  For example, you may
-not impose a license fee, royalty, or other charge for exercise of
-rights granted under this License, and you may not initiate litigation
-(including a cross-claim or counterclaim in a lawsuit) alleging that
-any patent claim is infringed by making, using, selling, offering for
-sale, or importing the Program or any portion of it.
-
-  11. Patents.
-
-  A "contributor" is a copyright holder who authorizes use under this
-License of the Program or a work on which the Program is based.  The
-work thus licensed is called the contributor's "contributor version".
-
-  A contributor's "essential patent claims" are all patent claims
-owned or controlled by the contributor, whether already acquired or
-hereafter acquired, that would be infringed by some manner, permitted
-by this License, of making, using, or selling its contributor version,
-but do not include claims that would be infringed only as a
-consequence of further modification of the contributor version.  For
-purposes of this definition, "control" includes the right to grant
-patent sublicenses in a manner consistent with the requirements of
-this License.
-
-  Each contributor grants you a non-exclusive, worldwide, royalty-free
-patent license under the contributor's essential patent claims, to
-make, use, sell, offer for sale, import and otherwise run, modify and
-propagate the contents of its contributor version.
-
-  In the following three paragraphs, a "patent license" is any express
-agreement or commitment, however denominated, not to enforce a patent
-(such as an express permission to practice a patent or covenant not to
-sue for patent infringement).  To "grant" such a patent license to a
-party means to make such an agreement or commitment not to enforce a
-patent against the party.
-
-  If you convey a covered work, knowingly relying on a patent license,
-and the Corresponding Source of the work is not available for anyone
-to copy, free of charge and under the terms of this License, through a
-publicly available network server or other readily accessible means,
-then you must either (1) cause the Corresponding Source to be so
-available, or (2) arrange to deprive yourself of the benefit of the
-patent license for this particular work, or (3) arrange, in a manner
-consistent with the requirements of this License, to extend the patent
-license to downstream recipients.  "Knowingly relying" means you have
-actual knowledge that, but for the patent license, your conveying the
-covered work in a country, or your recipient's use of the covered work
-in a country, would infringe one or more identifiable patents in that
-country that you have reason to believe are valid.
-
-  If, pursuant to or in connection with a single transaction or
-arrangement, you convey, or propagate by procuring conveyance of, a
-covered work, and grant a patent license to some of the parties
-receiving the covered work authorizing them to use, propagate, modify
-or convey a specific copy of the covered work, then the patent license
-you grant is automatically extended to all recipients of the covered
-work and works based on it.
-
-  A patent license is "discriminatory" if it does not include within
-the scope of its coverage, prohibits the exercise of, or is
-conditioned on the non-exercise of one or more of the rights that are
-specifically granted under this License.  You may not convey a covered
-work if you are a party to an arrangement with a third party that is
-in the business of distributing software, under which you make payment
-to the third party based on the extent of your activity of conveying
-the work, and under which the third party grants, to any of the
-parties who would receive the covered work from you, a discriminatory
-patent license (a) in connection with copies of the covered work
-conveyed by you (or copies made from those copies), or (b) primarily
-for and in connection with specific products or compilations that
-contain the covered work, unless you entered into that arrangement,
-or that patent license was granted, prior to 28 March 2007.
-
-  Nothing in this License shall be construed as excluding or limiting
-any implied license or other defenses to infringement that may
-otherwise be available to you under applicable patent law.
-
-  12. No Surrender of Others' Freedom.
-
-  If conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot convey a
-covered work so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you may
-not convey it at all.  For example, if you agree to terms that obligate you
-to collect a royalty for further conveying from those to whom you convey
-the Program, the only way you could satisfy both those terms and this
-License would be to refrain entirely from conveying the Program.
-
-  13. Use with the GNU Affero General Public License.
-
-  Notwithstanding any other provision of this License, you have
-permission to link or combine any covered work with a work licensed
-under version 3 of the GNU Affero General Public License into a single
-combined work, and to convey the resulting work.  The terms of this
-License will continue to apply to the part which is the covered work,
-but the special requirements of the GNU Affero General Public License,
-section 13, concerning interaction through a network will apply to the
-combination as such.
-
-  14. Revised Versions of this License.
-
-  The Free Software Foundation may publish revised and/or new versions of
-the GNU General Public License from time to time.  Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-  Each version is given a distinguishing version number.  If the
-Program specifies that a certain numbered version of the GNU General
-Public License "or any later version" applies to it, you have the
-option of following the terms and conditions either of that numbered
-version or of any later version published by the Free Software
-Foundation.  If the Program does not specify a version number of the
-GNU General Public License, you may choose any version ever published
-by the Free Software Foundation.
-
-  If the Program specifies that a proxy can decide which future
-versions of the GNU General Public License can be used, that proxy's
-public statement of acceptance of a version permanently authorizes you
-to choose that version for the Program.
-
-  Later license versions may give you additional or different
-permissions.  However, no additional obligations are imposed on any
-author or copyright holder as a result of your choosing to follow a
-later version.
-
-  15. Disclaimer of Warranty.
-
-  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
-APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
-HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
-OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
-THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
-IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
-ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
-  16. Limitation of Liability.
-
-  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
-THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
-GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
-USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
-DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
-PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
-EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGES.
-
-  17. Interpretation of Sections 15 and 16.
-
-  If the disclaimer of warranty and limitation of liability provided
-above cannot be given local legal effect according to their terms,
-reviewing courts shall apply local law that most closely approximates
-an absolute waiver of all civil liability in connection with the
-Program, unless a warranty or assumption of liability accompanies a
-copy of the Program in return for a fee.
-
-                     END OF TERMS AND CONDITIONS
-
-            How to Apply These Terms to Your New Programs
-
-  If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
-  To do so, attach the following notices to the program.  It is safest
-to attach them to the start of each source file to most effectively
-state the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    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 <https://www.gnu.org/licenses/>.
-
-Also add information on how to contact you by electronic and paper mail.
-
-  If the program does terminal interaction, make it output a short
-notice like this when it starts in an interactive mode:
-
-    <program>  Copyright (C) <year>  <name of author>
-    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
-    This is free software, and you are welcome to redistribute it
-    under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License.  Of course, your program's commands
-might be different; for a GUI interface, you would use an "about box".
-
-  You should also get your employer (if you work as a programmer) or school,
-if any, to sign a "copyright disclaimer" for the program, if necessary.
-For more information on this, and how to apply and follow the GNU GPL, see
-<https://www.gnu.org/licenses/>.
-
-  The GNU General Public License does not permit incorporating your program
-into proprietary programs.  If your program is a subroutine library, you
-may consider it more useful to permit linking proprietary applications with
-the library.  If this is what you want to do, use the GNU Lesser General
-Public License instead of this License.  But first, please read
-<https://www.gnu.org/licenses/why-not-lgpl.html>.

+ 0 - 40
non_catalog_apps/gps_nmea_uart/README.md

@@ -1,40 +0,0 @@
-# GPS for Flipper Zero
-
-[Original link](https://github.com/ezod/flipperzero-gps)
-
-[Adafruit Ultimate GPS Breakout].
-
-![ui](ui.png)
-
-Heavy lifting (NMEA parsing) provided by [minmea], which is included in this
-repository.
-
-## Modifications made by @xMasterX
-- Ability to change baudrate using Up button, hold button to switch between baudrates (9600, 57600, 115200) (i set 57600 as default)
-- Ok button will set backlight to always on mode, to disable press ok button again (it will restore default settings after app exit too)
-- Long press Right button to change speed from knots to kilometers per hour
-- Exit from app using long press on back button instead of short press, may be useful in case you want to turn backlight on and accidentally click back
-
-## Hardware Setup
-
-Connect the GPS module to power and the USART using GPIO pins 9 (3.3V), 11
-(GND), 13 (TX), and 14 (RX), as appropriate.
-
-![wiring](wiring.png)
-
-
-## Contributing
-
-This project was a learning exercise and is more or less "complete" from my
-perspective, but I will happily accept pull requests that improve and enhance
-the functionality for others.
-
-Currently, the app only parses RMC and GGA sentences, and displays a subset of
-the data that fits on the screen. The UART is also hard-coded to 9600 baud.
-These limitations are largely driven by the GPS module I have to work with. A
-more elaborate UI with scrolling or multiple screens, as well as a configurable
-baud rate, may be useful for other GPS modules.
-
-[Adafruit Ultimate GPS Breakout]: https://www.adafruit.com/product/746
-[minmea]: https://github.com/kosma/minmea
-[flipperzero-firmware]: https://github.com/flipperdevices/flipperzero-firmware

+ 0 - 14
non_catalog_apps/gps_nmea_uart/application.fam

@@ -1,14 +0,0 @@
-App(
-    appid="gps_nmea",
-    name="[NMEA] GPS",
-    apptype=FlipperAppType.EXTERNAL,
-    entry_point="gps_app",
-    requires=["gui"],
-    stack_size=1 * 1024,
-    order=35,
-    fap_icon="gps_10px.png",
-    fap_category="GPIO",
-    fap_author="@ezod & @xMasterX",
-    fap_version="1.0",
-    fap_description="Works with GPS modules via UART, using NMEA protocol.",
-)

+ 0 - 190
non_catalog_apps/gps_nmea_uart/gps.c

@@ -1,190 +0,0 @@
-#include "gps_uart.h"
-
-#include <furi.h>
-#include <gui/gui.h>
-#include <string.h>
-
-typedef enum {
-    EventTypeTick,
-    EventTypeKey,
-} EventType;
-
-typedef struct {
-    EventType type;
-    InputEvent input;
-} PluginEvent;
-
-static void render_callback(Canvas* const canvas, void* context) {
-    furi_assert(context);
-    GpsUart* gps_uart = context;
-    furi_mutex_acquire(gps_uart->mutex, FuriWaitForever);
-
-    if(!gps_uart->changing_baudrate) {
-        canvas_set_font(canvas, FontPrimary);
-        canvas_draw_str_aligned(canvas, 32, 8, AlignCenter, AlignBottom, "Latitude");
-        canvas_draw_str_aligned(canvas, 96, 8, AlignCenter, AlignBottom, "Longitude");
-        canvas_draw_str_aligned(canvas, 21, 30, AlignCenter, AlignBottom, "Course");
-        canvas_draw_str_aligned(canvas, 64, 30, AlignCenter, AlignBottom, "Speed");
-        canvas_draw_str_aligned(canvas, 107, 30, AlignCenter, AlignBottom, "Altitude");
-        canvas_draw_str_aligned(canvas, 32, 52, AlignCenter, AlignBottom, "Satellites");
-        canvas_draw_str_aligned(canvas, 96, 52, AlignCenter, AlignBottom, "Last Fix");
-
-        canvas_set_font(canvas, FontSecondary);
-        char buffer[64];
-        snprintf(buffer, 64, "%f", (double)gps_uart->status.latitude);
-        canvas_draw_str_aligned(canvas, 32, 18, AlignCenter, AlignBottom, buffer);
-        snprintf(buffer, 64, "%f", (double)gps_uart->status.longitude);
-        canvas_draw_str_aligned(canvas, 96, 18, AlignCenter, AlignBottom, buffer);
-        snprintf(buffer, 64, "%.1f", (double)gps_uart->status.course);
-        canvas_draw_str_aligned(canvas, 21, 40, AlignCenter, AlignBottom, buffer);
-        if(!gps_uart->speed_in_kms) {
-            snprintf(buffer, 64, "%.2f kn", (double)gps_uart->status.speed);
-        } else {
-            snprintf(buffer, 64, "%.2f km", (double)(gps_uart->status.speed * 1.852));
-        }
-        canvas_draw_str_aligned(canvas, 64, 40, AlignCenter, AlignBottom, buffer);
-        snprintf(
-            buffer,
-            64,
-            "%.1f %c",
-            (double)gps_uart->status.altitude,
-            tolower(gps_uart->status.altitude_units));
-        canvas_draw_str_aligned(canvas, 107, 40, AlignCenter, AlignBottom, buffer);
-        snprintf(buffer, 64, "%d", gps_uart->status.satellites_tracked);
-        canvas_draw_str_aligned(canvas, 32, 62, AlignCenter, AlignBottom, buffer);
-        snprintf(
-            buffer,
-            64,
-            "%02d:%02d:%02d UTC",
-            gps_uart->status.time_hours,
-            gps_uart->status.time_minutes,
-            gps_uart->status.time_seconds);
-        canvas_draw_str_aligned(canvas, 96, 62, AlignCenter, AlignBottom, buffer);
-    } else {
-        char buffer[64];
-        canvas_set_font(canvas, FontPrimary);
-        canvas_draw_str_aligned(canvas, 64, 32, AlignCenter, AlignBottom, "Baudrate set to:");
-
-        snprintf(buffer, 64, "%ld baud", gps_uart->baudrate);
-        canvas_draw_str_aligned(canvas, 64, 47, AlignCenter, AlignBottom, buffer);
-    }
-
-    furi_mutex_release(gps_uart->mutex);
-}
-
-static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) {
-    furi_assert(event_queue);
-
-    PluginEvent event = {.type = EventTypeKey, .input = *input_event};
-    furi_message_queue_put(event_queue, &event, FuriWaitForever);
-}
-
-int32_t gps_app(void* p) {
-    UNUSED(p);
-
-    FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(PluginEvent));
-
-    GpsUart* gps_uart = gps_uart_enable();
-
-    gps_uart->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
-    if(!gps_uart->mutex) {
-        FURI_LOG_E("GPS", "cannot create mutex\r\n");
-        free(gps_uart);
-        return 255;
-    }
-
-    // set system callbacks
-    ViewPort* view_port = view_port_alloc();
-    view_port_draw_callback_set(view_port, render_callback, gps_uart);
-    view_port_input_callback_set(view_port, input_callback, event_queue);
-
-    // open GUI and register view_port
-    Gui* gui = furi_record_open(RECORD_GUI);
-    gui_add_view_port(gui, view_port, GuiLayerFullscreen);
-
-    PluginEvent event;
-    for(bool processing = true; processing;) {
-        FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);
-
-        furi_mutex_acquire(gps_uart->mutex, FuriWaitForever);
-
-        if(event_status == FuriStatusOk) {
-            // press events
-            if(event.type == EventTypeKey) {
-                if(event.input.type == InputTypeShort) {
-                    switch(event.input.key) {
-                    case InputKeyUp:
-                    case InputKeyDown:
-                    case InputKeyRight:
-                    case InputKeyLeft:
-                    case InputKeyBack:
-                        break;
-                    case InputKeyOk:
-                        if(!gps_uart->backlight_on) {
-                            notification_message_block(
-                                gps_uart->notifications, &sequence_display_backlight_enforce_on);
-                            gps_uart->backlight_on = true;
-                        } else {
-                            notification_message_block(
-                                gps_uart->notifications, &sequence_display_backlight_enforce_auto);
-                            notification_message(
-                                gps_uart->notifications, &sequence_display_backlight_off);
-                            gps_uart->backlight_on = false;
-                        }
-                        break;
-                    default:
-                        break;
-                    }
-                } else if(event.input.type == InputTypeLong) {
-                    switch(event.input.key) {
-                    case InputKeyUp:
-                        gps_uart_deinit_thread(gps_uart);
-                        const int baudrate_length =
-                            sizeof(gps_baudrates) / sizeof(gps_baudrates[0]);
-                        current_gps_baudrate++;
-                        if(current_gps_baudrate >= baudrate_length) {
-                            current_gps_baudrate = 0;
-                        }
-                        gps_uart->baudrate = gps_baudrates[current_gps_baudrate];
-
-                        gps_uart_init_thread(gps_uart);
-                        gps_uart->changing_baudrate = true;
-                        view_port_update(view_port);
-                        furi_mutex_release(gps_uart->mutex);
-                        break;
-                    case InputKeyRight:
-                        if(gps_uart->speed_in_kms) {
-                            gps_uart->speed_in_kms = false;
-                        } else {
-                            gps_uart->speed_in_kms = true;
-                        }
-                        break;
-                    case InputKeyBack:
-                        processing = false;
-                        break;
-                    default:
-                        break;
-                    }
-                }
-            }
-        }
-        if(!gps_uart->changing_baudrate) {
-            view_port_update(view_port);
-            furi_mutex_release(gps_uart->mutex);
-        } else {
-            furi_delay_ms(1000);
-            gps_uart->changing_baudrate = false;
-        }
-    }
-
-    notification_message_block(gps_uart->notifications, &sequence_display_backlight_enforce_auto);
-    view_port_enabled_set(view_port, false);
-    gui_remove_view_port(gui, view_port);
-    furi_record_close(RECORD_GUI);
-    view_port_free(view_port);
-    furi_message_queue_free(event_queue);
-    furi_mutex_free(gps_uart->mutex);
-    gps_uart_disable(gps_uart);
-
-    return 0;
-}

BIN
non_catalog_apps/gps_nmea_uart/gps_10px.png


+ 0 - 217
non_catalog_apps/gps_nmea_uart/gps_uart.c

@@ -1,217 +0,0 @@
-#include <string.h>
-
-#include "minmea.h"
-#include "gps_uart.h"
-
-typedef enum {
-    WorkerEvtStop = (1 << 0),
-    WorkerEvtRxDone = (1 << 1),
-} WorkerEvtFlags;
-
-#define WORKER_ALL_RX_EVENTS (WorkerEvtStop | WorkerEvtRxDone)
-
-static void gps_uart_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) {
-    GpsUart* gps_uart = (GpsUart*)context;
-
-    if(ev == UartIrqEventRXNE) {
-        furi_stream_buffer_send(gps_uart->rx_stream, &data, 1, 0);
-        furi_thread_flags_set(furi_thread_get_id(gps_uart->thread), WorkerEvtRxDone);
-    }
-}
-
-static void gps_uart_serial_init(GpsUart* gps_uart) {
-    furi_hal_console_disable();
-    furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, gps_uart_on_irq_cb, gps_uart);
-    furi_hal_uart_set_br(FuriHalUartIdUSART1, gps_uart->baudrate);
-}
-
-static void gps_uart_serial_deinit(GpsUart* gps_uart) {
-    UNUSED(gps_uart);
-    furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, NULL, NULL);
-    furi_hal_console_enable();
-}
-
-static void gps_uart_parse_nmea(GpsUart* gps_uart, char* line) {
-    switch(minmea_sentence_id(line, false)) {
-    case MINMEA_SENTENCE_RMC: {
-        struct minmea_sentence_rmc frame;
-        if(minmea_parse_rmc(&frame, line)) {
-            gps_uart->status.valid = frame.valid;
-            gps_uart->status.latitude = minmea_tocoord(&frame.latitude);
-            gps_uart->status.longitude = minmea_tocoord(&frame.longitude);
-            gps_uart->status.speed = minmea_tofloat(&frame.speed);
-            gps_uart->status.course = minmea_tofloat(&frame.course);
-            gps_uart->status.time_hours = frame.time.hours;
-            gps_uart->status.time_minutes = frame.time.minutes;
-            gps_uart->status.time_seconds = frame.time.seconds;
-
-            notification_message_block(gps_uart->notifications, &sequence_blink_green_10);
-        }
-    } break;
-
-    case MINMEA_SENTENCE_GGA: {
-        struct minmea_sentence_gga frame;
-        if(minmea_parse_gga(&frame, line)) {
-            gps_uart->status.latitude = minmea_tocoord(&frame.latitude);
-            gps_uart->status.longitude = minmea_tocoord(&frame.longitude);
-            gps_uart->status.altitude = minmea_tofloat(&frame.altitude);
-            gps_uart->status.altitude_units = frame.altitude_units;
-            gps_uart->status.fix_quality = frame.fix_quality;
-            gps_uart->status.satellites_tracked = frame.satellites_tracked;
-            gps_uart->status.time_hours = frame.time.hours;
-            gps_uart->status.time_minutes = frame.time.minutes;
-            gps_uart->status.time_seconds = frame.time.seconds;
-
-            notification_message_block(gps_uart->notifications, &sequence_blink_magenta_10);
-        }
-    } break;
-
-    case MINMEA_SENTENCE_GLL: {
-        struct minmea_sentence_gll frame;
-        if(minmea_parse_gll(&frame, line)) {
-            gps_uart->status.latitude = minmea_tocoord(&frame.latitude);
-            gps_uart->status.longitude = minmea_tocoord(&frame.longitude);
-            gps_uart->status.time_hours = frame.time.hours;
-            gps_uart->status.time_minutes = frame.time.minutes;
-            gps_uart->status.time_seconds = frame.time.seconds;
-
-            notification_message_block(gps_uart->notifications, &sequence_blink_red_10);
-        }
-    } break;
-
-    default:
-        break;
-    }
-}
-
-static int32_t gps_uart_worker(void* context) {
-    GpsUart* gps_uart = (GpsUart*)context;
-
-    size_t rx_offset = 0;
-
-    while(1) {
-        uint32_t events =
-            furi_thread_flags_wait(WORKER_ALL_RX_EVENTS, FuriFlagWaitAny, FuriWaitForever);
-        furi_check((events & FuriFlagError) == 0);
-
-        if(events & WorkerEvtStop) {
-            break;
-        }
-
-        if(events & WorkerEvtRxDone) {
-            size_t len = 0;
-            do {
-                // receive serial bytes into rx_buf, starting at rx_offset from the start of the buffer
-                // the maximum we can receive is RX_BUF_SIZE - 1 - rx_offset
-                len = furi_stream_buffer_receive(
-                    gps_uart->rx_stream,
-                    gps_uart->rx_buf + rx_offset,
-                    RX_BUF_SIZE - 1 - rx_offset,
-                    0);
-                if(len > 0) {
-                    // increase rx_offset by the number of bytes received, and null-terminate rx_buf
-                    rx_offset += len;
-                    gps_uart->rx_buf[rx_offset] = '\0';
-
-                    // look for strings ending in newlines, starting at the start of rx_buf
-                    char* line_current = (char*)gps_uart->rx_buf;
-                    while(1) {
-                        // skip null characters
-                        while(*line_current == '\0' &&
-                              line_current < (char*)gps_uart->rx_buf + rx_offset - 1) {
-                            line_current++;
-                        }
-
-                        // find the next newline
-                        char* newline = strchr(line_current, '\n');
-                        if(newline) // newline found
-                        {
-                            // put a null terminator in place of the newline, to delimit the line string
-                            *newline = '\0';
-
-                            // attempt to parse the line as a NMEA sentence
-                            gps_uart_parse_nmea(gps_uart, line_current);
-
-                            // move the cursor to the character after the newline
-                            line_current = newline + 1;
-                        } else // no more newlines found
-                        {
-                            if(line_current >
-                               (char*)gps_uart->rx_buf) // at least one line was found
-                            {
-                                // clear parsed lines, and move any leftover bytes to the start of rx_buf
-                                rx_offset = 0;
-                                while(
-                                    *line_current) // stop when the original rx_offset terminator is reached
-                                {
-                                    gps_uart->rx_buf[rx_offset++] = *(line_current++);
-                                }
-                            }
-                            break; // go back to receiving bytes from the serial stream
-                        }
-                    }
-                }
-            } while(len > 0);
-        }
-    }
-
-    gps_uart_serial_deinit(gps_uart);
-    furi_stream_buffer_free(gps_uart->rx_stream);
-
-    return 0;
-}
-
-void gps_uart_init_thread(GpsUart* gps_uart) {
-    furi_assert(gps_uart);
-    gps_uart->status.valid = false;
-    gps_uart->status.latitude = 0.0;
-    gps_uart->status.longitude = 0.0;
-    gps_uart->status.speed = 0.0;
-    gps_uart->status.course = 0.0;
-    gps_uart->status.altitude = 0.0;
-    gps_uart->status.altitude_units = ' ';
-    gps_uart->status.fix_quality = 0;
-    gps_uart->status.satellites_tracked = 0;
-    gps_uart->status.time_hours = 0;
-    gps_uart->status.time_minutes = 0;
-    gps_uart->status.time_seconds = 0;
-
-    gps_uart->rx_stream = furi_stream_buffer_alloc(RX_BUF_SIZE * 5, 1);
-
-    gps_uart->thread = furi_thread_alloc();
-    furi_thread_set_name(gps_uart->thread, "GpsUartWorker");
-    furi_thread_set_stack_size(gps_uart->thread, 1024);
-    furi_thread_set_context(gps_uart->thread, gps_uart);
-    furi_thread_set_callback(gps_uart->thread, gps_uart_worker);
-
-    furi_thread_start(gps_uart->thread);
-
-    gps_uart_serial_init(gps_uart);
-}
-
-void gps_uart_deinit_thread(GpsUart* gps_uart) {
-    furi_assert(gps_uart);
-    furi_thread_flags_set(furi_thread_get_id(gps_uart->thread), WorkerEvtStop);
-    furi_thread_join(gps_uart->thread);
-    furi_thread_free(gps_uart->thread);
-}
-
-GpsUart* gps_uart_enable() {
-    GpsUart* gps_uart = malloc(sizeof(GpsUart));
-
-    gps_uart->notifications = furi_record_open(RECORD_NOTIFICATION);
-
-    gps_uart->baudrate = gps_baudrates[current_gps_baudrate];
-
-    gps_uart_init_thread(gps_uart);
-
-    return gps_uart;
-}
-
-void gps_uart_disable(GpsUart* gps_uart) {
-    furi_assert(gps_uart);
-    gps_uart_deinit_thread(gps_uart);
-    furi_record_close(RECORD_NOTIFICATION);
-
-    free(gps_uart);
-}

+ 0 - 46
non_catalog_apps/gps_nmea_uart/gps_uart.h

@@ -1,46 +0,0 @@
-#pragma once
-
-#include <furi_hal.h>
-#include <notification/notification_messages.h>
-
-#define RX_BUF_SIZE 1024
-
-static const int gps_baudrates[5] = {9600, 19200, 38400, 57600, 115200};
-static int current_gps_baudrate = 3;
-
-typedef struct {
-    bool valid;
-    float latitude;
-    float longitude;
-    float speed;
-    float course;
-    float altitude;
-    char altitude_units;
-    int fix_quality;
-    int satellites_tracked;
-    int time_hours;
-    int time_minutes;
-    int time_seconds;
-} GpsStatus;
-
-typedef struct {
-    FuriMutex* mutex;
-    FuriThread* thread;
-    FuriStreamBuffer* rx_stream;
-    uint8_t rx_buf[RX_BUF_SIZE];
-
-    NotificationApp* notifications;
-    uint32_t baudrate;
-    bool changing_baudrate;
-    bool backlight_on;
-    bool speed_in_kms;
-
-    GpsStatus status;
-} GpsUart;
-
-void gps_uart_init_thread(GpsUart* gps_uart);
-void gps_uart_deinit_thread(GpsUart* gps_uart);
-
-GpsUart* gps_uart_enable();
-
-void gps_uart_disable(GpsUart* gps_uart);

+ 0 - 640
non_catalog_apps/gps_nmea_uart/minmea.c

@@ -1,640 +0,0 @@
-/*
- * Copyright © 2014 Kosma Moczek <kosma@cloudyourcar.com>
- * This program is free software. It comes without any warranty, to the extent
- * permitted by applicable law. You can redistribute it and/or modify it under
- * the terms of the Do What The Fuck You Want To Public License, Version 2, as
- * published by Sam Hocevar. See the COPYING file for more details.
- */
-
-#include "minmea.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-
-#define boolstr(s) ((s) ? "true" : "false")
-
-static int hex2int(char c) {
-    if(c >= '0' && c <= '9') return c - '0';
-    if(c >= 'A' && c <= 'F') return c - 'A' + 10;
-    if(c >= 'a' && c <= 'f') return c - 'a' + 10;
-    return -1;
-}
-
-uint8_t minmea_checksum(const char* sentence) {
-    // Support senteces with or without the starting dollar sign.
-    if(*sentence == '$') sentence++;
-
-    uint8_t checksum = 0x00;
-
-    // The optional checksum is an XOR of all bytes between "$" and "*".
-    while(*sentence && *sentence != '*') checksum ^= *sentence++;
-
-    return checksum;
-}
-
-bool minmea_check(const char* sentence, bool strict) {
-    uint8_t checksum = 0x00;
-
-    // A valid sentence starts with "$".
-    if(*sentence++ != '$') return false;
-
-    // The optional checksum is an XOR of all bytes between "$" and "*".
-    while(*sentence && *sentence != '*' && isprint((unsigned char)*sentence))
-        checksum ^= *sentence++;
-
-    // If checksum is present...
-    if(*sentence == '*') {
-        // Extract checksum.
-        sentence++;
-        int upper = hex2int(*sentence++);
-        if(upper == -1) return false;
-        int lower = hex2int(*sentence++);
-        if(lower == -1) return false;
-        int expected = upper << 4 | lower;
-
-        // Check for checksum mismatch.
-        if(checksum != expected) return false;
-    } else if(strict) {
-        // Discard non-checksummed frames in strict mode.
-        return false;
-    }
-
-    // The only stuff allowed at this point is a newline.
-    while(*sentence == '\r' || *sentence == '\n') {
-        sentence++;
-    }
-
-    if(*sentence) {
-        return false;
-    }
-
-    return true;
-}
-
-bool minmea_scan(const char* sentence, const char* format, ...) {
-    bool result = false;
-    bool optional = false;
-
-    if(sentence == NULL) return false;
-
-    va_list ap;
-    va_start(ap, format);
-
-    const char* field = sentence;
-#define next_field()                                 \
-    do {                                             \
-        /* Progress to the next field. */            \
-        while(minmea_isfield(*sentence)) sentence++; \
-        /* Make sure there is a field there. */      \
-        if(*sentence == ',') {                       \
-            sentence++;                              \
-            field = sentence;                        \
-        } else {                                     \
-            field = NULL;                            \
-        }                                            \
-    } while(0)
-
-    while(*format) {
-        char type = *format++;
-
-        if(type == ';') {
-            // All further fields are optional.
-            optional = true;
-            continue;
-        }
-
-        if(!field && !optional) {
-            // Field requested but we ran out if input. Bail out.
-            goto parse_error;
-        }
-
-        switch(type) {
-        case 'c': { // Single character field (char).
-            char value = '\0';
-
-            if(field && minmea_isfield(*field)) value = *field;
-
-            *va_arg(ap, char*) = value;
-        } break;
-
-        case 'd': { // Single character direction field (int).
-            int value = 0;
-
-            if(field && minmea_isfield(*field)) {
-                switch(*field) {
-                case 'N':
-                case 'E':
-                    value = 1;
-                    break;
-                case 'S':
-                case 'W':
-                    value = -1;
-                    break;
-                default:
-                    goto parse_error;
-                }
-            }
-
-            *va_arg(ap, int*) = value;
-        } break;
-
-        case 'f': { // Fractional value with scale (struct minmea_float).
-            int sign = 0;
-            int_least32_t value = -1;
-            int_least32_t scale = 0;
-
-            if(field) {
-                while(minmea_isfield(*field)) {
-                    if(*field == '+' && !sign && value == -1) {
-                        sign = 1;
-                    } else if(*field == '-' && !sign && value == -1) {
-                        sign = -1;
-                    } else if(isdigit((unsigned char)*field)) {
-                        int digit = *field - '0';
-                        if(value == -1) value = 0;
-                        if(value > (INT_LEAST32_MAX - digit) / 10) {
-                            /* we ran out of bits, what do we do? */
-                            if(scale) {
-                                /* truncate extra precision */
-                                break;
-                            } else {
-                                /* integer overflow. bail out. */
-                                goto parse_error;
-                            }
-                        }
-                        value = (10 * value) + digit;
-                        if(scale) scale *= 10;
-                    } else if(*field == '.' && scale == 0) {
-                        scale = 1;
-                    } else if(*field == ' ') {
-                        /* Allow spaces at the start of the field. Not NMEA
-                             * conformant, but some modules do this. */
-                        if(sign != 0 || value != -1 || scale != 0) goto parse_error;
-                    } else {
-                        goto parse_error;
-                    }
-                    field++;
-                }
-            }
-
-            if((sign || scale) && value == -1) goto parse_error;
-
-            if(value == -1) {
-                /* No digits were scanned. */
-                value = 0;
-                scale = 0;
-            } else if(scale == 0) {
-                /* No decimal point. */
-                scale = 1;
-            }
-            if(sign) value *= sign;
-
-            *va_arg(ap, struct minmea_float*) = (struct minmea_float){value, scale};
-        } break;
-
-        case 'i': { // Integer value, default 0 (int).
-            int value = 0;
-
-            if(field) {
-                char* endptr;
-                value = strtol(field, &endptr, 10);
-                if(minmea_isfield(*endptr)) goto parse_error;
-            }
-
-            *va_arg(ap, int*) = value;
-        } break;
-
-        case 's': { // String value (char *).
-            char* buf = va_arg(ap, char*);
-
-            if(field) {
-                while(minmea_isfield(*field)) *buf++ = *field++;
-            }
-
-            *buf = '\0';
-        } break;
-
-        case 't': { // NMEA talker+sentence identifier (char *).
-            // This field is always mandatory.
-            if(!field) goto parse_error;
-
-            if(field[0] != '$') goto parse_error;
-            for(int f = 0; f < 5; f++)
-                if(!minmea_isfield(field[1 + f])) goto parse_error;
-
-            char* buf = va_arg(ap, char*);
-            memcpy(buf, field + 1, 5);
-            buf[5] = '\0';
-        } break;
-
-        case 'D': { // Date (int, int, int), -1 if empty.
-            struct minmea_date* date = va_arg(ap, struct minmea_date*);
-
-            int d = -1, m = -1, y = -1;
-
-            if(field && minmea_isfield(*field)) {
-                // Always six digits.
-                for(int f = 0; f < 6; f++)
-                    if(!isdigit((unsigned char)field[f])) goto parse_error;
-
-                char dArr[] = {field[0], field[1], '\0'};
-                char mArr[] = {field[2], field[3], '\0'};
-                char yArr[] = {field[4], field[5], '\0'};
-                d = strtol(dArr, NULL, 10);
-                m = strtol(mArr, NULL, 10);
-                y = strtol(yArr, NULL, 10);
-            }
-
-            date->day = d;
-            date->month = m;
-            date->year = y;
-        } break;
-
-        case 'T': { // Time (int, int, int, int), -1 if empty.
-            struct minmea_time* time_ = va_arg(ap, struct minmea_time*);
-
-            int h = -1, i = -1, s = -1, u = -1;
-
-            if(field && minmea_isfield(*field)) {
-                // Minimum required: integer time.
-                for(int f = 0; f < 6; f++)
-                    if(!isdigit((unsigned char)field[f])) goto parse_error;
-
-                char hArr[] = {field[0], field[1], '\0'};
-                char iArr[] = {field[2], field[3], '\0'};
-                char sArr[] = {field[4], field[5], '\0'};
-                h = strtol(hArr, NULL, 10);
-                i = strtol(iArr, NULL, 10);
-                s = strtol(sArr, NULL, 10);
-                field += 6;
-
-                // Extra: fractional time. Saved as microseconds.
-                if(*field++ == '.') {
-                    uint32_t value = 0;
-                    uint32_t scale = 1000000LU;
-                    while(isdigit((unsigned char)*field) && scale > 1) {
-                        value = (value * 10) + (*field++ - '0');
-                        scale /= 10;
-                    }
-                    u = value * scale;
-                } else {
-                    u = 0;
-                }
-            }
-
-            time_->hours = h;
-            time_->minutes = i;
-            time_->seconds = s;
-            time_->microseconds = u;
-        } break;
-
-        case '_': { // Ignore the field.
-        } break;
-
-        default: { // Unknown.
-            goto parse_error;
-        }
-        }
-
-        next_field();
-    }
-
-    result = true;
-
-parse_error:
-    va_end(ap);
-    return result;
-}
-
-bool minmea_talker_id(char talker[3], const char* sentence) {
-    char type[6];
-    if(!minmea_scan(sentence, "t", type)) return false;
-
-    talker[0] = type[0];
-    talker[1] = type[1];
-    talker[2] = '\0';
-
-    return true;
-}
-
-enum minmea_sentence_id minmea_sentence_id(const char* sentence, bool strict) {
-    if(!minmea_check(sentence, strict)) return MINMEA_INVALID;
-
-    char type[6];
-    if(!minmea_scan(sentence, "t", type)) return MINMEA_INVALID;
-
-    if(!strcmp(type + 2, "GBS")) return MINMEA_SENTENCE_GBS;
-    if(!strcmp(type + 2, "GGA")) return MINMEA_SENTENCE_GGA;
-    if(!strcmp(type + 2, "GLL")) return MINMEA_SENTENCE_GLL;
-    if(!strcmp(type + 2, "GSA")) return MINMEA_SENTENCE_GSA;
-    if(!strcmp(type + 2, "GST")) return MINMEA_SENTENCE_GST;
-    if(!strcmp(type + 2, "GSV")) return MINMEA_SENTENCE_GSV;
-    if(!strcmp(type + 2, "RMC")) return MINMEA_SENTENCE_RMC;
-    if(!strcmp(type + 2, "VTG")) return MINMEA_SENTENCE_VTG;
-    if(!strcmp(type + 2, "ZDA")) return MINMEA_SENTENCE_ZDA;
-
-    return MINMEA_UNKNOWN;
-}
-
-bool minmea_parse_gbs(struct minmea_sentence_gbs* frame, const char* sentence) {
-    // $GNGBS,170556.00,3.0,2.9,8.3,,,,*5C
-    char type[6];
-    if(!minmea_scan(
-           sentence,
-           "tTfffifff",
-           type,
-           &frame->time,
-           &frame->err_latitude,
-           &frame->err_longitude,
-           &frame->err_altitude,
-           &frame->svid,
-           &frame->prob,
-           &frame->bias,
-           &frame->stddev))
-        return false;
-    if(strcmp(type + 2, "GBS")) return false;
-
-    return true;
-}
-
-bool minmea_parse_rmc(struct minmea_sentence_rmc* frame, const char* sentence) {
-    // $GPRMC,081836,A,3751.65,S,14507.36,E,000.0,360.0,130998,011.3,E*62
-    char type[6];
-    char validity;
-    int latitude_direction;
-    int longitude_direction;
-    int variation_direction;
-    if(!minmea_scan(
-           sentence,
-           "tTcfdfdffDfd",
-           type,
-           &frame->time,
-           &validity,
-           &frame->latitude,
-           &latitude_direction,
-           &frame->longitude,
-           &longitude_direction,
-           &frame->speed,
-           &frame->course,
-           &frame->date,
-           &frame->variation,
-           &variation_direction))
-        return false;
-    if(strcmp(type + 2, "RMC")) return false;
-
-    frame->valid = (validity == 'A');
-    frame->latitude.value *= latitude_direction;
-    frame->longitude.value *= longitude_direction;
-    frame->variation.value *= variation_direction;
-
-    return true;
-}
-
-bool minmea_parse_gga(struct minmea_sentence_gga* frame, const char* sentence) {
-    // $GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47
-    char type[6];
-    int latitude_direction;
-    int longitude_direction;
-
-    if(!minmea_scan(
-           sentence,
-           "tTfdfdiiffcfcf_",
-           type,
-           &frame->time,
-           &frame->latitude,
-           &latitude_direction,
-           &frame->longitude,
-           &longitude_direction,
-           &frame->fix_quality,
-           &frame->satellites_tracked,
-           &frame->hdop,
-           &frame->altitude,
-           &frame->altitude_units,
-           &frame->height,
-           &frame->height_units,
-           &frame->dgps_age))
-        return false;
-    if(strcmp(type + 2, "GGA")) return false;
-
-    frame->latitude.value *= latitude_direction;
-    frame->longitude.value *= longitude_direction;
-
-    return true;
-}
-
-bool minmea_parse_gsa(struct minmea_sentence_gsa* frame, const char* sentence) {
-    // $GPGSA,A,3,04,05,,09,12,,,24,,,,,2.5,1.3,2.1*39
-    char type[6];
-
-    if(!minmea_scan(
-           sentence,
-           "tciiiiiiiiiiiiifff",
-           type,
-           &frame->mode,
-           &frame->fix_type,
-           &frame->sats[0],
-           &frame->sats[1],
-           &frame->sats[2],
-           &frame->sats[3],
-           &frame->sats[4],
-           &frame->sats[5],
-           &frame->sats[6],
-           &frame->sats[7],
-           &frame->sats[8],
-           &frame->sats[9],
-           &frame->sats[10],
-           &frame->sats[11],
-           &frame->pdop,
-           &frame->hdop,
-           &frame->vdop))
-        return false;
-    if(strcmp(type + 2, "GSA")) return false;
-
-    return true;
-}
-
-bool minmea_parse_gll(struct minmea_sentence_gll* frame, const char* sentence) {
-    // $GPGLL,3723.2475,N,12158.3416,W,161229.487,A,A*41$;
-    char type[6];
-    int latitude_direction;
-    int longitude_direction;
-
-    if(!minmea_scan(
-           sentence,
-           "tfdfdTc;c",
-           type,
-           &frame->latitude,
-           &latitude_direction,
-           &frame->longitude,
-           &longitude_direction,
-           &frame->time,
-           &frame->status,
-           &frame->mode))
-        return false;
-    if(strcmp(type + 2, "GLL")) return false;
-
-    frame->latitude.value *= latitude_direction;
-    frame->longitude.value *= longitude_direction;
-
-    return true;
-}
-
-bool minmea_parse_gst(struct minmea_sentence_gst* frame, const char* sentence) {
-    // $GPGST,024603.00,3.2,6.6,4.7,47.3,5.8,5.6,22.0*58
-    char type[6];
-
-    if(!minmea_scan(
-           sentence,
-           "tTfffffff",
-           type,
-           &frame->time,
-           &frame->rms_deviation,
-           &frame->semi_major_deviation,
-           &frame->semi_minor_deviation,
-           &frame->semi_major_orientation,
-           &frame->latitude_error_deviation,
-           &frame->longitude_error_deviation,
-           &frame->altitude_error_deviation))
-        return false;
-    if(strcmp(type + 2, "GST")) return false;
-
-    return true;
-}
-
-bool minmea_parse_gsv(struct minmea_sentence_gsv* frame, const char* sentence) {
-    // $GPGSV,3,1,11,03,03,111,00,04,15,270,00,06,01,010,00,13,06,292,00*74
-    // $GPGSV,3,3,11,22,42,067,42,24,14,311,43,27,05,244,00,,,,*4D
-    // $GPGSV,4,2,11,08,51,203,30,09,45,215,28*75
-    // $GPGSV,4,4,13,39,31,170,27*40
-    // $GPGSV,4,4,13*7B
-    char type[6];
-
-    if(!minmea_scan(
-           sentence,
-           "tiii;iiiiiiiiiiiiiiii",
-           type,
-           &frame->total_msgs,
-           &frame->msg_nr,
-           &frame->total_sats,
-           &frame->sats[0].nr,
-           &frame->sats[0].elevation,
-           &frame->sats[0].azimuth,
-           &frame->sats[0].snr,
-           &frame->sats[1].nr,
-           &frame->sats[1].elevation,
-           &frame->sats[1].azimuth,
-           &frame->sats[1].snr,
-           &frame->sats[2].nr,
-           &frame->sats[2].elevation,
-           &frame->sats[2].azimuth,
-           &frame->sats[2].snr,
-           &frame->sats[3].nr,
-           &frame->sats[3].elevation,
-           &frame->sats[3].azimuth,
-           &frame->sats[3].snr)) {
-        return false;
-    }
-    if(strcmp(type + 2, "GSV")) return false;
-
-    return true;
-}
-
-bool minmea_parse_vtg(struct minmea_sentence_vtg* frame, const char* sentence) {
-    // $GPVTG,054.7,T,034.4,M,005.5,N,010.2,K*48
-    // $GPVTG,156.1,T,140.9,M,0.0,N,0.0,K*41
-    // $GPVTG,096.5,T,083.5,M,0.0,N,0.0,K,D*22
-    // $GPVTG,188.36,T,,M,0.820,N,1.519,K,A*3F
-    char type[6];
-    char c_true, c_magnetic, c_knots, c_kph, c_faa_mode;
-
-    if(!minmea_scan(
-           sentence,
-           "t;fcfcfcfcc",
-           type,
-           &frame->true_track_degrees,
-           &c_true,
-           &frame->magnetic_track_degrees,
-           &c_magnetic,
-           &frame->speed_knots,
-           &c_knots,
-           &frame->speed_kph,
-           &c_kph,
-           &c_faa_mode))
-        return false;
-    if(strcmp(type + 2, "VTG")) return false;
-    // values are only valid with the accompanying characters
-    if(c_true != 'T') frame->true_track_degrees.scale = 0;
-    if(c_magnetic != 'M') frame->magnetic_track_degrees.scale = 0;
-    if(c_knots != 'N') frame->speed_knots.scale = 0;
-    if(c_kph != 'K') frame->speed_kph.scale = 0;
-    frame->faa_mode = (enum minmea_faa_mode)c_faa_mode;
-
-    return true;
-}
-
-bool minmea_parse_zda(struct minmea_sentence_zda* frame, const char* sentence) {
-    // $GPZDA,201530.00,04,07,2002,00,00*60
-    char type[6];
-
-    if(!minmea_scan(
-           sentence,
-           "tTiiiii",
-           type,
-           &frame->time,
-           &frame->date.day,
-           &frame->date.month,
-           &frame->date.year,
-           &frame->hour_offset,
-           &frame->minute_offset))
-        return false;
-    if(strcmp(type + 2, "ZDA")) return false;
-
-    // check offsets
-    if(abs(frame->hour_offset) > 13 || frame->minute_offset > 59 || frame->minute_offset < 0)
-        return false;
-
-    return true;
-}
-
-int minmea_getdatetime(
-    struct tm* tm,
-    const struct minmea_date* date,
-    const struct minmea_time* time_) {
-    if(date->year == -1 || time_->hours == -1) return -1;
-
-    memset(tm, 0, sizeof(*tm));
-    if(date->year < 80) {
-        tm->tm_year = 2000 + date->year - 1900; // 2000-2079
-    } else if(date->year >= 1900) {
-        tm->tm_year = date->year - 1900; // 4 digit year, use directly
-    } else {
-        tm->tm_year = date->year; // 1980-1999
-    }
-    tm->tm_mon = date->month - 1;
-    tm->tm_mday = date->day;
-    tm->tm_hour = time_->hours;
-    tm->tm_min = time_->minutes;
-    tm->tm_sec = time_->seconds;
-
-    return 0;
-}
-
-int minmea_gettime(
-    struct timespec* ts,
-    const struct minmea_date* date,
-    const struct minmea_time* time_) {
-    struct tm tm;
-    if(minmea_getdatetime(&tm, date, time_)) return -1;
-
-    time_t timestamp = mktime(&tm); /* See README.md if your system lacks timegm(). */
-    if(timestamp != (time_t)-1) {
-        ts->tv_sec = timestamp;
-        ts->tv_nsec = time_->microseconds * 1000;
-        return 0;
-    } else {
-        return -1;
-    }
-}
-
-/* vim: set ts=4 sw=4 et: */

+ 0 - 295
non_catalog_apps/gps_nmea_uart/minmea.h

@@ -1,295 +0,0 @@
-/*
- * Copyright © 2014 Kosma Moczek <kosma@cloudyourcar.com>
- * This program is free software. It comes without any warranty, to the extent
- * permitted by applicable law. You can redistribute it and/or modify it under
- * the terms of the Do What The Fuck You Want To Public License, Version 2, as
- * published by Sam Hocevar. See the COPYING file for more details.
- */
-
-#ifndef MINMEA_H
-#define MINMEA_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <ctype.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <time.h>
-#include <math.h>
-#ifdef MINMEA_INCLUDE_COMPAT
-#include <minmea_compat.h>
-#endif
-
-#ifndef MINMEA_MAX_SENTENCE_LENGTH
-#define MINMEA_MAX_SENTENCE_LENGTH 80
-#endif
-
-enum minmea_sentence_id {
-    MINMEA_INVALID = -1,
-    MINMEA_UNKNOWN = 0,
-    MINMEA_SENTENCE_GBS,
-    MINMEA_SENTENCE_GGA,
-    MINMEA_SENTENCE_GLL,
-    MINMEA_SENTENCE_GSA,
-    MINMEA_SENTENCE_GST,
-    MINMEA_SENTENCE_GSV,
-    MINMEA_SENTENCE_RMC,
-    MINMEA_SENTENCE_VTG,
-    MINMEA_SENTENCE_ZDA,
-};
-
-struct minmea_float {
-    int_least32_t value;
-    int_least32_t scale;
-};
-
-struct minmea_date {
-    int day;
-    int month;
-    int year;
-};
-
-struct minmea_time {
-    int hours;
-    int minutes;
-    int seconds;
-    int microseconds;
-};
-
-struct minmea_sentence_gbs {
-    struct minmea_time time;
-    struct minmea_float err_latitude;
-    struct minmea_float err_longitude;
-    struct minmea_float err_altitude;
-    int svid;
-    struct minmea_float prob;
-    struct minmea_float bias;
-    struct minmea_float stddev;
-};
-
-struct minmea_sentence_rmc {
-    struct minmea_time time;
-    bool valid;
-    struct minmea_float latitude;
-    struct minmea_float longitude;
-    struct minmea_float speed;
-    struct minmea_float course;
-    struct minmea_date date;
-    struct minmea_float variation;
-};
-
-struct minmea_sentence_gga {
-    struct minmea_time time;
-    struct minmea_float latitude;
-    struct minmea_float longitude;
-    int fix_quality;
-    int satellites_tracked;
-    struct minmea_float hdop;
-    struct minmea_float altitude;
-    char altitude_units;
-    struct minmea_float height;
-    char height_units;
-    struct minmea_float dgps_age;
-};
-
-enum minmea_gll_status {
-    MINMEA_GLL_STATUS_DATA_VALID = 'A',
-    MINMEA_GLL_STATUS_DATA_NOT_VALID = 'V',
-};
-
-// FAA mode added to some fields in NMEA 2.3.
-enum minmea_faa_mode {
-    MINMEA_FAA_MODE_AUTONOMOUS = 'A',
-    MINMEA_FAA_MODE_DIFFERENTIAL = 'D',
-    MINMEA_FAA_MODE_ESTIMATED = 'E',
-    MINMEA_FAA_MODE_MANUAL = 'M',
-    MINMEA_FAA_MODE_SIMULATED = 'S',
-    MINMEA_FAA_MODE_NOT_VALID = 'N',
-    MINMEA_FAA_MODE_PRECISE = 'P',
-};
-
-struct minmea_sentence_gll {
-    struct minmea_float latitude;
-    struct minmea_float longitude;
-    struct minmea_time time;
-    char status;
-    char mode;
-};
-
-struct minmea_sentence_gst {
-    struct minmea_time time;
-    struct minmea_float rms_deviation;
-    struct minmea_float semi_major_deviation;
-    struct minmea_float semi_minor_deviation;
-    struct minmea_float semi_major_orientation;
-    struct minmea_float latitude_error_deviation;
-    struct minmea_float longitude_error_deviation;
-    struct minmea_float altitude_error_deviation;
-};
-
-enum minmea_gsa_mode {
-    MINMEA_GPGSA_MODE_AUTO = 'A',
-    MINMEA_GPGSA_MODE_FORCED = 'M',
-};
-
-enum minmea_gsa_fix_type {
-    MINMEA_GPGSA_FIX_NONE = 1,
-    MINMEA_GPGSA_FIX_2D = 2,
-    MINMEA_GPGSA_FIX_3D = 3,
-};
-
-struct minmea_sentence_gsa {
-    char mode;
-    int fix_type;
-    int sats[12];
-    struct minmea_float pdop;
-    struct minmea_float hdop;
-    struct minmea_float vdop;
-};
-
-struct minmea_sat_info {
-    int nr;
-    int elevation;
-    int azimuth;
-    int snr;
-};
-
-struct minmea_sentence_gsv {
-    int total_msgs;
-    int msg_nr;
-    int total_sats;
-    struct minmea_sat_info sats[4];
-};
-
-struct minmea_sentence_vtg {
-    struct minmea_float true_track_degrees;
-    struct minmea_float magnetic_track_degrees;
-    struct minmea_float speed_knots;
-    struct minmea_float speed_kph;
-    enum minmea_faa_mode faa_mode;
-};
-
-struct minmea_sentence_zda {
-    struct minmea_time time;
-    struct minmea_date date;
-    int hour_offset;
-    int minute_offset;
-};
-
-/**
- * Calculate raw sentence checksum. Does not check sentence integrity.
- */
-uint8_t minmea_checksum(const char* sentence);
-
-/**
- * Check sentence validity and checksum. Returns true for valid sentences.
- */
-bool minmea_check(const char* sentence, bool strict);
-
-/**
- * Determine talker identifier.
- */
-bool minmea_talker_id(char talker[3], const char* sentence);
-
-/**
- * Determine sentence identifier.
- */
-enum minmea_sentence_id minmea_sentence_id(const char* sentence, bool strict);
-
-/**
- * Scanf-like processor for NMEA sentences. Supports the following formats:
- * c - single character (char *)
- * d - direction, returned as 1/-1, default 0 (int *)
- * f - fractional, returned as value + scale (struct minmea_float *)
- * i - decimal, default zero (int *)
- * s - string (char *)
- * t - talker identifier and type (char *)
- * D - date (struct minmea_date *)
- * T - time stamp (struct minmea_time *)
- * _ - ignore this field
- * ; - following fields are optional
- * Returns true on success. See library source code for details.
- */
-bool minmea_scan(const char* sentence, const char* format, ...);
-
-/*
- * Parse a specific type of sentence. Return true on success.
- */
-bool minmea_parse_gbs(struct minmea_sentence_gbs* frame, const char* sentence);
-bool minmea_parse_rmc(struct minmea_sentence_rmc* frame, const char* sentence);
-bool minmea_parse_gga(struct minmea_sentence_gga* frame, const char* sentence);
-bool minmea_parse_gsa(struct minmea_sentence_gsa* frame, const char* sentence);
-bool minmea_parse_gll(struct minmea_sentence_gll* frame, const char* sentence);
-bool minmea_parse_gst(struct minmea_sentence_gst* frame, const char* sentence);
-bool minmea_parse_gsv(struct minmea_sentence_gsv* frame, const char* sentence);
-bool minmea_parse_vtg(struct minmea_sentence_vtg* frame, const char* sentence);
-bool minmea_parse_zda(struct minmea_sentence_zda* frame, const char* sentence);
-
-/**
- * Convert GPS UTC date/time representation to a UNIX calendar time.
- */
-int minmea_getdatetime(
-    struct tm* tm,
-    const struct minmea_date* date,
-    const struct minmea_time* time_);
-
-/**
- * Convert GPS UTC date/time representation to a UNIX timestamp.
- */
-int minmea_gettime(
-    struct timespec* ts,
-    const struct minmea_date* date,
-    const struct minmea_time* time_);
-
-/**
- * Rescale a fixed-point value to a different scale. Rounds towards zero.
- */
-static inline int_least32_t minmea_rescale(const struct minmea_float* f, int_least32_t new_scale) {
-    if(f->scale == 0) return 0;
-    if(f->scale == new_scale) return f->value;
-    if(f->scale > new_scale)
-        return (f->value + ((f->value > 0) - (f->value < 0)) * f->scale / new_scale / 2) /
-               (f->scale / new_scale);
-    else
-        return f->value * (new_scale / f->scale);
-}
-
-/**
- * Convert a fixed-point value to a floating-point value.
- * Returns NaN for "unknown" values.
- */
-static inline float minmea_tofloat(const struct minmea_float* f) {
-    if(f->scale == 0) return NAN;
-    return (float)f->value / (float)f->scale;
-}
-
-/**
- * Convert a raw coordinate to a floating point DD.DDD... value.
- * Returns NaN for "unknown" values.
- */
-static inline float minmea_tocoord(const struct minmea_float* f) {
-    if(f->scale == 0) return NAN;
-    if(f->scale > (INT_LEAST32_MAX / 100)) return NAN;
-    if(f->scale < (INT_LEAST32_MIN / 100)) return NAN;
-    int_least32_t degrees = f->value / (f->scale * 100);
-    int_least32_t minutes = f->value % (f->scale * 100);
-    return (float)degrees + (float)minutes / (60 * f->scale);
-}
-
-/**
- * Check whether a character belongs to the set of characters allowed in a
- * sentence data field.
- */
-static inline bool minmea_isfield(char c) {
-    return isprint((unsigned char)c) && c != ',' && c != '*';
-}
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* MINMEA_H */
-
-/* vim: set ts=4 sw=4 et: */

BIN
non_catalog_apps/gps_nmea_uart/ui.png


BIN
non_catalog_apps/gps_nmea_uart/wiring.png


+ 0 - 16
non_catalog_apps/hc_sr04/application.fam

@@ -1,16 +0,0 @@
-App(
-    appid="hc_sr04",
-    name="[HC-SR] Dist. Sensor",
-    apptype=FlipperAppType.EXTERNAL,
-    entry_point="hc_sr04_app",
-    requires=[
-        "gui",
-    ],
-    stack_size=2 * 1024,
-    order=20,
-    fap_icon="dist_sensor10px.png",
-    fap_category="GPIO",
-    fap_author="@xMasterX (first implementation by @Sanqui)",
-    fap_version="1.0",
-    fap_description="HC-SR(04) Distance sensor reader",
-)

BIN
non_catalog_apps/hc_sr04/dist_sensor10px.png


+ 0 - 275
non_catalog_apps/hc_sr04/hc_sr04.c

@@ -1,275 +0,0 @@
-// insired by
-// https://github.com/esphome/esphome/blob/ac0d921413c3884752193fe568fa82853f0f99e9/esphome/components/ultrasonic/ultrasonic_sensor.cpp
-// Ported and modified by @xMasterX
-
-#include <furi.h>
-#include <furi_hal.h>
-#include <furi_hal_power.h>
-#include <furi_hal_console.h>
-#include <gui/gui.h>
-#include <input/input.h>
-#include <stdlib.h>
-#include <gui/elements.h>
-#include <notification/notification.h>
-#include <notification/notification_messages.h>
-
-typedef enum {
-    EventTypeTick,
-    EventTypeKey,
-} EventType;
-
-typedef struct {
-    EventType type;
-    InputEvent input;
-} PluginEvent;
-
-typedef struct {
-    FuriMutex* mutex;
-    NotificationApp* notification;
-    bool have_5v;
-    bool measurement_made;
-    uint32_t echo; // us
-    float distance; // meters
-} PluginState;
-
-const NotificationSequence sequence_done = {
-    &message_display_backlight_on,
-    &message_green_255,
-    &message_note_c5,
-    &message_delay_50,
-    &message_sound_off,
-    NULL,
-};
-
-static void render_callback(Canvas* const canvas, void* ctx) {
-    furi_assert(ctx);
-    const PluginState* plugin_state = ctx;
-    furi_mutex_acquire(plugin_state->mutex, FuriWaitForever);
-
-    // border around the edge of the screen
-    // canvas_draw_frame(canvas, 0, 0, 128, 64);
-
-    canvas_set_font(canvas, FontPrimary);
-    elements_multiline_text_aligned(
-        canvas, 64, 2, AlignCenter, AlignTop, "HC-SR04 Ultrasonic\nDistance Sensor");
-
-    canvas_set_font(canvas, FontSecondary);
-
-    if(!plugin_state->have_5v) {
-        elements_multiline_text_aligned(
-            canvas,
-            4,
-            28,
-            AlignLeft,
-            AlignTop,
-            "5V on GPIO must be\nenabled, or USB must\nbe connected.");
-    } else {
-        if(!plugin_state->measurement_made) {
-            elements_multiline_text_aligned(
-                canvas, 64, 28, AlignCenter, AlignTop, "Press OK button to measure");
-            elements_multiline_text_aligned(
-                canvas, 64, 40, AlignCenter, AlignTop, "13/TX -> Trig\n14/RX -> Echo");
-        } else {
-            elements_multiline_text_aligned(canvas, 4, 28, AlignLeft, AlignTop, "Readout:");
-
-            FuriString* str_buf;
-            str_buf = furi_string_alloc();
-            furi_string_printf(str_buf, "Echo: %ld us", plugin_state->echo);
-
-            canvas_draw_str_aligned(
-                canvas, 8, 38, AlignLeft, AlignTop, furi_string_get_cstr(str_buf));
-            furi_string_printf(str_buf, "Distance: %02f m", (double)plugin_state->distance);
-            canvas_draw_str_aligned(
-                canvas, 8, 48, AlignLeft, AlignTop, furi_string_get_cstr(str_buf));
-
-            furi_string_free(str_buf);
-        }
-    }
-
-    furi_mutex_release(plugin_state->mutex);
-}
-
-static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) {
-    furi_assert(event_queue);
-
-    PluginEvent event = {.type = EventTypeKey, .input = *input_event};
-    furi_message_queue_put(event_queue, &event, FuriWaitForever);
-}
-
-static void hc_sr04_state_init(PluginState* const plugin_state) {
-    plugin_state->echo = -1;
-    plugin_state->distance = -1;
-    plugin_state->measurement_made = false;
-
-    furi_hal_power_suppress_charge_enter();
-
-    plugin_state->have_5v = false;
-    if(furi_hal_power_is_otg_enabled() || furi_hal_power_is_charging()) {
-        plugin_state->have_5v = true;
-    } else {
-        furi_hal_power_enable_otg();
-        plugin_state->have_5v = true;
-    }
-}
-
-float hc_sr04_us_to_m(uint32_t us) {
-    //speed of sound for 20°C, 50% relative humidity
-    //331.3 + 20 * 0.606 + 50 * 0.0124 = 0.034404
-    const float speed_sound_m_per_s = 344.04f;
-    const float time_s = us / 1e6f;
-    const float total_dist = time_s * speed_sound_m_per_s;
-    return total_dist / 2.0f;
-}
-
-static void hc_sr04_measure(PluginState* const plugin_state) {
-    //plugin_state->echo = 1;
-    //return;
-
-    if(!plugin_state->have_5v) {
-        if(furi_hal_power_is_otg_enabled() || furi_hal_power_is_charging()) {
-            plugin_state->have_5v = true;
-        } else {
-            return;
-        }
-    }
-
-    //furi_hal_light_set(LightRed, 0xFF);
-    notification_message(plugin_state->notification, &sequence_blink_start_yellow);
-
-    const uint32_t timeout_ms = 2000;
-    // Pin 13 / TX -> Trig
-    furi_hal_gpio_write(&gpio_usart_tx, false);
-    furi_hal_gpio_init(&gpio_usart_tx, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
-
-    // Pin 14 / RX -> Echo
-    furi_hal_gpio_write(&gpio_usart_rx, false);
-    furi_hal_gpio_init(&gpio_usart_rx, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh);
-
-    //FURI_CRITICAL_ENTER();
-    // 10 ms pulse on TX
-    furi_hal_gpio_write(&gpio_usart_tx, true);
-    furi_delay_ms(10);
-    furi_hal_gpio_write(&gpio_usart_tx, false);
-
-    const uint32_t start = furi_get_tick();
-
-    while(furi_get_tick() - start < timeout_ms && furi_hal_gpio_read(&gpio_usart_rx))
-        ;
-    while(furi_get_tick() - start < timeout_ms && !furi_hal_gpio_read(&gpio_usart_rx))
-        ;
-
-    const uint32_t pulse_start = DWT->CYCCNT;
-
-    while(furi_get_tick() - start < timeout_ms && furi_hal_gpio_read(&gpio_usart_rx))
-        ;
-    const uint32_t pulse_end = DWT->CYCCNT;
-
-    //FURI_CRITICAL_EXIT();
-
-    plugin_state->echo =
-        (pulse_end - pulse_start) / furi_hal_cortex_instructions_per_microsecond();
-    plugin_state->distance = hc_sr04_us_to_m(plugin_state->echo);
-    plugin_state->measurement_made = true;
-
-    //furi_hal_light_set(LightRed, 0x00);
-    notification_message(plugin_state->notification, &sequence_blink_stop);
-    notification_message(plugin_state->notification, &sequence_done);
-}
-
-int32_t hc_sr04_app() {
-    FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(PluginEvent));
-
-    PluginState* plugin_state = malloc(sizeof(PluginState));
-
-    hc_sr04_state_init(plugin_state);
-
-    furi_hal_console_disable();
-
-    plugin_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
-    if(!plugin_state->mutex) {
-        FURI_LOG_E("hc_sr04", "cannot create mutex\r\n");
-        if(furi_hal_power_is_otg_enabled()) {
-            furi_hal_power_disable_otg();
-        }
-        furi_hal_console_enable();
-        furi_hal_power_suppress_charge_exit();
-        furi_message_queue_free(event_queue);
-        free(plugin_state);
-        return 255;
-    }
-
-    plugin_state->notification = furi_record_open(RECORD_NOTIFICATION);
-
-    // Set system callbacks
-    ViewPort* view_port = view_port_alloc();
-    view_port_draw_callback_set(view_port, render_callback, plugin_state);
-    view_port_input_callback_set(view_port, input_callback, event_queue);
-
-    // Open GUI and register view_port
-    Gui* gui = furi_record_open(RECORD_GUI);
-    gui_add_view_port(gui, view_port, GuiLayerFullscreen);
-
-    PluginEvent event;
-    for(bool processing = true; processing;) {
-        FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);
-
-        furi_mutex_acquire(plugin_state->mutex, FuriWaitForever);
-
-        if(event_status == FuriStatusOk) {
-            // press events
-            if(event.type == EventTypeKey) {
-                if(event.input.type == InputTypePress) {
-                    switch(event.input.key) {
-                    case InputKeyUp:
-                    case InputKeyDown:
-                    case InputKeyRight:
-                    case InputKeyLeft:
-                        break;
-                    case InputKeyOk:
-                        hc_sr04_measure(plugin_state);
-                        break;
-                    case InputKeyBack:
-                        processing = false;
-                        break;
-                    default:
-                        break;
-                    }
-                }
-            }
-        }
-
-        view_port_update(view_port);
-        furi_mutex_release(plugin_state->mutex);
-    }
-
-    if(furi_hal_power_is_otg_enabled()) {
-        furi_hal_power_disable_otg();
-    }
-    furi_hal_power_suppress_charge_exit();
-
-    // Return TX / RX back to usart mode
-    furi_hal_gpio_init_ex(
-        &gpio_usart_tx,
-        GpioModeAltFunctionPushPull,
-        GpioPullUp,
-        GpioSpeedVeryHigh,
-        GpioAltFn7USART1);
-    furi_hal_gpio_init_ex(
-        &gpio_usart_rx,
-        GpioModeAltFunctionPushPull,
-        GpioPullUp,
-        GpioSpeedVeryHigh,
-        GpioAltFn7USART1);
-    furi_hal_console_enable();
-
-    view_port_enabled_set(view_port, false);
-    gui_remove_view_port(gui, view_port);
-    furi_record_close(RECORD_GUI);
-    furi_record_close(RECORD_NOTIFICATION);
-    view_port_free(view_port);
-    furi_message_queue_free(event_queue);
-    furi_mutex_free(plugin_state->mutex);
-    free(plugin_state);
-
-    return 0;
-}

+ 0 - 21
non_catalog_apps/lightmeter/LICENSE

@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2022 Oleksii Kutuzov
-
-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.

+ 0 - 21
non_catalog_apps/lightmeter/README.md

@@ -1,21 +0,0 @@
-# flipperzero-lightmeter 
-
-[Original link](https://github.com/oleksiikutuzov/flipperzero-lightmeter)
-
-
-<img src="images/framed_gui_main.png" width="500px">  
-
-## Wiring
-
-```
-VCC -> 3.3V
-GND -> GND
-SCL -> C0
-SDA -> C1
-```
-
-## TODO
-- [ ] Save settings to sd card
-
-## References
-App inspired by [lightmeter](https://github.com/vpominchuk/lightmeter) project for Arduino by [vpominchuk](https://github.com/vpominchuk).

+ 0 - 26
non_catalog_apps/lightmeter/application.fam

@@ -1,26 +0,0 @@
-App(
-    appid="lightmeter",
-    name="[BH1750] Lightmeter",
-    apptype=FlipperAppType.EXTERNAL,
-    entry_point="lightmeter_app",
-    requires=[
-        "gui",
-    ],
-    stack_size=1 * 1024,
-    order=90,
-    fap_icon="lightmeter.png",
-    fap_category="GPIO",
-    fap_private_libs=[
-        Lib(
-            name="BH1750",
-            cincludes=["."],
-            sources=[
-                "BH1750.c",
-            ],
-        ),
-    ],
-    fap_icon_assets="icons",
-    fap_author="@oleksiikutuzov",
-    fap_version="1.0",
-    fap_description="Lightmeter app for photography based on BH1750 sensor",
-)

+ 0 - 30
non_catalog_apps/lightmeter/gui/scenes/config/lightmeter_scene.c

@@ -1,30 +0,0 @@
-#include "lightmeter_scene.h"
-
-// Generate scene on_enter handlers array
-#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter,
-void (*const lightmeter_on_enter_handlers[])(void*) = {
-#include "lightmeter_scene_config.h"
-};
-#undef ADD_SCENE
-
-// Generate scene on_event handlers array
-#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event,
-bool (*const lightmeter_on_event_handlers[])(void* context, SceneManagerEvent event) = {
-#include "lightmeter_scene_config.h"
-};
-#undef ADD_SCENE
-
-// Generate scene on_exit handlers array
-#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit,
-void (*const lightmeter_on_exit_handlers[])(void* context) = {
-#include "lightmeter_scene_config.h"
-};
-#undef ADD_SCENE
-
-// Initialize scene handlers configuration structure
-const SceneManagerHandlers lightmeter_scene_handlers = {
-    .on_enter_handlers = lightmeter_on_enter_handlers,
-    .on_event_handlers = lightmeter_on_event_handlers,
-    .on_exit_handlers = lightmeter_on_exit_handlers,
-    .scene_num = LightMeterAppSceneNum,
-};

+ 0 - 29
non_catalog_apps/lightmeter/gui/scenes/config/lightmeter_scene.h

@@ -1,29 +0,0 @@
-#pragma once
-
-#include <gui/scene_manager.h>
-
-// Generate scene id and total number
-#define ADD_SCENE(prefix, name, id) LightMeterAppScene##id,
-typedef enum {
-#include "lightmeter_scene_config.h"
-    LightMeterAppSceneNum,
-} LightMeterAppScene;
-#undef ADD_SCENE
-
-extern const SceneManagerHandlers lightmeter_scene_handlers;
-
-// Generate scene on_enter handlers declaration
-#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*);
-#include "lightmeter_scene_config.h"
-#undef ADD_SCENE
-
-// Generate scene on_event handlers declaration
-#define ADD_SCENE(prefix, name, id) \
-    bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event);
-#include "lightmeter_scene_config.h"
-#undef ADD_SCENE
-
-// Generate scene on_exit handlers declaration
-#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context);
-#include "lightmeter_scene_config.h"
-#undef ADD_SCENE

+ 0 - 4
non_catalog_apps/lightmeter/gui/scenes/config/lightmeter_scene_config.h

@@ -1,4 +0,0 @@
-ADD_SCENE(lightmeter, main, Main)
-ADD_SCENE(lightmeter, config, Config)
-ADD_SCENE(lightmeter, help, Help)
-ADD_SCENE(lightmeter, about, About)

+ 0 - 71
non_catalog_apps/lightmeter/gui/scenes/lightmeter_scene_about.c

@@ -1,71 +0,0 @@
-#include "../../lightmeter.h"
-
-void lightmeter_scene_about_widget_callback(GuiButtonType result, InputType type, void* context) {
-    LightMeterApp* app = context;
-
-    UNUSED(app);
-    UNUSED(result);
-    UNUSED(type);
-    if(type == InputTypeShort) {
-        view_dispatcher_send_custom_event(app->view_dispatcher, result);
-    }
-}
-
-void lightmeter_scene_about_on_enter(void* context) {
-    LightMeterApp* app = context;
-
-    FuriString* temp_str;
-    temp_str = furi_string_alloc();
-    furi_string_printf(temp_str, "\e#%s\n", "Information");
-
-    furi_string_cat_printf(temp_str, "Version: %s\n", LM_VERSION_APP);
-    furi_string_cat_printf(temp_str, "Developed by: %s\n", LM_DEVELOPED);
-    furi_string_cat_printf(temp_str, "Github: %s\n\n", LM_GITHUB);
-
-    furi_string_cat_printf(temp_str, "\e#%s\n", "Description");
-    furi_string_cat_printf(
-        temp_str,
-        "Showing suggested camera\nsettings based on ambient\nlight or flash.\n\nInspired by a lightmeter\nproject by vpominchuk\n");
-
-    widget_add_text_box_element(
-        app->widget,
-        0,
-        0,
-        128,
-        14,
-        AlignCenter,
-        AlignBottom,
-        "\e#\e!                                                      \e!\n",
-        false);
-    widget_add_text_box_element(
-        app->widget,
-        0,
-        2,
-        128,
-        14,
-        AlignCenter,
-        AlignBottom,
-        "\e#\e!            Lightmeter            \e!\n",
-        false);
-    widget_add_text_scroll_element(app->widget, 0, 16, 128, 50, furi_string_get_cstr(temp_str));
-    furi_string_free(temp_str);
-
-    view_dispatcher_switch_to_view(app->view_dispatcher, LightMeterAppViewAbout);
-}
-
-bool lightmeter_scene_about_on_event(void* context, SceneManagerEvent event) {
-    LightMeterApp* app = context;
-
-    bool consumed = false;
-    UNUSED(app);
-    UNUSED(event);
-
-    return consumed;
-}
-
-void lightmeter_scene_about_on_exit(void* context) {
-    LightMeterApp* app = context;
-
-    // Clear views
-    widget_reset(app->widget);
-}

+ 0 - 216
non_catalog_apps/lightmeter/gui/scenes/lightmeter_scene_config.c

@@ -1,216 +0,0 @@
-#include "../../lightmeter.h"
-
-#define TAG "Scene Config"
-
-static const char* iso_numbers[] = {
-    [ISO_6] = "6",
-    [ISO_12] = "12",
-    [ISO_25] = "25",
-    [ISO_50] = "50",
-    [ISO_100] = "100",
-    [ISO_200] = "200",
-    [ISO_400] = "400",
-    [ISO_800] = "800",
-    [ISO_1600] = "1600",
-    [ISO_3200] = "3200",
-    [ISO_6400] = "6400",
-    [ISO_12800] = "12800",
-    [ISO_25600] = "25600",
-    [ISO_51200] = "51200",
-    [ISO_102400] = "102400",
-};
-
-static const char* nd_numbers[] = {
-    [ND_0] = "0",
-    [ND_2] = "2",
-    [ND_4] = "4",
-    [ND_8] = "8",
-    [ND_16] = "16",
-    [ND_32] = "32",
-    [ND_64] = "64",
-    [ND_128] = "128",
-    [ND_256] = "256",
-    [ND_512] = "512",
-    [ND_1024] = "1024",
-    [ND_2048] = "2048",
-    [ND_4096] = "4096",
-};
-
-static const char* diffusion_dome[] = {
-    [WITHOUT_DOME] = "No",
-    [WITH_DOME] = "Yes",
-};
-
-static const char* backlight[] = {
-    [BACKLIGHT_AUTO] = "Auto",
-    [BACKLIGHT_ON] = "On",
-};
-
-static const char* lux_only[] = {
-    [LUX_ONLY_OFF] = "Off",
-    [LUX_ONLY_ON] = "On",
-};
-
-enum LightMeterSubmenuIndex {
-    LightMeterSubmenuIndexISO,
-    LightMeterSubmenuIndexND,
-    LightMeterSubmenuIndexDome,
-    LightMeterSubmenuIndexBacklight,
-    LightMeterSubmenuIndexLuxMeter,
-    LightMeterSubmenuIndexHelp,
-    LightMeterSubmenuIndexAbout,
-};
-
-static void iso_numbers_cb(VariableItem* item) {
-    LightMeterApp* app = variable_item_get_context(item);
-    uint8_t index = variable_item_get_current_value_index(item);
-
-    variable_item_set_current_value_text(item, iso_numbers[index]);
-
-    LightMeterConfig* config = app->config;
-    config->iso = index;
-    lightmeter_app_set_config(app, config);
-}
-
-static void nd_numbers_cb(VariableItem* item) {
-    LightMeterApp* app = variable_item_get_context(item);
-    uint8_t index = variable_item_get_current_value_index(item);
-
-    variable_item_set_current_value_text(item, nd_numbers[index]);
-
-    LightMeterConfig* config = app->config;
-    config->nd = index;
-    lightmeter_app_set_config(app, config);
-}
-
-static void dome_presence_cb(VariableItem* item) {
-    LightMeterApp* app = variable_item_get_context(item);
-    uint8_t index = variable_item_get_current_value_index(item);
-
-    variable_item_set_current_value_text(item, diffusion_dome[index]);
-
-    LightMeterConfig* config = app->config;
-    config->dome = index;
-    lightmeter_app_set_config(app, config);
-}
-
-static void backlight_cb(VariableItem* item) {
-    LightMeterApp* app = variable_item_get_context(item);
-    uint8_t index = variable_item_get_current_value_index(item);
-
-    variable_item_set_current_value_text(item, backlight[index]);
-
-    LightMeterConfig* config = app->config;
-    if(index != config->backlight) {
-        if(index == BACKLIGHT_ON) {
-            notification_message(
-                app->notifications,
-                &sequence_display_backlight_enforce_on); // force on backlight
-        } else {
-            notification_message(
-                app->notifications,
-                &sequence_display_backlight_enforce_auto); // force auto backlight
-        }
-    }
-    config->backlight = index;
-    lightmeter_app_set_config(app, config);
-}
-
-static void lux_only_cb(VariableItem* item) {
-    LightMeterApp* app = variable_item_get_context(item);
-    uint8_t index = variable_item_get_current_value_index(item);
-
-    variable_item_set_current_value_text(item, lux_only[index]);
-
-    LightMeterConfig* config = app->config;
-    config->lux_only = index;
-    lightmeter_app_set_config(app, config);
-}
-
-static void ok_cb(void* context, uint32_t index) {
-    LightMeterApp* app = context;
-    UNUSED(app);
-    switch(index) {
-    case LightMeterSubmenuIndexHelp:
-        view_dispatcher_send_custom_event(app->view_dispatcher, LightMeterAppCustomEventHelp);
-        break;
-    case LightMeterSubmenuIndexAbout:
-        view_dispatcher_send_custom_event(app->view_dispatcher, LightMeterAppCustomEventAbout);
-        break;
-    default:
-        break;
-    }
-}
-
-void lightmeter_scene_config_on_enter(void* context) {
-    LightMeterApp* app = context;
-    VariableItemList* var_item_list = app->var_item_list;
-    VariableItem* item;
-    LightMeterConfig* config = app->config;
-
-    item =
-        variable_item_list_add(var_item_list, "ISO", COUNT_OF(iso_numbers), iso_numbers_cb, app);
-    variable_item_set_current_value_index(item, config->iso);
-    variable_item_set_current_value_text(item, iso_numbers[config->iso]);
-
-    item = variable_item_list_add(
-        var_item_list, "ND factor", COUNT_OF(nd_numbers), nd_numbers_cb, app);
-    variable_item_set_current_value_index(item, config->nd);
-    variable_item_set_current_value_text(item, nd_numbers[config->nd]);
-
-    item = variable_item_list_add(
-        var_item_list, "Diffusion dome", COUNT_OF(diffusion_dome), dome_presence_cb, app);
-    variable_item_set_current_value_index(item, config->dome);
-    variable_item_set_current_value_text(item, diffusion_dome[config->dome]);
-
-    item =
-        variable_item_list_add(var_item_list, "Backlight", COUNT_OF(backlight), backlight_cb, app);
-    variable_item_set_current_value_index(item, config->backlight);
-    variable_item_set_current_value_text(item, backlight[config->backlight]);
-
-    item = variable_item_list_add(
-        var_item_list, "Lux meter only", COUNT_OF(lux_only), lux_only_cb, app);
-    variable_item_set_current_value_index(item, config->lux_only);
-    variable_item_set_current_value_text(item, lux_only[config->lux_only]);
-
-    item = variable_item_list_add(var_item_list, "Help and Pinout", 0, NULL, NULL);
-    item = variable_item_list_add(var_item_list, "About", 0, NULL, NULL);
-
-    variable_item_list_set_selected_item(
-        var_item_list,
-        scene_manager_get_scene_state(app->scene_manager, LightMeterAppSceneConfig));
-
-    variable_item_list_set_enter_callback(var_item_list, ok_cb, app);
-
-    view_dispatcher_switch_to_view(app->view_dispatcher, LightMeterAppViewVarItemList);
-}
-
-bool lightmeter_scene_config_on_event(void* context, SceneManagerEvent event) {
-    LightMeterApp* app = context;
-    bool consumed = false;
-
-    if(event.type == SceneManagerEventTypeTick) {
-        consumed = true;
-    } else if(event.type == SceneManagerEventTypeCustom) {
-        switch(event.event) {
-        case LightMeterAppCustomEventHelp:
-            scene_manager_next_scene(app->scene_manager, LightMeterAppSceneHelp);
-            consumed = true;
-            break;
-        case LightMeterAppCustomEventAbout:
-            scene_manager_next_scene(app->scene_manager, LightMeterAppSceneAbout);
-            consumed = true;
-            break;
-        }
-    }
-    return consumed;
-}
-
-void lightmeter_scene_config_on_exit(void* context) {
-    LightMeterApp* app = context;
-    variable_item_list_reset(app->var_item_list);
-    main_view_set_iso(app->main_view, app->config->iso);
-    main_view_set_nd(app->main_view, app->config->nd);
-    main_view_set_dome(app->main_view, app->config->dome);
-    main_view_set_lux_only(app->main_view, app->config->lux_only);
-}

+ 0 - 34
non_catalog_apps/lightmeter/gui/scenes/lightmeter_scene_help.c

@@ -1,34 +0,0 @@
-#include "../../lightmeter.h"
-
-void lightmeter_scene_help_on_enter(void* context) {
-    LightMeterApp* app = context;
-
-    FuriString* temp_str;
-    temp_str = furi_string_alloc();
-    furi_string_printf(
-        temp_str, "App works with BH1750\nambient light sensor\nconnected via I2C interface\n\n");
-    furi_string_cat(temp_str, "\e#Pinout:\r\n");
-    furi_string_cat(
-        temp_str,
-        "    VCC: 3.3V\r\n"
-        "    GND: GND\r\n"
-        "    SDA: 15 [C1]\r\n"
-        "    SCL: 16 [C0]\r\n");
-
-    widget_add_text_scroll_element(app->widget, 0, 0, 128, 64, furi_string_get_cstr(temp_str));
-    furi_string_free(temp_str);
-
-    view_dispatcher_switch_to_view(app->view_dispatcher, LightMeterAppViewHelp);
-}
-
-bool lightmeter_scene_help_on_event(void* context, SceneManagerEvent event) {
-    UNUSED(context);
-    UNUSED(event);
-    return false;
-}
-
-void lightmeter_scene_help_on_exit(void* context) {
-    LightMeterApp* app = context;
-
-    widget_reset(app->widget);
-}

+ 0 - 43
non_catalog_apps/lightmeter/gui/scenes/lightmeter_scene_main.c

@@ -1,43 +0,0 @@
-#include "../../lightmeter.h"
-
-static void lightmeter_scene_main_on_left(void* context) {
-    LightMeterApp* app = context;
-
-    view_dispatcher_send_custom_event(app->view_dispatcher, LightMeterAppCustomEventConfig);
-}
-
-void lightmeter_scene_main_on_enter(void* context) {
-    LightMeterApp* app = context;
-
-    lightmeter_main_view_set_left_callback(app->main_view, lightmeter_scene_main_on_left, app);
-    view_dispatcher_switch_to_view(app->view_dispatcher, LightMeterAppViewMainView);
-}
-
-bool lightmeter_scene_main_on_event(void* context, SceneManagerEvent event) {
-    LightMeterApp* app = context;
-
-    bool response = false;
-
-    switch(event.type) {
-    case SceneManagerEventTypeCustom:
-        if(event.event == LightMeterAppCustomEventConfig) {
-            scene_manager_next_scene(app->scene_manager, LightMeterAppSceneConfig);
-            response = true;
-        }
-        break;
-
-    case SceneManagerEventTypeTick:
-        lightmeter_app_i2c_callback(app);
-        response = true;
-        break;
-
-    default:
-        break;
-    }
-
-    return response;
-}
-
-void lightmeter_scene_main_on_exit(void* context) {
-    UNUSED(context);
-}

+ 0 - 470
non_catalog_apps/lightmeter/gui/views/main_view.c

@@ -1,470 +0,0 @@
-#include "main_view.h"
-#include <furi.h>
-#include <furi_hal.h>
-#include <gui/elements.h>
-#include "../../lightmeter.h"
-#include "../../lightmeter_helper.h"
-
-#define WORKER_TAG "Main View"
-
-static const int iso_numbers[] = {
-    [ISO_6] = 6,
-    [ISO_12] = 12,
-    [ISO_25] = 25,
-    [ISO_50] = 50,
-    [ISO_100] = 100,
-    [ISO_200] = 200,
-    [ISO_400] = 400,
-    [ISO_800] = 800,
-    [ISO_1600] = 1600,
-    [ISO_3200] = 3200,
-    [ISO_6400] = 6400,
-    [ISO_12800] = 12800,
-    [ISO_25600] = 25600,
-    [ISO_51200] = 51200,
-    [ISO_102400] = 102400,
-};
-
-static const int nd_numbers[] = {
-    [ND_0] = 0,
-    [ND_2] = 2,
-    [ND_4] = 4,
-    [ND_8] = 8,
-    [ND_16] = 16,
-    [ND_32] = 32,
-    [ND_64] = 64,
-    [ND_128] = 128,
-    [ND_256] = 256,
-    [ND_512] = 512,
-    [ND_1024] = 1024,
-    [ND_2048] = 2048,
-    [ND_4096] = 4096,
-};
-
-const float aperture_numbers[] = {
-    [AP_1] = 1.0,
-    [AP_1_4] = 1.4,
-    [AP_2] = 2.0,
-    [AP_2_8] = 2.8,
-    [AP_4] = 4.0,
-    [AP_5_6] = 5.6,
-    [AP_8] = 8,
-    [AP_11] = 11,
-    [AP_16] = 16,
-    [AP_22] = 22,
-    [AP_32] = 32,
-    [AP_45] = 45,
-    [AP_64] = 64,
-    [AP_90] = 90,
-    [AP_128] = 128,
-};
-
-const float speed_numbers[] = {
-    [SPEED_8000] = 1.0 / 8000, [SPEED_4000] = 1.0 / 4000, [SPEED_2000] = 1.0 / 2000,
-    [SPEED_1000] = 1.0 / 1000, [SPEED_500] = 1.0 / 500,   [SPEED_250] = 1.0 / 250,
-    [SPEED_125] = 1.0 / 125,   [SPEED_60] = 1.0 / 60,     [SPEED_48] = 1.0 / 48,
-    [SPEED_30] = 1.0 / 30,     [SPEED_15] = 1.0 / 15,     [SPEED_8] = 1.0 / 8,
-    [SPEED_4] = 1.0 / 4,       [SPEED_2] = 1.0 / 2,       [SPEED_1S] = 1.0,
-    [SPEED_2S] = 2.0,          [SPEED_4S] = 4.0,          [SPEED_8S] = 8.0,
-    [SPEED_15S] = 15.0,        [SPEED_30S] = 30.0,
-};
-
-struct MainView {
-    View* view;
-    LightMeterMainViewButtonCallback cb_left;
-    void* cb_context;
-};
-
-void lightmeter_main_view_set_left_callback(
-    MainView* lightmeter_main_view,
-    LightMeterMainViewButtonCallback callback,
-    void* context) {
-    with_view_model(
-        lightmeter_main_view->view,
-        MainViewModel * model,
-        {
-            UNUSED(model);
-            lightmeter_main_view->cb_left = callback;
-            lightmeter_main_view->cb_context = context;
-        },
-        true);
-}
-
-static void main_view_draw_callback(Canvas* canvas, void* context) {
-    furi_assert(context);
-    MainViewModel* model = context;
-
-    canvas_clear(canvas);
-
-    // draw button
-    canvas_set_font(canvas, FontSecondary);
-    elements_button_left(canvas, "Config");
-
-    if(!model->lux_only) {
-        // top row
-        draw_top_row(canvas, model);
-
-        // add f, T values
-        canvas_set_font(canvas, FontBigNumbers);
-
-        // draw f icon and number
-        canvas_draw_icon(canvas, 15, 17, &I_f_10x14);
-        draw_aperture(canvas, model);
-
-        // draw T icon and number
-        canvas_draw_icon(canvas, 15, 34, &I_T_10x14);
-        draw_speed(canvas, model);
-
-        // draw ND number
-        draw_nd_number(canvas, model);
-
-        // draw EV number
-        canvas_set_font(canvas, FontSecondary);
-        draw_EV_number(canvas, model);
-
-        // draw mode indicator
-        draw_mode_indicator(canvas, model);
-    } else {
-        draw_lux_only_mode(canvas, model);
-    }
-}
-
-static void main_view_process(MainView* main_view, InputEvent* event) {
-    with_view_model(
-        main_view->view,
-        MainViewModel * model,
-        {
-            if(event->type == InputTypePress) {
-                if(event->key == InputKeyUp) {
-                    switch(model->current_mode) {
-                    case FIXED_APERTURE:
-                        if(model->aperture < AP_NUM - 1) model->aperture++;
-                        break;
-
-                    case FIXED_SPEED:
-                        if(model->speed < SPEED_NUM - 1) model->speed++;
-                        break;
-
-                    default:
-                        break;
-                    }
-                } else if(event->key == InputKeyDown) {
-                    switch(model->current_mode) {
-                    case FIXED_APERTURE:
-                        if(model->aperture > 0) model->aperture--;
-                        break;
-
-                    case FIXED_SPEED:
-                        if(model->speed > 0) model->speed--;
-                        break;
-
-                    default:
-                        break;
-                    }
-                } else if(event->key == InputKeyOk) {
-                    switch(model->current_mode) {
-                    case FIXED_SPEED:
-                        model->current_mode = FIXED_APERTURE;
-                        break;
-
-                    case FIXED_APERTURE:
-                        model->current_mode = FIXED_SPEED;
-                        break;
-
-                    default:
-                        break;
-                    }
-                }
-            }
-        },
-        true);
-}
-
-static bool main_view_input_callback(InputEvent* event, void* context) {
-    furi_assert(context);
-    MainView* main_view = context;
-    bool consumed = false;
-
-    if(event->type == InputTypeShort && event->key == InputKeyLeft) {
-        if(main_view->cb_left) {
-            main_view->cb_left(main_view->cb_context);
-        }
-        consumed = true;
-    } else if(event->type == InputTypeShort && event->key == InputKeyBack) {
-    } else {
-        main_view_process(main_view, event);
-        consumed = true;
-    }
-
-    return consumed;
-}
-
-MainView* main_view_alloc() {
-    MainView* main_view = malloc(sizeof(MainView));
-    main_view->view = view_alloc();
-    view_set_context(main_view->view, main_view);
-    view_allocate_model(main_view->view, ViewModelTypeLocking, sizeof(MainViewModel));
-    view_set_draw_callback(main_view->view, main_view_draw_callback);
-    view_set_input_callback(main_view->view, main_view_input_callback);
-
-    return main_view;
-}
-
-void main_view_free(MainView* main_view) {
-    furi_assert(main_view);
-    view_free(main_view->view);
-    free(main_view);
-}
-
-View* main_view_get_view(MainView* main_view) {
-    furi_assert(main_view);
-    return main_view->view;
-}
-
-void main_view_set_lux(MainView* main_view, float val) {
-    furi_assert(main_view);
-    with_view_model(
-        main_view->view, MainViewModel * model, { model->lux = val; }, true);
-}
-
-void main_view_set_EV(MainView* main_view, float val) {
-    furi_assert(main_view);
-    with_view_model(
-        main_view->view, MainViewModel * model, { model->EV = val; }, true);
-}
-
-void main_view_set_response(MainView* main_view, bool val) {
-    furi_assert(main_view);
-    with_view_model(
-        main_view->view, MainViewModel * model, { model->response = val; }, true);
-}
-
-void main_view_set_iso(MainView* main_view, int iso) {
-    furi_assert(main_view);
-    with_view_model(
-        main_view->view, MainViewModel * model, { model->iso = iso; }, true);
-}
-
-void main_view_set_nd(MainView* main_view, int nd) {
-    furi_assert(main_view);
-    with_view_model(
-        main_view->view, MainViewModel * model, { model->nd = nd; }, true);
-}
-
-void main_view_set_aperture(MainView* main_view, int aperture) {
-    furi_assert(main_view);
-    with_view_model(
-        main_view->view, MainViewModel * model, { model->aperture = aperture; }, true);
-}
-
-void main_view_set_speed(MainView* main_view, int speed) {
-    furi_assert(main_view);
-    with_view_model(
-        main_view->view, MainViewModel * model, { model->speed = speed; }, true);
-}
-
-void main_view_set_dome(MainView* main_view, bool dome) {
-    furi_assert(main_view);
-    with_view_model(
-        main_view->view, MainViewModel * model, { model->dome = dome; }, true);
-}
-
-void main_view_set_lux_only(MainView* main_view, bool lux_only) {
-    furi_assert(main_view);
-    with_view_model(
-        main_view->view, MainViewModel * model, { model->lux_only = lux_only; }, true);
-}
-
-bool main_view_get_dome(MainView* main_view) {
-    furi_assert(main_view);
-    bool val = false;
-    with_view_model(
-        main_view->view, MainViewModel * model, { val = model->dome; }, true);
-    return val;
-}
-
-void draw_top_row(Canvas* canvas, MainViewModel* context) {
-    MainViewModel* model = context;
-
-    char str[12];
-
-    if(!model->response) {
-        canvas_draw_box(canvas, 0, 0, 128, 12);
-        canvas_set_color(canvas, ColorWhite);
-        canvas_set_font(canvas, FontPrimary);
-        canvas_draw_str(canvas, 24, 10, "No sensor found");
-        canvas_set_color(canvas, ColorBlack);
-    } else {
-        model->iso_val = iso_numbers[model->iso];
-        if(model->nd > 0) model->iso_val /= nd_numbers[model->nd];
-
-        if(model->lux > 0) {
-            if(model->current_mode == FIXED_APERTURE) {
-                model->speed_val = 100 * pow(aperture_numbers[model->aperture], 2) /
-                                   (double)model->iso_val / pow(2, model->EV);
-            } else {
-                model->aperture_val = sqrt(
-                    pow(2, model->EV) * (double)model->iso_val *
-                    (double)speed_numbers[model->speed] / 100);
-            }
-        }
-
-        // TODO when T:30, f/0 instead of f/128
-
-        canvas_draw_line(canvas, 0, 10, 128, 10);
-
-        canvas_set_font(canvas, FontPrimary);
-        // metering mode A – ambient, F – flash
-        // canvas_draw_str_aligned(canvas, 1, 1, AlignLeft, AlignTop, "A");
-
-        snprintf(str, sizeof(str), "ISO: %d", iso_numbers[model->iso]);
-        canvas_draw_str_aligned(canvas, 19, 1, AlignLeft, AlignTop, str);
-
-        canvas_set_font(canvas, FontSecondary);
-        snprintf(str, sizeof(str), "lx: %.0f", (double)model->lux);
-        canvas_draw_str_aligned(canvas, 87, 2, AlignLeft, AlignTop, str);
-    }
-}
-
-void draw_aperture(Canvas* canvas, MainViewModel* context) {
-    MainViewModel* model = context;
-
-    char str[12];
-
-    switch(model->current_mode) {
-    case FIXED_APERTURE:
-        if(model->response) {
-            if(model->aperture < AP_8) {
-                snprintf(str, sizeof(str), "/%.1f", (double)aperture_numbers[model->aperture]);
-            } else {
-                snprintf(str, sizeof(str), "/%.0f", (double)aperture_numbers[model->aperture]);
-            }
-        } else {
-            snprintf(str, sizeof(str), " ---");
-        }
-        canvas_draw_str_aligned(canvas, 27, 15, AlignLeft, AlignTop, str);
-        break;
-    case FIXED_SPEED:
-        if(model->aperture_val < aperture_numbers[0] || !model->response) {
-            snprintf(str, sizeof(str), " ---");
-        } else if(model->aperture_val < aperture_numbers[AP_8]) {
-            snprintf(str, sizeof(str), "/%.1f", (double)normalizeAperture(model->aperture_val));
-        } else {
-            snprintf(str, sizeof(str), "/%.0f", (double)normalizeAperture(model->aperture_val));
-        }
-        canvas_draw_str_aligned(canvas, 27, 15, AlignLeft, AlignTop, str);
-        break;
-    default:
-        break;
-    }
-}
-
-void draw_speed(Canvas* canvas, MainViewModel* context) {
-    MainViewModel* model = context;
-
-    char str[12];
-
-    switch(model->current_mode) {
-    case FIXED_APERTURE:
-        if(model->lux > 0 && model->response) {
-            if(model->speed_val < 1 && model->speed_val > 0) {
-                snprintf(str, sizeof(str), ":1/%.0f", 1 / (double)normalizeTime(model->speed_val));
-            } else {
-                snprintf(str, sizeof(str), ":%.0f", (double)normalizeTime(model->speed_val));
-            }
-        } else {
-            snprintf(str, sizeof(str), " ---");
-        }
-        canvas_draw_str_aligned(canvas, 27, 34, AlignLeft, AlignTop, str);
-        break;
-
-    case FIXED_SPEED:
-        if(model->response) {
-            if(model->speed < SPEED_1S) {
-                snprintf(str, sizeof(str), ":1/%.0f", 1 / (double)speed_numbers[model->speed]);
-            } else {
-                snprintf(str, sizeof(str), ":%.0f", (double)speed_numbers[model->speed]);
-            }
-        } else {
-            snprintf(str, sizeof(str), " ---");
-        }
-        canvas_draw_str_aligned(canvas, 27, 34, AlignLeft, AlignTop, str);
-        break;
-
-    default:
-        break;
-    }
-}
-
-void draw_mode_indicator(Canvas* canvas, MainViewModel* context) {
-    MainViewModel* model = context;
-
-    switch(model->current_mode) {
-    case FIXED_SPEED:
-        canvas_set_font(canvas, FontBigNumbers);
-        canvas_draw_str_aligned(canvas, 3, 36, AlignLeft, AlignTop, "*");
-        break;
-
-    case FIXED_APERTURE:
-        canvas_set_font(canvas, FontBigNumbers);
-        canvas_draw_str_aligned(canvas, 3, 17, AlignLeft, AlignTop, "*");
-        break;
-
-    default:
-        break;
-    }
-}
-
-void draw_nd_number(Canvas* canvas, MainViewModel* context) {
-    MainViewModel* model = context;
-
-    char str[9];
-
-    canvas_set_font(canvas, FontSecondary);
-
-    if(model->response) {
-        snprintf(str, sizeof(str), "ND: %d", nd_numbers[model->nd]);
-    } else {
-        snprintf(str, sizeof(str), "ND: ---");
-    }
-    canvas_draw_str_aligned(canvas, 87, 20, AlignLeft, AlignBottom, str);
-}
-
-void draw_EV_number(Canvas* canvas, MainViewModel* context) {
-    MainViewModel* model = context;
-
-    char str[7];
-
-    if(model->lux > 0 && model->response) {
-        snprintf(str, sizeof(str), "EV: %1.0f", (double)model->EV);
-        canvas_draw_str_aligned(canvas, 87, 29, AlignLeft, AlignBottom, str);
-    } else {
-        canvas_draw_str_aligned(canvas, 87, 29, AlignLeft, AlignBottom, "EV: --");
-    }
-}
-
-void draw_lux_only_mode(Canvas* canvas, MainViewModel* context) {
-    MainViewModel* model = context;
-
-    if(!model->response) {
-        canvas_draw_box(canvas, 0, 0, 128, 12);
-        canvas_set_color(canvas, ColorWhite);
-        canvas_set_font(canvas, FontPrimary);
-        canvas_draw_str(canvas, 24, 10, "No sensor found");
-        canvas_set_color(canvas, ColorBlack);
-    } else {
-        char str[12];
-
-        canvas_set_font(canvas, FontPrimary);
-
-        canvas_draw_line(canvas, 0, 10, 128, 10);
-        canvas_draw_str_aligned(canvas, 64, 1, AlignCenter, AlignTop, "Lux meter mode");
-
-        canvas_set_font(canvas, FontBigNumbers);
-        snprintf(str, sizeof(str), "%.0f", (double)model->lux);
-        canvas_draw_str_aligned(canvas, 80, 32, AlignRight, AlignCenter, str);
-
-        canvas_set_font(canvas, FontSecondary);
-        canvas_draw_str_aligned(canvas, 85, 39, AlignLeft, AlignBottom, "Lux");
-    }
-}

+ 0 - 78
non_catalog_apps/lightmeter/gui/views/main_view.h

@@ -1,78 +0,0 @@
-#pragma once
-
-#include <gui/view.h>
-#include "lightmeter_icons.h"
-#include "../../lightmeter_config.h"
-
-typedef struct MainView MainView;
-
-typedef enum {
-    FIXED_APERTURE,
-    FIXED_SPEED,
-
-    MODES_SIZE
-} MainViewMode;
-
-typedef struct {
-    uint8_t recv[2];
-    MainViewMode current_mode;
-    float lux;
-    float EV;
-    float aperture_val;
-    float speed_val;
-    int iso_val;
-    bool response;
-    int iso;
-    int nd;
-    int aperture;
-    int speed;
-    bool dome;
-    bool lux_only;
-} MainViewModel;
-
-typedef void (*LightMeterMainViewButtonCallback)(void* context);
-
-void lightmeter_main_view_set_left_callback(
-    MainView* lightmeter_main_view,
-    LightMeterMainViewButtonCallback callback,
-    void* context);
-
-MainView* main_view_alloc();
-
-void main_view_free(MainView* main_view);
-
-View* main_view_get_view(MainView* main_view);
-
-void main_view_set_lux(MainView* main_view, float val);
-
-void main_view_set_EV(MainView* main_view_, float val);
-
-void main_view_set_response(MainView* main_view_, bool val);
-
-void main_view_set_iso(MainView* main_view, int val);
-
-void main_view_set_nd(MainView* main_view, int val);
-
-void main_view_set_aperture(MainView* main_view, int val);
-
-void main_view_set_speed(MainView* main_view, int val);
-
-void main_view_set_dome(MainView* main_view, bool val);
-
-void main_view_set_lux_only(MainView* main_view, bool val);
-
-bool main_view_get_dome(MainView* main_view);
-
-void draw_top_row(Canvas* canvas, MainViewModel* context);
-
-void draw_aperture(Canvas* canvas, MainViewModel* context);
-
-void draw_speed(Canvas* canvas, MainViewModel* context);
-
-void draw_mode_indicator(Canvas* canvas, MainViewModel* context);
-
-void draw_nd_number(Canvas* canvas, MainViewModel* context);
-
-void draw_EV_number(Canvas* canvas, MainViewModel* context);
-
-void draw_lux_only_mode(Canvas* canvas, MainViewModel* context);

BIN
non_catalog_apps/lightmeter/icons/T_10x14.png


BIN
non_catalog_apps/lightmeter/icons/f_10x14.png


+ 0 - 150
non_catalog_apps/lightmeter/lib/BH1750/BH1750.c

@@ -1,150 +0,0 @@
-/**
- * @file BH1750.h
- * @author Oleksii Kutuzov (oleksii.kutuzov@icloud.com)
- * @brief 
- * @version 0.1
- * @date 2022-11-06
- * 
- * @copyright Copyright (c) 2022
- * 
- * Ported from:
- * https://github.com/lamik/Light_Sensors_STM32
- */
-
-#include "BH1750.h"
-
-BH1750_mode bh1750_mode = BH1750_DEFAULT_MODE; // Current sensor mode
-uint8_t bh1750_mt_reg = BH1750_DEFAULT_MTREG; // Current MT register value
-uint8_t bh1750_addr = BH1750_ADDRESS;
-
-BH1750_STATUS bh1750_init() {
-    if(BH1750_OK == bh1750_reset()) {
-        if(BH1750_OK == bh1750_set_mt_reg(BH1750_DEFAULT_MTREG)) {
-            return BH1750_OK;
-        }
-    }
-    return BH1750_ERROR;
-}
-
-BH1750_STATUS bh1750_init_with_addr(uint8_t addr) {
-    bh1750_addr = (addr << 1);
-    return bh1750_init();
-}
-
-BH1750_STATUS bh1750_reset() {
-    uint8_t command = 0x07;
-    bool status;
-
-    furi_hal_i2c_acquire(I2C_BUS);
-    status = furi_hal_i2c_tx(I2C_BUS, bh1750_addr, &command, 1, I2C_TIMEOUT);
-    furi_hal_i2c_release(I2C_BUS);
-
-    if(status) {
-        return BH1750_OK;
-    }
-
-    return BH1750_ERROR;
-}
-
-BH1750_STATUS bh1750_set_power_state(uint8_t PowerOn) {
-    PowerOn = (PowerOn ? 1 : 0);
-    bool status;
-
-    furi_hal_i2c_acquire(I2C_BUS);
-    status = furi_hal_i2c_tx(I2C_BUS, bh1750_addr, &PowerOn, 1, I2C_TIMEOUT);
-    furi_hal_i2c_release(I2C_BUS);
-
-    if(status) {
-        return BH1750_OK;
-    }
-
-    return BH1750_ERROR;
-}
-
-BH1750_STATUS bh1750_set_mode(BH1750_mode mode) {
-    if(!((mode >> 4) || (mode >> 5))) {
-        return BH1750_ERROR;
-    }
-
-    if((mode & 0x0F) > 3) {
-        return BH1750_ERROR;
-    }
-
-    bool status;
-
-    bh1750_mode = mode;
-
-    furi_hal_i2c_acquire(I2C_BUS);
-    status = furi_hal_i2c_tx(I2C_BUS, bh1750_addr, &mode, 1, I2C_TIMEOUT);
-    furi_hal_i2c_release(I2C_BUS);
-
-    if(status) {
-        return BH1750_OK;
-    }
-
-    return BH1750_ERROR;
-}
-
-BH1750_STATUS bh1750_set_mt_reg(uint8_t mt_reg) {
-    if(mt_reg < 31 || mt_reg > 254) {
-        return BH1750_ERROR;
-    }
-
-    bh1750_mt_reg = mt_reg;
-
-    uint8_t tmp[2];
-    bool status;
-
-    tmp[0] = (0x40 | (mt_reg >> 5));
-    tmp[1] = (0x60 | (mt_reg & 0x1F));
-
-    furi_hal_i2c_acquire(I2C_BUS);
-    status = furi_hal_i2c_tx(I2C_BUS, bh1750_addr, &tmp[0], 1, I2C_TIMEOUT);
-    furi_hal_i2c_release(I2C_BUS);
-    if(!status) {
-        return BH1750_ERROR;
-    }
-
-    furi_hal_i2c_acquire(I2C_BUS);
-    status = furi_hal_i2c_tx(I2C_BUS, bh1750_addr, &tmp[1], 1, I2C_TIMEOUT);
-    furi_hal_i2c_release(I2C_BUS);
-    if(status) {
-        return BH1750_OK;
-    }
-
-    return BH1750_ERROR;
-}
-
-BH1750_STATUS bh1750_trigger_manual_conversion() {
-    if(BH1750_OK == bh1750_set_mode(bh1750_mode)) {
-        return BH1750_OK;
-    }
-    return BH1750_ERROR;
-}
-
-BH1750_STATUS bh1750_read_light(float* result) {
-    float result_tmp;
-    uint8_t rcv[2];
-    bool status;
-
-    furi_hal_i2c_acquire(I2C_BUS);
-    status = furi_hal_i2c_rx(I2C_BUS, bh1750_addr, rcv, 2, I2C_TIMEOUT);
-    furi_hal_i2c_release(I2C_BUS);
-
-    if(status) {
-        result_tmp = (rcv[0] << 8) | (rcv[1]);
-
-        if(bh1750_mt_reg != BH1750_DEFAULT_MTREG) {
-            result_tmp *= (float)((uint8_t)BH1750_DEFAULT_MTREG / (float)bh1750_mt_reg);
-        }
-
-        if(bh1750_mode == ONETIME_HIGH_RES_MODE_2 || bh1750_mode == CONTINUOUS_HIGH_RES_MODE_2) {
-            result_tmp /= 2.0;
-        }
-
-        *result = result_tmp / BH1750_CONVERSION_FACTOR;
-
-        return BH1750_OK;
-    }
-    return BH1750_ERROR;
-}

+ 0 - 110
non_catalog_apps/lightmeter/lib/BH1750/BH1750.h

@@ -1,110 +0,0 @@
-/**
- * @file BH1750.h
- * @author Oleksii Kutuzov (oleksii.kutuzov@icloud.com)
- * @brief 
- * @version 0.1
- * @date 2022-11-06
- * 
- * @copyright Copyright (c) 2022
- * 
- * Ported from:
- * https://github.com/lamik/Light_Sensors_STM32
- */
-
-#include <furi.h>
-#include <furi_hal.h>
-
-#ifndef BH1750_H_
-#define BH1750_H_
-
-// I2C BUS
-#define I2C_BUS &furi_hal_i2c_handle_external
-#define I2C_TIMEOUT 10
-
-#define BH1750_ADDRESS (0x23 << 1)
-
-#define BH1750_POWER_DOWN 0x00
-#define BH1750_POWER_ON 0x01
-#define BH1750_RESET 0x07
-#define BH1750_DEFAULT_MTREG 69
-#define BH1750_DEFAULT_MODE ONETIME_HIGH_RES_MODE
-
-#define BH1750_CONVERSION_FACTOR 1.2
-
-typedef enum { BH1750_OK = 0, BH1750_ERROR = 1 } BH1750_STATUS;
-
-typedef enum {
-    CONTINUOUS_HIGH_RES_MODE = 0x10,
-    CONTINUOUS_HIGH_RES_MODE_2 = 0x11,
-    CONTINUOUS_LOW_RES_MODE = 0x13,
-    ONETIME_HIGH_RES_MODE = 0x20,
-    ONETIME_HIGH_RES_MODE_2 = 0x21,
-    ONETIME_LOW_RES_MODE = 0x23
-} BH1750_mode;
-
-/**
- * @brief Initialize the sensor. Sends the reset command and sets the measurement register to the default value.
- * 
- * @return BH1750_STATUS
- */
-BH1750_STATUS bh1750_init();
-
-/**
- * @brief Change the I2C device address and then initialize the sensor.
- * 
- * @return BH1750_STATUS
- */
-BH1750_STATUS bh1750_init_with_addr(uint8_t addr);
-
-/**
- * @brief Reset all registers to the default value.
- * 
- * @return BH1750_STATUS 
- */
-BH1750_STATUS bh1750_reset();
-
-/**
- * @brief Sets the power state. 1 - running; 0 - sleep, low power. 
- * 
- * @param PowerOn sensor state.
- * @return BH1750_STATUS 
- */
-BH1750_STATUS bh1750_set_power_state(uint8_t PowerOn);
-
-/**
- * @brief Set the Measurement Time register. It allows to increase or decrease the sensitivity.
- * 
- * @param MTreg value from 31 to 254, defaults to 69.
- * 
- * @return BH1750_STATUS 
- */
-BH1750_STATUS bh1750_set_mt_reg(uint8_t MTreg);
-
-/**
- * @brief Set the mode of converting. Look into the bh1750_mode enum.
- * 
- * @param Mode mode enumerator
- * @return BH1750_STATUS 
- */
-BH1750_STATUS bh1750_set_mode(BH1750_mode Mode);
-
-/**
- * @brief Trigger the conversion in manual modes. 
- * 
- * @details a low-resolution mode, the conversion time is typically 16 ms, and for a high-resolution 
- * mode is 120 ms. You need to wait until reading the measurement value. There is no need 
- * to exit low-power mode for manual conversion. It makes automatically.
- * 
- * @return BH1750_STATUS 
- */
-BH1750_STATUS bh1750_trigger_manual_conversion();
-
-/**
- * @brief Read the converted value and calculate the result.
- * 
- * @param Result stores received value to this variable.
- * @return BH1750_STATUS 
- */
-BH1750_STATUS bh1750_read_light(float* Result);
-
-#endif /* BH1750_H_ */

+ 0 - 21
non_catalog_apps/lightmeter/lib/BH1750/LICENSE

@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2022 Oleksii Kutuzov
-
-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.

+ 0 - 2
non_catalog_apps/lightmeter/lib/BH1750/README.md

@@ -1,2 +0,0 @@
-# flipperzero-BH1750
-BH1750 light sensor library for Flipper Zero 

BIN
non_catalog_apps/lightmeter/lib/BH1750/docs/BH1750.pdf


+ 0 - 161
non_catalog_apps/lightmeter/lightmeter.c

@@ -1,161 +0,0 @@
-#include "lightmeter.h"
-#include "lightmeter_helper.h"
-
-#define TAG "MAIN APP"
-
-static bool lightmeter_custom_event_callback(void* context, uint32_t event) {
-    furi_assert(context);
-    LightMeterApp* app = context;
-
-    return scene_manager_handle_custom_event(app->scene_manager, event);
-}
-
-static bool lightmeter_back_event_callback(void* context) {
-    furi_assert(context);
-    LightMeterApp* app = context;
-
-    return scene_manager_handle_back_event(app->scene_manager);
-}
-
-static void lightmeter_tick_event_callback(void* context) {
-    furi_assert(context);
-    LightMeterApp* app = context;
-
-    scene_manager_handle_tick_event(app->scene_manager);
-}
-
-LightMeterApp* lightmeter_app_alloc(uint32_t first_scene) {
-    LightMeterApp* app = malloc(sizeof(LightMeterApp));
-
-    // Sensor
-    bh1750_set_power_state(1);
-    bh1750_init();
-    bh1750_set_mode(ONETIME_HIGH_RES_MODE);
-
-    // Set default values to config
-    app->config = malloc(sizeof(LightMeterConfig));
-    app->config->iso = DEFAULT_ISO;
-    app->config->nd = DEFAULT_ND;
-    app->config->aperture = DEFAULT_APERTURE;
-    app->config->dome = DEFAULT_DOME;
-    app->config->backlight = DEFAULT_BACKLIGHT;
-
-    // Records
-    app->gui = furi_record_open(RECORD_GUI);
-    app->notifications = furi_record_open(RECORD_NOTIFICATION);
-
-    // View dispatcher
-    app->view_dispatcher = view_dispatcher_alloc();
-    app->scene_manager = scene_manager_alloc(&lightmeter_scene_handlers, app);
-    view_dispatcher_enable_queue(app->view_dispatcher);
-    view_dispatcher_set_event_callback_context(app->view_dispatcher, app);
-    view_dispatcher_set_custom_event_callback(
-        app->view_dispatcher, lightmeter_custom_event_callback);
-    view_dispatcher_set_navigation_event_callback(
-        app->view_dispatcher, lightmeter_back_event_callback);
-    view_dispatcher_set_tick_event_callback(
-        app->view_dispatcher, lightmeter_tick_event_callback, furi_ms_to_ticks(200));
-    view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen);
-
-    // Views
-    app->main_view = main_view_alloc();
-    view_dispatcher_add_view(
-        app->view_dispatcher, LightMeterAppViewMainView, main_view_get_view(app->main_view));
-
-    // Set default values to main view from config
-    main_view_set_iso(app->main_view, app->config->iso);
-    main_view_set_nd(app->main_view, app->config->nd);
-    main_view_set_aperture(app->main_view, app->config->aperture);
-    main_view_set_speed(app->main_view, DEFAULT_SPEED);
-    main_view_set_dome(app->main_view, app->config->dome);
-
-    // Variable item list
-    app->var_item_list = variable_item_list_alloc();
-    view_dispatcher_add_view(
-        app->view_dispatcher,
-        LightMeterAppViewVarItemList,
-        variable_item_list_get_view(app->var_item_list));
-
-    // Widget
-    app->widget = widget_alloc();
-    view_dispatcher_add_view(
-        app->view_dispatcher, LightMeterAppViewAbout, widget_get_view(app->widget));
-    view_dispatcher_add_view(
-        app->view_dispatcher, LightMeterAppViewHelp, widget_get_view(app->widget));
-
-    // Set first scene
-    scene_manager_next_scene(app->scene_manager, first_scene);
-    return app;
-}
-
-void lightmeter_app_free(LightMeterApp* app) {
-    furi_assert(app);
-
-    // Views
-    view_dispatcher_remove_view(app->view_dispatcher, LightMeterAppViewMainView);
-    main_view_free(app->main_view);
-
-    // Variable item list
-    view_dispatcher_remove_view(app->view_dispatcher, LightMeterAppViewVarItemList);
-    variable_item_list_free(app->var_item_list);
-
-    //  Widget
-    view_dispatcher_remove_view(app->view_dispatcher, LightMeterAppViewAbout);
-    view_dispatcher_remove_view(app->view_dispatcher, LightMeterAppViewHelp);
-    widget_free(app->widget);
-
-    // View dispatcher
-    scene_manager_free(app->scene_manager);
-    view_dispatcher_free(app->view_dispatcher);
-
-    // Records
-    furi_record_close(RECORD_GUI);
-    if(app->config->backlight != BACKLIGHT_AUTO) {
-        notification_message(
-            app->notifications,
-            &sequence_display_backlight_enforce_auto); // set backlight back to auto
-    }
-    furi_record_close(RECORD_NOTIFICATION);
-
-    bh1750_set_power_state(0);
-
-    free(app->config);
-    free(app);
-}
-
-int32_t lightmeter_app(void* p) {
-    UNUSED(p);
-    uint32_t first_scene = LightMeterAppSceneMain;
-    LightMeterApp* app = lightmeter_app_alloc(first_scene);
-    view_dispatcher_run(app->view_dispatcher);
-    lightmeter_app_free(app);
-    return 0;
-}
-
-void lightmeter_app_set_config(LightMeterApp* context, LightMeterConfig* config) {
-    LightMeterApp* app = context;
-
-    app->config = config;
-}
-
-void lightmeter_app_i2c_callback(LightMeterApp* context) {
-    LightMeterApp* app = context;
-
-    float EV = 0;
-    float lux = 0;
-    bool response = 0;
-
-    if(bh1750_trigger_manual_conversion() == BH1750_OK) response = 1;
-
-    if(response) {
-        bh1750_read_light(&lux);
-
-        if(main_view_get_dome(app->main_view)) lux *= DOME_COEFFICIENT;
-
-        EV = lux2ev(lux);
-    }
-
-    main_view_set_lux(app->main_view, lux);
-    main_view_set_EV(app->main_view, EV);
-    main_view_set_response(app->main_view, response);
-}

+ 0 - 58
non_catalog_apps/lightmeter/lightmeter.h

@@ -1,58 +0,0 @@
-#pragma once
-
-#include <furi.h>
-#include <furi_hal.h>
-
-#include <gui/gui.h>
-#include <gui/view.h>
-#include <gui/view_dispatcher.h>
-#include <gui/scene_manager.h>
-
-#include "gui/views/main_view.h"
-
-#include <gui/modules/widget.h>
-#include <gui/modules/variable_item_list.h>
-
-#include "gui/scenes/config/lightmeter_scene.h"
-#include <notification/notification_messages.h>
-
-#include "lightmeter_config.h"
-#include <BH1750.h>
-
-typedef struct {
-    int iso;
-    int nd;
-    int aperture;
-    int dome;
-    int backlight;
-    int lux_only;
-} LightMeterConfig;
-
-typedef struct {
-    Gui* gui;
-    SceneManager* scene_manager;
-    ViewDispatcher* view_dispatcher;
-    MainView* main_view;
-    VariableItemList* var_item_list;
-    LightMeterConfig* config;
-    NotificationApp* notifications;
-    Widget* widget;
-} LightMeterApp;
-
-typedef enum {
-    LightMeterAppViewMainView,
-    LightMeterAppViewConfigView,
-    LightMeterAppViewVarItemList,
-    LightMeterAppViewAbout,
-    LightMeterAppViewHelp,
-} LightMeterAppView;
-
-typedef enum {
-    LightMeterAppCustomEventConfig,
-    LightMeterAppCustomEventHelp,
-    LightMeterAppCustomEventAbout,
-} LightMeterAppCustomEvent;
-
-void lightmeter_app_set_config(LightMeterApp* context, LightMeterConfig* config);
-
-void lightmeter_app_i2c_callback(LightMeterApp* context);

BIN
non_catalog_apps/lightmeter/lightmeter.png


+ 0 - 108
non_catalog_apps/lightmeter/lightmeter_config.h

@@ -1,108 +0,0 @@
-#pragma once
-
-#define LM_VERSION_APP "0.7"
-#define LM_DEVELOPED "Oleksii Kutuzov"
-#define LM_GITHUB "https://github.com/oleksiikutuzov/flipperzero-lightmeter"
-
-#define DOME_COEFFICIENT 2.3
-#define DEFAULT_ISO ISO_100
-#define DEFAULT_ND ND_0
-#define DEFAULT_APERTURE AP_2_8
-#define DEFAULT_SPEED SPEED_125
-#define DEFAULT_DOME WITHOUT_DOME
-#define DEFAULT_BACKLIGHT BACKLIGHT_AUTO
-
-typedef enum {
-    ISO_6,
-    ISO_12,
-    ISO_25,
-    ISO_50,
-    ISO_100,
-    ISO_200,
-    ISO_400,
-    ISO_800,
-    ISO_1600,
-    ISO_3200,
-    ISO_6400,
-    ISO_12800,
-    ISO_25600,
-    ISO_51200,
-    ISO_102400,
-
-    ISO_NUM,
-} LightMeterISONumbers;
-
-typedef enum {
-    ND_0,
-    ND_2,
-    ND_4,
-    ND_8,
-    ND_16,
-    ND_32,
-    ND_64,
-    ND_128,
-    ND_256,
-    ND_512,
-    ND_1024,
-    ND_2048,
-    ND_4096,
-
-    ND_NUM,
-} LightMeterNDNumbers;
-
-typedef enum {
-    AP_1,
-    AP_1_4,
-    AP_2,
-    AP_2_8,
-    AP_4,
-    AP_5_6,
-    AP_8,
-    AP_11,
-    AP_16,
-    AP_22,
-    AP_32,
-    AP_45,
-    AP_64,
-    AP_90,
-    AP_128,
-
-    AP_NUM,
-} LightMeterApertureNumbers;
-
-typedef enum {
-    SPEED_8000,
-    SPEED_4000,
-    SPEED_2000,
-    SPEED_1000,
-    SPEED_500,
-    SPEED_250,
-    SPEED_125,
-    SPEED_60,
-    SPEED_48,
-    SPEED_30,
-    SPEED_15,
-    SPEED_8,
-    SPEED_4,
-    SPEED_2,
-    SPEED_1S,
-    SPEED_2S,
-    SPEED_4S,
-    SPEED_8S,
-    SPEED_15S,
-    SPEED_30S,
-
-    SPEED_NUM,
-} LightMeterSpeedNumbers;
-
-typedef enum {
-    WITHOUT_DOME,
-    WITH_DOME,
-} LightMeterDomePresence;
-
-typedef enum {
-    LUX_ONLY_OFF,
-    LUX_ONLY_ON,
-} LightMeterLuxOnlyMode;
-
-typedef enum { BACKLIGHT_AUTO, BACKLIGHT_ON } LightMeterBacklight;

+ 0 - 43
non_catalog_apps/lightmeter/lightmeter_helper.c

@@ -1,43 +0,0 @@
-#include "lightmeter_helper.h"
-#include "lightmeter_config.h"
-
-extern const float aperture_numbers[];
-extern const float speed_numbers[];
-
-float lux2ev(float lux) {
-    return log2(lux / 2.5);
-}
-
-float getMinDistance(float x, float v1, float v2) {
-    if(x - v1 > v2 - x) {
-        return v2;
-    }
-
-    return v1;
-}
-
-float normalizeAperture(float a) {
-    for(int i = 0; i < AP_NUM; i++) {
-        float a1 = aperture_numbers[i];
-        float a2 = aperture_numbers[i + 1];
-
-        if(a1 < a && a2 >= a) {
-            return getMinDistance(a, a1, a2);
-        }
-    }
-
-    return 0;
-}
-
-float normalizeTime(float a) {
-    for(int i = 0; i < SPEED_NUM; i++) {
-        float a1 = speed_numbers[i];
-        float a2 = speed_numbers[i + 1];
-
-        if(a1 < a && a2 >= a) {
-            return getMinDistance(a, a1, a2);
-        }
-    }
-
-    return 0;
-}

+ 0 - 11
non_catalog_apps/lightmeter/lightmeter_helper.h

@@ -1,11 +0,0 @@
-#pragma once
-
-#include <math.h>
-
-float lux2ev(float lux);
-
-float getMinDistance(float x, float v1, float v2);
-
-float normalizeAperture(float a);
-
-float normalizeTime(float a);

+ 0 - 26
non_catalog_apps/mousejacker/application.fam

@@ -1,26 +0,0 @@
-App(
-    appid="nrf24_mouse_jacker",
-    name="[NRF24] Mouse Jacker",
-    apptype=FlipperAppType.EXTERNAL,
-    entry_point="mousejacker_app",
-    requires=[
-        "gui",
-        "dialogs",
-    ],
-    stack_size=2 * 1024,
-    order=60,
-    fap_icon="mouse_10px.png",
-    fap_category="GPIO",
-    fap_author="@mothball187 & @xMasterX",
-    fap_version="1.0",
-    fap_description="App works with NRF24 Sniffer app to perform mousejack attacks",
-    fap_icon_assets="images",
-    fap_private_libs=[
-        Lib(
-            name="nrf24",
-            sources=[
-                "nrf24.c",
-            ],
-        ),
-    ],
-)

BIN
non_catalog_apps/mousejacker/images/badusb_10px.png


BIN
non_catalog_apps/mousejacker/images/sub1_10px.png


+ 0 - 520
non_catalog_apps/mousejacker/lib/nrf24/nrf24.c

@@ -1,520 +0,0 @@
-#include "nrf24.h"
-#include <furi.h>
-#include <furi_hal.h>
-#include <furi_hal_resources.h>
-#include <assert.h>
-#include <string.h>
-
-void nrf24_init() {
-    furi_hal_spi_bus_handle_init(nrf24_HANDLE);
-    furi_hal_spi_acquire(nrf24_HANDLE);
-    furi_hal_gpio_init(nrf24_CE_PIN, GpioModeOutputPushPull, GpioPullUp, GpioSpeedVeryHigh);
-    furi_hal_gpio_write(nrf24_CE_PIN, false);
-}
-
-void nrf24_deinit() {
-    furi_hal_spi_release(nrf24_HANDLE);
-    furi_hal_spi_bus_handle_deinit(nrf24_HANDLE);
-    furi_hal_gpio_write(nrf24_CE_PIN, false);
-    furi_hal_gpio_init(nrf24_CE_PIN, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
-}
-
-void nrf24_spi_trx(
-    FuriHalSpiBusHandle* handle,
-    uint8_t* tx,
-    uint8_t* rx,
-    uint8_t size,
-    uint32_t timeout) {
-    UNUSED(timeout);
-    furi_hal_gpio_write(handle->cs, false);
-    furi_hal_spi_bus_trx(handle, tx, rx, size, nrf24_TIMEOUT);
-    furi_hal_gpio_write(handle->cs, true);
-}
-
-uint8_t nrf24_write_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t data) {
-    uint8_t tx[2] = {W_REGISTER | (REGISTER_MASK & reg), data};
-    uint8_t rx[2] = {0};
-    nrf24_spi_trx(handle, tx, rx, 2, nrf24_TIMEOUT);
-    return rx[0];
-}
-
-uint8_t
-    nrf24_write_buf_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t* data, uint8_t size) {
-    uint8_t tx[size + 1];
-    uint8_t rx[size + 1];
-    memset(rx, 0, size + 1);
-    tx[0] = W_REGISTER | (REGISTER_MASK & reg);
-    memcpy(&tx[1], data, size);
-    nrf24_spi_trx(handle, tx, rx, size + 1, nrf24_TIMEOUT);
-    return rx[0];
-}
-
-uint8_t nrf24_read_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t* data, uint8_t size) {
-    uint8_t tx[size + 1];
-    uint8_t rx[size + 1];
-    memset(rx, 0, size + 1);
-    tx[0] = R_REGISTER | (REGISTER_MASK & reg);
-    memset(&tx[1], 0, size);
-    nrf24_spi_trx(handle, tx, rx, size + 1, nrf24_TIMEOUT);
-    memcpy(data, &rx[1], size);
-    return rx[0];
-}
-
-uint8_t nrf24_flush_rx(FuriHalSpiBusHandle* handle) {
-    uint8_t tx[] = {FLUSH_RX};
-    uint8_t rx[] = {0};
-    nrf24_spi_trx(handle, tx, rx, 1, nrf24_TIMEOUT);
-    return rx[0];
-}
-
-uint8_t nrf24_flush_tx(FuriHalSpiBusHandle* handle) {
-    uint8_t tx[] = {FLUSH_TX};
-    uint8_t rx[] = {0};
-    nrf24_spi_trx(handle, tx, rx, 1, nrf24_TIMEOUT);
-    return rx[0];
-}
-
-uint8_t nrf24_get_maclen(FuriHalSpiBusHandle* handle) {
-    uint8_t maclen;
-    nrf24_read_reg(handle, REG_SETUP_AW, &maclen, 1);
-    maclen &= 3;
-    return maclen + 2;
-}
-
-uint8_t nrf24_set_maclen(FuriHalSpiBusHandle* handle, uint8_t maclen) {
-    assert(maclen > 1 && maclen < 6);
-    uint8_t status = 0;
-    status = nrf24_write_reg(handle, REG_SETUP_AW, maclen - 2);
-    return status;
-}
-
-uint8_t nrf24_status(FuriHalSpiBusHandle* handle) {
-    uint8_t status;
-    uint8_t tx[] = {R_REGISTER | (REGISTER_MASK & REG_STATUS)};
-    nrf24_spi_trx(handle, tx, &status, 1, nrf24_TIMEOUT);
-    return status;
-}
-
-uint32_t nrf24_get_rate(FuriHalSpiBusHandle* handle) {
-    uint8_t setup = 0;
-    uint32_t rate = 0;
-    nrf24_read_reg(handle, REG_RF_SETUP, &setup, 1);
-    setup &= 0x28;
-    if(setup == 0x20)
-        rate = 250000; // 250kbps
-    else if(setup == 0x08)
-        rate = 2000000; // 2Mbps
-    else if(setup == 0x00)
-        rate = 1000000; // 1Mbps
-
-    return rate;
-}
-
-uint8_t nrf24_set_rate(FuriHalSpiBusHandle* handle, uint32_t rate) {
-    uint8_t r6 = 0;
-    uint8_t status = 0;
-    if(!rate) rate = 2000000;
-
-    nrf24_read_reg(handle, REG_RF_SETUP, &r6, 1); // RF_SETUP register
-    r6 = r6 & (~0x28); // Clear rate fields.
-    if(rate == 2000000)
-        r6 = r6 | 0x08;
-    else if(rate == 1000000)
-        r6 = r6;
-    else if(rate == 250000)
-        r6 = r6 | 0x20;
-
-    status = nrf24_write_reg(handle, REG_RF_SETUP, r6); // Write new rate.
-    return status;
-}
-
-uint8_t nrf24_get_chan(FuriHalSpiBusHandle* handle) {
-    uint8_t channel = 0;
-    nrf24_read_reg(handle, REG_RF_CH, &channel, 1);
-    return channel;
-}
-
-uint8_t nrf24_set_chan(FuriHalSpiBusHandle* handle, uint8_t chan) {
-    uint8_t status;
-    status = nrf24_write_reg(handle, REG_RF_CH, chan);
-    return status;
-}
-
-uint8_t nrf24_get_src_mac(FuriHalSpiBusHandle* handle, uint8_t* mac) {
-    uint8_t size = 0;
-    uint8_t status = 0;
-    size = nrf24_get_maclen(handle);
-    status = nrf24_read_reg(handle, REG_RX_ADDR_P0, mac, size);
-    return status;
-}
-
-uint8_t nrf24_set_src_mac(FuriHalSpiBusHandle* handle, uint8_t* mac, uint8_t size) {
-    uint8_t status = 0;
-    uint8_t clearmac[] = {0, 0, 0, 0, 0};
-    nrf24_set_maclen(handle, size);
-    nrf24_write_buf_reg(handle, REG_RX_ADDR_P0, clearmac, 5);
-    status = nrf24_write_buf_reg(handle, REG_RX_ADDR_P0, mac, size);
-    return status;
-}
-
-uint8_t nrf24_get_dst_mac(FuriHalSpiBusHandle* handle, uint8_t* mac) {
-    uint8_t size = 0;
-    uint8_t status = 0;
-    size = nrf24_get_maclen(handle);
-    status = nrf24_read_reg(handle, REG_TX_ADDR, mac, size);
-    return status;
-}
-
-uint8_t nrf24_set_dst_mac(FuriHalSpiBusHandle* handle, uint8_t* mac, uint8_t size) {
-    uint8_t status = 0;
-    uint8_t clearmac[] = {0, 0, 0, 0, 0};
-    nrf24_set_maclen(handle, size);
-    nrf24_write_buf_reg(handle, REG_TX_ADDR, clearmac, 5);
-    status = nrf24_write_buf_reg(handle, REG_TX_ADDR, mac, size);
-    return status;
-}
-
-uint8_t nrf24_get_packetlen(FuriHalSpiBusHandle* handle) {
-    uint8_t len = 0;
-    nrf24_read_reg(handle, RX_PW_P0, &len, 1);
-    return len;
-}
-
-uint8_t nrf24_set_packetlen(FuriHalSpiBusHandle* handle, uint8_t len) {
-    uint8_t status = 0;
-    status = nrf24_write_reg(handle, RX_PW_P0, len);
-    return status;
-}
-
-uint8_t
-    nrf24_rxpacket(FuriHalSpiBusHandle* handle, uint8_t* packet, uint8_t* packetsize, bool full) {
-    uint8_t status = 0;
-    uint8_t size = 0;
-    uint8_t tx_pl_wid[] = {R_RX_PL_WID, 0};
-    uint8_t rx_pl_wid[] = {0, 0};
-    uint8_t tx_cmd[33] = {0}; // 32 max payload size + 1 for command
-    uint8_t tmp_packet[33] = {0};
-
-    status = nrf24_status(handle);
-
-    if(status & 0x40) {
-        if(full)
-            size = nrf24_get_packetlen(handle);
-        else {
-            nrf24_spi_trx(handle, tx_pl_wid, rx_pl_wid, 2, nrf24_TIMEOUT);
-            size = rx_pl_wid[1];
-        }
-
-        tx_cmd[0] = R_RX_PAYLOAD;
-        nrf24_spi_trx(handle, tx_cmd, tmp_packet, size + 1, nrf24_TIMEOUT);
-        nrf24_write_reg(handle, REG_STATUS, 0x40); // clear bit.
-        memcpy(packet, &tmp_packet[1], size);
-    } else if(status == 0) {
-        nrf24_flush_rx(handle);
-        nrf24_write_reg(handle, REG_STATUS, 0x40); // clear bit.
-    }
-
-    *packetsize = size;
-    return status;
-}
-
-uint8_t nrf24_txpacket(FuriHalSpiBusHandle* handle, uint8_t* payload, uint8_t size, bool ack) {
-    uint8_t status = 0;
-    uint8_t tx[size + 1];
-    uint8_t rx[size + 1];
-    memset(tx, 0, size + 1);
-    memset(rx, 0, size + 1);
-
-    if(!ack)
-        tx[0] = W_TX_PAYLOAD_NOACK;
-    else
-        tx[0] = W_TX_PAYLOAD;
-
-    memcpy(&tx[1], payload, size);
-    nrf24_spi_trx(handle, tx, rx, size + 1, nrf24_TIMEOUT);
-    nrf24_set_tx_mode(handle);
-
-    while(!(status & (TX_DS | MAX_RT))) status = nrf24_status(handle);
-
-    if(status & MAX_RT) nrf24_flush_tx(handle);
-
-    nrf24_set_idle(handle);
-    nrf24_write_reg(handle, REG_STATUS, TX_DS | MAX_RT);
-    return status & TX_DS;
-}
-
-uint8_t nrf24_power_up(FuriHalSpiBusHandle* handle) {
-    uint8_t status = 0;
-    uint8_t cfg = 0;
-    nrf24_read_reg(handle, REG_CONFIG, &cfg, 1);
-    cfg = cfg | 2;
-    status = nrf24_write_reg(handle, REG_CONFIG, cfg);
-    furi_delay_ms(5000);
-    return status;
-}
-
-uint8_t nrf24_set_idle(FuriHalSpiBusHandle* handle) {
-    uint8_t status = 0;
-    uint8_t cfg = 0;
-    nrf24_read_reg(handle, REG_CONFIG, &cfg, 1);
-    cfg &= 0xfc; // clear bottom two bits to power down the radio
-    status = nrf24_write_reg(handle, REG_CONFIG, cfg);
-    //nr204_write_reg(handle, REG_EN_RXADDR, 0x0);
-    furi_hal_gpio_write(nrf24_CE_PIN, false);
-    return status;
-}
-
-uint8_t nrf24_set_rx_mode(FuriHalSpiBusHandle* handle) {
-    uint8_t status = 0;
-    uint8_t cfg = 0;
-    //status = nrf24_write_reg(handle, REG_CONFIG, 0x0F); // enable 2-byte CRC, PWR_UP, and PRIM_RX
-    nrf24_read_reg(handle, REG_CONFIG, &cfg, 1);
-    cfg |= 0x03; // PWR_UP, and PRIM_RX
-    status = nrf24_write_reg(handle, REG_CONFIG, cfg);
-    //nr204_write_reg(REG_EN_RXADDR, 0x03) // Set RX Pipe 0 and 1
-    furi_hal_gpio_write(nrf24_CE_PIN, true);
-    furi_delay_ms(2000);
-    return status;
-}
-
-uint8_t nrf24_set_tx_mode(FuriHalSpiBusHandle* handle) {
-    uint8_t status = 0;
-    uint8_t cfg = 0;
-    furi_hal_gpio_write(nrf24_CE_PIN, false);
-    nrf24_write_reg(handle, REG_STATUS, 0x30);
-    //status = nrf24_write_reg(handle, REG_CONFIG, 0x0E); // enable 2-byte CRC, PWR_UP
-    nrf24_read_reg(handle, REG_CONFIG, &cfg, 1);
-    cfg &= 0xfe; // disable PRIM_RX
-    cfg |= 0x02; // PWR_UP
-    status = nrf24_write_reg(handle, REG_CONFIG, cfg);
-    furi_hal_gpio_write(nrf24_CE_PIN, true);
-    furi_delay_ms(2);
-    return status;
-}
-
-void nrf24_configure(
-    FuriHalSpiBusHandle* handle,
-    uint8_t rate,
-    uint8_t* srcmac,
-    uint8_t* dstmac,
-    uint8_t maclen,
-    uint8_t channel,
-    bool noack,
-    bool disable_aa) {
-    assert(channel <= 125);
-    assert(rate == 1 || rate == 2);
-    if(rate == 2)
-        rate = 8; // 2Mbps
-    else
-        rate = 0; // 1Mbps
-
-    nrf24_write_reg(handle, REG_CONFIG, 0x00); // Stop nRF
-    nrf24_set_idle(handle);
-    nrf24_write_reg(handle, REG_STATUS, 0x1c); // clear interrupts
-    if(disable_aa)
-        nrf24_write_reg(handle, REG_EN_AA, 0x00); // Disable Shockburst
-    else
-        nrf24_write_reg(handle, REG_EN_AA, 0x1F); // Enable Shockburst
-
-    nrf24_write_reg(handle, REG_DYNPD, 0x3F); // enable dynamic payload length on all pipes
-    if(noack)
-        nrf24_write_reg(handle, REG_FEATURE, 0x05); // disable payload-with-ack, enable noack
-    else {
-        nrf24_write_reg(handle, REG_CONFIG, 0x0C); // 2 byte CRC
-        nrf24_write_reg(handle, REG_FEATURE, 0x07); // enable dyn payload and ack
-        nrf24_write_reg(
-            handle, REG_SETUP_RETR, 0x1f); // 15 retries for AA, 500us auto retransmit delay
-    }
-
-    nrf24_set_idle(handle);
-    nrf24_flush_rx(handle);
-    nrf24_flush_tx(handle);
-
-    if(maclen) nrf24_set_maclen(handle, maclen);
-    if(srcmac) nrf24_set_src_mac(handle, srcmac, maclen);
-    if(dstmac) nrf24_set_dst_mac(handle, dstmac, maclen);
-
-    nrf24_write_reg(handle, REG_RF_CH, channel);
-    nrf24_write_reg(handle, REG_RF_SETUP, rate);
-    furi_delay_ms(200);
-}
-
-void nrf24_init_promisc_mode(FuriHalSpiBusHandle* handle, uint8_t channel, uint8_t rate) {
-    //uint8_t preamble[] = {0x55, 0x00}; // little endian
-    uint8_t preamble[] = {0xAA, 0x00}; // little endian
-    //uint8_t preamble[] = {0x00, 0x55}; // little endian
-    //uint8_t preamble[] = {0x00, 0xAA}; // little endian
-    nrf24_write_reg(handle, REG_CONFIG, 0x00); // Stop nRF
-    nrf24_write_reg(handle, REG_STATUS, 0x1c); // clear interrupts
-    nrf24_write_reg(handle, REG_DYNPD, 0x0); // disable shockburst
-    nrf24_write_reg(handle, REG_EN_AA, 0x00); // Disable Shockburst
-    nrf24_write_reg(handle, REG_FEATURE, 0x05); // disable payload-with-ack, enable noack
-    nrf24_set_maclen(handle, 2); // shortest address
-    nrf24_set_src_mac(handle, preamble, 2); // set src mac to preamble bits to catch everything
-    nrf24_set_packetlen(handle, 32); // set max packet length
-    nrf24_set_idle(handle);
-    nrf24_flush_rx(handle);
-    nrf24_flush_tx(handle);
-    nrf24_write_reg(handle, REG_RF_CH, channel);
-    nrf24_write_reg(handle, REG_RF_SETUP, rate);
-
-    // prime for RX, no checksum
-    nrf24_write_reg(handle, REG_CONFIG, 0x03); // PWR_UP and PRIM_RX, disable AA and CRC
-    furi_hal_gpio_write(nrf24_CE_PIN, true);
-    furi_delay_ms(100);
-}
-
-void hexlify(uint8_t* in, uint8_t size, char* out) {
-    memset(out, 0, size * 2);
-    for(int i = 0; i < size; i++)
-        snprintf(out + strlen(out), sizeof(out + strlen(out)), "%02X", in[i]);
-}
-
-uint64_t bytes_to_int64(uint8_t* bytes, uint8_t size, bool bigendian) {
-    uint64_t ret = 0;
-    for(int i = 0; i < size; i++)
-        if(bigendian)
-            ret |= bytes[i] << ((size - 1 - i) * 8);
-        else
-            ret |= bytes[i] << (i * 8);
-
-    return ret;
-}
-
-void int64_to_bytes(uint64_t val, uint8_t* out, bool bigendian) {
-    for(int i = 0; i < 8; i++) {
-        if(bigendian)
-            out[i] = (val >> ((7 - i) * 8)) & 0xff;
-        else
-            out[i] = (val >> (i * 8)) & 0xff;
-    }
-}
-
-uint32_t bytes_to_int32(uint8_t* bytes, bool bigendian) {
-    uint32_t ret = 0;
-    for(int i = 0; i < 4; i++)
-        if(bigendian)
-            ret |= bytes[i] << ((3 - i) * 8);
-        else
-            ret |= bytes[i] << (i * 8);
-
-    return ret;
-}
-
-void int32_to_bytes(uint32_t val, uint8_t* out, bool bigendian) {
-    for(int i = 0; i < 4; i++) {
-        if(bigendian)
-            out[i] = (val >> ((3 - i) * 8)) & 0xff;
-        else
-            out[i] = (val >> (i * 8)) & 0xff;
-    }
-}
-
-uint64_t bytes_to_int16(uint8_t* bytes, bool bigendian) {
-    uint16_t ret = 0;
-    for(int i = 0; i < 2; i++)
-        if(bigendian)
-            ret |= bytes[i] << ((1 - i) * 8);
-        else
-            ret |= bytes[i] << (i * 8);
-
-    return ret;
-}
-
-void int16_to_bytes(uint16_t val, uint8_t* out, bool bigendian) {
-    for(int i = 0; i < 2; i++) {
-        if(bigendian)
-            out[i] = (val >> ((1 - i) * 8)) & 0xff;
-        else
-            out[i] = (val >> (i * 8)) & 0xff;
-    }
-}
-
-// handle iffyness with preamble processing sometimes being a bit (literally) off
-void alt_address_old(uint8_t* packet, uint8_t* altaddr) {
-    uint8_t macmess_hi_b[4];
-    uint8_t macmess_lo_b[2];
-    uint32_t macmess_hi;
-    uint16_t macmess_lo;
-    uint8_t preserved;
-
-    // get first 6 bytes into 32-bit and 16-bit variables
-    memcpy(macmess_hi_b, packet, 4);
-    memcpy(macmess_lo_b, packet + 4, 2);
-
-    macmess_hi = bytes_to_int32(macmess_hi_b, true);
-
-    //preserve least 7 bits from hi that will be shifted down to lo
-    preserved = macmess_hi & 0x7f;
-    macmess_hi >>= 7;
-
-    macmess_lo = bytes_to_int16(macmess_lo_b, true);
-    macmess_lo >>= 7;
-    macmess_lo = (preserved << 9) | macmess_lo;
-    int32_to_bytes(macmess_hi, macmess_hi_b, true);
-    int16_to_bytes(macmess_lo, macmess_lo_b, true);
-    memcpy(altaddr, &macmess_hi_b[1], 3);
-    memcpy(altaddr + 3, macmess_lo_b, 2);
-}
-
-bool validate_address(uint8_t* addr) {
-    uint8_t bad[][3] = {{0x55, 0x55}, {0xAA, 0xAA}, {0x00, 0x00}, {0xFF, 0xFF}};
-    for(int i = 0; i < 4; i++)
-        for(int j = 0; j < 2; j++)
-            if(!memcmp(addr + j * 2, bad[i], 2)) return false;
-
-    return true;
-}
-
-bool nrf24_sniff_address(FuriHalSpiBusHandle* handle, uint8_t maclen, uint8_t* address) {
-    bool found = false;
-    uint8_t packet[32] = {0};
-    uint8_t packetsize;
-    //char printit[65];
-    uint8_t status = 0;
-    status = nrf24_rxpacket(handle, packet, &packetsize, true);
-    if(status & 0x40) {
-        if(validate_address(packet)) {
-            for(int i = 0; i < maclen; i++) address[i] = packet[maclen - 1 - i];
-
-            /*
-            alt_address(packet, packet);
-
-            for(i = 0; i < maclen; i++)
-                address[i + 5] = packet[maclen - 1 - i];
-            */
-
-            //memcpy(address, packet, maclen);
-            //hexlify(packet, packetsize, printit);
-            found = true;
-        }
-    }
-
-    return found;
-}
-
-uint8_t nrf24_find_channel(
-    FuriHalSpiBusHandle* handle,
-    uint8_t* srcmac,
-    uint8_t* dstmac,
-    uint8_t maclen,
-    uint8_t rate,
-    uint8_t min_channel,
-    uint8_t max_channel,
-    bool autoinit) {
-    uint8_t ping_packet[] = {0x0f, 0x0f, 0x0f, 0x0f}; // this can be anything, we just need an ack
-    uint8_t ch = max_channel + 1; // means fail
-    nrf24_configure(handle, rate, srcmac, dstmac, maclen, 2, false, false);
-    for(ch = min_channel; ch <= max_channel + 1; ch++) {
-        nrf24_write_reg(handle, REG_RF_CH, ch);
-        if(nrf24_txpacket(handle, ping_packet, 4, true)) break;
-    }
-
-    if(autoinit) {
-        FURI_LOG_D("nrf24", "initializing radio for channel %d", ch);
-        nrf24_configure(handle, rate, srcmac, dstmac, maclen, ch, false, false);
-        return ch;
-    }
-
-    return ch;
-}

+ 0 - 366
non_catalog_apps/mousejacker/lib/nrf24/nrf24.h

@@ -1,366 +0,0 @@
-#pragma once
-#include <stdbool.h>
-#include <stdint.h>
-#include <furi_hal_spi.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define R_REGISTER 0x00
-#define W_REGISTER 0x20
-#define REGISTER_MASK 0x1F
-#define ACTIVATE 0x50
-#define R_RX_PL_WID 0x60
-#define R_RX_PAYLOAD 0x61
-#define W_TX_PAYLOAD 0xA0
-#define W_TX_PAYLOAD_NOACK 0xB0
-#define W_ACK_PAYLOAD 0xA8
-#define FLUSH_TX 0xE1
-#define FLUSH_RX 0xE2
-#define REUSE_TX_PL 0xE3
-#define RF24_NOP 0xFF
-
-#define REG_CONFIG 0x00
-#define REG_EN_AA 0x01
-#define REG_EN_RXADDR 0x02
-#define REG_SETUP_AW 0x03
-#define REG_SETUP_RETR 0x04
-#define REG_DYNPD 0x1C
-#define REG_FEATURE 0x1D
-#define REG_RF_SETUP 0x06
-#define REG_STATUS 0x07
-#define REG_RX_ADDR_P0 0x0A
-#define REG_RF_CH 0x05
-#define REG_TX_ADDR 0x10
-
-#define RX_PW_P0 0x11
-#define TX_DS 0x20
-#define MAX_RT 0x10
-
-#define nrf24_TIMEOUT 500
-#define nrf24_CE_PIN &gpio_ext_pb2
-#define nrf24_HANDLE &furi_hal_spi_bus_handle_external
-
-/* Low level API */
-
-/** Write device register
- *
- * @param      handle  - pointer to FuriHalSpiHandle
- * @param      reg     - register
- * @param      data    - data to write
- *
- * @return     device status
- */
-uint8_t nrf24_write_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t data);
-
-/** Write buffer to device register
- *
- * @param      handle  - pointer to FuriHalSpiHandle
- * @param      reg     - register
- * @param      data    - data to write
- * @param      size    - size of data to write
- *
- * @return     device status
- */
-uint8_t nrf24_write_buf_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t* data, uint8_t size);
-
-/** Read device register
- *
- * @param      handle  - pointer to FuriHalSpiHandle
- * @param      reg     - register
- * @param[out] data    - pointer to data
- *
- * @return     device status
- */
-uint8_t nrf24_read_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t* data, uint8_t size);
-
-/** Power up the radio for operation
- * 
- * @param      handle  - pointer to FuriHalSpiHandle
- * 
- * @return     device status
- */
-uint8_t nrf24_power_up(FuriHalSpiBusHandle* handle);
-
-/** Power down the radio
- * 
- * @param      handle  - pointer to FuriHalSpiHandle
- * 
- * @return     device status
- */
-uint8_t nrf24_set_idle(FuriHalSpiBusHandle* handle);
-
-/** Sets the radio to RX mode
- *
- * @param      handle  - pointer to FuriHalSpiHandle
- * 
- * @return     device status
- */
-uint8_t nrf24_set_rx_mode(FuriHalSpiBusHandle* handle);
-
-/** Sets the radio to TX mode
- *
- * @param      handle  - pointer to FuriHalSpiHandle
- * 
- * @return     device status
- */
-uint8_t nrf24_set_tx_mode(FuriHalSpiBusHandle* handle);
-
-/*=============================================================================================================*/
-
-/* High level API */
-
-/** Must call this before using any other nrf24 API
- * 
- */
-void nrf24_init();
-
-/** Must call this when we end using nrf24 device
- * 
- */
-void nrf24_deinit();
-
-/** Send flush rx command
- *
- * @param      handle  - pointer to FuriHalSpiHandle
- *
- * @return     device status
- */
-uint8_t nrf24_flush_rx(FuriHalSpiBusHandle* handle);
-
-/** Send flush tx command
- *
- * @param      handle  - pointer to FuriHalSpiHandle
- *
- * @return     device status
- */
-uint8_t nrf24_flush_tx(FuriHalSpiBusHandle* handle);
-
-/** Gets the RX packet length in data pipe 0
- * 
- * @param      handle  - pointer to FuriHalSpiHandle
- * 
- * @return     packet length in data pipe 0
- */
-uint8_t nrf24_get_packetlen(FuriHalSpiBusHandle* handle);
-
-/** Sets the RX packet length in data pipe 0
- * 
- * @param      handle  - pointer to FuriHalSpiHandle
- * @param      len - length to set
- * 
- * @return     device status
- */
-uint8_t nrf24_set_packetlen(FuriHalSpiBusHandle* handle, uint8_t len);
-
-/** Gets configured length of MAC address
- *
- * @param      handle  - pointer to FuriHalSpiHandle
- * 
- * @return     MAC address length
- */
-uint8_t nrf24_get_maclen(FuriHalSpiBusHandle* handle);
-
-/** Sets configured length of MAC address
- *
- * @param      handle  - pointer to FuriHalSpiHandle
- * @param      maclen - length to set MAC address to, must be greater than 1 and less than 6
- * 
- * @return     MAC address length
- */
-uint8_t nrf24_set_maclen(FuriHalSpiBusHandle* handle, uint8_t maclen);
-
-/** Gets the current status flags from the STATUS register
- * 
- * @param      handle  - pointer to FuriHalSpiHandle
- * 
- * @return     status flags
- */
-uint8_t nrf24_status(FuriHalSpiBusHandle* handle);
-
-/** Gets the current transfer rate
- * 
- * @param      handle  - pointer to FuriHalSpiHandle
- * 
- * @return     transfer rate in bps
- */
-uint32_t nrf24_get_rate(FuriHalSpiBusHandle* handle);
-
-/** Sets the transfer rate
- *
- * @param      handle  - pointer to FuriHalSpiHandle
- * @param      rate - the transfer rate in bps
- * 
- * @return     device status
- */
-uint8_t nrf24_set_rate(FuriHalSpiBusHandle* handle, uint32_t rate);
-
-/** Gets the current channel
- * In nrf24, the channel number is multiplied times 1MHz and added to 2400MHz to get the frequency
- * 
- * @param      handle  - pointer to FuriHalSpiHandle
- * 
- * @return     channel
- */
-uint8_t nrf24_get_chan(FuriHalSpiBusHandle* handle);
-
-/** Sets the channel
- *
- * @param      handle  - pointer to FuriHalSpiHandle
- * @param      frequency - the frequency in hertz
- * 
- * @return     device status
- */
-uint8_t nrf24_set_chan(FuriHalSpiBusHandle* handle, uint8_t chan);
-
-/** Gets the source mac address
- *
- * @param      handle  - pointer to FuriHalSpiHandle
- * @param[out] mac - the source mac address
- * 
- * @return     device status
- */
-uint8_t nrf24_get_src_mac(FuriHalSpiBusHandle* handle, uint8_t* mac);
-
-/** Sets the source mac address
- *
- * @param      handle  - pointer to FuriHalSpiHandle
- * @param      mac - the mac address to set
- * @param      size - the size of the mac address (2 to 5)
- * 
- * @return     device status
- */
-uint8_t nrf24_set_src_mac(FuriHalSpiBusHandle* handle, uint8_t* mac, uint8_t size);
-
-/** Gets the dest mac address
- *
- * @param      handle  - pointer to FuriHalSpiHandle
- * @param[out] mac - the source mac address
- * 
- * @return     device status
- */
-uint8_t nrf24_get_dst_mac(FuriHalSpiBusHandle* handle, uint8_t* mac);
-
-/** Sets the dest mac address
- *
- * @param      handle  - pointer to FuriHalSpiHandle
- * @param      mac - the mac address to set
- * @param      size - the size of the mac address (2 to 5)
- * 
- * @return     device status
- */
-uint8_t nrf24_set_dst_mac(FuriHalSpiBusHandle* handle, uint8_t* mac, uint8_t size);
-
-/** Reads RX packet
- *
- * @param      handle  - pointer to FuriHalSpiHandle
- * @param[out] packet - the packet contents
- * @param[out] packetsize - size of the received packet
- * @param      full - boolean set to true, packet length is determined by RX_PW_P0 register, false it is determined by dynamic payload length command
- * 
- * @return     device status
- */
-uint8_t
-    nrf24_rxpacket(FuriHalSpiBusHandle* handle, uint8_t* packet, uint8_t* packetsize, bool full);
-
-/** Sends TX packet
- *
- * @param      handle  - pointer to FuriHalSpiHandle
- * @param      packet - the packet contents
- * @param      size - packet size
- * @param      ack - boolean to determine whether an ACK is required for the packet or not
- * 
- * @return     device status
- */
-uint8_t nrf24_txpacket(FuriHalSpiBusHandle* handle, uint8_t* payload, uint8_t size, bool ack);
-
-/** Configure the radio
- * This is not comprehensive, but covers a lot of the common configuration options that may be changed
- * @param      handle  - pointer to FuriHalSpiHandle
- * @param      rate - transfer rate in Mbps (1 or 2)
- * @param      srcmac - source mac address
- * @param      dstmac - destination mac address
- * @param      maclen - length of mac address
- * @param      channel - channel to tune to
- * @param      noack - if true, disable auto-acknowledge
- * @param      disable_aa - if true, disable ShockBurst
- * 
- */
-void nrf24_configure(
-    FuriHalSpiBusHandle* handle,
-    uint8_t rate,
-    uint8_t* srcmac,
-    uint8_t* dstmac,
-    uint8_t maclen,
-    uint8_t channel,
-    bool noack,
-    bool disable_aa);
-
-/** Configures the radio for "promiscuous mode" and primes it for rx
- * This is not an actual mode of the nrf24, but this function exploits a few bugs in the chip that allows it to act as if it were.
- * See http://travisgoodspeed.blogspot.com/2011/02/promiscuity-is-nrf24l01s-duty.html for details.
- * @param      handle  - pointer to FuriHalSpiHandle
- * @param      channel - channel to tune to
- * @param      rate - transfer rate in Mbps (1 or 2) 
- */
-void nrf24_init_promisc_mode(FuriHalSpiBusHandle* handle, uint8_t channel, uint8_t rate);
-
-/** Listens for a packet and returns first possible address sniffed
- * Call this only after calling nrf24_init_promisc_mode
- * @param      handle  - pointer to FuriHalSpiHandle
- * @param      maclen - length of target mac address
- * @param[out] addresses - sniffed address
- * 
- * @return     success
- */
-bool nrf24_sniff_address(FuriHalSpiBusHandle* handle, uint8_t maclen, uint8_t* address);
-
-/** Sends ping packet on each channel for designated tx mac looking for ack
- * 
- * @param      handle  - pointer to FuriHalSpiHandle
- * @param      srcmac - source address
- * @param      dstmac - destination address
- * @param      maclen - length of address
- * @param      rate - transfer rate in Mbps (1 or 2) 
- * @param      min_channel - channel to start with
- * @param      max_channel - channel to end at
- * @param      autoinit - if true, automatically configure radio for this channel
- * 
- * @return     channel that the address is listening on, if this value is above the max_channel param, it failed
- */
-uint8_t nrf24_find_channel(
-    FuriHalSpiBusHandle* handle,
-    uint8_t* srcmac,
-    uint8_t* dstmac,
-    uint8_t maclen,
-    uint8_t rate,
-    uint8_t min_channel,
-    uint8_t max_channel,
-    bool autoinit);
-
-/** Converts 64 bit value into uint8_t array
- * @param      val  - 64-bit integer
- * @param[out] out - bytes out
- * @param      bigendian - if true, convert as big endian, otherwise little endian
- */
-void int64_to_bytes(uint64_t val, uint8_t* out, bool bigendian);
-
-/** Converts 32 bit value into uint8_t array
- * @param      val  - 32-bit integer
- * @param[out] out - bytes out
- * @param      bigendian - if true, convert as big endian, otherwise little endian
- */
-void int32_to_bytes(uint32_t val, uint8_t* out, bool bigendian);
-
-/** Converts uint8_t array into 32 bit value
- * @param      bytes  - uint8_t array
- * @param      bigendian - if true, convert as big endian, otherwise little endian
- * 
- * @return     32-bit value
- */
-uint32_t bytes_to_int32(uint8_t* bytes, bool bigendian);
-
-#ifdef __cplusplus
-}
-#endif

BIN
non_catalog_apps/mousejacker/mouse_10px.png


+ 0 - 398
non_catalog_apps/mousejacker/mousejacker.c

@@ -1,398 +0,0 @@
-#include <furi.h>
-#include <gui/gui.h>
-#include <dialogs/dialogs.h>
-#include <input/input.h>
-#include <stdlib.h>
-#include <furi_hal.h>
-#include <furi_hal_gpio.h>
-#include <furi_hal_spi.h>
-#include <furi_hal_interrupt.h>
-#include <furi_hal_resources.h>
-#include <nrf24.h>
-#include "mousejacker_ducky.h"
-#include <nrf24_mouse_jacker_icons.h>
-
-#define TAG "mousejacker"
-#define LOGITECH_MAX_CHANNEL 85
-#define NRFSNIFF_APP_PATH_FOLDER "/ext/nrfsniff"
-#define NRFSNIFF_APP_PATH_EXTENSION ".txt"
-#define NRFSNIFF_APP_FILENAME "addresses.txt"
-#define MOUSEJACKER_APP_PATH_FOLDER "/ext/mousejacker"
-#define MOUSEJACKER_APP_PATH_EXTENSION ".txt"
-#define MAX_ADDRS 100
-
-typedef enum {
-    EventTypeTick,
-    EventTypeKey,
-} EventType;
-
-typedef struct {
-    EventType type;
-    InputEvent input;
-} PluginEvent;
-
-uint8_t addrs_count = 0;
-uint8_t addr_idx = 0;
-uint8_t loaded_addrs[MAX_ADDRS][6]; // first byte is rate, the rest are the address
-
-char target_fmt_text[] = "Target addr: %s";
-char target_address_str[12] = "None";
-char target_text[30];
-
-static void render_callback(Canvas* const canvas, void* ctx) {
-    furi_assert(ctx);
-    const PluginState* plugin_state = ctx;
-    furi_mutex_acquire(plugin_state->mutex, FuriWaitForever);
-
-    // border around the edge of the screen
-    canvas_draw_frame(canvas, 0, 0, 128, 64);
-
-    canvas_set_font(canvas, FontSecondary);
-    if(!plugin_state->addr_err && !plugin_state->ducky_err && !plugin_state->is_thread_running &&
-       !plugin_state->is_ducky_running) {
-        snprintf(target_text, sizeof(target_text), target_fmt_text, target_address_str);
-        canvas_draw_str_aligned(canvas, 7, 10, AlignLeft, AlignBottom, target_text);
-        canvas_draw_str_aligned(canvas, 22, 20, AlignLeft, AlignBottom, "<- select address ->");
-        canvas_draw_str_aligned(canvas, 10, 30, AlignLeft, AlignBottom, "Press Ok button to ");
-        canvas_draw_str_aligned(canvas, 10, 40, AlignLeft, AlignBottom, "browse for ducky script");
-    } else if(plugin_state->addr_err) {
-        canvas_draw_str_aligned(
-            canvas, 10, 10, AlignLeft, AlignBottom, "Error: No nrfsniff folder");
-        canvas_draw_str_aligned(canvas, 10, 20, AlignLeft, AlignBottom, "or addresses.txt file");
-        canvas_draw_str_aligned(
-            canvas, 10, 30, AlignLeft, AlignBottom, "loading error / empty file");
-        canvas_draw_str_aligned(
-            canvas, 7, 40, AlignLeft, AlignBottom, "Run (NRF24: Sniff) app first!");
-    } else if(plugin_state->ducky_err) {
-        canvas_draw_str_aligned(
-            canvas, 3, 10, AlignLeft, AlignBottom, "Error: No mousejacker folder");
-        canvas_draw_str_aligned(canvas, 3, 20, AlignLeft, AlignBottom, "or duckyscript file");
-        canvas_draw_str_aligned(canvas, 3, 30, AlignLeft, AlignBottom, "loading error");
-    } else if(plugin_state->is_thread_running && !plugin_state->is_ducky_running) {
-        canvas_draw_str_aligned(canvas, 3, 10, AlignLeft, AlignBottom, "Loading...");
-        canvas_draw_str_aligned(canvas, 3, 20, AlignLeft, AlignBottom, "Please wait!");
-    } else if(plugin_state->is_thread_running && plugin_state->is_ducky_running) {
-        canvas_draw_str_aligned(canvas, 3, 10, AlignLeft, AlignBottom, "Running duckyscript");
-        canvas_draw_str_aligned(canvas, 3, 20, AlignLeft, AlignBottom, "Please wait!");
-        canvas_draw_str_aligned(
-            canvas, 3, 30, AlignLeft, AlignBottom, "Press back to exit (if it stuck)");
-    } else {
-        canvas_draw_str_aligned(canvas, 3, 10, AlignLeft, AlignBottom, "Unknown Error");
-        canvas_draw_str_aligned(canvas, 3, 20, AlignLeft, AlignBottom, "press back");
-        canvas_draw_str_aligned(canvas, 3, 30, AlignLeft, AlignBottom, "to exit");
-    }
-
-    furi_mutex_release(plugin_state->mutex);
-}
-
-static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) {
-    furi_assert(event_queue);
-
-    PluginEvent event = {.type = EventTypeKey, .input = *input_event};
-    furi_message_queue_put(event_queue, &event, FuriWaitForever);
-}
-
-static void mousejacker_state_init(PluginState* const plugin_state) {
-    plugin_state->is_thread_running = false;
-}
-
-static void hexlify(uint8_t* in, uint8_t size, char* out) {
-    memset(out, 0, size * 2);
-    for(int i = 0; i < size; i++)
-        snprintf(out + strlen(out), sizeof(out + strlen(out)), "%02X", in[i]);
-}
-
-static bool open_ducky_script(Stream* stream, PluginState* plugin_state) {
-    DialogsApp* dialogs = furi_record_open("dialogs");
-    bool result = false;
-    FuriString* path;
-    path = furi_string_alloc();
-    furi_string_set(path, MOUSEJACKER_APP_PATH_FOLDER);
-
-    DialogsFileBrowserOptions browser_options;
-    dialog_file_browser_set_basic_options(
-        &browser_options, MOUSEJACKER_APP_PATH_EXTENSION, &I_badusb_10px);
-    browser_options.hide_ext = false;
-
-    bool ret = dialog_file_browser_show(dialogs, path, path, &browser_options);
-
-    furi_record_close("dialogs");
-    if(ret) {
-        if(!file_stream_open(stream, furi_string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) {
-            FURI_LOG_D(TAG, "Cannot open file \"%s\"", furi_string_get_cstr(path));
-        } else {
-            result = true;
-        }
-    }
-    furi_string_free(path);
-
-    plugin_state->is_ducky_running = true;
-
-    return result;
-}
-
-static bool open_addrs_file(Stream* stream) {
-    DialogsApp* dialogs = furi_record_open("dialogs");
-    bool result = false;
-    FuriString* path;
-    path = furi_string_alloc();
-    furi_string_set(path, NRFSNIFF_APP_PATH_FOLDER);
-
-    DialogsFileBrowserOptions browser_options;
-    dialog_file_browser_set_basic_options(
-        &browser_options, NRFSNIFF_APP_PATH_EXTENSION, &I_sub1_10px);
-    browser_options.hide_ext = false;
-
-    bool ret = dialog_file_browser_show(dialogs, path, path, &browser_options);
-
-    furi_record_close("dialogs");
-    if(ret) {
-        if(!file_stream_open(stream, furi_string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) {
-            FURI_LOG_D(TAG, "Cannot open file \"%s\"", furi_string_get_cstr(path));
-        } else {
-            result = true;
-        }
-    }
-    furi_string_free(path);
-    return result;
-}
-
-static bool process_ducky_file(
-    Stream* file_stream,
-    uint8_t* addr,
-    uint8_t addr_size,
-    uint8_t rate,
-    PluginState* plugin_state) {
-    size_t file_size = 0;
-    size_t bytes_read = 0;
-    uint8_t* file_buf;
-    bool loaded = false;
-    FURI_LOG_D(TAG, "opening ducky script");
-    if(open_ducky_script(file_stream, plugin_state)) {
-        file_size = stream_size(file_stream);
-        if(file_size == (size_t)0) {
-            FURI_LOG_D(TAG, "load failed. file_size: %d", file_size);
-            plugin_state->is_ducky_running = false;
-            return loaded;
-        }
-        file_buf = malloc(file_size);
-        memset(file_buf, 0, file_size);
-        bytes_read = stream_read(file_stream, file_buf, file_size);
-        if(bytes_read == file_size) {
-            FURI_LOG_D(TAG, "executing ducky script");
-            mj_process_ducky_script(
-                nrf24_HANDLE, addr, addr_size, rate, (char*)file_buf, plugin_state);
-            FURI_LOG_D(TAG, "finished execution");
-            loaded = true;
-        } else {
-            FURI_LOG_D(TAG, "load failed. file size: %d", file_size);
-        }
-        free(file_buf);
-    }
-    plugin_state->is_ducky_running = false;
-    return loaded;
-}
-
-static bool load_addrs_file(Stream* file_stream) {
-    size_t file_size = 0;
-    size_t bytes_read = 0;
-    uint8_t* file_buf;
-    char* line_ptr;
-    uint8_t rate;
-    uint8_t addrlen = 0;
-    uint32_t counter = 0;
-    uint8_t addr[5] = {0};
-    uint32_t i_addr_lo = 0;
-    uint32_t i_addr_hi = 0;
-    bool loaded = false;
-    FURI_LOG_D(TAG, "opening addrs file");
-    addrs_count = 0;
-    if(open_addrs_file(file_stream)) {
-        file_size = stream_size(file_stream);
-        if(file_size == (size_t)0) {
-            FURI_LOG_D(TAG, "load failed. file_size: %d", file_size);
-            return loaded;
-        }
-        file_buf = malloc(file_size);
-        memset(file_buf, 0, file_size);
-        bytes_read = stream_read(file_stream, file_buf, file_size);
-        if(bytes_read == file_size) {
-            FURI_LOG_D(TAG, "loading addrs file");
-            char* line = strtok((char*)file_buf, "\n");
-
-            while(line != NULL) {
-                line_ptr = strstr((char*)line, ",");
-                *line_ptr = 0;
-                rate = atoi(line_ptr + 1);
-                addrlen = (uint8_t)(strlen(line) / 2);
-                i_addr_lo = strtoul(line + 2, NULL, 16);
-                line[2] = (char)0;
-                i_addr_hi = strtoul(line, NULL, 16);
-                int32_to_bytes(i_addr_lo, &addr[1], true);
-                addr[0] = (uint8_t)(i_addr_hi & 0xFF);
-                memset(loaded_addrs[counter], rate, 1);
-                memcpy(&loaded_addrs[counter++][1], addr, addrlen);
-                addrs_count++;
-                line = strtok(NULL, "\n");
-                loaded = true;
-            }
-        } else {
-            FURI_LOG_D(TAG, "load failed. file size: %d", file_size);
-        }
-        free(file_buf);
-    }
-    return loaded;
-}
-
-// entrypoint for worker
-static int32_t mj_worker_thread(void* ctx) {
-    PluginState* plugin_state = ctx;
-    bool ducky_ok = false;
-    if(!plugin_state->addr_err) {
-        plugin_state->is_thread_running = true;
-        plugin_state->file_stream = file_stream_alloc(plugin_state->storage);
-        nrf24_find_channel(
-            nrf24_HANDLE,
-            loaded_addrs[addr_idx] + 1,
-            loaded_addrs[addr_idx] + 1,
-            5,
-            loaded_addrs[addr_idx][0],
-            2,
-            LOGITECH_MAX_CHANNEL,
-            true);
-        ducky_ok = process_ducky_file(
-            plugin_state->file_stream,
-            loaded_addrs[addr_idx] + 1,
-            5,
-            loaded_addrs[addr_idx][0],
-            plugin_state);
-        if(!ducky_ok) {
-            plugin_state->ducky_err = true;
-        } else {
-            plugin_state->ducky_err = false;
-        }
-        stream_free(plugin_state->file_stream);
-    }
-    plugin_state->is_thread_running = false;
-    return 0;
-}
-
-void start_mjthread(PluginState* plugin_state) {
-    if(!plugin_state->is_thread_running) {
-        furi_thread_start(plugin_state->mjthread);
-    }
-}
-
-int32_t mousejacker_app(void* p) {
-    UNUSED(p);
-    FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(PluginEvent));
-
-    PluginState* plugin_state = malloc(sizeof(PluginState));
-    mousejacker_state_init(plugin_state);
-    plugin_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
-    if(!plugin_state->mutex) {
-        FURI_LOG_E("mousejacker", "cannot create mutex\r\n");
-        furi_message_queue_free(event_queue);
-        free(plugin_state);
-        return 255;
-    }
-
-    // Set system callbacks
-    ViewPort* view_port = view_port_alloc();
-    view_port_draw_callback_set(view_port, render_callback, plugin_state);
-    view_port_input_callback_set(view_port, input_callback, event_queue);
-
-    // Open GUI and register view_port
-    Gui* gui = furi_record_open(RECORD_GUI);
-    gui_add_view_port(gui, view_port, GuiLayerFullscreen);
-
-    plugin_state->storage = furi_record_open(RECORD_STORAGE);
-    storage_common_mkdir(plugin_state->storage, MOUSEJACKER_APP_PATH_FOLDER);
-    plugin_state->file_stream = file_stream_alloc(plugin_state->storage);
-
-    plugin_state->mjthread = furi_thread_alloc();
-    furi_thread_set_name(plugin_state->mjthread, "MJ Worker");
-    furi_thread_set_stack_size(plugin_state->mjthread, 2048);
-    furi_thread_set_context(plugin_state->mjthread, plugin_state);
-    furi_thread_set_callback(plugin_state->mjthread, mj_worker_thread);
-
-    // spawn load file dialog to choose sniffed addresses file
-    if(load_addrs_file(plugin_state->file_stream)) {
-        addr_idx = 0;
-        hexlify(&loaded_addrs[addr_idx][1], 5, target_address_str);
-        plugin_state->addr_err = false;
-    } else {
-        plugin_state->addr_err = true;
-    }
-    stream_free(plugin_state->file_stream);
-    nrf24_init();
-
-    PluginEvent event;
-    for(bool processing = true; processing;) {
-        FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);
-        furi_mutex_acquire(plugin_state->mutex, FuriWaitForever);
-
-        if(event_status == FuriStatusOk) {
-            // press events
-            if(event.type == EventTypeKey) {
-                if(event.input.type == InputTypePress) {
-                    switch(event.input.key) {
-                    case InputKeyUp:
-                        break;
-                    case InputKeyDown:
-                        break;
-                    case InputKeyRight:
-                        if(!plugin_state->addr_err) {
-                            addr_idx++;
-                            if(addr_idx > addrs_count) addr_idx = 0;
-                            hexlify(loaded_addrs[addr_idx] + 1, 5, target_address_str);
-                        }
-                        break;
-                    case InputKeyLeft:
-                        if(!plugin_state->addr_err) {
-                            addr_idx--;
-                            if(addr_idx == 0) addr_idx = addrs_count - 1;
-                            hexlify(loaded_addrs[addr_idx] + 1, 5, target_address_str);
-                        }
-                        break;
-                    case InputKeyOk:
-                        if(!plugin_state->addr_err) {
-                            if(!plugin_state->is_thread_running) {
-                                start_mjthread(plugin_state);
-                                view_port_update(view_port);
-                            }
-                        }
-                        break;
-                    case InputKeyBack:
-                        plugin_state->close_thread_please = true;
-                        if(plugin_state->is_thread_running && plugin_state->mjthread) {
-                            furi_thread_join(
-                                plugin_state->mjthread); // wait until thread is finished
-                        }
-                        plugin_state->close_thread_please = false;
-                        processing = false;
-                        break;
-                    default:
-                        break;
-                    }
-                }
-            }
-        }
-
-        view_port_update(view_port);
-        furi_mutex_release(plugin_state->mutex);
-    }
-
-    furi_thread_free(plugin_state->mjthread);
-    nrf24_deinit();
-    view_port_enabled_set(view_port, false);
-    gui_remove_view_port(gui, view_port);
-    furi_record_close(RECORD_GUI);
-    furi_record_close(RECORD_STORAGE);
-    view_port_free(view_port);
-    furi_message_queue_free(event_queue);
-    furi_mutex_free(plugin_state->mutex);
-    free(plugin_state);
-
-    return 0;
-}

+ 0 - 460
non_catalog_apps/mousejacker/mousejacker_ducky.c

@@ -1,460 +0,0 @@
-#include "mousejacker_ducky.h"
-
-static const char ducky_cmd_comment[] = {"REM"};
-static const char ducky_cmd_delay[] = {"DELAY "};
-static const char ducky_cmd_string[] = {"STRING "};
-static const char ducky_cmd_altstring[] = {"ALTSTRING "};
-static const char ducky_cmd_repeat[] = {"REPEAT "};
-
-static uint8_t LOGITECH_HID_TEMPLATE[] =
-    {0x00, 0xC1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-static uint8_t LOGITECH_HELLO[] = {0x00, 0x4F, 0x00, 0x04, 0xB0, 0x10, 0x00, 0x00, 0x00, 0xED};
-static uint8_t LOGITECH_KEEPALIVE[] = {0x00, 0x40, 0x00, 0x55, 0x6B};
-
-uint8_t prev_hid = 0;
-static bool holding_ctrl = false;
-static bool holding_shift = false;
-static bool holding_alt = false;
-static bool holding_gui = false;
-
-#define RT_THRESHOLD 50
-#define LOGITECH_MIN_CHANNEL 2
-#define LOGITECH_MAX_CHANNEL 83
-#define LOGITECH_KEEPALIVE_SIZE 5
-#define LOGITECH_HID_TEMPLATE_SIZE 10
-#define LOGITECH_HELLO_SIZE 10
-#define TAG "mousejacker_ducky"
-
-MJDuckyKey mj_ducky_keys[] = {{" ", 44, 0},         {"!", 30, 2},          {"\"", 52, 2},
-                              {"#", 32, 2},         {"$", 33, 2},          {"%", 34, 2},
-                              {"&", 36, 2},         {"'", 52, 0},          {"(", 38, 2},
-                              {")", 39, 2},         {"*", 37, 2},          {"+", 46, 2},
-                              {",", 54, 0},         {"-", 45, 0},          {".", 55, 0},
-                              {"/", 56, 0},         {"0", 39, 0},          {"1", 30, 0},
-                              {"2", 31, 0},         {"3", 32, 0},          {"4", 33, 0},
-                              {"5", 34, 0},         {"6", 35, 0},          {"7", 36, 0},
-                              {"8", 37, 0},         {"9", 38, 0},          {":", 51, 2},
-                              {";", 51, 0},         {"<", 54, 2},          {"=", 46, 0},
-                              {">", 55, 2},         {"?", 56, 2},          {"@", 31, 2},
-                              {"A", 4, 2},          {"B", 5, 2},           {"C", 6, 2},
-                              {"D", 7, 2},          {"E", 8, 2},           {"F", 9, 2},
-                              {"G", 10, 2},         {"H", 11, 2},          {"I", 12, 2},
-                              {"J", 13, 2},         {"K", 14, 2},          {"L", 15, 2},
-                              {"M", 16, 2},         {"N", 17, 2},          {"O", 18, 2},
-                              {"P", 19, 2},         {"Q", 20, 2},          {"R", 21, 2},
-                              {"S", 22, 2},         {"T", 23, 2},          {"U", 24, 2},
-                              {"V", 25, 2},         {"W", 26, 2},          {"X", 27, 2},
-                              {"Y", 28, 2},         {"Z", 29, 2},          {"[", 47, 0},
-                              {"\\", 49, 0},        {"]", 48, 0},          {"^", 35, 2},
-                              {"_", 45, 2},         {"`", 53, 0},          {"a", 4, 0},
-                              {"b", 5, 0},          {"c", 6, 0},           {"d", 7, 0},
-                              {"e", 8, 0},          {"f", 9, 0},           {"g", 10, 0},
-                              {"h", 11, 0},         {"i", 12, 0},          {"j", 13, 0},
-                              {"k", 14, 0},         {"l", 15, 0},          {"m", 16, 0},
-                              {"n", 17, 0},         {"o", 18, 0},          {"p", 19, 0},
-                              {"q", 20, 0},         {"r", 21, 0},          {"s", 22, 0},
-                              {"t", 23, 0},         {"u", 24, 0},          {"v", 25, 0},
-                              {"w", 26, 0},         {"x", 27, 0},          {"y", 28, 0},
-                              {"z", 29, 0},         {"{", 47, 2},          {"|", 49, 2},
-                              {"}", 48, 2},         {"~", 53, 2},          {"BACKSPACE", 42, 0},
-                              {"", 0, 0},           {"ALT", 0, 4},         {"SHIFT", 0, 2},
-                              {"CTRL", 0, 1},       {"GUI", 0, 8},         {"SCROLLLOCK", 71, 0},
-                              {"ENTER", 40, 0},     {"F12", 69, 0},        {"HOME", 74, 0},
-                              {"F10", 67, 0},       {"F9", 66, 0},         {"ESCAPE", 41, 0},
-                              {"PAGEUP", 75, 0},    {"TAB", 43, 0},        {"PRINTSCREEN", 70, 0},
-                              {"F2", 59, 0},        {"CAPSLOCK", 57, 0},   {"F1", 58, 0},
-                              {"F4", 61, 0},        {"F6", 63, 0},         {"F8", 65, 0},
-                              {"DOWNARROW", 81, 0}, {"DELETE", 42, 0},     {"RIGHT", 79, 0},
-                              {"F3", 60, 0},        {"DOWN", 81, 0},       {"DEL", 76, 0},
-                              {"END", 77, 0},       {"INSERT", 73, 0},     {"F5", 62, 0},
-                              {"LEFTARROW", 80, 0}, {"RIGHTARROW", 79, 0}, {"PAGEDOWN", 78, 0},
-                              {"PAUSE", 72, 0},     {"SPACE", 44, 0},      {"UPARROW", 82, 0},
-                              {"F11", 68, 0},       {"F7", 64, 0},         {"UP", 82, 0},
-                              {"LEFT", 80, 0},      {"NUM 1", 89, 0},      {"NUM 2", 90, 0},
-                              {"NUM 3", 91, 0},     {"NUM 4", 92, 0},      {"NUM 5", 93, 0},
-                              {"NUM 6", 94, 0},     {"NUM 7", 95, 0},      {"NUM 8", 96, 0},
-                              {"NUM 9", 97, 0},     {"NUM 0", 98, 0}};
-
-/*
-static bool mj_ducky_get_number(const char* param, uint32_t* val) {
-    uint32_t value = 0;
-    if(sscanf(param, "%lu", &value) == 1) {
-        *val = value;
-        return true;
-    }
-    return false;
-}
-*/
-
-static uint32_t mj_ducky_get_command_len(const char* line) {
-    uint32_t len = strlen(line);
-    for(uint32_t i = 0; i < len; i++) {
-        if(line[i] == ' ') return i;
-    }
-    return 0;
-}
-
-static bool mj_get_ducky_key(char* key, size_t keylen, MJDuckyKey* dk) {
-    //FURI_LOG_D(TAG, "looking up key %s with length %d", key, keylen);
-    for(uint i = 0; i < sizeof(mj_ducky_keys) / sizeof(MJDuckyKey); i++) {
-        if(strlen(mj_ducky_keys[i].name) == keylen &&
-           !strncmp(mj_ducky_keys[i].name, key, keylen)) {
-            memcpy(dk, &mj_ducky_keys[i], sizeof(MJDuckyKey));
-            return true;
-        }
-    }
-
-    return false;
-}
-
-static void checksum(uint8_t* payload, uint len) {
-    // This is also from the KeyKeriki paper
-    // Thanks Thorsten and Max!
-    uint8_t cksum = 0xff;
-    for(uint n = 0; n < len - 2; n++) cksum = (cksum - payload[n]) & 0xff;
-    cksum = (cksum + 1) & 0xff;
-    payload[len - 1] = cksum;
-}
-
-static void inject_packet(
-    FuriHalSpiBusHandle* handle,
-    uint8_t* addr,
-    uint8_t addr_size,
-    uint8_t rate,
-    uint8_t* payload,
-    size_t payload_size,
-    PluginState* plugin_state) {
-    uint8_t rt_count = 0;
-    while(1) {
-        if(!plugin_state->is_thread_running || plugin_state->close_thread_please) {
-            return;
-        }
-        if(nrf24_txpacket(handle, payload, payload_size, true)) {
-            break;
-        }
-
-        rt_count++;
-        // retransmit threshold exceeded, scan for new channel
-        if(rt_count > RT_THRESHOLD) {
-            if(nrf24_find_channel(
-                   handle,
-                   addr,
-                   addr,
-                   addr_size,
-                   rate,
-                   LOGITECH_MIN_CHANNEL,
-                   LOGITECH_MAX_CHANNEL,
-                   true) > LOGITECH_MAX_CHANNEL) {
-                return; // fail
-            }
-            //FURI_LOG_D("mj", "find channel passed, %d", tessst);
-
-            rt_count = 0;
-        }
-    }
-}
-
-static void build_hid_packet(uint8_t mod, uint8_t hid, uint8_t* payload) {
-    memcpy(payload, LOGITECH_HID_TEMPLATE, LOGITECH_HID_TEMPLATE_SIZE);
-    payload[2] = mod;
-    payload[3] = hid;
-    checksum(payload, LOGITECH_HID_TEMPLATE_SIZE);
-}
-
-static void release_key(
-    FuriHalSpiBusHandle* handle,
-    uint8_t* addr,
-    uint8_t addr_size,
-    uint8_t rate,
-    PluginState* plugin_state) {
-    // This function release keys currently pressed, but keep pressing special keys
-    // if holding mod keys variable are set to true
-
-    uint8_t hid_payload[LOGITECH_HID_TEMPLATE_SIZE] = {0};
-    build_hid_packet(
-        0 | holding_ctrl | holding_shift << 1 | holding_alt << 2 | holding_gui << 3,
-        0,
-        hid_payload);
-    inject_packet(
-        handle,
-        addr,
-        addr_size,
-        rate,
-        hid_payload,
-        LOGITECH_HID_TEMPLATE_SIZE,
-        plugin_state); // empty hid packet
-}
-
-static void send_hid_packet(
-    FuriHalSpiBusHandle* handle,
-    uint8_t* addr,
-    uint8_t addr_size,
-    uint8_t rate,
-    uint8_t mod,
-    uint8_t hid,
-    PluginState* plugin_state) {
-    uint8_t hid_payload[LOGITECH_HID_TEMPLATE_SIZE] = {0};
-    if(hid == prev_hid) release_key(handle, addr, addr_size, rate, plugin_state);
-
-    prev_hid = hid;
-    build_hid_packet(
-        mod | holding_ctrl | holding_shift << 1 | holding_alt << 2 | holding_gui << 3,
-        hid,
-        hid_payload);
-    inject_packet(
-        handle, addr, addr_size, rate, hid_payload, LOGITECH_HID_TEMPLATE_SIZE, plugin_state);
-    furi_delay_ms(12);
-}
-
-static bool ducky_end_line(const char chr) {
-    return ((chr == ' ') || (chr == '\0') || (chr == '\r') || (chr == '\n'));
-}
-
-// returns false if there was an error processing script line
-static bool mj_process_ducky_line(
-    FuriHalSpiBusHandle* handle,
-    uint8_t* addr,
-    uint8_t addr_size,
-    uint8_t rate,
-    char* line,
-    char* prev_line,
-    PluginState* plugin_state) {
-    MJDuckyKey dk;
-    uint8_t hid_payload[LOGITECH_HID_TEMPLATE_SIZE] = {0};
-    char* line_tmp = line;
-    uint32_t line_len = strlen(line);
-    if(!plugin_state->is_thread_running || plugin_state->close_thread_please) {
-        return true;
-    }
-    for(uint32_t i = 0; i < line_len; i++) {
-        if((line_tmp[i] != ' ') && (line_tmp[i] != '\t') && (line_tmp[i] != '\n')) {
-            line_tmp = &line_tmp[i];
-            break; // Skip spaces and tabs
-        }
-        if(i == line_len - 1) return true; // Skip empty lines
-    }
-
-    FURI_LOG_D(TAG, "line: %s", line_tmp);
-
-    // General commands
-    if(strncmp(line_tmp, ducky_cmd_comment, strlen(ducky_cmd_comment)) == 0) {
-        // REM - comment line
-        return true;
-    } else if(strncmp(line_tmp, ducky_cmd_delay, strlen(ducky_cmd_delay)) == 0) {
-        // DELAY
-        line_tmp = &line_tmp[mj_ducky_get_command_len(line_tmp) + 1];
-        uint32_t delay_val = 0;
-        delay_val = atoi(line_tmp);
-        if(delay_val > 0) {
-            uint32_t delay_count = delay_val / 10;
-            build_hid_packet(0, 0, hid_payload);
-            inject_packet(
-                handle,
-                addr,
-                addr_size,
-                rate,
-                hid_payload,
-                LOGITECH_HID_TEMPLATE_SIZE,
-                plugin_state); // empty hid packet
-            for(uint32_t i = 0; i < delay_count; i++) {
-                if(!plugin_state->is_thread_running || plugin_state->close_thread_please) {
-                    return true;
-                }
-                inject_packet(
-                    handle,
-                    addr,
-                    addr_size,
-                    rate,
-                    LOGITECH_KEEPALIVE,
-                    LOGITECH_KEEPALIVE_SIZE,
-                    plugin_state);
-                furi_delay_ms(10);
-            }
-            return true;
-        }
-        return false;
-    } else if(strncmp(line_tmp, ducky_cmd_string, strlen(ducky_cmd_string)) == 0) {
-        // STRING
-        line_tmp = &line_tmp[mj_ducky_get_command_len(line_tmp) + 1];
-        for(size_t i = 0; i < strlen(line_tmp); i++) {
-            if(!mj_get_ducky_key(&line_tmp[i], 1, &dk)) return false;
-
-            send_hid_packet(handle, addr, addr_size, rate, dk.mod, dk.hid, plugin_state);
-        }
-
-        return true;
-    } else if(strncmp(line_tmp, ducky_cmd_altstring, strlen(ducky_cmd_altstring)) == 0) {
-        // ALTSTRING
-        line_tmp = &line_tmp[mj_ducky_get_command_len(line_tmp) + 1];
-        for(size_t i = 0; i < strlen(line_tmp); i++) {
-            if((line_tmp[i] < ' ') || (line_tmp[i] > '~')) {
-                continue; // Skip non-printable chars
-            }
-
-            char alt_code[4];
-            // Getting altcode of the char
-            snprintf(alt_code, 4, "%u", line_tmp[i]);
-
-            uint8_t j = 0;
-            while(!ducky_end_line(alt_code[j])) {
-                char pad_num[5] = {'N', 'U', 'M', ' ', alt_code[j]};
-                if(!mj_get_ducky_key(pad_num, 5, &dk)) return false;
-                holding_alt = true;
-                FURI_LOG_D(TAG, "Sending %s", pad_num);
-                send_hid_packet(handle, addr, addr_size, rate, dk.mod, dk.hid, plugin_state);
-                j++;
-            }
-            holding_alt = false;
-            release_key(handle, addr, addr_size, rate, plugin_state);
-        }
-
-        return true;
-    } else if(strncmp(line_tmp, ducky_cmd_repeat, strlen(ducky_cmd_repeat)) == 0) {
-        // REPEAT
-        uint32_t repeat_cnt = 0;
-        if(prev_line == NULL) return false;
-
-        line_tmp = &line_tmp[mj_ducky_get_command_len(line_tmp) + 1];
-        repeat_cnt = atoi(line_tmp);
-        if(repeat_cnt < 2) return false;
-
-        FURI_LOG_D(TAG, "repeating %s %ld times", prev_line, repeat_cnt);
-        for(uint32_t i = 0; i < repeat_cnt; i++)
-            mj_process_ducky_line(handle, addr, addr_size, rate, prev_line, NULL, plugin_state);
-
-        return true;
-    } else if(strncmp(line_tmp, "ALT", strlen("ALT")) == 0) {
-        line_tmp = &line_tmp[mj_ducky_get_command_len(line_tmp) + 1];
-        if(!mj_get_ducky_key(line_tmp, strlen(line_tmp), &dk)) return false;
-        holding_alt = true;
-        send_hid_packet(handle, addr, addr_size, rate, dk.mod, dk.hid, plugin_state);
-        holding_alt = false;
-        return true;
-    } else if(
-        strncmp(line_tmp, "GUI", strlen("GUI")) == 0 ||
-        strncmp(line_tmp, "WINDOWS", strlen("WINDOWS")) == 0 ||
-        strncmp(line_tmp, "COMMAND", strlen("COMMAND")) == 0) {
-        line_tmp = &line_tmp[mj_ducky_get_command_len(line_tmp) + 1];
-        if(!mj_get_ducky_key(line_tmp, strlen(line_tmp), &dk)) return false;
-        holding_gui = true;
-        send_hid_packet(handle, addr, addr_size, rate, dk.mod, dk.hid, plugin_state);
-        holding_gui = false;
-        return true;
-    } else if(
-        strncmp(line_tmp, "CTRL-ALT", strlen("CTRL-ALT")) == 0 ||
-        strncmp(line_tmp, "CONTROL-ALT", strlen("CONTROL-ALT")) == 0) {
-        line_tmp = &line_tmp[mj_ducky_get_command_len(line_tmp) + 1];
-        if(!mj_get_ducky_key(line_tmp, strlen(line_tmp), &dk)) return false;
-        holding_ctrl = true;
-        holding_alt = true;
-        send_hid_packet(handle, addr, addr_size, rate, dk.mod, dk.hid, plugin_state);
-        holding_ctrl = false;
-        holding_alt = false;
-        return true;
-    } else if(
-        strncmp(line_tmp, "CTRL-SHIFT", strlen("CTRL-SHIFT")) == 0 ||
-        strncmp(line_tmp, "CONTROL-SHIFT", strlen("CONTROL-SHIFT")) == 0) {
-        line_tmp = &line_tmp[mj_ducky_get_command_len(line_tmp) + 1];
-        if(!mj_get_ducky_key(line_tmp, strlen(line_tmp), &dk)) return false;
-        holding_ctrl = true;
-        holding_shift = true;
-        send_hid_packet(handle, addr, addr_size, rate, dk.mod, dk.hid, plugin_state);
-        holding_ctrl = false;
-        holding_shift = false;
-        return true;
-    } else if(
-        strncmp(line_tmp, "CTRL", strlen("CTRL")) == 0 ||
-        strncmp(line_tmp, "CONTROL", strlen("CONTROL")) == 0) {
-        line_tmp = &line_tmp[mj_ducky_get_command_len(line_tmp) + 1];
-        if(!mj_get_ducky_key(line_tmp, strlen(line_tmp), &dk)) return false;
-        holding_ctrl = true;
-        send_hid_packet(handle, addr, addr_size, rate, dk.mod, dk.hid, plugin_state);
-        holding_ctrl = false;
-        return true;
-    } else if(strncmp(line_tmp, "SHIFT", strlen("SHIFT")) == 0) {
-        line_tmp = &line_tmp[mj_ducky_get_command_len(line_tmp) + 1];
-        if(!mj_get_ducky_key(line_tmp, strlen(line_tmp), &dk)) return false;
-        holding_shift = true;
-        send_hid_packet(handle, addr, addr_size, rate, dk.mod, dk.hid, plugin_state);
-        holding_shift = false;
-        return true;
-    } else if(
-        strncmp(line_tmp, "ESC", strlen("ESC")) == 0 ||
-        strncmp(line_tmp, "APP", strlen("APP")) == 0 ||
-        strncmp(line_tmp, "ESCAPE", strlen("ESCAPE")) == 0) {
-        if(!mj_get_ducky_key("ESCAPE", 6, &dk)) return false;
-        send_hid_packet(handle, addr, addr_size, rate, dk.mod, dk.hid, plugin_state);
-        return true;
-    } else if(strncmp(line_tmp, "ENTER", strlen("ENTER")) == 0) {
-        if(!mj_get_ducky_key("ENTER", 5, &dk)) return false;
-        send_hid_packet(handle, addr, addr_size, rate, dk.mod, dk.hid, plugin_state);
-        return true;
-    } else if(
-        strncmp(line_tmp, "UP", strlen("UP")) == 0 ||
-        strncmp(line_tmp, "UPARROW", strlen("UPARROW")) == 0) {
-        if(!mj_get_ducky_key("UP", 2, &dk)) return false;
-        send_hid_packet(handle, addr, addr_size, rate, dk.mod, dk.hid, plugin_state);
-        return true;
-    } else if(
-        strncmp(line_tmp, "DOWN", strlen("DOWN")) == 0 ||
-        strncmp(line_tmp, "DOWNARROW", strlen("DOWNARROW")) == 0) {
-        if(!mj_get_ducky_key("DOWN", 4, &dk)) return false;
-        send_hid_packet(handle, addr, addr_size, rate, dk.mod, dk.hid, plugin_state);
-        return true;
-    } else if(
-        strncmp(line_tmp, "LEFT", strlen("LEFT")) == 0 ||
-        strncmp(line_tmp, "LEFTARROW", strlen("LEFTARROW")) == 0) {
-        if(!mj_get_ducky_key("LEFT", 4, &dk)) return false;
-        send_hid_packet(handle, addr, addr_size, rate, dk.mod, dk.hid, plugin_state);
-        return true;
-    } else if(
-        strncmp(line_tmp, "RIGHT", strlen("RIGHT")) == 0 ||
-        strncmp(line_tmp, "RIGHTARROW", strlen("RIGHTARROW")) == 0) {
-        if(!mj_get_ducky_key("RIGHT", 5, &dk)) return false;
-        send_hid_packet(handle, addr, addr_size, rate, dk.mod, dk.hid, plugin_state);
-        return true;
-    } else if(strncmp(line_tmp, "SPACE", strlen("SPACE")) == 0) {
-        if(!mj_get_ducky_key("SPACE", 5, &dk)) return false;
-        send_hid_packet(handle, addr, addr_size, rate, dk.mod, dk.hid, plugin_state);
-        return true;
-    } else if(strncmp(line_tmp, "TAB", strlen("TAB")) == 0) {
-        if(!mj_get_ducky_key("TAB", 3, &dk)) return false;
-        send_hid_packet(handle, addr, addr_size, rate, dk.mod, dk.hid, plugin_state);
-        return true;
-    }
-
-    return false;
-}
-
-void mj_process_ducky_script(
-    FuriHalSpiBusHandle* handle,
-    uint8_t* addr,
-    uint8_t addr_size,
-    uint8_t rate,
-    char* script,
-    PluginState* plugin_state) {
-    uint8_t hid_payload[LOGITECH_HID_TEMPLATE_SIZE] = {0};
-    char* prev_line = NULL;
-
-    inject_packet(
-        handle, addr, addr_size, rate, LOGITECH_HELLO, LOGITECH_HELLO_SIZE, plugin_state);
-    char* line = strtok(script, "\n");
-    while(line != NULL) {
-        if(strcmp(&line[strlen(line) - 1], "\r") == 0) line[strlen(line) - 1] = (char)0;
-
-        if(!mj_process_ducky_line(handle, addr, addr_size, rate, line, prev_line, plugin_state))
-            FURI_LOG_D(TAG, "unable to process ducky script line: %s", line);
-
-        prev_line = line;
-        line = strtok(NULL, "\n");
-    }
-    build_hid_packet(0, 0, hid_payload);
-    inject_packet(
-        handle,
-        addr,
-        addr_size,
-        rate,
-        hid_payload,
-        LOGITECH_HID_TEMPLATE_SIZE,
-        plugin_state); // empty hid packet at end
-}

+ 0 - 45
non_catalog_apps/mousejacker/mousejacker_ducky.h

@@ -1,45 +0,0 @@
-#pragma once
-#include <stdlib.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <furi_hal_spi.h>
-#include <stdio.h>
-#include <string.h>
-#include <nrf24.h>
-#include <furi.h>
-#include <furi_hal.h>
-#include <toolbox/stream/file_stream.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct {
-    char* name;
-    uint8_t hid;
-    uint8_t mod;
-} MJDuckyKey;
-
-typedef struct {
-    FuriMutex* mutex;
-    bool ducky_err;
-    bool addr_err;
-    bool is_thread_running;
-    bool is_ducky_running;
-    bool close_thread_please;
-    Storage* storage;
-    FuriThread* mjthread;
-    Stream* file_stream;
-} PluginState;
-
-void mj_process_ducky_script(
-    FuriHalSpiBusHandle* handle,
-    uint8_t* addr,
-    uint8_t addr_size,
-    uint8_t rate,
-    char* script,
-    PluginState* plugin_state);
-
-#ifdef __cplusplus
-}
-#endif

+ 0 - 22
non_catalog_apps/nrfsniff/application.fam

@@ -1,22 +0,0 @@
-App(
-    appid="nrf24_sniffer",
-    name="[NRF24] Sniffer",
-    apptype=FlipperAppType.EXTERNAL,
-    entry_point="nrfsniff_app",
-    requires=["gui"],
-    stack_size=2 * 1024,
-    order=70,
-    fap_icon="nrfsniff_10px.png",
-    fap_category="GPIO",
-    fap_author="@mothball187 & @xMasterX",
-    fap_version="1.0",
-    fap_description="App captures addresses to use with NRF24 Mouse Jacker app to perform mousejack attacks",
-    fap_private_libs=[
-        Lib(
-            name="nrf24",
-            sources=[
-                "nrf24.c",
-            ],
-        ),
-    ],
-)

+ 0 - 520
non_catalog_apps/nrfsniff/lib/nrf24/nrf24.c

@@ -1,520 +0,0 @@
-#include "nrf24.h"
-#include <furi.h>
-#include <furi_hal.h>
-#include <furi_hal_resources.h>
-#include <assert.h>
-#include <string.h>
-
-void nrf24_init() {
-    furi_hal_spi_bus_handle_init(nrf24_HANDLE);
-    furi_hal_spi_acquire(nrf24_HANDLE);
-    furi_hal_gpio_init(nrf24_CE_PIN, GpioModeOutputPushPull, GpioPullUp, GpioSpeedVeryHigh);
-    furi_hal_gpio_write(nrf24_CE_PIN, false);
-}
-
-void nrf24_deinit() {
-    furi_hal_spi_release(nrf24_HANDLE);
-    furi_hal_spi_bus_handle_deinit(nrf24_HANDLE);
-    furi_hal_gpio_write(nrf24_CE_PIN, false);
-    furi_hal_gpio_init(nrf24_CE_PIN, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
-}
-
-void nrf24_spi_trx(
-    FuriHalSpiBusHandle* handle,
-    uint8_t* tx,
-    uint8_t* rx,
-    uint8_t size,
-    uint32_t timeout) {
-    UNUSED(timeout);
-    furi_hal_gpio_write(handle->cs, false);
-    furi_hal_spi_bus_trx(handle, tx, rx, size, nrf24_TIMEOUT);
-    furi_hal_gpio_write(handle->cs, true);
-}
-
-uint8_t nrf24_write_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t data) {
-    uint8_t tx[2] = {W_REGISTER | (REGISTER_MASK & reg), data};
-    uint8_t rx[2] = {0};
-    nrf24_spi_trx(handle, tx, rx, 2, nrf24_TIMEOUT);
-    return rx[0];
-}
-
-uint8_t
-    nrf24_write_buf_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t* data, uint8_t size) {
-    uint8_t tx[size + 1];
-    uint8_t rx[size + 1];
-    memset(rx, 0, size + 1);
-    tx[0] = W_REGISTER | (REGISTER_MASK & reg);
-    memcpy(&tx[1], data, size);
-    nrf24_spi_trx(handle, tx, rx, size + 1, nrf24_TIMEOUT);
-    return rx[0];
-}
-
-uint8_t nrf24_read_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t* data, uint8_t size) {
-    uint8_t tx[size + 1];
-    uint8_t rx[size + 1];
-    memset(rx, 0, size + 1);
-    tx[0] = R_REGISTER | (REGISTER_MASK & reg);
-    memset(&tx[1], 0, size);
-    nrf24_spi_trx(handle, tx, rx, size + 1, nrf24_TIMEOUT);
-    memcpy(data, &rx[1], size);
-    return rx[0];
-}
-
-uint8_t nrf24_flush_rx(FuriHalSpiBusHandle* handle) {
-    uint8_t tx[] = {FLUSH_RX};
-    uint8_t rx[] = {0};
-    nrf24_spi_trx(handle, tx, rx, 1, nrf24_TIMEOUT);
-    return rx[0];
-}
-
-uint8_t nrf24_flush_tx(FuriHalSpiBusHandle* handle) {
-    uint8_t tx[] = {FLUSH_TX};
-    uint8_t rx[] = {0};
-    nrf24_spi_trx(handle, tx, rx, 1, nrf24_TIMEOUT);
-    return rx[0];
-}
-
-uint8_t nrf24_get_maclen(FuriHalSpiBusHandle* handle) {
-    uint8_t maclen;
-    nrf24_read_reg(handle, REG_SETUP_AW, &maclen, 1);
-    maclen &= 3;
-    return maclen + 2;
-}
-
-uint8_t nrf24_set_maclen(FuriHalSpiBusHandle* handle, uint8_t maclen) {
-    assert(maclen > 1 && maclen < 6);
-    uint8_t status = 0;
-    status = nrf24_write_reg(handle, REG_SETUP_AW, maclen - 2);
-    return status;
-}
-
-uint8_t nrf24_status(FuriHalSpiBusHandle* handle) {
-    uint8_t status;
-    uint8_t tx[] = {R_REGISTER | (REGISTER_MASK & REG_STATUS)};
-    nrf24_spi_trx(handle, tx, &status, 1, nrf24_TIMEOUT);
-    return status;
-}
-
-uint32_t nrf24_get_rate(FuriHalSpiBusHandle* handle) {
-    uint8_t setup = 0;
-    uint32_t rate = 0;
-    nrf24_read_reg(handle, REG_RF_SETUP, &setup, 1);
-    setup &= 0x28;
-    if(setup == 0x20)
-        rate = 250000; // 250kbps
-    else if(setup == 0x08)
-        rate = 2000000; // 2Mbps
-    else if(setup == 0x00)
-        rate = 1000000; // 1Mbps
-
-    return rate;
-}
-
-uint8_t nrf24_set_rate(FuriHalSpiBusHandle* handle, uint32_t rate) {
-    uint8_t r6 = 0;
-    uint8_t status = 0;
-    if(!rate) rate = 2000000;
-
-    nrf24_read_reg(handle, REG_RF_SETUP, &r6, 1); // RF_SETUP register
-    r6 = r6 & (~0x28); // Clear rate fields.
-    if(rate == 2000000)
-        r6 = r6 | 0x08;
-    else if(rate == 1000000)
-        r6 = r6;
-    else if(rate == 250000)
-        r6 = r6 | 0x20;
-
-    status = nrf24_write_reg(handle, REG_RF_SETUP, r6); // Write new rate.
-    return status;
-}
-
-uint8_t nrf24_get_chan(FuriHalSpiBusHandle* handle) {
-    uint8_t channel = 0;
-    nrf24_read_reg(handle, REG_RF_CH, &channel, 1);
-    return channel;
-}
-
-uint8_t nrf24_set_chan(FuriHalSpiBusHandle* handle, uint8_t chan) {
-    uint8_t status;
-    status = nrf24_write_reg(handle, REG_RF_CH, chan);
-    return status;
-}
-
-uint8_t nrf24_get_src_mac(FuriHalSpiBusHandle* handle, uint8_t* mac) {
-    uint8_t size = 0;
-    uint8_t status = 0;
-    size = nrf24_get_maclen(handle);
-    status = nrf24_read_reg(handle, REG_RX_ADDR_P0, mac, size);
-    return status;
-}
-
-uint8_t nrf24_set_src_mac(FuriHalSpiBusHandle* handle, uint8_t* mac, uint8_t size) {
-    uint8_t status = 0;
-    uint8_t clearmac[] = {0, 0, 0, 0, 0};
-    nrf24_set_maclen(handle, size);
-    nrf24_write_buf_reg(handle, REG_RX_ADDR_P0, clearmac, 5);
-    status = nrf24_write_buf_reg(handle, REG_RX_ADDR_P0, mac, size);
-    return status;
-}
-
-uint8_t nrf24_get_dst_mac(FuriHalSpiBusHandle* handle, uint8_t* mac) {
-    uint8_t size = 0;
-    uint8_t status = 0;
-    size = nrf24_get_maclen(handle);
-    status = nrf24_read_reg(handle, REG_TX_ADDR, mac, size);
-    return status;
-}
-
-uint8_t nrf24_set_dst_mac(FuriHalSpiBusHandle* handle, uint8_t* mac, uint8_t size) {
-    uint8_t status = 0;
-    uint8_t clearmac[] = {0, 0, 0, 0, 0};
-    nrf24_set_maclen(handle, size);
-    nrf24_write_buf_reg(handle, REG_TX_ADDR, clearmac, 5);
-    status = nrf24_write_buf_reg(handle, REG_TX_ADDR, mac, size);
-    return status;
-}
-
-uint8_t nrf24_get_packetlen(FuriHalSpiBusHandle* handle) {
-    uint8_t len = 0;
-    nrf24_read_reg(handle, RX_PW_P0, &len, 1);
-    return len;
-}
-
-uint8_t nrf24_set_packetlen(FuriHalSpiBusHandle* handle, uint8_t len) {
-    uint8_t status = 0;
-    status = nrf24_write_reg(handle, RX_PW_P0, len);
-    return status;
-}
-
-uint8_t
-    nrf24_rxpacket(FuriHalSpiBusHandle* handle, uint8_t* packet, uint8_t* packetsize, bool full) {
-    uint8_t status = 0;
-    uint8_t size = 0;
-    uint8_t tx_pl_wid[] = {R_RX_PL_WID, 0};
-    uint8_t rx_pl_wid[] = {0, 0};
-    uint8_t tx_cmd[33] = {0}; // 32 max payload size + 1 for command
-    uint8_t tmp_packet[33] = {0};
-
-    status = nrf24_status(handle);
-
-    if(status & 0x40) {
-        if(full)
-            size = nrf24_get_packetlen(handle);
-        else {
-            nrf24_spi_trx(handle, tx_pl_wid, rx_pl_wid, 2, nrf24_TIMEOUT);
-            size = rx_pl_wid[1];
-        }
-
-        tx_cmd[0] = R_RX_PAYLOAD;
-        nrf24_spi_trx(handle, tx_cmd, tmp_packet, size + 1, nrf24_TIMEOUT);
-        nrf24_write_reg(handle, REG_STATUS, 0x40); // clear bit.
-        memcpy(packet, &tmp_packet[1], size);
-    } else if(status == 0) {
-        nrf24_flush_rx(handle);
-        nrf24_write_reg(handle, REG_STATUS, 0x40); // clear bit.
-    }
-
-    *packetsize = size;
-    return status;
-}
-
-uint8_t nrf24_txpacket(FuriHalSpiBusHandle* handle, uint8_t* payload, uint8_t size, bool ack) {
-    uint8_t status = 0;
-    uint8_t tx[size + 1];
-    uint8_t rx[size + 1];
-    memset(tx, 0, size + 1);
-    memset(rx, 0, size + 1);
-
-    if(!ack)
-        tx[0] = W_TX_PAYLOAD_NOACK;
-    else
-        tx[0] = W_TX_PAYLOAD;
-
-    memcpy(&tx[1], payload, size);
-    nrf24_spi_trx(handle, tx, rx, size + 1, nrf24_TIMEOUT);
-    nrf24_set_tx_mode(handle);
-
-    while(!(status & (TX_DS | MAX_RT))) status = nrf24_status(handle);
-
-    if(status & MAX_RT) nrf24_flush_tx(handle);
-
-    nrf24_set_idle(handle);
-    nrf24_write_reg(handle, REG_STATUS, TX_DS | MAX_RT);
-    return status & TX_DS;
-}
-
-uint8_t nrf24_power_up(FuriHalSpiBusHandle* handle) {
-    uint8_t status = 0;
-    uint8_t cfg = 0;
-    nrf24_read_reg(handle, REG_CONFIG, &cfg, 1);
-    cfg = cfg | 2;
-    status = nrf24_write_reg(handle, REG_CONFIG, cfg);
-    furi_delay_ms(5000);
-    return status;
-}
-
-uint8_t nrf24_set_idle(FuriHalSpiBusHandle* handle) {
-    uint8_t status = 0;
-    uint8_t cfg = 0;
-    nrf24_read_reg(handle, REG_CONFIG, &cfg, 1);
-    cfg &= 0xfc; // clear bottom two bits to power down the radio
-    status = nrf24_write_reg(handle, REG_CONFIG, cfg);
-    //nr204_write_reg(handle, REG_EN_RXADDR, 0x0);
-    furi_hal_gpio_write(nrf24_CE_PIN, false);
-    return status;
-}
-
-uint8_t nrf24_set_rx_mode(FuriHalSpiBusHandle* handle) {
-    uint8_t status = 0;
-    uint8_t cfg = 0;
-    //status = nrf24_write_reg(handle, REG_CONFIG, 0x0F); // enable 2-byte CRC, PWR_UP, and PRIM_RX
-    nrf24_read_reg(handle, REG_CONFIG, &cfg, 1);
-    cfg |= 0x03; // PWR_UP, and PRIM_RX
-    status = nrf24_write_reg(handle, REG_CONFIG, cfg);
-    //nr204_write_reg(REG_EN_RXADDR, 0x03) // Set RX Pipe 0 and 1
-    furi_hal_gpio_write(nrf24_CE_PIN, true);
-    furi_delay_ms(2000);
-    return status;
-}
-
-uint8_t nrf24_set_tx_mode(FuriHalSpiBusHandle* handle) {
-    uint8_t status = 0;
-    uint8_t cfg = 0;
-    furi_hal_gpio_write(nrf24_CE_PIN, false);
-    nrf24_write_reg(handle, REG_STATUS, 0x30);
-    //status = nrf24_write_reg(handle, REG_CONFIG, 0x0E); // enable 2-byte CRC, PWR_UP
-    nrf24_read_reg(handle, REG_CONFIG, &cfg, 1);
-    cfg &= 0xfe; // disable PRIM_RX
-    cfg |= 0x02; // PWR_UP
-    status = nrf24_write_reg(handle, REG_CONFIG, cfg);
-    furi_hal_gpio_write(nrf24_CE_PIN, true);
-    furi_delay_ms(2);
-    return status;
-}
-
-void nrf24_configure(
-    FuriHalSpiBusHandle* handle,
-    uint8_t rate,
-    uint8_t* srcmac,
-    uint8_t* dstmac,
-    uint8_t maclen,
-    uint8_t channel,
-    bool noack,
-    bool disable_aa) {
-    assert(channel <= 125);
-    assert(rate == 1 || rate == 2);
-    if(rate == 2)
-        rate = 8; // 2Mbps
-    else
-        rate = 0; // 1Mbps
-
-    nrf24_write_reg(handle, REG_CONFIG, 0x00); // Stop nRF
-    nrf24_set_idle(handle);
-    nrf24_write_reg(handle, REG_STATUS, 0x1c); // clear interrupts
-    if(disable_aa)
-        nrf24_write_reg(handle, REG_EN_AA, 0x00); // Disable Shockburst
-    else
-        nrf24_write_reg(handle, REG_EN_AA, 0x1F); // Enable Shockburst
-
-    nrf24_write_reg(handle, REG_DYNPD, 0x3F); // enable dynamic payload length on all pipes
-    if(noack)
-        nrf24_write_reg(handle, REG_FEATURE, 0x05); // disable payload-with-ack, enable noack
-    else {
-        nrf24_write_reg(handle, REG_CONFIG, 0x0C); // 2 byte CRC
-        nrf24_write_reg(handle, REG_FEATURE, 0x07); // enable dyn payload and ack
-        nrf24_write_reg(
-            handle, REG_SETUP_RETR, 0x1f); // 15 retries for AA, 500us auto retransmit delay
-    }
-
-    nrf24_set_idle(handle);
-    nrf24_flush_rx(handle);
-    nrf24_flush_tx(handle);
-
-    if(maclen) nrf24_set_maclen(handle, maclen);
-    if(srcmac) nrf24_set_src_mac(handle, srcmac, maclen);
-    if(dstmac) nrf24_set_dst_mac(handle, dstmac, maclen);
-
-    nrf24_write_reg(handle, REG_RF_CH, channel);
-    nrf24_write_reg(handle, REG_RF_SETUP, rate);
-    furi_delay_ms(200);
-}
-
-void nrf24_init_promisc_mode(FuriHalSpiBusHandle* handle, uint8_t channel, uint8_t rate) {
-    //uint8_t preamble[] = {0x55, 0x00}; // little endian
-    uint8_t preamble[] = {0xAA, 0x00}; // little endian
-    //uint8_t preamble[] = {0x00, 0x55}; // little endian
-    //uint8_t preamble[] = {0x00, 0xAA}; // little endian
-    nrf24_write_reg(handle, REG_CONFIG, 0x00); // Stop nRF
-    nrf24_write_reg(handle, REG_STATUS, 0x1c); // clear interrupts
-    nrf24_write_reg(handle, REG_DYNPD, 0x0); // disable shockburst
-    nrf24_write_reg(handle, REG_EN_AA, 0x00); // Disable Shockburst
-    nrf24_write_reg(handle, REG_FEATURE, 0x05); // disable payload-with-ack, enable noack
-    nrf24_set_maclen(handle, 2); // shortest address
-    nrf24_set_src_mac(handle, preamble, 2); // set src mac to preamble bits to catch everything
-    nrf24_set_packetlen(handle, 32); // set max packet length
-    nrf24_set_idle(handle);
-    nrf24_flush_rx(handle);
-    nrf24_flush_tx(handle);
-    nrf24_write_reg(handle, REG_RF_CH, channel);
-    nrf24_write_reg(handle, REG_RF_SETUP, rate);
-
-    // prime for RX, no checksum
-    nrf24_write_reg(handle, REG_CONFIG, 0x03); // PWR_UP and PRIM_RX, disable AA and CRC
-    furi_hal_gpio_write(nrf24_CE_PIN, true);
-    furi_delay_ms(100);
-}
-
-void hexlify(uint8_t* in, uint8_t size, char* out) {
-    memset(out, 0, size * 2);
-    for(int i = 0; i < size; i++)
-        snprintf(out + strlen(out), sizeof(out + strlen(out)), "%02X", in[i]);
-}
-
-uint64_t bytes_to_int64(uint8_t* bytes, uint8_t size, bool bigendian) {
-    uint64_t ret = 0;
-    for(int i = 0; i < size; i++)
-        if(bigendian)
-            ret |= bytes[i] << ((size - 1 - i) * 8);
-        else
-            ret |= bytes[i] << (i * 8);
-
-    return ret;
-}
-
-void int64_to_bytes(uint64_t val, uint8_t* out, bool bigendian) {
-    for(int i = 0; i < 8; i++) {
-        if(bigendian)
-            out[i] = (val >> ((7 - i) * 8)) & 0xff;
-        else
-            out[i] = (val >> (i * 8)) & 0xff;
-    }
-}
-
-uint32_t bytes_to_int32(uint8_t* bytes, bool bigendian) {
-    uint32_t ret = 0;
-    for(int i = 0; i < 4; i++)
-        if(bigendian)
-            ret |= bytes[i] << ((3 - i) * 8);
-        else
-            ret |= bytes[i] << (i * 8);
-
-    return ret;
-}
-
-void int32_to_bytes(uint32_t val, uint8_t* out, bool bigendian) {
-    for(int i = 0; i < 4; i++) {
-        if(bigendian)
-            out[i] = (val >> ((3 - i) * 8)) & 0xff;
-        else
-            out[i] = (val >> (i * 8)) & 0xff;
-    }
-}
-
-uint64_t bytes_to_int16(uint8_t* bytes, bool bigendian) {
-    uint16_t ret = 0;
-    for(int i = 0; i < 2; i++)
-        if(bigendian)
-            ret |= bytes[i] << ((1 - i) * 8);
-        else
-            ret |= bytes[i] << (i * 8);
-
-    return ret;
-}
-
-void int16_to_bytes(uint16_t val, uint8_t* out, bool bigendian) {
-    for(int i = 0; i < 2; i++) {
-        if(bigendian)
-            out[i] = (val >> ((1 - i) * 8)) & 0xff;
-        else
-            out[i] = (val >> (i * 8)) & 0xff;
-    }
-}
-
-// handle iffyness with preamble processing sometimes being a bit (literally) off
-void alt_address_old(uint8_t* packet, uint8_t* altaddr) {
-    uint8_t macmess_hi_b[4];
-    uint8_t macmess_lo_b[2];
-    uint32_t macmess_hi;
-    uint16_t macmess_lo;
-    uint8_t preserved;
-
-    // get first 6 bytes into 32-bit and 16-bit variables
-    memcpy(macmess_hi_b, packet, 4);
-    memcpy(macmess_lo_b, packet + 4, 2);
-
-    macmess_hi = bytes_to_int32(macmess_hi_b, true);
-
-    //preserve least 7 bits from hi that will be shifted down to lo
-    preserved = macmess_hi & 0x7f;
-    macmess_hi >>= 7;
-
-    macmess_lo = bytes_to_int16(macmess_lo_b, true);
-    macmess_lo >>= 7;
-    macmess_lo = (preserved << 9) | macmess_lo;
-    int32_to_bytes(macmess_hi, macmess_hi_b, true);
-    int16_to_bytes(macmess_lo, macmess_lo_b, true);
-    memcpy(altaddr, &macmess_hi_b[1], 3);
-    memcpy(altaddr + 3, macmess_lo_b, 2);
-}
-
-bool validate_address(uint8_t* addr) {
-    uint8_t bad[][3] = {{0x55, 0x55}, {0xAA, 0xAA}, {0x00, 0x00}, {0xFF, 0xFF}};
-    for(int i = 0; i < 4; i++)
-        for(int j = 0; j < 2; j++)
-            if(!memcmp(addr + j * 2, bad[i], 2)) return false;
-
-    return true;
-}
-
-bool nrf24_sniff_address(FuriHalSpiBusHandle* handle, uint8_t maclen, uint8_t* address) {
-    bool found = false;
-    uint8_t packet[32] = {0};
-    uint8_t packetsize;
-    //char printit[65];
-    uint8_t status = 0;
-    status = nrf24_rxpacket(handle, packet, &packetsize, true);
-    if(status & 0x40) {
-        if(validate_address(packet)) {
-            for(int i = 0; i < maclen; i++) address[i] = packet[maclen - 1 - i];
-
-            /*
-            alt_address(packet, packet);
-
-            for(i = 0; i < maclen; i++)
-                address[i + 5] = packet[maclen - 1 - i];
-            */
-
-            //memcpy(address, packet, maclen);
-            //hexlify(packet, packetsize, printit);
-            found = true;
-        }
-    }
-
-    return found;
-}
-
-uint8_t nrf24_find_channel(
-    FuriHalSpiBusHandle* handle,
-    uint8_t* srcmac,
-    uint8_t* dstmac,
-    uint8_t maclen,
-    uint8_t rate,
-    uint8_t min_channel,
-    uint8_t max_channel,
-    bool autoinit) {
-    uint8_t ping_packet[] = {0x0f, 0x0f, 0x0f, 0x0f}; // this can be anything, we just need an ack
-    uint8_t ch = max_channel + 1; // means fail
-    nrf24_configure(handle, rate, srcmac, dstmac, maclen, 2, false, false);
-    for(ch = min_channel; ch <= max_channel + 1; ch++) {
-        nrf24_write_reg(handle, REG_RF_CH, ch);
-        if(nrf24_txpacket(handle, ping_packet, 4, true)) break;
-    }
-
-    if(autoinit) {
-        FURI_LOG_D("nrf24", "initializing radio for channel %d", ch);
-        nrf24_configure(handle, rate, srcmac, dstmac, maclen, ch, false, false);
-        return ch;
-    }
-
-    return ch;
-}

+ 0 - 366
non_catalog_apps/nrfsniff/lib/nrf24/nrf24.h

@@ -1,366 +0,0 @@
-#pragma once
-#include <stdbool.h>
-#include <stdint.h>
-#include <furi_hal_spi.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define R_REGISTER 0x00
-#define W_REGISTER 0x20
-#define REGISTER_MASK 0x1F
-#define ACTIVATE 0x50
-#define R_RX_PL_WID 0x60
-#define R_RX_PAYLOAD 0x61
-#define W_TX_PAYLOAD 0xA0
-#define W_TX_PAYLOAD_NOACK 0xB0
-#define W_ACK_PAYLOAD 0xA8
-#define FLUSH_TX 0xE1
-#define FLUSH_RX 0xE2
-#define REUSE_TX_PL 0xE3
-#define RF24_NOP 0xFF
-
-#define REG_CONFIG 0x00
-#define REG_EN_AA 0x01
-#define REG_EN_RXADDR 0x02
-#define REG_SETUP_AW 0x03
-#define REG_SETUP_RETR 0x04
-#define REG_DYNPD 0x1C
-#define REG_FEATURE 0x1D
-#define REG_RF_SETUP 0x06
-#define REG_STATUS 0x07
-#define REG_RX_ADDR_P0 0x0A
-#define REG_RF_CH 0x05
-#define REG_TX_ADDR 0x10
-
-#define RX_PW_P0 0x11
-#define TX_DS 0x20
-#define MAX_RT 0x10
-
-#define nrf24_TIMEOUT 500
-#define nrf24_CE_PIN &gpio_ext_pb2
-#define nrf24_HANDLE &furi_hal_spi_bus_handle_external
-
-/* Low level API */
-
-/** Write device register
- *
- * @param      handle  - pointer to FuriHalSpiHandle
- * @param      reg     - register
- * @param      data    - data to write
- *
- * @return     device status
- */
-uint8_t nrf24_write_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t data);
-
-/** Write buffer to device register
- *
- * @param      handle  - pointer to FuriHalSpiHandle
- * @param      reg     - register
- * @param      data    - data to write
- * @param      size    - size of data to write
- *
- * @return     device status
- */
-uint8_t nrf24_write_buf_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t* data, uint8_t size);
-
-/** Read device register
- *
- * @param      handle  - pointer to FuriHalSpiHandle
- * @param      reg     - register
- * @param[out] data    - pointer to data
- *
- * @return     device status
- */
-uint8_t nrf24_read_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t* data, uint8_t size);
-
-/** Power up the radio for operation
- * 
- * @param      handle  - pointer to FuriHalSpiHandle
- * 
- * @return     device status
- */
-uint8_t nrf24_power_up(FuriHalSpiBusHandle* handle);
-
-/** Power down the radio
- * 
- * @param      handle  - pointer to FuriHalSpiHandle
- * 
- * @return     device status
- */
-uint8_t nrf24_set_idle(FuriHalSpiBusHandle* handle);
-
-/** Sets the radio to RX mode
- *
- * @param      handle  - pointer to FuriHalSpiHandle
- * 
- * @return     device status
- */
-uint8_t nrf24_set_rx_mode(FuriHalSpiBusHandle* handle);
-
-/** Sets the radio to TX mode
- *
- * @param      handle  - pointer to FuriHalSpiHandle
- * 
- * @return     device status
- */
-uint8_t nrf24_set_tx_mode(FuriHalSpiBusHandle* handle);
-
-/*=============================================================================================================*/
-
-/* High level API */
-
-/** Must call this before using any other nrf24 API
- * 
- */
-void nrf24_init();
-
-/** Must call this when we end using nrf24 device
- * 
- */
-void nrf24_deinit();
-
-/** Send flush rx command
- *
- * @param      handle  - pointer to FuriHalSpiHandle
- *
- * @return     device status
- */
-uint8_t nrf24_flush_rx(FuriHalSpiBusHandle* handle);
-
-/** Send flush tx command
- *
- * @param      handle  - pointer to FuriHalSpiHandle
- *
- * @return     device status
- */
-uint8_t nrf24_flush_tx(FuriHalSpiBusHandle* handle);
-
-/** Gets the RX packet length in data pipe 0
- * 
- * @param      handle  - pointer to FuriHalSpiHandle
- * 
- * @return     packet length in data pipe 0
- */
-uint8_t nrf24_get_packetlen(FuriHalSpiBusHandle* handle);
-
-/** Sets the RX packet length in data pipe 0
- * 
- * @param      handle  - pointer to FuriHalSpiHandle
- * @param      len - length to set
- * 
- * @return     device status
- */
-uint8_t nrf24_set_packetlen(FuriHalSpiBusHandle* handle, uint8_t len);
-
-/** Gets configured length of MAC address
- *
- * @param      handle  - pointer to FuriHalSpiHandle
- * 
- * @return     MAC address length
- */
-uint8_t nrf24_get_maclen(FuriHalSpiBusHandle* handle);
-
-/** Sets configured length of MAC address
- *
- * @param      handle  - pointer to FuriHalSpiHandle
- * @param      maclen - length to set MAC address to, must be greater than 1 and less than 6
- * 
- * @return     MAC address length
- */
-uint8_t nrf24_set_maclen(FuriHalSpiBusHandle* handle, uint8_t maclen);
-
-/** Gets the current status flags from the STATUS register
- * 
- * @param      handle  - pointer to FuriHalSpiHandle
- * 
- * @return     status flags
- */
-uint8_t nrf24_status(FuriHalSpiBusHandle* handle);
-
-/** Gets the current transfer rate
- * 
- * @param      handle  - pointer to FuriHalSpiHandle
- * 
- * @return     transfer rate in bps
- */
-uint32_t nrf24_get_rate(FuriHalSpiBusHandle* handle);
-
-/** Sets the transfer rate
- *
- * @param      handle  - pointer to FuriHalSpiHandle
- * @param      rate - the transfer rate in bps
- * 
- * @return     device status
- */
-uint8_t nrf24_set_rate(FuriHalSpiBusHandle* handle, uint32_t rate);
-
-/** Gets the current channel
- * In nrf24, the channel number is multiplied times 1MHz and added to 2400MHz to get the frequency
- * 
- * @param      handle  - pointer to FuriHalSpiHandle
- * 
- * @return     channel
- */
-uint8_t nrf24_get_chan(FuriHalSpiBusHandle* handle);
-
-/** Sets the channel
- *
- * @param      handle  - pointer to FuriHalSpiHandle
- * @param      frequency - the frequency in hertz
- * 
- * @return     device status
- */
-uint8_t nrf24_set_chan(FuriHalSpiBusHandle* handle, uint8_t chan);
-
-/** Gets the source mac address
- *
- * @param      handle  - pointer to FuriHalSpiHandle
- * @param[out] mac - the source mac address
- * 
- * @return     device status
- */
-uint8_t nrf24_get_src_mac(FuriHalSpiBusHandle* handle, uint8_t* mac);
-
-/** Sets the source mac address
- *
- * @param      handle  - pointer to FuriHalSpiHandle
- * @param      mac - the mac address to set
- * @param      size - the size of the mac address (2 to 5)
- * 
- * @return     device status
- */
-uint8_t nrf24_set_src_mac(FuriHalSpiBusHandle* handle, uint8_t* mac, uint8_t size);
-
-/** Gets the dest mac address
- *
- * @param      handle  - pointer to FuriHalSpiHandle
- * @param[out] mac - the source mac address
- * 
- * @return     device status
- */
-uint8_t nrf24_get_dst_mac(FuriHalSpiBusHandle* handle, uint8_t* mac);
-
-/** Sets the dest mac address
- *
- * @param      handle  - pointer to FuriHalSpiHandle
- * @param      mac - the mac address to set
- * @param      size - the size of the mac address (2 to 5)
- * 
- * @return     device status
- */
-uint8_t nrf24_set_dst_mac(FuriHalSpiBusHandle* handle, uint8_t* mac, uint8_t size);
-
-/** Reads RX packet
- *
- * @param      handle  - pointer to FuriHalSpiHandle
- * @param[out] packet - the packet contents
- * @param[out] packetsize - size of the received packet
- * @param      full - boolean set to true, packet length is determined by RX_PW_P0 register, false it is determined by dynamic payload length command
- * 
- * @return     device status
- */
-uint8_t
-    nrf24_rxpacket(FuriHalSpiBusHandle* handle, uint8_t* packet, uint8_t* packetsize, bool full);
-
-/** Sends TX packet
- *
- * @param      handle  - pointer to FuriHalSpiHandle
- * @param      packet - the packet contents
- * @param      size - packet size
- * @param      ack - boolean to determine whether an ACK is required for the packet or not
- * 
- * @return     device status
- */
-uint8_t nrf24_txpacket(FuriHalSpiBusHandle* handle, uint8_t* payload, uint8_t size, bool ack);
-
-/** Configure the radio
- * This is not comprehensive, but covers a lot of the common configuration options that may be changed
- * @param      handle  - pointer to FuriHalSpiHandle
- * @param      rate - transfer rate in Mbps (1 or 2)
- * @param      srcmac - source mac address
- * @param      dstmac - destination mac address
- * @param      maclen - length of mac address
- * @param      channel - channel to tune to
- * @param      noack - if true, disable auto-acknowledge
- * @param      disable_aa - if true, disable ShockBurst
- * 
- */
-void nrf24_configure(
-    FuriHalSpiBusHandle* handle,
-    uint8_t rate,
-    uint8_t* srcmac,
-    uint8_t* dstmac,
-    uint8_t maclen,
-    uint8_t channel,
-    bool noack,
-    bool disable_aa);
-
-/** Configures the radio for "promiscuous mode" and primes it for rx
- * This is not an actual mode of the nrf24, but this function exploits a few bugs in the chip that allows it to act as if it were.
- * See http://travisgoodspeed.blogspot.com/2011/02/promiscuity-is-nrf24l01s-duty.html for details.
- * @param      handle  - pointer to FuriHalSpiHandle
- * @param      channel - channel to tune to
- * @param      rate - transfer rate in Mbps (1 or 2) 
- */
-void nrf24_init_promisc_mode(FuriHalSpiBusHandle* handle, uint8_t channel, uint8_t rate);
-
-/** Listens for a packet and returns first possible address sniffed
- * Call this only after calling nrf24_init_promisc_mode
- * @param      handle  - pointer to FuriHalSpiHandle
- * @param      maclen - length of target mac address
- * @param[out] addresses - sniffed address
- * 
- * @return     success
- */
-bool nrf24_sniff_address(FuriHalSpiBusHandle* handle, uint8_t maclen, uint8_t* address);
-
-/** Sends ping packet on each channel for designated tx mac looking for ack
- * 
- * @param      handle  - pointer to FuriHalSpiHandle
- * @param      srcmac - source address
- * @param      dstmac - destination address
- * @param      maclen - length of address
- * @param      rate - transfer rate in Mbps (1 or 2) 
- * @param      min_channel - channel to start with
- * @param      max_channel - channel to end at
- * @param      autoinit - if true, automatically configure radio for this channel
- * 
- * @return     channel that the address is listening on, if this value is above the max_channel param, it failed
- */
-uint8_t nrf24_find_channel(
-    FuriHalSpiBusHandle* handle,
-    uint8_t* srcmac,
-    uint8_t* dstmac,
-    uint8_t maclen,
-    uint8_t rate,
-    uint8_t min_channel,
-    uint8_t max_channel,
-    bool autoinit);
-
-/** Converts 64 bit value into uint8_t array
- * @param      val  - 64-bit integer
- * @param[out] out - bytes out
- * @param      bigendian - if true, convert as big endian, otherwise little endian
- */
-void int64_to_bytes(uint64_t val, uint8_t* out, bool bigendian);
-
-/** Converts 32 bit value into uint8_t array
- * @param      val  - 32-bit integer
- * @param[out] out - bytes out
- * @param      bigendian - if true, convert as big endian, otherwise little endian
- */
-void int32_to_bytes(uint32_t val, uint8_t* out, bool bigendian);
-
-/** Converts uint8_t array into 32 bit value
- * @param      bytes  - uint8_t array
- * @param      bigendian - if true, convert as big endian, otherwise little endian
- * 
- * @return     32-bit value
- */
-uint32_t bytes_to_int32(uint8_t* bytes, bool bigendian);
-
-#ifdef __cplusplus
-}
-#endif

+ 0 - 456
non_catalog_apps/nrfsniff/nrfsniff.c

@@ -1,456 +0,0 @@
-#include <furi.h>
-#include <furi_hal.h>
-#include <gui/gui.h>
-#include <input/input.h>
-#include <notification/notification_messages.h>
-#include <stdlib.h>
-
-#include <nrf24.h>
-#include <toolbox/stream/file_stream.h>
-
-#define LOGITECH_MAX_CHANNEL 85
-#define COUNT_THRESHOLD 2
-#define DEFAULT_SAMPLE_TIME 8000
-#define MAX_ADDRS 100
-#define MAX_CONFIRMED 32
-
-#define NRFSNIFF_APP_PATH_FOLDER "/ext/nrfsniff"
-#define NRFSNIFF_APP_FILENAME "addresses.txt"
-#define TAG "nrfsniff"
-
-typedef enum {
-    EventTypeTick,
-    EventTypeKey,
-} EventType;
-
-typedef struct {
-    EventType type;
-    InputEvent input;
-} PluginEvent;
-
-typedef struct {
-    FuriMutex* mutex;
-} PluginState;
-
-char rate_text_fmt[] = "Transfer rate: %dMbps";
-char sample_text_fmt[] = "Sample Time: %d ms";
-char channel_text_fmt[] = "Channel: %d    Sniffing: %s";
-char preamble_text_fmt[] = "Preamble: %02X";
-char sniff_text_fmt[] = "Found: %d       Unique: %u";
-char addresses_header_text[] = "Address,rate";
-char sniffed_address_fmt[] = "%s,%d";
-char rate_text[46];
-char channel_text[38];
-char sample_text[32];
-char preamble_text[14];
-char sniff_text[38];
-char sniffed_address[14];
-
-uint8_t target_channel = 0;
-uint32_t found_count = 0;
-uint32_t unique_saved_count = 0;
-uint32_t sample_time = DEFAULT_SAMPLE_TIME;
-uint8_t target_rate = 8; // rate can be either 8 (2Mbps) or 0 (1Mbps)
-uint8_t target_preamble[] = {0xAA, 0x00};
-uint8_t sniffing_state = false;
-char top_address[12];
-
-uint8_t candidates[MAX_ADDRS][5] = {0}; // last 100 sniffed addresses
-uint32_t counts[MAX_ADDRS];
-uint8_t confirmed[MAX_CONFIRMED][5] = {0}; // first 32 confirmed addresses
-uint8_t confirmed_idx = 0;
-uint32_t total_candidates = 0;
-uint32_t candidate_idx = 0;
-
-static int get_addr_index(uint8_t* addr, uint8_t addr_size) {
-    for(uint32_t i = 0; i < total_candidates; i++) {
-        uint8_t* arr_item = candidates[i];
-        if(!memcmp(arr_item, addr, addr_size)) return i;
-    }
-
-    return -1;
-}
-
-static int get_highest_idx() {
-    uint32_t highest = 0;
-    int highest_idx = 0;
-    for(uint32_t i = 0; i < total_candidates; i++) {
-        if(counts[i] > highest) {
-            highest = counts[i];
-            highest_idx = i;
-        }
-    }
-
-    return highest_idx;
-}
-
-// if array is full, start over from beginning
-static void insert_addr(uint8_t* addr, uint8_t addr_size) {
-    if(candidate_idx >= MAX_ADDRS) candidate_idx = 0;
-
-    memcpy(candidates[candidate_idx], addr, addr_size);
-    counts[candidate_idx] = 1;
-    if(total_candidates < MAX_ADDRS) total_candidates++;
-    candidate_idx++;
-}
-
-static void render_callback(Canvas* const canvas, void* ctx) {
-    furi_assert(ctx);
-    const PluginState* plugin_state = ctx;
-    furi_mutex_acquire(plugin_state->mutex, FuriWaitForever);
-
-    uint8_t rate = 2;
-    char sniffing[] = "Yes";
-
-    // border around the edge of the screen
-    canvas_draw_frame(canvas, 0, 0, 128, 64);
-    canvas_set_font(canvas, FontSecondary);
-
-    if(target_rate == 0) rate = 1;
-
-    if(!sniffing_state) strcpy(sniffing, "No");
-
-    snprintf(rate_text, sizeof(rate_text), rate_text_fmt, (int)rate);
-    snprintf(channel_text, sizeof(channel_text), channel_text_fmt, (int)target_channel, sniffing);
-    snprintf(sample_text, sizeof(sample_text), sample_text_fmt, (int)sample_time);
-    //snprintf(preamble_text, sizeof(preamble_text), preamble_text_fmt, target_preamble[0]);
-    snprintf(sniff_text, sizeof(sniff_text), sniff_text_fmt, found_count, unique_saved_count);
-    snprintf(
-        sniffed_address, sizeof(sniffed_address), sniffed_address_fmt, top_address, (int)rate);
-    canvas_draw_str_aligned(canvas, 10, 10, AlignLeft, AlignBottom, rate_text);
-    canvas_draw_str_aligned(canvas, 10, 20, AlignLeft, AlignBottom, sample_text);
-    canvas_draw_str_aligned(canvas, 10, 30, AlignLeft, AlignBottom, channel_text);
-    //canvas_draw_str_aligned(canvas, 10, 30, AlignLeft, AlignBottom, preamble_text);
-    canvas_draw_str_aligned(canvas, 10, 40, AlignLeft, AlignBottom, sniff_text);
-    canvas_draw_str_aligned(canvas, 30, 50, AlignLeft, AlignBottom, addresses_header_text);
-    canvas_draw_str_aligned(canvas, 30, 60, AlignLeft, AlignBottom, sniffed_address);
-
-    furi_mutex_release(plugin_state->mutex);
-}
-
-static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) {
-    furi_assert(event_queue);
-
-    PluginEvent event = {.type = EventTypeKey, .input = *input_event};
-    furi_message_queue_put(event_queue, &event, FuriWaitForever);
-}
-
-static void hexlify(uint8_t* in, uint8_t size, char* out) {
-    memset(out, 0, size * 2);
-    for(int i = 0; i < size; i++)
-        snprintf(out + strlen(out), sizeof(out + strlen(out)), "%02X", in[i]);
-}
-
-static bool save_addr_to_file(
-    Storage* storage,
-    uint8_t* data,
-    uint8_t size,
-    NotificationApp* notification) {
-    size_t file_size = 0;
-    uint8_t linesize = 0;
-    char filepath[42] = {0};
-    char addrline[14] = {0};
-    char ending[4];
-    uint8_t* file_contents;
-    uint8_t rate = 1;
-    Stream* stream = file_stream_alloc(storage);
-
-    if(target_rate == 8) rate = 2;
-    snprintf(ending, sizeof(ending), ",%d\n", rate);
-    hexlify(data, size, addrline);
-    strcat(addrline, ending);
-    linesize = strlen(addrline);
-    strcpy(filepath, NRFSNIFF_APP_PATH_FOLDER);
-    strcat(filepath, "/");
-    strcat(filepath, NRFSNIFF_APP_FILENAME);
-    stream_seek(stream, 0, StreamOffsetFromStart);
-
-    // check if address already exists in file
-    if(file_stream_open(stream, filepath, FSAM_READ_WRITE, FSOM_OPEN_APPEND)) {
-        bool found = false;
-        file_size = stream_size(stream);
-        stream_seek(stream, 0, StreamOffsetFromStart);
-        if(file_size > 0) {
-            file_contents = malloc(file_size + 1);
-            memset(file_contents, 0, file_size + 1);
-            if(stream_read(stream, file_contents, file_size) > 0) {
-                char* line = strtok((char*)file_contents, "\n");
-
-                while(line != NULL) {
-                    if(!memcmp(line, addrline, 12)) {
-                        found = true;
-                        break;
-                    }
-                    line = strtok(NULL, "\n");
-                }
-            }
-            free(file_contents);
-        }
-
-        if(found) {
-            FURI_LOG_I(TAG, "Address exists in file. Ending save process.");
-            stream_free(stream);
-            return false;
-        } else {
-            if(stream_write(stream, (uint8_t*)addrline, linesize) != linesize) {
-                FURI_LOG_I(TAG, "Failed to write bytes to file stream.");
-                stream_free(stream);
-                return false;
-            } else {
-                FURI_LOG_I(TAG, "Found a new address: %s", addrline);
-                FURI_LOG_I(TAG, "Save successful!");
-
-                notification_message(notification, &sequence_success);
-
-                stream_free(stream);
-                unique_saved_count++;
-                return true;
-            }
-        }
-    } else {
-        FURI_LOG_I(TAG, "Cannot open file \"%s\"", filepath);
-        stream_free(stream);
-        return false;
-    }
-}
-
-void alt_address(uint8_t* addr, uint8_t* altaddr) {
-    uint8_t macmess_hi_b[4];
-    uint32_t macmess_hi;
-    uint8_t macmess_lo;
-    uint8_t preserved;
-    uint8_t tmpaddr[5];
-
-    // swap bytes
-    for(int i = 0; i < 5; i++) tmpaddr[i] = addr[4 - i];
-
-    // get address into 32-bit and 8-bit variables
-    memcpy(macmess_hi_b, tmpaddr, 4);
-    macmess_lo = tmpaddr[4];
-
-    macmess_hi = bytes_to_int32(macmess_hi_b, true);
-
-    //preserve lowest bit from hi to shift to low
-    preserved = macmess_hi & 1;
-    macmess_hi >>= 1;
-    macmess_lo >>= 1;
-    macmess_lo = (preserved << 7) | macmess_lo;
-    int32_to_bytes(macmess_hi, macmess_hi_b, true);
-    memcpy(tmpaddr, macmess_hi_b, 4);
-    tmpaddr[4] = macmess_lo;
-
-    // swap bytes back
-    for(int i = 0; i < 5; i++) altaddr[i] = tmpaddr[4 - i];
-}
-
-static bool previously_confirmed(uint8_t* addr) {
-    bool found = false;
-    for(int i = 0; i < MAX_CONFIRMED; i++) {
-        if(!memcmp(confirmed[i], addr, 5)) {
-            found = true;
-            break;
-        }
-    }
-
-    return found;
-}
-
-static void wrap_up(Storage* storage, NotificationApp* notification) {
-    uint8_t ch;
-    uint8_t addr[5];
-    uint8_t altaddr[5];
-    char trying[12];
-    int idx;
-    uint8_t rate = 0;
-    if(target_rate == 8) rate = 2;
-
-    nrf24_set_idle(nrf24_HANDLE);
-
-    while(true) {
-        idx = get_highest_idx();
-        if(counts[idx] < COUNT_THRESHOLD) break;
-
-        counts[idx] = 0;
-        memcpy(addr, candidates[idx], 5);
-        hexlify(addr, 5, trying);
-        FURI_LOG_I(TAG, "trying address %s", trying);
-        ch = nrf24_find_channel(nrf24_HANDLE, addr, addr, 5, rate, 2, LOGITECH_MAX_CHANNEL, false);
-        FURI_LOG_I(TAG, "find_channel returned %d", (int)ch);
-        if(ch > LOGITECH_MAX_CHANNEL) {
-            alt_address(addr, altaddr);
-            hexlify(altaddr, 5, trying);
-            FURI_LOG_I(TAG, "trying alternate address %s", trying);
-            ch = nrf24_find_channel(
-                nrf24_HANDLE, altaddr, altaddr, 5, rate, 2, LOGITECH_MAX_CHANNEL, false);
-            FURI_LOG_I(TAG, "find_channel returned %d", (int)ch);
-            memcpy(addr, altaddr, 5);
-        }
-
-        if(ch <= LOGITECH_MAX_CHANNEL) {
-            hexlify(addr, 5, top_address);
-            found_count++;
-            save_addr_to_file(storage, addr, 5, notification);
-            if(confirmed_idx < MAX_CONFIRMED) memcpy(confirmed[confirmed_idx++], addr, 5);
-            break;
-        }
-    }
-}
-
-static void clear_cache() {
-    found_count = 0;
-    unique_saved_count = 0;
-    confirmed_idx = 0;
-    candidate_idx = 0;
-    target_channel = 2;
-    total_candidates = 0;
-    memset(candidates, 0, sizeof(candidates));
-    memset(counts, 0, sizeof(counts));
-    memset(confirmed, 0, sizeof(confirmed));
-}
-
-static void start_sniffing() {
-    nrf24_init_promisc_mode(nrf24_HANDLE, target_channel, target_rate);
-}
-
-int32_t nrfsniff_app(void* p) {
-    UNUSED(p);
-    uint8_t address[5] = {0};
-    uint32_t start = 0;
-    hexlify(address, 5, top_address);
-    FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(PluginEvent));
-    PluginState* plugin_state = malloc(sizeof(PluginState));
-    plugin_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
-    if(!plugin_state->mutex) {
-        furi_message_queue_free(event_queue);
-        FURI_LOG_E(TAG, "cannot create mutex\r\n");
-        free(plugin_state);
-        return 255;
-    }
-
-    nrf24_init();
-
-    // Set system callbacks
-    ViewPort* view_port = view_port_alloc();
-    view_port_draw_callback_set(view_port, render_callback, plugin_state);
-    view_port_input_callback_set(view_port, input_callback, event_queue);
-
-    // Open GUI and register view_port
-    Gui* gui = furi_record_open(RECORD_GUI);
-    gui_add_view_port(gui, view_port, GuiLayerFullscreen);
-
-    NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION);
-
-    Storage* storage = furi_record_open(RECORD_STORAGE);
-    storage_common_mkdir(storage, NRFSNIFF_APP_PATH_FOLDER);
-
-    PluginEvent event;
-    for(bool processing = true; processing;) {
-        FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);
-        furi_mutex_acquire(plugin_state->mutex, FuriWaitForever);
-
-        if(event_status == FuriStatusOk) {
-            // press events
-            if(event.type == EventTypeKey) {
-                if(event.input.type == InputTypePress ||
-                   (event.input.type == InputTypeLong && event.input.key == InputKeyBack)) {
-                    switch(event.input.key) {
-                    case InputKeyUp:
-                        // toggle rate  1/2Mbps
-                        if(!sniffing_state) {
-                            if(target_rate == 0)
-                                target_rate = 8;
-                            else
-                                target_rate = 0;
-                        }
-                        break;
-                    case InputKeyDown:
-                        // toggle preamble
-                        if(!sniffing_state) {
-                            if(target_preamble[0] == 0x55)
-                                target_preamble[0] = 0xAA;
-                            else
-                                target_preamble[0] = 0x55;
-
-                            nrf24_set_src_mac(nrf24_HANDLE, target_preamble, 2);
-                        }
-                        break;
-                    case InputKeyRight:
-                        // increment channel
-                        //if(!sniffing_state && target_channel <= LOGITECH_MAX_CHANNEL)
-                        //    target_channel++;
-                        sample_time += 500;
-                        break;
-                    case InputKeyLeft:
-                        // decrement channel
-                        //if(!sniffing_state && target_channel > 0) target_channel--;
-                        if(sample_time > 500) sample_time -= 500;
-                        break;
-                    case InputKeyOk:
-                        // toggle sniffing
-                        sniffing_state = !sniffing_state;
-                        if(sniffing_state) {
-                            clear_cache();
-                            start_sniffing();
-                            start = furi_get_tick();
-                        } else
-                            wrap_up(storage, notification);
-                        break;
-                    case InputKeyBack:
-                        if(event.input.type == InputTypeLong) processing = false;
-                        break;
-                    default:
-                        break;
-                    }
-                }
-            }
-        }
-
-        if(sniffing_state) {
-            if(nrf24_sniff_address(nrf24_HANDLE, 5, address)) {
-                int idx;
-                uint8_t* top_addr;
-                if(!previously_confirmed(address)) {
-                    idx = get_addr_index(address, 5);
-                    if(idx == -1)
-                        insert_addr(address, 5);
-                    else
-                        counts[idx]++;
-
-                    top_addr = candidates[get_highest_idx()];
-                    hexlify(top_addr, 5, top_address);
-                }
-            }
-
-            if(furi_get_tick() - start >= sample_time) {
-                target_channel++;
-                if(target_channel > LOGITECH_MAX_CHANNEL) target_channel = 2;
-                {
-                    wrap_up(storage, notification);
-                    start_sniffing();
-                }
-
-                start = furi_get_tick();
-            }
-        }
-
-        view_port_update(view_port);
-        furi_mutex_release(plugin_state->mutex);
-    }
-
-    clear_cache();
-    sample_time = DEFAULT_SAMPLE_TIME;
-    target_rate = 8; // rate can be either 8 (2Mbps) or 0 (1Mbps)
-    sniffing_state = false;
-    nrf24_deinit();
-    view_port_enabled_set(view_port, false);
-    gui_remove_view_port(gui, view_port);
-    furi_record_close(RECORD_GUI);
-    furi_record_close(RECORD_NOTIFICATION);
-    furi_record_close(RECORD_STORAGE);
-    view_port_free(view_port);
-    furi_message_queue_free(event_queue);
-    furi_mutex_free(plugin_state->mutex);
-    free(plugin_state);
-
-    return 0;
-}

BIN
non_catalog_apps/nrfsniff/nrfsniff_10px.png


+ 0 - 674
non_catalog_apps/unitemp/LICENSE.md

@@ -1,674 +0,0 @@
-                    GNU GENERAL PUBLIC LICENSE
-                       Version 3, 29 June 2007
-
- Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-                            Preamble
-
-  The GNU General Public License is a free, copyleft license for
-software and other kinds of works.
-
-  The licenses for most software and other practical works are designed
-to take away your freedom to share and change the works.  By contrast,
-the GNU General Public License is intended to guarantee your freedom to
-share and change all versions of a program--to make sure it remains free
-software for all its users.  We, the Free Software Foundation, use the
-GNU General Public License for most of our software; it applies also to
-any other work released this way by its authors.  You can apply it to
-your programs, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-them if you wish), that you receive source code or can get it if you
-want it, that you can change the software or use pieces of it in new
-free programs, and that you know you can do these things.
-
-  To protect your rights, we need to prevent others from denying you
-these rights or asking you to surrender the rights.  Therefore, you have
-certain responsibilities if you distribute copies of the software, or if
-you modify it: responsibilities to respect the freedom of others.
-
-  For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must pass on to the recipients the same
-freedoms that you received.  You must make sure that they, too, receive
-or can get the source code.  And you must show them these terms so they
-know their rights.
-
-  Developers that use the GNU GPL protect your rights with two steps:
-(1) assert copyright on the software, and (2) offer you this License
-giving you legal permission to copy, distribute and/or modify it.
-
-  For the developers' and authors' protection, the GPL clearly explains
-that there is no warranty for this free software.  For both users' and
-authors' sake, the GPL requires that modified versions be marked as
-changed, so that their problems will not be attributed erroneously to
-authors of previous versions.
-
-  Some devices are designed to deny users access to install or run
-modified versions of the software inside them, although the manufacturer
-can do so.  This is fundamentally incompatible with the aim of
-protecting users' freedom to change the software.  The systematic
-pattern of such abuse occurs in the area of products for individuals to
-use, which is precisely where it is most unacceptable.  Therefore, we
-have designed this version of the GPL to prohibit the practice for those
-products.  If such problems arise substantially in other domains, we
-stand ready to extend this provision to those domains in future versions
-of the GPL, as needed to protect the freedom of users.
-
-  Finally, every program is threatened constantly by software patents.
-States should not allow patents to restrict development and use of
-software on general-purpose computers, but in those that do, we wish to
-avoid the special danger that patents applied to a free program could
-make it effectively proprietary.  To prevent this, the GPL assures that
-patents cannot be used to render the program non-free.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.
-
-                       TERMS AND CONDITIONS
-
-  0. Definitions.
-
-  "This License" refers to version 3 of the GNU General Public License.
-
-  "Copyright" also means copyright-like laws that apply to other kinds of
-works, such as semiconductor masks.
-
-  "The Program" refers to any copyrightable work licensed under this
-License.  Each licensee is addressed as "you".  "Licensees" and
-"recipients" may be individuals or organizations.
-
-  To "modify" a work means to copy from or adapt all or part of the work
-in a fashion requiring copyright permission, other than the making of an
-exact copy.  The resulting work is called a "modified version" of the
-earlier work or a work "based on" the earlier work.
-
-  A "covered work" means either the unmodified Program or a work based
-on the Program.
-
-  To "propagate" a work means to do anything with it that, without
-permission, would make you directly or secondarily liable for
-infringement under applicable copyright law, except executing it on a
-computer or modifying a private copy.  Propagation includes copying,
-distribution (with or without modification), making available to the
-public, and in some countries other activities as well.
-
-  To "convey" a work means any kind of propagation that enables other
-parties to make or receive copies.  Mere interaction with a user through
-a computer network, with no transfer of a copy, is not conveying.
-
-  An interactive user interface displays "Appropriate Legal Notices"
-to the extent that it includes a convenient and prominently visible
-feature that (1) displays an appropriate copyright notice, and (2)
-tells the user that there is no warranty for the work (except to the
-extent that warranties are provided), that licensees may convey the
-work under this License, and how to view a copy of this License.  If
-the interface presents a list of user commands or options, such as a
-menu, a prominent item in the list meets this criterion.
-
-  1. Source Code.
-
-  The "source code" for a work means the preferred form of the work
-for making modifications to it.  "Object code" means any non-source
-form of a work.
-
-  A "Standard Interface" means an interface that either is an official
-standard defined by a recognized standards body, or, in the case of
-interfaces specified for a particular programming language, one that
-is widely used among developers working in that language.
-
-  The "System Libraries" of an executable work include anything, other
-than the work as a whole, that (a) is included in the normal form of
-packaging a Major Component, but which is not part of that Major
-Component, and (b) serves only to enable use of the work with that
-Major Component, or to implement a Standard Interface for which an
-implementation is available to the public in source code form.  A
-"Major Component", in this context, means a major essential component
-(kernel, window system, and so on) of the specific operating system
-(if any) on which the executable work runs, or a compiler used to
-produce the work, or an object code interpreter used to run it.
-
-  The "Corresponding Source" for a work in object code form means all
-the source code needed to generate, install, and (for an executable
-work) run the object code and to modify the work, including scripts to
-control those activities.  However, it does not include the work's
-System Libraries, or general-purpose tools or generally available free
-programs which are used unmodified in performing those activities but
-which are not part of the work.  For example, Corresponding Source
-includes interface definition files associated with source files for
-the work, and the source code for shared libraries and dynamically
-linked subprograms that the work is specifically designed to require,
-such as by intimate data communication or control flow between those
-subprograms and other parts of the work.
-
-  The Corresponding Source need not include anything that users
-can regenerate automatically from other parts of the Corresponding
-Source.
-
-  The Corresponding Source for a work in source code form is that
-same work.
-
-  2. Basic Permissions.
-
-  All rights granted under this License are granted for the term of
-copyright on the Program, and are irrevocable provided the stated
-conditions are met.  This License explicitly affirms your unlimited
-permission to run the unmodified Program.  The output from running a
-covered work is covered by this License only if the output, given its
-content, constitutes a covered work.  This License acknowledges your
-rights of fair use or other equivalent, as provided by copyright law.
-
-  You may make, run and propagate covered works that you do not
-convey, without conditions so long as your license otherwise remains
-in force.  You may convey covered works to others for the sole purpose
-of having them make modifications exclusively for you, or provide you
-with facilities for running those works, provided that you comply with
-the terms of this License in conveying all material for which you do
-not control copyright.  Those thus making or running the covered works
-for you must do so exclusively on your behalf, under your direction
-and control, on terms that prohibit them from making any copies of
-your copyrighted material outside their relationship with you.
-
-  Conveying under any other circumstances is permitted solely under
-the conditions stated below.  Sublicensing is not allowed; section 10
-makes it unnecessary.
-
-  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
-
-  No covered work shall be deemed part of an effective technological
-measure under any applicable law fulfilling obligations under article
-11 of the WIPO copyright treaty adopted on 20 December 1996, or
-similar laws prohibiting or restricting circumvention of such
-measures.
-
-  When you convey a covered work, you waive any legal power to forbid
-circumvention of technological measures to the extent such circumvention
-is effected by exercising rights under this License with respect to
-the covered work, and you disclaim any intention to limit operation or
-modification of the work as a means of enforcing, against the work's
-users, your or third parties' legal rights to forbid circumvention of
-technological measures.
-
-  4. Conveying Verbatim Copies.
-
-  You may convey verbatim copies of the Program's source code as you
-receive it, in any medium, provided that you conspicuously and
-appropriately publish on each copy an appropriate copyright notice;
-keep intact all notices stating that this License and any
-non-permissive terms added in accord with section 7 apply to the code;
-keep intact all notices of the absence of any warranty; and give all
-recipients a copy of this License along with the Program.
-
-  You may charge any price or no price for each copy that you convey,
-and you may offer support or warranty protection for a fee.
-
-  5. Conveying Modified Source Versions.
-
-  You may convey a work based on the Program, or the modifications to
-produce it from the Program, in the form of source code under the
-terms of section 4, provided that you also meet all of these conditions:
-
-    a) The work must carry prominent notices stating that you modified
-    it, and giving a relevant date.
-
-    b) The work must carry prominent notices stating that it is
-    released under this License and any conditions added under section
-    7.  This requirement modifies the requirement in section 4 to
-    "keep intact all notices".
-
-    c) You must license the entire work, as a whole, under this
-    License to anyone who comes into possession of a copy.  This
-    License will therefore apply, along with any applicable section 7
-    additional terms, to the whole of the work, and all its parts,
-    regardless of how they are packaged.  This License gives no
-    permission to license the work in any other way, but it does not
-    invalidate such permission if you have separately received it.
-
-    d) If the work has interactive user interfaces, each must display
-    Appropriate Legal Notices; however, if the Program has interactive
-    interfaces that do not display Appropriate Legal Notices, your
-    work need not make them do so.
-
-  A compilation of a covered work with other separate and independent
-works, which are not by their nature extensions of the covered work,
-and which are not combined with it such as to form a larger program,
-in or on a volume of a storage or distribution medium, is called an
-"aggregate" if the compilation and its resulting copyright are not
-used to limit the access or legal rights of the compilation's users
-beyond what the individual works permit.  Inclusion of a covered work
-in an aggregate does not cause this License to apply to the other
-parts of the aggregate.
-
-  6. Conveying Non-Source Forms.
-
-  You may convey a covered work in object code form under the terms
-of sections 4 and 5, provided that you also convey the
-machine-readable Corresponding Source under the terms of this License,
-in one of these ways:
-
-    a) Convey the object code in, or embodied in, a physical product
-    (including a physical distribution medium), accompanied by the
-    Corresponding Source fixed on a durable physical medium
-    customarily used for software interchange.
-
-    b) Convey the object code in, or embodied in, a physical product
-    (including a physical distribution medium), accompanied by a
-    written offer, valid for at least three years and valid for as
-    long as you offer spare parts or customer support for that product
-    model, to give anyone who possesses the object code either (1) a
-    copy of the Corresponding Source for all the software in the
-    product that is covered by this License, on a durable physical
-    medium customarily used for software interchange, for a price no
-    more than your reasonable cost of physically performing this
-    conveying of source, or (2) access to copy the
-    Corresponding Source from a network server at no charge.
-
-    c) Convey individual copies of the object code with a copy of the
-    written offer to provide the Corresponding Source.  This
-    alternative is allowed only occasionally and noncommercially, and
-    only if you received the object code with such an offer, in accord
-    with subsection 6b.
-
-    d) Convey the object code by offering access from a designated
-    place (gratis or for a charge), and offer equivalent access to the
-    Corresponding Source in the same way through the same place at no
-    further charge.  You need not require recipients to copy the
-    Corresponding Source along with the object code.  If the place to
-    copy the object code is a network server, the Corresponding Source
-    may be on a different server (operated by you or a third party)
-    that supports equivalent copying facilities, provided you maintain
-    clear directions next to the object code saying where to find the
-    Corresponding Source.  Regardless of what server hosts the
-    Corresponding Source, you remain obligated to ensure that it is
-    available for as long as needed to satisfy these requirements.
-
-    e) Convey the object code using peer-to-peer transmission, provided
-    you inform other peers where the object code and Corresponding
-    Source of the work are being offered to the general public at no
-    charge under subsection 6d.
-
-  A separable portion of the object code, whose source code is excluded
-from the Corresponding Source as a System Library, need not be
-included in conveying the object code work.
-
-  A "User Product" is either (1) a "consumer product", which means any
-tangible personal property which is normally used for personal, family,
-or household purposes, or (2) anything designed or sold for incorporation
-into a dwelling.  In determining whether a product is a consumer product,
-doubtful cases shall be resolved in favor of coverage.  For a particular
-product received by a particular user, "normally used" refers to a
-typical or common use of that class of product, regardless of the status
-of the particular user or of the way in which the particular user
-actually uses, or expects or is expected to use, the product.  A product
-is a consumer product regardless of whether the product has substantial
-commercial, industrial or non-consumer uses, unless such uses represent
-the only significant mode of use of the product.
-
-  "Installation Information" for a User Product means any methods,
-procedures, authorization keys, or other information required to install
-and execute modified versions of a covered work in that User Product from
-a modified version of its Corresponding Source.  The information must
-suffice to ensure that the continued functioning of the modified object
-code is in no case prevented or interfered with solely because
-modification has been made.
-
-  If you convey an object code work under this section in, or with, or
-specifically for use in, a User Product, and the conveying occurs as
-part of a transaction in which the right of possession and use of the
-User Product is transferred to the recipient in perpetuity or for a
-fixed term (regardless of how the transaction is characterized), the
-Corresponding Source conveyed under this section must be accompanied
-by the Installation Information.  But this requirement does not apply
-if neither you nor any third party retains the ability to install
-modified object code on the User Product (for example, the work has
-been installed in ROM).
-
-  The requirement to provide Installation Information does not include a
-requirement to continue to provide support service, warranty, or updates
-for a work that has been modified or installed by the recipient, or for
-the User Product in which it has been modified or installed.  Access to a
-network may be denied when the modification itself materially and
-adversely affects the operation of the network or violates the rules and
-protocols for communication across the network.
-
-  Corresponding Source conveyed, and Installation Information provided,
-in accord with this section must be in a format that is publicly
-documented (and with an implementation available to the public in
-source code form), and must require no special password or key for
-unpacking, reading or copying.
-
-  7. Additional Terms.
-
-  "Additional permissions" are terms that supplement the terms of this
-License by making exceptions from one or more of its conditions.
-Additional permissions that are applicable to the entire Program shall
-be treated as though they were included in this License, to the extent
-that they are valid under applicable law.  If additional permissions
-apply only to part of the Program, that part may be used separately
-under those permissions, but the entire Program remains governed by
-this License without regard to the additional permissions.
-
-  When you convey a copy of a covered work, you may at your option
-remove any additional permissions from that copy, or from any part of
-it.  (Additional permissions may be written to require their own
-removal in certain cases when you modify the work.)  You may place
-additional permissions on material, added by you to a covered work,
-for which you have or can give appropriate copyright permission.
-
-  Notwithstanding any other provision of this License, for material you
-add to a covered work, you may (if authorized by the copyright holders of
-that material) supplement the terms of this License with terms:
-
-    a) Disclaiming warranty or limiting liability differently from the
-    terms of sections 15 and 16 of this License; or
-
-    b) Requiring preservation of specified reasonable legal notices or
-    author attributions in that material or in the Appropriate Legal
-    Notices displayed by works containing it; or
-
-    c) Prohibiting misrepresentation of the origin of that material, or
-    requiring that modified versions of such material be marked in
-    reasonable ways as different from the original version; or
-
-    d) Limiting the use for publicity purposes of names of licensors or
-    authors of the material; or
-
-    e) Declining to grant rights under trademark law for use of some
-    trade names, trademarks, or service marks; or
-
-    f) Requiring indemnification of licensors and authors of that
-    material by anyone who conveys the material (or modified versions of
-    it) with contractual assumptions of liability to the recipient, for
-    any liability that these contractual assumptions directly impose on
-    those licensors and authors.
-
-  All other non-permissive additional terms are considered "further
-restrictions" within the meaning of section 10.  If the Program as you
-received it, or any part of it, contains a notice stating that it is
-governed by this License along with a term that is a further
-restriction, you may remove that term.  If a license document contains
-a further restriction but permits relicensing or conveying under this
-License, you may add to a covered work material governed by the terms
-of that license document, provided that the further restriction does
-not survive such relicensing or conveying.
-
-  If you add terms to a covered work in accord with this section, you
-must place, in the relevant source files, a statement of the
-additional terms that apply to those files, or a notice indicating
-where to find the applicable terms.
-
-  Additional terms, permissive or non-permissive, may be stated in the
-form of a separately written license, or stated as exceptions;
-the above requirements apply either way.
-
-  8. Termination.
-
-  You may not propagate or modify a covered work except as expressly
-provided under this License.  Any attempt otherwise to propagate or
-modify it is void, and will automatically terminate your rights under
-this License (including any patent licenses granted under the third
-paragraph of section 11).
-
-  However, if you cease all violation of this License, then your
-license from a particular copyright holder is reinstated (a)
-provisionally, unless and until the copyright holder explicitly and
-finally terminates your license, and (b) permanently, if the copyright
-holder fails to notify you of the violation by some reasonable means
-prior to 60 days after the cessation.
-
-  Moreover, your license from a particular copyright holder is
-reinstated permanently if the copyright holder notifies you of the
-violation by some reasonable means, this is the first time you have
-received notice of violation of this License (for any work) from that
-copyright holder, and you cure the violation prior to 30 days after
-your receipt of the notice.
-
-  Termination of your rights under this section does not terminate the
-licenses of parties who have received copies or rights from you under
-this License.  If your rights have been terminated and not permanently
-reinstated, you do not qualify to receive new licenses for the same
-material under section 10.
-
-  9. Acceptance Not Required for Having Copies.
-
-  You are not required to accept this License in order to receive or
-run a copy of the Program.  Ancillary propagation of a covered work
-occurring solely as a consequence of using peer-to-peer transmission
-to receive a copy likewise does not require acceptance.  However,
-nothing other than this License grants you permission to propagate or
-modify any covered work.  These actions infringe copyright if you do
-not accept this License.  Therefore, by modifying or propagating a
-covered work, you indicate your acceptance of this License to do so.
-
-  10. Automatic Licensing of Downstream Recipients.
-
-  Each time you convey a covered work, the recipient automatically
-receives a license from the original licensors, to run, modify and
-propagate that work, subject to this License.  You are not responsible
-for enforcing compliance by third parties with this License.
-
-  An "entity transaction" is a transaction transferring control of an
-organization, or substantially all assets of one, or subdividing an
-organization, or merging organizations.  If propagation of a covered
-work results from an entity transaction, each party to that
-transaction who receives a copy of the work also receives whatever
-licenses to the work the party's predecessor in interest had or could
-give under the previous paragraph, plus a right to possession of the
-Corresponding Source of the work from the predecessor in interest, if
-the predecessor has it or can get it with reasonable efforts.
-
-  You may not impose any further restrictions on the exercise of the
-rights granted or affirmed under this License.  For example, you may
-not impose a license fee, royalty, or other charge for exercise of
-rights granted under this License, and you may not initiate litigation
-(including a cross-claim or counterclaim in a lawsuit) alleging that
-any patent claim is infringed by making, using, selling, offering for
-sale, or importing the Program or any portion of it.
-
-  11. Patents.
-
-  A "contributor" is a copyright holder who authorizes use under this
-License of the Program or a work on which the Program is based.  The
-work thus licensed is called the contributor's "contributor version".
-
-  A contributor's "essential patent claims" are all patent claims
-owned or controlled by the contributor, whether already acquired or
-hereafter acquired, that would be infringed by some manner, permitted
-by this License, of making, using, or selling its contributor version,
-but do not include claims that would be infringed only as a
-consequence of further modification of the contributor version.  For
-purposes of this definition, "control" includes the right to grant
-patent sublicenses in a manner consistent with the requirements of
-this License.
-
-  Each contributor grants you a non-exclusive, worldwide, royalty-free
-patent license under the contributor's essential patent claims, to
-make, use, sell, offer for sale, import and otherwise run, modify and
-propagate the contents of its contributor version.
-
-  In the following three paragraphs, a "patent license" is any express
-agreement or commitment, however denominated, not to enforce a patent
-(such as an express permission to practice a patent or covenant not to
-sue for patent infringement).  To "grant" such a patent license to a
-party means to make such an agreement or commitment not to enforce a
-patent against the party.
-
-  If you convey a covered work, knowingly relying on a patent license,
-and the Corresponding Source of the work is not available for anyone
-to copy, free of charge and under the terms of this License, through a
-publicly available network server or other readily accessible means,
-then you must either (1) cause the Corresponding Source to be so
-available, or (2) arrange to deprive yourself of the benefit of the
-patent license for this particular work, or (3) arrange, in a manner
-consistent with the requirements of this License, to extend the patent
-license to downstream recipients.  "Knowingly relying" means you have
-actual knowledge that, but for the patent license, your conveying the
-covered work in a country, or your recipient's use of the covered work
-in a country, would infringe one or more identifiable patents in that
-country that you have reason to believe are valid.
-
-  If, pursuant to or in connection with a single transaction or
-arrangement, you convey, or propagate by procuring conveyance of, a
-covered work, and grant a patent license to some of the parties
-receiving the covered work authorizing them to use, propagate, modify
-or convey a specific copy of the covered work, then the patent license
-you grant is automatically extended to all recipients of the covered
-work and works based on it.
-
-  A patent license is "discriminatory" if it does not include within
-the scope of its coverage, prohibits the exercise of, or is
-conditioned on the non-exercise of one or more of the rights that are
-specifically granted under this License.  You may not convey a covered
-work if you are a party to an arrangement with a third party that is
-in the business of distributing software, under which you make payment
-to the third party based on the extent of your activity of conveying
-the work, and under which the third party grants, to any of the
-parties who would receive the covered work from you, a discriminatory
-patent license (a) in connection with copies of the covered work
-conveyed by you (or copies made from those copies), or (b) primarily
-for and in connection with specific products or compilations that
-contain the covered work, unless you entered into that arrangement,
-or that patent license was granted, prior to 28 March 2007.
-
-  Nothing in this License shall be construed as excluding or limiting
-any implied license or other defenses to infringement that may
-otherwise be available to you under applicable patent law.
-
-  12. No Surrender of Others' Freedom.
-
-  If conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot convey a
-covered work so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you may
-not convey it at all.  For example, if you agree to terms that obligate you
-to collect a royalty for further conveying from those to whom you convey
-the Program, the only way you could satisfy both those terms and this
-License would be to refrain entirely from conveying the Program.
-
-  13. Use with the GNU Affero General Public License.
-
-  Notwithstanding any other provision of this License, you have
-permission to link or combine any covered work with a work licensed
-under version 3 of the GNU Affero General Public License into a single
-combined work, and to convey the resulting work.  The terms of this
-License will continue to apply to the part which is the covered work,
-but the special requirements of the GNU Affero General Public License,
-section 13, concerning interaction through a network will apply to the
-combination as such.
-
-  14. Revised Versions of this License.
-
-  The Free Software Foundation may publish revised and/or new versions of
-the GNU General Public License from time to time.  Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-  Each version is given a distinguishing version number.  If the
-Program specifies that a certain numbered version of the GNU General
-Public License "or any later version" applies to it, you have the
-option of following the terms and conditions either of that numbered
-version or of any later version published by the Free Software
-Foundation.  If the Program does not specify a version number of the
-GNU General Public License, you may choose any version ever published
-by the Free Software Foundation.
-
-  If the Program specifies that a proxy can decide which future
-versions of the GNU General Public License can be used, that proxy's
-public statement of acceptance of a version permanently authorizes you
-to choose that version for the Program.
-
-  Later license versions may give you additional or different
-permissions.  However, no additional obligations are imposed on any
-author or copyright holder as a result of your choosing to follow a
-later version.
-
-  15. Disclaimer of Warranty.
-
-  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
-APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
-HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
-OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
-THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
-IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
-ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
-  16. Limitation of Liability.
-
-  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
-THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
-GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
-USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
-DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
-PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
-EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGES.
-
-  17. Interpretation of Sections 15 and 16.
-
-  If the disclaimer of warranty and limitation of liability provided
-above cannot be given local legal effect according to their terms,
-reviewing courts shall apply local law that most closely approximates
-an absolute waiver of all civil liability in connection with the
-Program, unless a warranty or assumption of liability accompanies a
-copy of the Program in return for a fee.
-
-                     END OF TERMS AND CONDITIONS
-
-            How to Apply These Terms to Your New Programs
-
-  If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
-  To do so, attach the following notices to the program.  It is safest
-to attach them to the start of each source file to most effectively
-state the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    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 <https://www.gnu.org/licenses/>.
-
-Also add information on how to contact you by electronic and paper mail.
-
-  If the program does terminal interaction, make it output a short
-notice like this when it starts in an interactive mode:
-
-    <program>  Copyright (C) <year>  <name of author>
-    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
-    This is free software, and you are welcome to redistribute it
-    under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License.  Of course, your program's commands
-might be different; for a GUI interface, you would use an "about box".
-
-  You should also get your employer (if you work as a programmer) or school,
-if any, to sign a "copyright disclaimer" for the program, if necessary.
-For more information on this, and how to apply and follow the GNU GPL, see
-<https://www.gnu.org/licenses/>.
-
-  The GNU General Public License does not permit incorporating your program
-into proprietary programs.  If your program is a subroutine library, you
-may consider it more useful to permit linking proprietary applications with
-the library.  If this is what you want to do, use the GNU Lesser General
-Public License instead of this License.  But first, please read
-<https://www.gnu.org/licenses/why-not-lgpl.html>.

+ 0 - 24
non_catalog_apps/unitemp/README.md

@@ -1,24 +0,0 @@
-![Flipper usage](https://user-images.githubusercontent.com/10090793/211182642-e41919c5-3091-4125-815a-2d6a77a859f6.png)
-# Unitemp - Universal temperature sensor reader
-[![GitHub release](https://img.shields.io/github/release/quen0n/unitemp-flipperzero?include_prereleases=&sort=semver&color=blue)](https://github.com/quen0n/unitemp-flipperzero/releases/)
-[![GitHub](https://img.shields.io/github/license/quen0n/unitemp-flipperzero)](https://github.com/quen0n/unitemp-flipperzero/blob/dev/LICENSE.md)
-[![Build dev](https://github.com/quen0n/unitemp-flipperzero/actions/workflows/build_dev.yml/badge.svg?branch=dev)](https://github.com/quen0n/unitemp-flipperzero/actions/workflows/build_dev.yml)  
-[Flipper Zero](https://flipperzero.one/) application for reading temperature, humidity and pressure sensors like a DHT11/22, DS18B20, BMP280, HTU21 and more. 
-## List of supported sensors
-![image](https://user-images.githubusercontent.com/10090793/215605424-54b1c08c-e41b-4fb4-b966-dd959507200b.png)
-
-## Installation
-1) Download [latest version](https://cloud.quenon.ru/index.php/s/h98rT9UnaOL4wxR/download?path=%2F&files=unitemp-latest.fap)
-2) Copy `unitemp-latest.fap` to `SD card/apps/GPIO` with qFlipper or mobile application
-3) Open application on your Flipper: `Applications->GPIO->Temp sensors reader`  
-Note: If you get the message "API version mismatch" after updating the firmware, download and install Unitemp again
-## Need help? Discussions?
-Join the discussion, ask a question or just send a photo of the flipper with sensors to [Discord](https://discord.com/channels/740930220399525928/1056727938747351060). [Invite link](https://discord.com/invite/flipper)
-## Gratitudes
-Thanks to [@Svaarich](https://github.com/Svaarich) for the UI design and to the Unleashed firmware community for sensors testing and feedbacks.
-
-## Some community photos
-![image](https://user-images.githubusercontent.com/10090793/210120132-7ddbc937-0a6b-4472-bd1c-7fbc3ecdf2ad.png)
-![image](https://user-images.githubusercontent.com/10090793/210120135-12fc5810-77ff-49db-b799-e9479e1f57a7.png)
-![image](https://user-images.githubusercontent.com/10090793/210120143-a2bae3ce-4190-421f-8c4f-c7c744903bd6.png)
-![image](https://user-images.githubusercontent.com/10090793/215224085-8099408e-b3de-4a0c-854e-fe4e4faa8ea3.png)

+ 0 - 653
non_catalog_apps/unitemp/Sensors.c

@@ -1,653 +0,0 @@
-/*
-    Unitemp - Universal temperature reader
-    Copyright (C) 2022-2023  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 <https://www.gnu.org/licenses/>.
-*/
-#include "Sensors.h"
-#include <furi_hal_power.h>
-
-//Порты ввода/вывода, которые не были обозначены в общем списке
-const GpioPin SWC_10 = {.pin = LL_GPIO_PIN_14, .port = GPIOA};
-const GpioPin SIO_12 = {.pin = LL_GPIO_PIN_13, .port = GPIOA};
-const GpioPin TX_13 = {.pin = LL_GPIO_PIN_6, .port = GPIOB};
-const GpioPin RX_14 = {.pin = LL_GPIO_PIN_7, .port = GPIOB};
-
-//Количество доступных портов ввода/вывода
-#define GPIO_ITEMS (sizeof(GPIOList) / sizeof(GPIO))
-//Количество интерфейсов
-#define INTERFACES_TYPES_COUNT (int)(sizeof(interfaces) / sizeof(const Interface*))
-//Количество типов датчиков
-#define SENSOR_TYPES_COUNT (int)(sizeof(sensorTypes) / sizeof(const SensorType*))
-
-//Перечень достуных портов ввода/вывода
-static const GPIO GPIOList[] = {
-    {2, "2 (A7)", &gpio_ext_pa7},
-    {3, "3 (A6)", &gpio_ext_pa6},
-    {4, "4 (A4)", &gpio_ext_pa4},
-    {5, "5 (B3)", &gpio_ext_pb3},
-    {6, "6 (B2)", &gpio_ext_pb2},
-    {7, "7 (C3)", &gpio_ext_pc3},
-    {10, " 10(SWC) ", &SWC_10},
-    {12, "12 (SIO)", &SIO_12},
-    {13, "13 (TX)", &TX_13},
-    {14, "14 (RX)", &RX_14},
-    {15, "15 (C1)", &gpio_ext_pc1},
-    {16, "16 (C0)", &gpio_ext_pc0},
-    {17, "17 (1W)", &gpio_ibutton}};
-
-//Список интерфейсов, которые прикреплены к GPIO (определяется индексом)
-//NULL - порт свободен, указатель на интерфейс - порт занят этим интерфейсом
-static const Interface* gpio_interfaces_list[GPIO_ITEMS] = {0};
-
-const Interface SINGLE_WIRE = {
-    .name = "Single wire",
-    .allocator = unitemp_singlewire_alloc,
-    .mem_releaser = unitemp_singlewire_free,
-    .updater = unitemp_singlewire_update};
-const Interface I2C = {
-    .name = "I2C",
-    .allocator = unitemp_I2C_sensor_alloc,
-    .mem_releaser = unitemp_I2C_sensor_free,
-    .updater = unitemp_I2C_sensor_update};
-const Interface ONE_WIRE = {
-    .name = "One wire",
-    .allocator = unitemp_onewire_sensor_alloc,
-    .mem_releaser = unitemp_onewire_sensor_free,
-    .updater = unitemp_onewire_sensor_update};
-const Interface SPI = {
-    .name = "SPI",
-    .allocator = unitemp_spi_sensor_alloc,
-    .mem_releaser = unitemp_spi_sensor_free,
-    .updater = unitemp_spi_sensor_update};
-
-//Перечень интерфейсов подключения
-//static const Interface* interfaces[] = {&SINGLE_WIRE, &I2C, &ONE_WIRE, &SPI};
-//Перечень датчиков
-static const SensorType* sensorTypes[] = {&DHT11,  &DHT12_SW,  &DHT20,      &DHT21,    &DHT22,
-                                          &Dallas, &AM2320_SW, &AM2320_I2C, &HTU21x,   &AHT10,
-                                          &SHT30,  &GXHT30,    &LM75,       &HDC1080,  &BMP180,
-                                          &BMP280, &BME280,    &BME680,     &MAX31855, &MAX6675,
-                                          &SCD30,  &SCD40};
-
-const SensorType* unitemp_sensors_getTypeFromInt(uint8_t index) {
-    if(index > SENSOR_TYPES_COUNT) return NULL;
-    return sensorTypes[index];
-}
-
-const SensorType* unitemp_sensors_getTypeFromStr(char* str) {
-    UNUSED(str);
-    if(str == NULL) return NULL;
-    for(uint8_t i = 0; i < unitemp_sensors_getTypesCount(); i++) {
-        if(!strcmp(str, sensorTypes[i]->typename)) {
-            return sensorTypes[i];
-        }
-    }
-    return NULL;
-}
-
-uint8_t unitemp_sensors_getTypesCount(void) {
-    return SENSOR_TYPES_COUNT;
-}
-const SensorType** unitemp_sensors_getTypes(void) {
-    return sensorTypes;
-}
-
-int unitemp_getIntFromType(const SensorType* type) {
-    for(int i = 0; i < SENSOR_TYPES_COUNT; i++) {
-        if(!strcmp(type->typename, sensorTypes[i]->typename)) {
-            return i;
-        }
-    }
-    return 255;
-}
-const GPIO* unitemp_gpio_getFromInt(uint8_t name) {
-    for(uint8_t i = 0; i < GPIO_ITEMS; i++) {
-        if(GPIOList[i].num == name) {
-            return &GPIOList[i];
-        }
-    }
-    return NULL;
-}
-
-const GPIO* unitemp_gpio_getFromIndex(uint8_t index) {
-    return &GPIOList[index];
-}
-
-uint8_t unitemp_gpio_toInt(const GPIO* gpio) {
-    if(gpio == NULL) return 255;
-    for(uint8_t i = 0; i < GPIO_ITEMS; i++) {
-        if(GPIOList[i].pin->pin == gpio->pin->pin && GPIOList[i].pin->port == gpio->pin->port) {
-            return GPIOList[i].num;
-        }
-    }
-    return 255;
-}
-
-uint8_t unitemp_gpio_to_index(const GpioPin* gpio) {
-    if(gpio == NULL) return 255;
-    for(uint8_t i = 0; i < GPIO_ITEMS; i++) {
-        if(GPIOList[i].pin->pin == gpio->pin && GPIOList[i].pin->port == gpio->port) {
-            return i;
-        }
-    }
-    return 255;
-}
-
-uint8_t unitemp_gpio_getAviablePortsCount(const Interface* interface, const GPIO* extraport) {
-    uint8_t aviable_ports_count = 0;
-    for(uint8_t i = 0; i < GPIO_ITEMS; i++) {
-        //Проверка для one wire
-        if(interface == &ONE_WIRE) {
-            if(((gpio_interfaces_list[i] == NULL || gpio_interfaces_list[i] == &ONE_WIRE)) ||
-               (unitemp_gpio_getFromIndex(i) == extraport)) {
-                aviable_ports_count++;
-            }
-        }
-
-        //Проверка для single wire
-        if(interface == &SINGLE_WIRE || interface == &SPI) {
-            if(gpio_interfaces_list[i] == NULL || (unitemp_gpio_getFromIndex(i) == extraport)) {
-                aviable_ports_count++;
-            }
-        }
-
-        if(interface == &I2C) {
-            //У I2C два фиксированых порта
-            return 0;
-        }
-    }
-    return aviable_ports_count;
-}
-
-void unitemp_gpio_lock(const GPIO* gpio, const Interface* interface) {
-    uint8_t i = unitemp_gpio_to_index(gpio->pin);
-    if(i == 255) return;
-    gpio_interfaces_list[i] = interface;
-}
-
-void unitemp_gpio_unlock(const GPIO* gpio) {
-    uint8_t i = unitemp_gpio_to_index(gpio->pin);
-    if(i == 255) return;
-    gpio_interfaces_list[i] = NULL;
-}
-
-const GPIO*
-    unitemp_gpio_getAviablePort(const Interface* interface, uint8_t index, const GPIO* extraport) {
-    //Проверка для I2C
-    if(interface == &I2C) {
-        if((gpio_interfaces_list[10] == NULL || gpio_interfaces_list[10] == &I2C) &&
-           (gpio_interfaces_list[11] == NULL || gpio_interfaces_list[11] == &I2C)) {
-            //Возврат истины
-            return unitemp_gpio_getFromIndex(0);
-        } else {
-            //Возврат лжи
-            return NULL;
-        }
-    }
-    if(interface == &SPI) {
-        if(!((gpio_interfaces_list[0] == NULL || gpio_interfaces_list[0] == &SPI) &&
-             (gpio_interfaces_list[1] == NULL || gpio_interfaces_list[1] == &SPI) &&
-             (gpio_interfaces_list[3] == NULL || gpio_interfaces_list[3] == &SPI))) {
-            return NULL;
-        }
-    }
-
-    uint8_t aviable_index = 0;
-    for(uint8_t i = 0; i < GPIO_ITEMS; i++) {
-        //Проверка для one wire
-        if(interface == &ONE_WIRE) {
-            if(((gpio_interfaces_list[i] == NULL || gpio_interfaces_list[i] == &ONE_WIRE)) ||
-               (unitemp_gpio_getFromIndex(i) == extraport)) {
-                if(aviable_index == index) {
-                    return unitemp_gpio_getFromIndex(i);
-                } else {
-                    aviable_index++;
-                }
-            }
-        }
-        //Проверка для single wire
-        if(interface == &SINGLE_WIRE || interface == &SPI) {
-            if(gpio_interfaces_list[i] == NULL || unitemp_gpio_getFromIndex(i) == extraport) {
-                if(aviable_index == index) {
-                    return unitemp_gpio_getFromIndex(i);
-                } else {
-                    aviable_index++;
-                }
-            }
-        }
-    }
-
-    return NULL;
-}
-
-void unitemp_sensor_delete(Sensor* sensor) {
-    for(uint8_t i = 0; i < app->sensors_count; i++) {
-        if(app->sensors[i] == sensor) {
-            app->sensors[i]->status = UT_SENSORSTATUS_INACTIVE;
-            unitemp_sensors_save();
-            unitemp_sensors_reload();
-            return;
-        }
-    }
-}
-
-Sensor* unitemp_sensor_getActive(uint8_t index) {
-    uint8_t aviable_index = 0;
-    for(uint8_t i = 0; i < app->sensors_count; i++) {
-        if(app->sensors[i]->status != UT_SENSORSTATUS_INACTIVE) {
-            if(aviable_index == index) {
-                return app->sensors[i];
-            } else {
-                aviable_index++;
-            }
-        }
-    }
-    return NULL;
-}
-
-uint8_t unitemp_sensors_getCount(void) {
-    if(app->sensors == NULL) return 0;
-    return app->sensors_count;
-}
-
-uint8_t unitemp_sensors_getActiveCount(void) {
-    if(app->sensors == NULL) return 0;
-    uint8_t counter = 0;
-    for(uint8_t i = 0; i < unitemp_sensors_getCount(); i++) {
-        if(app->sensors[i]->status != UT_SENSORSTATUS_INACTIVE) counter++;
-    }
-    return counter;
-}
-
-void unitemp_sensors_add(Sensor* sensor) {
-    app->sensors =
-        (Sensor**)realloc(app->sensors, (unitemp_sensors_getCount() + 1) * sizeof(Sensor*));
-    app->sensors[unitemp_sensors_getCount()] = sensor;
-    app->sensors_count++;
-}
-
-bool unitemp_sensors_load(void) {
-    UNITEMP_DEBUG("Loading sensors...");
-
-    //Выделение памяти на поток
-    app->file_stream = file_stream_alloc(app->storage);
-
-    //Переменная пути к файлу
-    FuriString* filepath = furi_string_alloc();
-    //Составление пути к файлу
-    furi_string_printf(filepath, "%s/%s", APP_PATH_FOLDER, APP_FILENAME_SENSORS);
-
-    //Открытие потока к файлу с датчиками
-    if(!file_stream_open(
-           app->file_stream, furi_string_get_cstr(filepath), FSAM_READ_WRITE, FSOM_OPEN_EXISTING)) {
-        if(file_stream_get_error(app->file_stream) == FSE_NOT_EXIST) {
-            FURI_LOG_W(APP_NAME, "Missing sensors file");
-            //Закрытие потока и освобождение памяти
-            file_stream_close(app->file_stream);
-            stream_free(app->file_stream);
-            return false;
-        } else {
-            FURI_LOG_E(
-                APP_NAME,
-                "An error occurred while loading the sensors file: %d",
-                file_stream_get_error(app->file_stream));
-            //Закрытие потока и освобождение памяти
-            file_stream_close(app->file_stream);
-            stream_free(app->file_stream);
-            return false;
-        }
-    }
-
-    //Вычисление размера файла
-    uint16_t file_size = stream_size(app->file_stream);
-    //Если файл пустой, то:
-    if(file_size == (uint8_t)0) {
-        FURI_LOG_W(APP_NAME, "Sensors file is empty");
-        //Закрытие потока и освобождение памяти
-        file_stream_close(app->file_stream);
-        stream_free(app->file_stream);
-        return false;
-    }
-    //Выделение памяти под загрузку файла
-    uint8_t* file_buf = malloc(file_size);
-    //Опустошение буфера файла
-    memset(file_buf, 0, file_size);
-    //Загрузка файла
-    if(stream_read(app->file_stream, file_buf, file_size) != file_size) {
-        //Выход при ошибке чтения
-        FURI_LOG_E(APP_NAME, "Error reading sensors file");
-        //Закрытие потока и освобождение памяти
-        file_stream_close(app->file_stream);
-        stream_free(app->file_stream);
-        free(file_buf);
-        return false;
-    }
-
-    //Указатель на начало строки
-    FuriString* file = furi_string_alloc_set_str((char*)file_buf);
-    //Сколько байт до конца строки
-    size_t line_end = 0;
-
-    while(line_end != ((size_t)-1) && line_end != (size_t)(file_size - 1)) {
-        //Имя датчика
-        char name[11] = {0};
-        //Тип датчика
-        char type[11] = {0};
-        //Смещение по температуре
-        int temp_offset = 0;
-        //Смещение по строке для отделения аргументов
-        int offset = 0;
-        //Чтение из строки
-        sscanf(((char*)(file_buf + line_end)), "%s %s %d %n", name, type, &temp_offset, &offset);
-        //Ограничение длины имени
-        name[10] = '\0';
-
-        //Замена ? на пробел
-        for(uint8_t i = 0; i < 10; i++) {
-            if(name[i] == '?') name[i] = ' ';
-        }
-
-        char* args = ((char*)(file_buf + line_end + offset));
-        const SensorType* stype = unitemp_sensors_getTypeFromStr(type);
-
-        //Проверка типа датчика
-        if(stype != NULL && sizeof(name) > 0 && sizeof(name) <= 11) {
-            Sensor* sensor =
-                unitemp_sensor_alloc(name, unitemp_sensors_getTypeFromStr(type), args);
-            if(sensor != NULL) {
-                sensor->temp_offset = temp_offset;
-                unitemp_sensors_add(sensor);
-            } else {
-                FURI_LOG_E(APP_NAME, "Failed sensor (%s:%s) mem allocation", name, type);
-            }
-        } else {
-            FURI_LOG_E(APP_NAME, "Unsupported sensor name (%s) or sensor type (%s)", name, type);
-        }
-        //Вычисление конца строки
-        line_end = furi_string_search_char(file, '\n', line_end + 1);
-    }
-
-    free(file_buf);
-    file_stream_close(app->file_stream);
-    stream_free(app->file_stream);
-
-    FURI_LOG_I(APP_NAME, "Sensors have been successfully loaded");
-    return true;
-}
-
-bool unitemp_sensors_save(void) {
-    UNITEMP_DEBUG("Saving sensors...");
-
-    //Выделение памяти для потока
-    app->file_stream = file_stream_alloc(app->storage);
-
-    //Переменная пути к файлу
-    FuriString* filepath = furi_string_alloc();
-    //Составление пути к файлу
-    furi_string_printf(filepath, "%s/%s", APP_PATH_FOLDER, APP_FILENAME_SENSORS);
-    //Создание папки плагина
-    storage_common_mkdir(app->storage, APP_PATH_FOLDER);
-    //Открытие потока
-    if(!file_stream_open(
-           app->file_stream, furi_string_get_cstr(filepath), FSAM_READ_WRITE, FSOM_CREATE_ALWAYS)) {
-        FURI_LOG_E(
-            APP_NAME,
-            "An error occurred while saving the sensors file: %d",
-            file_stream_get_error(app->file_stream));
-        //Закрытие потока и освобождение памяти
-        file_stream_close(app->file_stream);
-        stream_free(app->file_stream);
-        return false;
-    }
-
-    //Сохранение датчиков
-    for(uint8_t i = 0; i < unitemp_sensors_getActiveCount(); i++) {
-        Sensor* sensor = unitemp_sensor_getActive(i);
-        //Замена пробела на ?
-        for(uint8_t i = 0; i < 10; i++) {
-            if(sensor->name[i] == ' ') sensor->name[i] = '?';
-        }
-
-        stream_write_format(
-            app->file_stream,
-            "%s %s %d ",
-            sensor->name,
-            sensor->type->typename,
-            sensor->temp_offset);
-
-        if(sensor->type->interface == &SINGLE_WIRE) {
-            stream_write_format(
-                app->file_stream, "%d\n", unitemp_singlewire_sensorGetGPIO(sensor)->num);
-        }
-        if(sensor->type->interface == &SPI) {
-            uint8_t gpio_num = ((SPISensor*)sensor->instance)->CS_pin->num;
-            stream_write_format(app->file_stream, "%d\n", gpio_num);
-        }
-
-        if(sensor->type->interface == &I2C) {
-            stream_write_format(
-                app->file_stream, "%X\n", ((I2CSensor*)sensor->instance)->currentI2CAdr);
-        }
-        if(sensor->type->interface == &ONE_WIRE) {
-            stream_write_format(
-                app->file_stream,
-                "%d %02X%02X%02X%02X%02X%02X%02X%02X\n",
-                ((OneWireSensor*)sensor->instance)->bus->gpio->num,
-                ((OneWireSensor*)sensor->instance)->deviceID[0],
-                ((OneWireSensor*)sensor->instance)->deviceID[1],
-                ((OneWireSensor*)sensor->instance)->deviceID[2],
-                ((OneWireSensor*)sensor->instance)->deviceID[3],
-                ((OneWireSensor*)sensor->instance)->deviceID[4],
-                ((OneWireSensor*)sensor->instance)->deviceID[5],
-                ((OneWireSensor*)sensor->instance)->deviceID[6],
-                ((OneWireSensor*)sensor->instance)->deviceID[7]);
-        }
-    }
-
-    //Закрытие потока и освобождение памяти
-    file_stream_close(app->file_stream);
-    stream_free(app->file_stream);
-
-    FURI_LOG_I(APP_NAME, "Sensors have been successfully saved");
-    return true;
-}
-void unitemp_sensors_reload(void) {
-    unitemp_sensors_deInit();
-    unitemp_sensors_free();
-
-    unitemp_sensors_load();
-    unitemp_sensors_init();
-}
-
-bool unitemp_sensor_isContains(Sensor* sensor) {
-    for(uint8_t i = 0; i < unitemp_sensors_getCount(); i++) {
-        if(app->sensors[i] == sensor) return true;
-    }
-    return false;
-}
-
-Sensor* unitemp_sensor_alloc(char* name, const SensorType* type, char* args) {
-    if(name == NULL || type == NULL) return NULL;
-    bool status = false;
-    //Выделение памяти под датчик
-    Sensor* sensor = malloc(sizeof(Sensor));
-    if(sensor == NULL) {
-        FURI_LOG_E(APP_NAME, "Sensor %s allocation error", name);
-        return false;
-    }
-
-    //Выделение памяти под имя
-    sensor->name = malloc(11);
-    if(sensor->name == NULL) {
-        FURI_LOG_E(APP_NAME, "Sensor %s name allocation error", name);
-        return false;
-    }
-    //Запись имени датчка
-    strcpy(sensor->name, name);
-    //Тип датчика
-    sensor->type = type;
-    //Статус датчика по умолчанию - ошибка
-    sensor->status = UT_SENSORSTATUS_ERROR;
-    //Время последнего опроса
-    sensor->lastPollingTime =
-        furi_get_tick() - 10000; //чтобы первый опрос произошёл как можно раньше
-
-    sensor->temp = -128.0f;
-    sensor->hum = -128.0f;
-    sensor->pressure = -128.0f;
-    sensor->temp_offset = 0;
-    //Выделение памяти под инстанс датчика в зависимости от его интерфейса
-    status = sensor->type->interface->allocator(sensor, args);
-
-    //Выход если датчик успешно развёрнут
-    if(status) {
-        UNITEMP_DEBUG("Sensor %s allocated", name);
-        return sensor;
-    }
-    //Выход с очисткой если память для датчика не была выделена
-    free(sensor->name);
-    free(sensor);
-    FURI_LOG_E(APP_NAME, "Sensor %s(%s) allocation error", name, type->typename);
-    return NULL;
-}
-
-void unitemp_sensor_free(Sensor* sensor) {
-    if(sensor == NULL) {
-        FURI_LOG_E(APP_NAME, "Null pointer sensor releasing");
-        return;
-    }
-    if(sensor->type == NULL) {
-        FURI_LOG_E(APP_NAME, "Sensor type is null");
-        return;
-    }
-    if(sensor->type->mem_releaser == NULL) {
-        FURI_LOG_E(APP_NAME, "Sensor releaser is null");
-        return;
-    }
-    bool status = false;
-    //Высвобождение памяти под инстанс
-    status = sensor->type->interface->mem_releaser(sensor);
-
-    if(status) {
-        UNITEMP_DEBUG("Sensor %s memory successfully released", sensor->name);
-    } else {
-        FURI_LOG_E(APP_NAME, "Sensor %s memory is not released", sensor->name);
-    }
-    free(sensor->name);
-}
-
-void unitemp_sensors_free(void) {
-    for(uint8_t i = 0; i < unitemp_sensors_getCount(); i++) {
-        unitemp_sensor_free(app->sensors[i]);
-    }
-    app->sensors_count = 0;
-}
-
-bool unitemp_sensors_init(void) {
-    bool result = true;
-
-    //Перебор датчиков из списка
-    for(uint8_t i = 0; i < unitemp_sensors_getCount(); i++) {
-        //Включение 5V если на порту 1 FZ его нет
-        //Может пропасть при отключении USB
-        if(furi_hal_power_is_otg_enabled() != true) {
-            furi_hal_power_enable_otg();
-            UNITEMP_DEBUG("OTG enabled");
-        }
-        if(!(*app->sensors[i]->type->initializer)(app->sensors[i])) {
-            FURI_LOG_E(
-                APP_NAME,
-                "An error occurred during sensor initialization %s",
-                app->sensors[i]->name);
-            result = false;
-        }
-        FURI_LOG_I(APP_NAME, "Sensor %s successfully initialized", app->sensors[i]->name);
-    }
-    app->sensors_ready = true;
-    return result;
-}
-
-bool unitemp_sensors_deInit(void) {
-    bool result = true;
-    //Выключение 5 В если до этого оно не было включено
-    if(app->settings.lastOTGState != true) {
-        furi_hal_power_disable_otg();
-        UNITEMP_DEBUG("OTG disabled");
-    }
-
-    //Перебор датчиков из списка
-    for(uint8_t i = 0; i < unitemp_sensors_getCount(); i++) {
-        if(!(*app->sensors[i]->type->deinitializer)(app->sensors[i])) {
-            FURI_LOG_E(
-                APP_NAME,
-                "An error occurred during sensor deinitialization %s",
-                app->sensors[i]->name);
-            result = false;
-        }
-    }
-    return result;
-}
-
-UnitempStatus unitemp_sensor_updateData(Sensor* sensor) {
-    if(sensor == NULL) return UT_SENSORSTATUS_ERROR;
-
-    //Проверка на допустимость опроса датчика
-    if(furi_get_tick() - sensor->lastPollingTime < sensor->type->pollingInterval) {
-        //Возврат ошибки если последний опрос датчика был неудачным
-        if(sensor->status == UT_SENSORSTATUS_TIMEOUT) {
-            return UT_SENSORSTATUS_TIMEOUT;
-        }
-        return UT_SENSORSTATUS_EARLYPOOL;
-    }
-
-    sensor->lastPollingTime = furi_get_tick();
-
-    if(!furi_hal_power_is_otg_enabled()) {
-        furi_hal_power_enable_otg();
-    }
-
-    sensor->status = sensor->type->interface->updater(sensor);
-
-    if(sensor->status != UT_SENSORSTATUS_OK && sensor->status != UT_SENSORSTATUS_POLLING) {
-        UNITEMP_DEBUG("Sensor %s update status %d", sensor->name, sensor->status);
-    }
-
-    if(sensor->status == UT_SENSORSTATUS_OK) {
-        if(app->settings.heat_index &&
-           ((sensor->type->datatype & (UT_TEMPERATURE | UT_HUMIDITY)) ==
-            (UT_TEMPERATURE | UT_HUMIDITY))) {
-            unitemp_calculate_heat_index(sensor);
-        }
-        if(app->settings.temp_unit == UT_TEMP_FAHRENHEIT) {
-            uintemp_celsiumToFarengate(sensor);
-        }
-
-        sensor->temp += sensor->temp_offset / 10.f;
-        if(app->settings.pressure_unit == UT_PRESSURE_MM_HG) {
-            unitemp_pascalToMmHg(sensor);
-        } else if(app->settings.pressure_unit == UT_PRESSURE_IN_HG) {
-            unitemp_pascalToInHg(sensor);
-        } else if(app->settings.pressure_unit == UT_PRESSURE_KPA) {
-            unitemp_pascalToKPa(sensor);
-        }
-    }
-    return sensor->status;
-}
-
-void unitemp_sensors_updateValues(void) {
-    for(uint8_t i = 0; i < unitemp_sensors_getCount(); i++) {
-        unitemp_sensor_updateData(unitemp_sensor_getActive(i));
-    }
-}

+ 0 - 339
non_catalog_apps/unitemp/Sensors.h

@@ -1,339 +0,0 @@
-/*
-    Unitemp - Universal temperature reader
-    Copyright (C) 2022-2023  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 <https://www.gnu.org/licenses/>.
-*/
-#ifndef UNITEMP_SENSORS
-#define UNITEMP_SENSORS
-#include <furi.h>
-#include <input/input.h>
-
-//Маски бит для определения типов возвращаемых значений
-#define UT_TEMPERATURE 0b00000001
-#define UT_HUMIDITY 0b00000010
-#define UT_PRESSURE 0b00000100
-#define UT_CO2 0b00001000
-
-//Статусы опроса датчика
-typedef enum {
-    UT_DATA_TYPE_TEMP = UT_TEMPERATURE,
-    UT_DATA_TYPE_TEMP_HUM = UT_TEMPERATURE | UT_HUMIDITY,
-    UT_DATA_TYPE_TEMP_PRESS = UT_TEMPERATURE | UT_PRESSURE,
-    UT_DATA_TYPE_TEMP_HUM_PRESS = UT_TEMPERATURE | UT_HUMIDITY | UT_PRESSURE,
-    UT_DATA_TYPE_TEMP_HUM_CO2 = UT_TEMPERATURE | UT_HUMIDITY | UT_CO2,
-} SensorDataType;
-
-//Типы возвращаемых данных
-typedef enum {
-    UT_SENSORSTATUS_OK, //Всё хорошо, опрос успешен
-    UT_SENSORSTATUS_TIMEOUT, //Датчик не отозвался
-    UT_SENSORSTATUS_EARLYPOOL, //Опрос раньше положенной задержки
-    UT_SENSORSTATUS_BADCRC, //Неверная контрольная сумма
-    UT_SENSORSTATUS_ERROR, //Прочие ошибки
-    UT_SENSORSTATUS_POLLING, //В датчике происходит преобразование
-    UT_SENSORSTATUS_INACTIVE, //Датчик на редактировании или удалён
-
-} UnitempStatus;
-
-//Порт ввода/вывода Flipper Zero
-typedef struct GPIO {
-    const uint8_t num;
-    const char* name;
-    const GpioPin* pin;
-} GPIO;
-
-typedef struct Sensor Sensor;
-
-/**
- * @brief Указатель функции выделения памяти и подготовки экземпляра датчика
- */
-typedef bool(SensorAllocator)(Sensor* sensor, char* args);
-/**
- * @brief Указатель на функцию высвобождении памяти датчика
- */
-typedef bool(SensorFree)(Sensor* sensor);
-/**
- * @brief Указатель функции инициализации датчика
- */
-typedef bool(SensorInitializer)(Sensor* sensor);
-/**
- * @brief Указатель функции деинициализации датчика
- */
-typedef bool(SensorDeinitializer)(Sensor* sensor);
-/**
- * @brief Указатель функции обновления значения датчика
- */
-typedef UnitempStatus(SensorUpdater)(Sensor* sensor);
-
-//Типы подключения датчиков
-typedef struct Interface {
-    //Имя интерфейса
-    const char* name;
-    //Функция выделения памяти интерфейса
-    SensorAllocator* allocator;
-    //Функция высвыбождения памяти интерфейса
-    SensorFree* mem_releaser;
-    //Функция обновления значения датчика по интерфейсу
-    SensorUpdater* updater;
-} Interface;
-
-//Типы датчиков
-typedef struct {
-    //Модель датчика
-    const char* typename;
-    //Полное имя с аналогами
-    const char* altname;
-    //Тип возвращаемых данных
-    SensorDataType datatype;
-    //Интерфейс подключения
-    const Interface* interface;
-    //Интервал опроса датчика
-    uint16_t pollingInterval;
-    //Функция выделения памяти для датчика
-    SensorAllocator* allocator;
-    //Функция высвыбождения памяти для датчика
-    SensorFree* mem_releaser;
-    //Функция инициализации датчика
-    SensorInitializer* initializer;
-    //Функция деинициализация датчика
-    SensorDeinitializer* deinitializer;
-    //Функция обновления значения датчка
-    SensorUpdater* updater;
-} SensorType;
-
-//Датчик
-typedef struct Sensor {
-    //Имя датчика
-    char* name;
-    //Температура
-    float temp;
-    float heat_index;
-    //Относительная влажность
-    float hum;
-    //Атмосферное давление
-    float pressure;
-    // Концентрация CO2
-    float co2;
-    //Тип датчика
-    const SensorType* type;
-    //Статус последнего опроса датчика
-    UnitempStatus status;
-    //Время последнего опроса датчика
-    uint32_t lastPollingTime;
-    //Смещение по температуре (x10)
-    int8_t temp_offset;
-    //Экземпляр датчика
-    void* instance;
-} Sensor;
-
-extern const Interface SINGLE_WIRE; //Собственный однопроводной протокол датчиков DHTXX и AM23XX
-extern const Interface ONE_WIRE; //Однопроводной протокол Dallas
-extern const Interface I2C; //I2C_2 (PC0, PC1)
-extern const Interface SPI; //SPI_1 (MOSI - 2, MISO - 3, CS - 4, SCK - 5)
-
-/* ============================= Датчик(и) ============================= */
-/**
- * @brief Выделение памяти под датчик
- * 
- * @param name Имя датчика
- * @param type Тип датчика
- * @param args Указатель на строку с парамерами датчика
- * @return Указатель на датчик в случае успешного выделения памяти, NULL при ошибке
- */
-Sensor* unitemp_sensor_alloc(char* name, const SensorType* type, char* args);
-
-/**
- * @brief Высвыбождение памяти конкретного датчка
- * @param sensor Указатель на датчик
- */
-void unitemp_sensor_free(Sensor* sensor);
-
-/**
- * @brief Обновление данных указанного датчика
- * @param sensor Указатель на датчик
- * @return Статус опроса датчика
- */
-UnitempStatus unitemp_sensor_updateData(Sensor* sensor);
-
-/**
- * @brief Проверка наличия датчика в памяти
- * 
- * @param sensor Указатель на датчик
- * @return Истина если этот датчик уже загружен, ложь если это новый датчик
- */
-bool unitemp_sensor_isContains(Sensor* sensor);
-
-/**
- * @brief Получить датчик из списка по индексу
- * 
- * @param index Индекс датчика (0 - unitemp_sensors_getCount())
- * @return Указатель на датчик при успехе, NULL при неудаче
- */
-Sensor* unitemp_sensor_getActive(uint8_t index);
-
-/**
- * @brief Загрузка датчиков с SD-карты
- * @return Истина если загрузка прошла успешно
- */
-bool unitemp_sensors_load();
-
-/**
- * @brief Функция перезагрузки датчиков с SD-карты
-*/
-void unitemp_sensors_reload(void);
-
-/**
- * @brief Сохранение датчиков на SD-карту
- * @return Истина если сохранение прошло успешно
- */
-bool unitemp_sensors_save(void);
-
-/**
- * @brief Удаление датчика
- * 
- * @param sensor Указатель на датчик
- */
-void unitemp_sensor_delete(Sensor* sensor);
-
-/**
- * @brief Инициализация загруженных датчиков
- * @return Истина если всё прошло успешно
- */
-bool unitemp_sensors_init(void);
-
-/**
- * @brief Деинициализация загруженных датчиков
- * @return Истина если всё прошло успешно
- */
-bool unitemp_sensors_deInit(void);
-
-/**
- * @brief Высвыбождение памяти всех датчиков
- */
-void unitemp_sensors_free(void);
-
-/**
- * @brief Обновить данные всех датчиков
- */
-void unitemp_sensors_updateValues(void);
-
-/**
- * @brief Получить количество загруженных датчиков
- * @return Количество датчиков
- */
-uint8_t unitemp_sensors_getCount(void);
-
-/**
- * @brief Добавить датчик в общий список
- * @param sensor Указатель на датчик
- */
-void unitemp_sensors_add(Sensor* sensor);
-
-/**
-* @brief Получить списк доступных типов датчиков
-* @return Указатель на список датчиков
-*/
-const SensorType** unitemp_sensors_getTypes(void);
-
-/**
-* @brief Получить количество доступных типов датчиков
-* @return Количество доступных типов датчиков
-*/
-uint8_t unitemp_sensors_getTypesCount(void);
-
-/**
- * @brief Получить тип сенсора по его индексу
- * @param index Индекс типа датчика (от 0 до SENSOR_TYPES_COUNT)
- * @return const SensorType* 
- */
-const SensorType* unitemp_sensors_getTypeFromInt(uint8_t index);
-
-/**
- * @brief Преобразовать строчное название датчка в указатель
- * 
- * @param str Имя датчика в виде строки
- * @return Указатель на тип датчика при успехе, иначе NULL
- */
-const SensorType* unitemp_sensors_getTypeFromStr(char* str);
-
-/**
- * @brief Получить количество активных датчиков
- * 
- * @return Количество активных датчиков
- */
-uint8_t unitemp_sensors_getActiveCount(void);
-
-/* ============================= GPIO ============================= */
-/**
- * @brief Конвертация номера порта на корпусе FZ в GPIO 
- * @param name Номер порта на корпусе FZ
- * @return Указатель на GPIO при успехе, NULL при ошибке
- */
-const GPIO* unitemp_gpio_getFromInt(uint8_t name);
-/**
- * @brief Конвертация GPIO в номер на корпусе FZ
- * @param gpio Указатель на порт
- * @return Номер порта на корпусе FZ
- */
-uint8_t unitemp_gpio_toInt(const GPIO* gpio);
-
-/**
- * @brief Блокировка GPIO указанным интерфейсом
- * @param gpio Указатель на порт
- * @param interface Указатель на интерфейс, которым порт будет занят
- */
-void unitemp_gpio_lock(const GPIO* gpio, const Interface* interface);
-
-/**
- * @brief Разблокировка порта
- * @param gpio Указатель на порт
- */
-void unitemp_gpio_unlock(const GPIO* gpio);
-/**
- * @brief Получить количество доступных портов для указанного интерфейса
- * @param interface Указатель на интерфейс
- * @return Количество доступных портов
- */
-uint8_t unitemp_gpio_getAviablePortsCount(const Interface* interface, const GPIO* extraport);
-/**
- * @brief Получить указатель на доступный для интерфейса порт по индексу 
- * @param interface Указатель на интерфейс
- * @param index Номер порта (от 0 до unitemp_gpio_getAviablePortsCount())
- * @param extraport Указатель на дополнительный порт, который будет принудительно считаться доступным. Можно указать NULL если не требуется
- * @return Указатель на доступный порт
- */
-const GPIO*
-    unitemp_gpio_getAviablePort(const Interface* interface, uint8_t index, const GPIO* extraport);
-
-/* Датчики */
-//DHTxx и их производные
-#include "./interfaces/SingleWireSensor.h"
-//DS18x2x
-#include "./interfaces/OneWireSensor.h"
-#include "./sensors/LM75.h"
-//BMP280, BME280, BME680
-#include "./sensors/BMx280.h"
-#include "./sensors/BME680.h"
-#include "./sensors/AM2320.h"
-#include "./sensors/DHT20.h"
-#include "./sensors/SHT30.h"
-#include "./sensors/BMP180.h"
-#include "./sensors/HTU21x.h"
-#include "./sensors/HDC1080.h"
-#include "./sensors/MAX31855.h"
-#include "./sensors/MAX6675.h"
-#include "./sensors/SCD30.h"
-#include "./sensors/SCD40.h"
-#endif

+ 0 - 19
non_catalog_apps/unitemp/application.fam

@@ -1,19 +0,0 @@
-App(
-    appid="unitemp",
-    name="Temp sensors reader",
-    apptype=FlipperAppType.EXTERNAL,
-    entry_point="unitemp_app",
-    requires=[
-        "gui",
-    ],
-    stack_size=2 * 1024,
-    order=100,
-    fap_description = "Universal temperature sensors reader",
-    fap_version="1.4",
-    fap_author = "@quen0n & (fixes by @xMasterX)",
-    fap_weburl = "https://github.com/quen0n/unitemp-flipperzero",
-    fap_category="GPIO",
-    fap_icon="icon.png",
-    fap_icon_assets="assets",
-    fap_libs=["assets"],
-)

+ 0 - 3
non_catalog_apps/unitemp/assets/README.MD

@@ -1,3 +0,0 @@
-# Unitemp assets
-
-Created by [@Svaarich](https://github.com/Svaarich)

BIN
non_catalog_apps/unitemp/assets/co2_11x14.png


BIN
non_catalog_apps/unitemp/assets/flipper_happy_2_60x38.png


BIN
non_catalog_apps/unitemp/assets/flipper_happy_60x38.png


BIN
non_catalog_apps/unitemp/assets/flipper_sad_60x38.png


BIN
non_catalog_apps/unitemp/assets/heat_index_11x14.png


BIN
non_catalog_apps/unitemp/assets/hum_9x15.png


BIN
non_catalog_apps/unitemp/assets/in_hg_15x15.png


BIN
non_catalog_apps/unitemp/assets/mm_hg_15x15.png


BIN
non_catalog_apps/unitemp/assets/pressure_7x13.png


BIN
non_catalog_apps/unitemp/assets/repo_qr_50x50.png


BIN
non_catalog_apps/unitemp/assets/sherlok_53x45.png


BIN
non_catalog_apps/unitemp/assets/temp_C_11x14.png


BIN
non_catalog_apps/unitemp/assets/temp_F_11x14.png


BIN
non_catalog_apps/unitemp/icon.png


+ 0 - 131
non_catalog_apps/unitemp/interfaces/I2CSensor.c

@@ -1,131 +0,0 @@
-/*
-    Unitemp - Universal temperature reader
-    Copyright (C) 2022-2023  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 <https://www.gnu.org/licenses/>.
-*/
-#include "I2CSensor.h"
-
-static uint8_t sensors_count = 0;
-
-void unitemp_i2c_acquire(FuriHalI2cBusHandle* handle) {
-    furi_hal_i2c_acquire(handle);
-    LL_GPIO_SetPinPull(gpio_ext_pc1.port, gpio_ext_pc1.pin, LL_GPIO_PULL_UP);
-    LL_GPIO_SetPinPull(gpio_ext_pc0.port, gpio_ext_pc0.pin, LL_GPIO_PULL_UP);
-}
-
-bool unitemp_i2c_isDeviceReady(I2CSensor* i2c_sensor) {
-    unitemp_i2c_acquire(i2c_sensor->i2c);
-    bool status = furi_hal_i2c_is_device_ready(i2c_sensor->i2c, i2c_sensor->currentI2CAdr, 10);
-    furi_hal_i2c_release(i2c_sensor->i2c);
-    return status;
-}
-
-uint8_t unitemp_i2c_readReg(I2CSensor* i2c_sensor, uint8_t reg) {
-    //Блокировка шины
-    unitemp_i2c_acquire(i2c_sensor->i2c);
-    uint8_t buff[1] = {0};
-    furi_hal_i2c_read_mem(i2c_sensor->i2c, i2c_sensor->currentI2CAdr, reg, buff, 1, 10);
-    furi_hal_i2c_release(i2c_sensor->i2c);
-    return buff[0];
-}
-
-bool unitemp_i2c_readArray(I2CSensor* i2c_sensor, uint8_t len, uint8_t* data) {
-    unitemp_i2c_acquire(i2c_sensor->i2c);
-    bool status = furi_hal_i2c_rx(i2c_sensor->i2c, i2c_sensor->currentI2CAdr, data, len, 10);
-    furi_hal_i2c_release(i2c_sensor->i2c);
-    return status;
-}
-
-bool unitemp_i2c_readRegArray(I2CSensor* i2c_sensor, uint8_t startReg, uint8_t len, uint8_t* data) {
-    unitemp_i2c_acquire(i2c_sensor->i2c);
-    bool status =
-        furi_hal_i2c_read_mem(i2c_sensor->i2c, i2c_sensor->currentI2CAdr, startReg, data, len, 10);
-    furi_hal_i2c_release(i2c_sensor->i2c);
-    return status;
-}
-
-bool unitemp_i2c_writeReg(I2CSensor* i2c_sensor, uint8_t reg, uint8_t value) {
-    //Блокировка шины
-    unitemp_i2c_acquire(i2c_sensor->i2c);
-    uint8_t buff[1] = {value};
-    bool status =
-        furi_hal_i2c_write_mem(i2c_sensor->i2c, i2c_sensor->currentI2CAdr, reg, buff, 1, 10);
-    furi_hal_i2c_release(i2c_sensor->i2c);
-    return status;
-}
-
-bool unitemp_i2c_writeArray(I2CSensor* i2c_sensor, uint8_t len, uint8_t* data) {
-    unitemp_i2c_acquire(i2c_sensor->i2c);
-    bool status = furi_hal_i2c_tx(i2c_sensor->i2c, i2c_sensor->currentI2CAdr, data, len, 10);
-    furi_hal_i2c_release(i2c_sensor->i2c);
-    return status;
-}
-
-bool unitemp_i2c_writeRegArray(I2CSensor* i2c_sensor, uint8_t startReg, uint8_t len, uint8_t* data) {
-    //Блокировка шины
-    unitemp_i2c_acquire(i2c_sensor->i2c);
-    bool status = furi_hal_i2c_write_mem(
-        i2c_sensor->i2c, i2c_sensor->currentI2CAdr, startReg, data, len, 10);
-    furi_hal_i2c_release(i2c_sensor->i2c);
-    return status;
-}
-
-bool unitemp_I2C_sensor_alloc(Sensor* sensor, char* args) {
-    bool status = false;
-    I2CSensor* instance = malloc(sizeof(I2CSensor));
-    if(instance == NULL) {
-        FURI_LOG_E(APP_NAME, "Sensor %s instance allocation error", sensor->name);
-        return false;
-    }
-    instance->i2c = &furi_hal_i2c_handle_external;
-    sensor->instance = instance;
-
-    //Указание функций инициализации, деинициализации и обновления данных, а так же адреса на шине I2C
-    status = sensor->type->allocator(sensor, args);
-    int i2c_addr;
-    sscanf(args, "%X", &i2c_addr);
-
-    //Установка адреса шины I2C
-    if(i2c_addr >= instance->minI2CAdr && i2c_addr <= instance->maxI2CAdr) {
-        instance->currentI2CAdr = i2c_addr;
-    } else {
-        instance->currentI2CAdr = instance->minI2CAdr;
-    }
-
-    //Блокировка портов GPIO
-    sensors_count++;
-    unitemp_gpio_lock(unitemp_gpio_getFromInt(15), &I2C);
-    unitemp_gpio_lock(unitemp_gpio_getFromInt(16), &I2C);
-
-    return status;
-}
-
-bool unitemp_I2C_sensor_free(Sensor* sensor) {
-    bool status = sensor->type->mem_releaser(sensor);
-    free(sensor->instance);
-    if(--sensors_count == 0) {
-        unitemp_gpio_unlock(unitemp_gpio_getFromInt(15));
-        unitemp_gpio_unlock(unitemp_gpio_getFromInt(16));
-    }
-
-    return status;
-}
-
-UnitempStatus unitemp_I2C_sensor_update(Sensor* sensor) {
-    if(sensor->status != UT_SENSORSTATUS_OK) {
-        sensor->type->initializer(sensor);
-    }
-    return sensor->type->updater(sensor);
-}

+ 0 - 128
non_catalog_apps/unitemp/interfaces/I2CSensor.h

@@ -1,128 +0,0 @@
-/*
-    Unitemp - Universal temperature reader
-    Copyright (C) 2022-2023  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 <https://www.gnu.org/licenses/>.
-*/
-#ifndef UNITEMP_I2C
-#define UNITEMP_I2C
-
-#include "../unitemp.h"
-
-#include <furi_hal_i2c.h>
-
-//Структура I2C датчика
-typedef struct I2CSensor {
-    //Указатель на интерфейс I2C
-    FuriHalI2cBusHandle* i2c;
-    //Минимальный адрес устройства на шине I2C
-    uint8_t minI2CAdr;
-    //Максимальный адрес устройства на шине I2C
-    uint8_t maxI2CAdr;
-    //Текущий адрес устройства на шине I2C
-    uint8_t currentI2CAdr;
-    //Указатель на собственный экземпляр датчика
-    void* sensorInstance;
-} I2CSensor;
-
-/**
- * @brief Заблокировать шину I2C
- * 
- * @param handle Указатель на шину
- */
-void unitemp_i2c_acquire(FuriHalI2cBusHandle* handle);
-
-/**
- * @brief Проверить наличие датчика на шине
- * 
- * @param i2c_sensor Указатель на датчик
- * @return Истина если устройство отозвалось
- */
-bool unitemp_i2c_isDeviceReady(I2CSensor* i2c_sensor);
-
-/**
- * @brief Выделение памяти для датчика на шине I2C
- * @param sensor Указатель на датчик
- * @param st Тип датчика
- * @return Истина если всё ок
- */
-bool unitemp_I2C_sensor_alloc(Sensor* sensor, char* args);
-
-/**
- * @brief Высвобождение памяти инстанса датчика
- * @param sensor Указатель на датчик
- */
-bool unitemp_I2C_sensor_free(Sensor* sensor);
-
-/**
- * @brief Обновить значение с датчка
- * @param sensor Указатель на датчик
- * @return Статус обновления
- */
-UnitempStatus unitemp_I2C_sensor_update(Sensor* sensor);
-/**
- * @brief Прочитать значение регистра reg
- * @param i2c_sensor Указатель на инстанс датчика
- * @param reg Номер регистра
- * @return Значение регистра
- */
-uint8_t unitemp_i2c_readReg(I2CSensor* i2c_sensor, uint8_t reg);
-
-/**
- * @brief Прочитать масссив значений из памяти
- * @param i2c_sensor Указатель на инстанс датчика
- * @param startReg Адрес регистра с которого начнётся чтение
- * @param len Количество байт для считывания из регистра
- * @param data Указатель на массив куда будут считаны данные
- * @return Истина если устройство вернуло данные
- */
-bool unitemp_i2c_readRegArray(I2CSensor* i2c_sensor, uint8_t startReg, uint8_t len, uint8_t* data);
-
-/**
- * @brief Записать значение в регистр
- * @param i2c_sensor Указатель на инстанс датчика
- * @param reg Номер регистра
- * @param value Значение для записи
- * @return Истина если значение записано
- */
-bool unitemp_i2c_writeReg(I2CSensor* i2c_sensor, uint8_t reg, uint8_t value);
-
-/**
- * @brief Записать масссив значений в память
- * @param i2c_sensor Указатель на инстанс датчика
- * @param startReg Адрес регистра с которого начнётся запись
- * @param len Количество байт для считывания из регистра
- * @param data Указатель на массив откуда будут записаны данные
- * @return Истина если устройство вернуло данные
- */
-bool unitemp_i2c_writeRegArray(I2CSensor* i2c_sensor, uint8_t startReg, uint8_t len, uint8_t* data);
-
-/**
- * @brief Прочитать массив данных по шине I2C
- * @param i2c_sensor Указатель на инстанс датчика
- * @param startReg Адрес регистра с которого начнётся чтение
- * @param data Указатель на массив куда будут считаны данные
- * @return Истина если устройство вернуло данные
- */
-bool unitemp_i2c_readArray(I2CSensor* i2c_sensor, uint8_t len, uint8_t* data);
-
-/**
- * @brief Записать масссив данных по шине I2C
- * @param i2c_sensor Указатель на инстанс датчика
- * @param len Количество байт для считывания из регистра
- * @param data Указатель на массив откуда будут записаны данные
- * @return Истина если устройство вернуло данные
- */
-bool unitemp_i2c_writeArray(I2CSensor* i2c_sensor, uint8_t len, uint8_t* data);
-#endif

Некоторые файлы не были показаны из-за большого количества измененных файлов