mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-05-10 05:59:08 -07:00
Merge remote-tracking branch 'origin/dev' into astra/3934-alarm-improvements
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
#include "expansion_worker.h"
|
||||
|
||||
#include <power/power_service/power.h>
|
||||
#include <furi_hal_power.h>
|
||||
|
||||
#include <furi_hal_serial.h>
|
||||
#include <furi_hal_serial_control.h>
|
||||
|
||||
@@ -250,9 +252,13 @@ static bool expansion_worker_handle_state_connected(
|
||||
if(!expansion_worker_rpc_session_open(instance)) break;
|
||||
instance->state = ExpansionWorkerStateRpcActive;
|
||||
} else if(command == ExpansionFrameControlCommandEnableOtg) {
|
||||
furi_hal_power_enable_otg();
|
||||
Power* power = furi_record_open(RECORD_POWER);
|
||||
power_enable_otg(power, true);
|
||||
furi_record_close(RECORD_POWER);
|
||||
} else if(command == ExpansionFrameControlCommandDisableOtg) {
|
||||
furi_hal_power_disable_otg();
|
||||
Power* power = furi_record_open(RECORD_POWER);
|
||||
power_enable_otg(power, false);
|
||||
furi_record_close(RECORD_POWER);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <gui/canvas.h>
|
||||
#include <gui/elements.h>
|
||||
#include <input/input.h>
|
||||
|
||||
#include <furi.h>
|
||||
#include <furi_hal_resources.h>
|
||||
@@ -46,6 +47,7 @@ ARRAY_DEF(ButtonMatrix, ButtonArray_t);
|
||||
|
||||
struct ButtonPanel {
|
||||
View* view;
|
||||
bool freeze_input;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
@@ -63,7 +65,7 @@ static void button_panel_process_up(ButtonPanel* button_panel);
|
||||
static void button_panel_process_down(ButtonPanel* button_panel);
|
||||
static void button_panel_process_left(ButtonPanel* button_panel);
|
||||
static void button_panel_process_right(ButtonPanel* button_panel);
|
||||
static void button_panel_process_ok(ButtonPanel* button_panel);
|
||||
static void button_panel_process_ok(ButtonPanel* button_panel, InputType input);
|
||||
static void button_panel_view_draw_callback(Canvas* canvas, void* _model);
|
||||
static bool button_panel_view_input_callback(InputEvent* event, void* context);
|
||||
|
||||
@@ -347,7 +349,7 @@ static void button_panel_process_right(ButtonPanel* button_panel) {
|
||||
true);
|
||||
}
|
||||
|
||||
void button_panel_process_ok(ButtonPanel* button_panel) {
|
||||
void button_panel_process_ok(ButtonPanel* button_panel, InputType type) {
|
||||
ButtonItem* button_item = NULL;
|
||||
|
||||
with_view_model(
|
||||
@@ -360,7 +362,7 @@ void button_panel_process_ok(ButtonPanel* button_panel) {
|
||||
true);
|
||||
|
||||
if(button_item && button_item->callback) {
|
||||
button_item->callback(button_item->callback_context, button_item->index);
|
||||
button_item->callback(button_item->callback_context, button_item->index, type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -368,8 +370,15 @@ static bool button_panel_view_input_callback(InputEvent* event, void* context) {
|
||||
ButtonPanel* button_panel = context;
|
||||
furi_assert(button_panel);
|
||||
bool consumed = false;
|
||||
|
||||
if(event->type == InputTypeShort) {
|
||||
if(event->key == InputKeyOk) {
|
||||
if((event->type == InputTypePress) || (event->type == InputTypeRelease)) {
|
||||
button_panel->freeze_input = (event->type == InputTypePress);
|
||||
}
|
||||
consumed = true;
|
||||
button_panel_process_ok(button_panel, event->type);
|
||||
}
|
||||
if(!button_panel->freeze_input &&
|
||||
(!(event->type == InputTypePress) && !(event->type == InputTypeRelease))) {
|
||||
switch(event->key) {
|
||||
case InputKeyUp:
|
||||
consumed = true;
|
||||
@@ -387,10 +396,6 @@ static bool button_panel_view_input_callback(InputEvent* event, void* context) {
|
||||
consumed = true;
|
||||
button_panel_process_right(button_panel);
|
||||
break;
|
||||
case InputKeyOk:
|
||||
consumed = true;
|
||||
button_panel_process_ok(button_panel);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ extern "C" {
|
||||
typedef struct ButtonPanel ButtonPanel;
|
||||
|
||||
/** Callback type to call for handling selecting button_panel items */
|
||||
typedef void (*ButtonItemCallback)(void* context, uint32_t index);
|
||||
typedef void (*ButtonItemCallback)(void* context, uint32_t index, InputType type);
|
||||
|
||||
/** Allocate new button_panel module.
|
||||
*
|
||||
|
||||
@@ -195,14 +195,27 @@ void widget_add_icon_element(Widget* widget, uint8_t x, uint8_t y, const Icon* i
|
||||
widget_add_element(widget, icon_element);
|
||||
}
|
||||
|
||||
void widget_add_frame_element(
|
||||
void widget_add_rect_element(
|
||||
Widget* widget,
|
||||
uint8_t x,
|
||||
uint8_t y,
|
||||
uint8_t width,
|
||||
uint8_t height,
|
||||
uint8_t radius) {
|
||||
uint8_t radius,
|
||||
bool fill) {
|
||||
furi_check(widget);
|
||||
WidgetElement* frame_element = widget_element_frame_create(x, y, width, height, radius);
|
||||
widget_add_element(widget, frame_element);
|
||||
WidgetElement* rect_element = widget_element_rect_create(x, y, width, height, radius, fill);
|
||||
widget_add_element(widget, rect_element);
|
||||
}
|
||||
|
||||
void widget_add_circle_element(Widget* widget, uint8_t x, uint8_t y, uint8_t radius, bool fill) {
|
||||
furi_check(widget);
|
||||
WidgetElement* circle_element = widget_element_circle_create(x, y, radius, fill);
|
||||
widget_add_element(widget, circle_element);
|
||||
}
|
||||
|
||||
void widget_add_line_element(Widget* widget, uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2) {
|
||||
furi_check(widget);
|
||||
WidgetElement* line_element = widget_element_line_create(x1, y1, x2, y2);
|
||||
widget_add_element(widget, line_element);
|
||||
}
|
||||
|
||||
@@ -152,21 +152,57 @@ void widget_add_button_element(
|
||||
void widget_add_icon_element(Widget* widget, uint8_t x, uint8_t y, const Icon* icon);
|
||||
|
||||
/** Add Frame Element
|
||||
*
|
||||
* @param widget Widget instance
|
||||
* @param x top left x coordinate
|
||||
* @param y top left y coordinate
|
||||
* @param width frame width
|
||||
* @param height frame height
|
||||
* @param radius frame radius
|
||||
*
|
||||
* @warning deprecated, use widget_add_rect_element instead
|
||||
*/
|
||||
#define widget_add_frame_element(widget, x, y, width, height, radius) \
|
||||
widget_add_rect_element((widget), (x), (y), (width), (height), (radius), false)
|
||||
|
||||
/** Add Rect Element
|
||||
*
|
||||
* @param widget Widget instance
|
||||
* @param x top left x coordinate
|
||||
* @param y top left y coordinate
|
||||
* @param width frame width
|
||||
* @param height frame height
|
||||
* @param radius frame radius
|
||||
* @param width rect width
|
||||
* @param height rect height
|
||||
* @param radius corner radius
|
||||
* @param fill whether to fill the box or not
|
||||
*/
|
||||
void widget_add_frame_element(
|
||||
void widget_add_rect_element(
|
||||
Widget* widget,
|
||||
uint8_t x,
|
||||
uint8_t y,
|
||||
uint8_t width,
|
||||
uint8_t height,
|
||||
uint8_t radius);
|
||||
uint8_t radius,
|
||||
bool fill);
|
||||
|
||||
/** Add Circle Element
|
||||
*
|
||||
* @param widget Widget instance
|
||||
* @param x center x coordinate
|
||||
* @param y center y coordinate
|
||||
* @param radius circle radius
|
||||
* @param fill whether to fill the circle or not
|
||||
*/
|
||||
void widget_add_circle_element(Widget* widget, uint8_t x, uint8_t y, uint8_t radius, bool fill);
|
||||
|
||||
/** Add Line Element
|
||||
*
|
||||
* @param widget Widget instance
|
||||
* @param x1 first x coordinate
|
||||
* @param y1 first y coordinate
|
||||
* @param x2 second x coordinate
|
||||
* @param y2 second y coordinate
|
||||
*/
|
||||
void widget_add_line_element(Widget* widget, uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <input/input.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
#include "widget_element_i.h"
|
||||
|
||||
typedef struct {
|
||||
uint8_t x;
|
||||
uint8_t y;
|
||||
uint8_t radius;
|
||||
bool fill;
|
||||
} GuiCircleModel;
|
||||
|
||||
static void gui_circle_draw(Canvas* canvas, WidgetElement* element) {
|
||||
furi_assert(canvas);
|
||||
furi_assert(element);
|
||||
GuiCircleModel* model = element->model;
|
||||
if(model->fill) {
|
||||
canvas_draw_disc(canvas, model->x, model->y, model->radius);
|
||||
} else {
|
||||
canvas_draw_circle(canvas, model->x, model->y, model->radius);
|
||||
}
|
||||
}
|
||||
|
||||
static void gui_circle_free(WidgetElement* gui_circle) {
|
||||
furi_assert(gui_circle);
|
||||
|
||||
free(gui_circle->model);
|
||||
free(gui_circle);
|
||||
}
|
||||
|
||||
WidgetElement* widget_element_circle_create(uint8_t x, uint8_t y, uint8_t radius, bool fill) {
|
||||
// Allocate and init model
|
||||
GuiCircleModel* model = malloc(sizeof(GuiCircleModel));
|
||||
model->x = x;
|
||||
model->y = y;
|
||||
model->radius = radius;
|
||||
model->fill = fill;
|
||||
|
||||
// Allocate and init Element
|
||||
WidgetElement* gui_circle = malloc(sizeof(WidgetElement));
|
||||
gui_circle->parent = NULL;
|
||||
gui_circle->input = NULL;
|
||||
gui_circle->draw = gui_circle_draw;
|
||||
gui_circle->free = gui_circle_free;
|
||||
gui_circle->model = model;
|
||||
|
||||
return gui_circle;
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
#include "widget_element_i.h"
|
||||
|
||||
typedef struct {
|
||||
uint8_t x;
|
||||
uint8_t y;
|
||||
uint8_t width;
|
||||
uint8_t height;
|
||||
uint8_t radius;
|
||||
} GuiFrameModel;
|
||||
|
||||
static void gui_frame_draw(Canvas* canvas, WidgetElement* element) {
|
||||
furi_assert(canvas);
|
||||
furi_assert(element);
|
||||
GuiFrameModel* model = element->model;
|
||||
canvas_draw_rframe(canvas, model->x, model->y, model->width, model->height, model->radius);
|
||||
}
|
||||
|
||||
static void gui_frame_free(WidgetElement* gui_frame) {
|
||||
furi_assert(gui_frame);
|
||||
|
||||
free(gui_frame->model);
|
||||
free(gui_frame);
|
||||
}
|
||||
|
||||
WidgetElement* widget_element_frame_create(
|
||||
uint8_t x,
|
||||
uint8_t y,
|
||||
uint8_t width,
|
||||
uint8_t height,
|
||||
uint8_t radius) {
|
||||
// Allocate and init model
|
||||
GuiFrameModel* model = malloc(sizeof(GuiFrameModel));
|
||||
model->x = x;
|
||||
model->y = y;
|
||||
model->width = width;
|
||||
model->height = height;
|
||||
model->radius = radius;
|
||||
|
||||
// Allocate and init Element
|
||||
WidgetElement* gui_frame = malloc(sizeof(WidgetElement));
|
||||
gui_frame->parent = NULL;
|
||||
gui_frame->input = NULL;
|
||||
gui_frame->draw = gui_frame_draw;
|
||||
gui_frame->free = gui_frame_free;
|
||||
gui_frame->model = model;
|
||||
|
||||
return gui_frame;
|
||||
}
|
||||
@@ -73,14 +73,16 @@ WidgetElement* widget_element_button_create(
|
||||
/** Create icon element */
|
||||
WidgetElement* widget_element_icon_create(uint8_t x, uint8_t y, const Icon* icon);
|
||||
|
||||
/** Create frame element */
|
||||
WidgetElement* widget_element_frame_create(
|
||||
/** Create rect element */
|
||||
WidgetElement* widget_element_rect_create(
|
||||
uint8_t x,
|
||||
uint8_t y,
|
||||
uint8_t width,
|
||||
uint8_t height,
|
||||
uint8_t radius);
|
||||
uint8_t radius,
|
||||
bool fill);
|
||||
|
||||
/** Create text scroll element */
|
||||
WidgetElement* widget_element_text_scroll_create(
|
||||
uint8_t x,
|
||||
uint8_t y,
|
||||
@@ -88,6 +90,12 @@ WidgetElement* widget_element_text_scroll_create(
|
||||
uint8_t height,
|
||||
const char* text);
|
||||
|
||||
/** Create circle element */
|
||||
WidgetElement* widget_element_circle_create(uint8_t x, uint8_t y, uint8_t radius, bool fill);
|
||||
|
||||
/** Create line element */
|
||||
WidgetElement* widget_element_line_create(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
#include "widget_element_i.h"
|
||||
|
||||
typedef struct {
|
||||
uint8_t x1;
|
||||
uint8_t y1;
|
||||
uint8_t x2;
|
||||
uint8_t y2;
|
||||
} GuiLineModel;
|
||||
|
||||
static void gui_line_draw(Canvas* canvas, WidgetElement* element) {
|
||||
furi_assert(canvas);
|
||||
furi_assert(element);
|
||||
GuiLineModel* model = element->model;
|
||||
canvas_draw_line(canvas, model->x1, model->y1, model->x2, model->y2);
|
||||
}
|
||||
|
||||
static void gui_line_free(WidgetElement* gui_line) {
|
||||
furi_assert(gui_line);
|
||||
|
||||
free(gui_line->model);
|
||||
free(gui_line);
|
||||
}
|
||||
|
||||
WidgetElement* widget_element_line_create(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2) {
|
||||
// Allocate and init model
|
||||
GuiLineModel* model = malloc(sizeof(GuiLineModel));
|
||||
model->x1 = x1;
|
||||
model->y1 = y1;
|
||||
model->x2 = x2;
|
||||
model->y2 = y2;
|
||||
|
||||
// Allocate and init Element
|
||||
WidgetElement* gui_line = malloc(sizeof(WidgetElement));
|
||||
gui_line->parent = NULL;
|
||||
gui_line->input = NULL;
|
||||
gui_line->draw = gui_line_draw;
|
||||
gui_line->free = gui_line_free;
|
||||
gui_line->model = model;
|
||||
|
||||
return gui_line;
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
#include "widget_element_i.h"
|
||||
|
||||
typedef struct {
|
||||
uint8_t x;
|
||||
uint8_t y;
|
||||
uint8_t width;
|
||||
uint8_t height;
|
||||
uint8_t radius;
|
||||
bool fill;
|
||||
} GuiRectModel;
|
||||
|
||||
static void gui_rect_draw(Canvas* canvas, WidgetElement* element) {
|
||||
furi_assert(canvas);
|
||||
furi_assert(element);
|
||||
GuiRectModel* model = element->model;
|
||||
if(model->fill) {
|
||||
canvas_draw_rbox(canvas, model->x, model->y, model->width, model->height, model->radius);
|
||||
} else {
|
||||
canvas_draw_rframe(canvas, model->x, model->y, model->width, model->height, model->radius);
|
||||
}
|
||||
}
|
||||
|
||||
static void gui_rect_free(WidgetElement* gui_rect) {
|
||||
furi_assert(gui_rect);
|
||||
|
||||
free(gui_rect->model);
|
||||
free(gui_rect);
|
||||
}
|
||||
|
||||
WidgetElement* widget_element_rect_create(
|
||||
uint8_t x,
|
||||
uint8_t y,
|
||||
uint8_t width,
|
||||
uint8_t height,
|
||||
uint8_t radius,
|
||||
bool fill) {
|
||||
// Allocate and init model
|
||||
GuiRectModel* model = malloc(sizeof(GuiRectModel));
|
||||
model->x = x;
|
||||
model->y = y;
|
||||
model->width = width;
|
||||
model->height = height;
|
||||
model->radius = radius;
|
||||
model->fill = fill;
|
||||
|
||||
// Allocate and init Element
|
||||
WidgetElement* gui_rect = malloc(sizeof(WidgetElement));
|
||||
gui_rect->parent = NULL;
|
||||
gui_rect->input = NULL;
|
||||
gui_rect->draw = gui_rect_draw;
|
||||
gui_rect->free = gui_rect_free;
|
||||
gui_rect->model = model;
|
||||
|
||||
return gui_rect;
|
||||
}
|
||||
@@ -230,6 +230,11 @@ bool scene_manager_search_and_switch_to_another_scene(
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t scene_manager_get_current_scene(SceneManager* scene_manager) {
|
||||
furi_check(scene_manager);
|
||||
return *SceneManagerIdStack_back(scene_manager->scene_id_stack);
|
||||
}
|
||||
|
||||
void scene_manager_stop(SceneManager* scene_manager) {
|
||||
furi_check(scene_manager);
|
||||
|
||||
|
||||
@@ -170,6 +170,14 @@ bool scene_manager_search_and_switch_to_another_scene(
|
||||
SceneManager* scene_manager,
|
||||
uint32_t scene_id);
|
||||
|
||||
/** Get id of current scene
|
||||
*
|
||||
* @param scene_manager SceneManager instance
|
||||
*
|
||||
* @return Scene ID
|
||||
*/
|
||||
uint32_t scene_manager_get_current_scene(SceneManager* scene_manager);
|
||||
|
||||
/** Exit from current scene
|
||||
*
|
||||
* @param scene_manager SceneManager instance
|
||||
|
||||
@@ -30,13 +30,16 @@ void power_cli_reboot2dfu(Cli* cli, FuriString* args) {
|
||||
|
||||
void power_cli_5v(Cli* cli, FuriString* args) {
|
||||
UNUSED(cli);
|
||||
Power* power = furi_record_open(RECORD_POWER);
|
||||
if(!furi_string_cmp(args, "0")) {
|
||||
furi_hal_power_disable_otg();
|
||||
power_enable_otg(power, false);
|
||||
} else if(!furi_string_cmp(args, "1")) {
|
||||
furi_hal_power_enable_otg();
|
||||
power_enable_otg(power, true);
|
||||
} else {
|
||||
cli_print_usage("power_otg", "<1|0>", furi_string_get_cstr(args));
|
||||
}
|
||||
|
||||
furi_record_close(RECORD_POWER);
|
||||
}
|
||||
|
||||
void power_cli_3v3(Cli* cli, FuriString* args) {
|
||||
|
||||
@@ -64,6 +64,7 @@ static bool power_update_info(Power* power) {
|
||||
.is_charging = furi_hal_power_is_charging(),
|
||||
.gauge_is_ok = furi_hal_power_gauge_is_ok(),
|
||||
.is_shutdown_requested = furi_hal_power_is_shutdown_requested(),
|
||||
.is_otg_enabled = furi_hal_power_is_otg_enabled(),
|
||||
.charge = furi_hal_power_get_pct(),
|
||||
.health = furi_hal_power_get_bat_health_pct(),
|
||||
.capacity_remaining = furi_hal_power_get_battery_remaining_capacity(),
|
||||
@@ -216,6 +217,30 @@ static void power_message_callback(FuriEventLoopObject* object, void* context) {
|
||||
case PowerMessageTypeShowBatteryLowWarning:
|
||||
power->show_battery_low_warning = *msg.bool_param;
|
||||
break;
|
||||
case PowerMessageTypeSwitchOTG:
|
||||
power->is_otg_requested = *msg.bool_param;
|
||||
if(power->is_otg_requested) {
|
||||
// Only try to enable if VBUS voltage is low, otherwise charger will refuse
|
||||
if(power->info.voltage_vbus < 4.5f) {
|
||||
size_t retries = 5;
|
||||
while(retries-- > 0) {
|
||||
if(furi_hal_power_enable_otg()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!retries) {
|
||||
FURI_LOG_W(TAG, "Failed to enable OTG, will try later");
|
||||
}
|
||||
} else {
|
||||
FURI_LOG_W(
|
||||
TAG,
|
||||
"Postponing OTG enable: VBUS(%0.1f) >= 4.5v",
|
||||
(double)power->info.voltage_vbus);
|
||||
}
|
||||
} else {
|
||||
furi_hal_power_disable_otg();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
furi_crash();
|
||||
}
|
||||
@@ -241,9 +266,18 @@ static void power_tick_callback(void* context) {
|
||||
if(need_refresh) {
|
||||
view_port_update(power->battery_view_port);
|
||||
}
|
||||
// Check OTG status and disable it in case of fault
|
||||
if(furi_hal_power_is_otg_enabled()) {
|
||||
furi_hal_power_check_otg_status();
|
||||
// Check OTG status, disable in case of a fault
|
||||
if(furi_hal_power_check_otg_fault()) {
|
||||
FURI_LOG_E(TAG, "OTG fault detected, disabling OTG");
|
||||
furi_hal_power_disable_otg();
|
||||
power->is_otg_requested = false;
|
||||
}
|
||||
|
||||
// Change OTG state if needed (i.e. after disconnecting USB power)
|
||||
if(power->is_otg_requested &&
|
||||
(!power->info.is_otg_enabled && power->info.voltage_vbus < 4.5f)) {
|
||||
FURI_LOG_D(TAG, "OTG requested but not enabled, enabling OTG");
|
||||
furi_hal_power_enable_otg();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ typedef struct {
|
||||
bool gauge_is_ok;
|
||||
bool is_charging;
|
||||
bool is_shutdown_requested;
|
||||
bool is_otg_enabled;
|
||||
|
||||
float current_charger;
|
||||
float current_gauge;
|
||||
@@ -96,6 +97,19 @@ bool power_is_battery_healthy(Power* power);
|
||||
*/
|
||||
void power_enable_low_battery_level_notification(Power* power, bool enable);
|
||||
|
||||
/** Enable or disable OTG
|
||||
*
|
||||
* @param power Power instance
|
||||
* @param enable true - enable, false - disable
|
||||
*/
|
||||
void power_enable_otg(Power* power, bool enable);
|
||||
|
||||
/** Check OTG status
|
||||
*
|
||||
* @return true if OTG is requested
|
||||
*/
|
||||
bool power_is_otg_enabled(Power* power);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -70,3 +70,22 @@ void power_enable_low_battery_level_notification(Power* power, bool enable) {
|
||||
furi_check(
|
||||
furi_message_queue_put(power->message_queue, &msg, FuriWaitForever) == FuriStatusOk);
|
||||
}
|
||||
|
||||
void power_enable_otg(Power* power, bool enable) {
|
||||
furi_check(power);
|
||||
|
||||
PowerMessage msg = {
|
||||
.type = PowerMessageTypeSwitchOTG,
|
||||
.bool_param = &enable,
|
||||
.lock = api_lock_alloc_locked(),
|
||||
};
|
||||
|
||||
furi_check(
|
||||
furi_message_queue_put(power->message_queue, &msg, FuriWaitForever) == FuriStatusOk);
|
||||
api_lock_wait_unlock_and_free(msg.lock);
|
||||
}
|
||||
|
||||
bool power_is_otg_enabled(Power* power) {
|
||||
furi_check(power);
|
||||
return power->is_otg_requested;
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ struct Power {
|
||||
|
||||
bool battery_low;
|
||||
bool show_battery_low_warning;
|
||||
bool is_otg_requested;
|
||||
uint8_t battery_level;
|
||||
uint8_t power_off_timeout;
|
||||
};
|
||||
@@ -48,6 +49,7 @@ typedef enum {
|
||||
PowerMessageTypeGetInfo,
|
||||
PowerMessageTypeIsBatteryHealthy,
|
||||
PowerMessageTypeShowBatteryLowWarning,
|
||||
PowerMessageTypeSwitchOTG,
|
||||
} PowerMessageType;
|
||||
|
||||
typedef struct {
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <furi_hal_gpio.h>
|
||||
#include <furi_hal_power.h>
|
||||
#include <furi_hal_resources.h>
|
||||
#include <power/power_service/power.h>
|
||||
|
||||
static const GpioPin* rpc_pin_to_hal_pin(PB_Gpio_GpioPin rpc_pin) {
|
||||
switch(rpc_pin) {
|
||||
@@ -218,12 +219,16 @@ void rpc_system_gpio_set_otg_mode(const PB_Main* request, void* context) {
|
||||
|
||||
const PB_Gpio_GpioOtgMode mode = request->content.gpio_set_otg_mode.mode;
|
||||
|
||||
Power* power = furi_record_open(RECORD_POWER);
|
||||
|
||||
if(mode == PB_Gpio_GpioOtgMode_OFF) {
|
||||
furi_hal_power_disable_otg();
|
||||
power_enable_otg(power, false);
|
||||
} else {
|
||||
furi_hal_power_enable_otg();
|
||||
power_enable_otg(power, true);
|
||||
}
|
||||
|
||||
furi_record_close(RECORD_POWER);
|
||||
|
||||
rpc_send_and_release_empty(session, request->command_id, PB_CommandStatus_OK);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user