ble: profile rework (#3272)

* ble: profile rework, initial
* apps: hid: fix for pairing cleanup
* app: hid: select transport based on #define
* fixing PVS warnings
* ble: serial service: fixed uid naming
* bt service: on-demand dialog init; ble profiles: docs; battery svc: proper update
* Added shci_cmd_resp_wait/shci_cmd_resp_release impl with semaphore
* app: hid: separated transport code
* ble: fixed service init order for serial svc; moved hardfault check to ble_glue
* cli: ps: added thread prio to output, fixed heap display
* ble_glue: naming changes; separate thread for event processing;
* furi: added runtime stats; cli: added cpu% to `ps`
* cli: fixed thread time calculation
* furi: added getter for thread priority
* fixing pvs warnings
* hid profile: fixed naming
* more naming fixes
* hal: ble init small cleanup
* cleanup & draft beacon api
* f18: api sync
* apps: moved example_custom_font from debug to examples
* BLE extra beacon demo app
* naming fix
* UI fixes for demo app (wip)
* desktop, ble svc: added statusbar icon for beacon
* minor cleanup
* Minor cleanup & naming fixes
* api sync
* Removed stale header
* hal: added FURI_BLE_EXTRA_LOG for extra logging; comments & code cleanup
* naming & macro fixes
* quick fixes from review
* Eliminated stock svc_ctl
* cli: ps: removed runtime stats
* minor include fixes
* (void)
* naming fixes
* More naming fixes
* fbt: always build all libs
* fbt: explicitly globbing libs; dist: logging SDK path
* scripts: fixed lib path precedence
* hal: bt: profiles: naming changes, support for passing params to a profile; include cleanup
* ble: hid: added parameter processing for profile template
* api sync
* BLE HID: long name trim
* Removed unused check
* desktop: updated beacon status icon; ble: hid: cleaner device name management
* desktop: updated status icon

Co-authored-by: あく <alleteam@gmail.com>
Co-authored-by: nminaylov <nm29719@gmail.com>
This commit is contained in:
hedger
2024-02-16 11:20:45 +04:00
committed by GitHub
parent 87804374c5
commit 60a9d7e6cf
91 changed files with 3361 additions and 1739 deletions

View File

@@ -1,28 +1,30 @@
#include "battery_service.h"
#include "app_common.h"
#include "gatt_char.h"
#include <core/check.h>
#include <furi_ble/gatt.h>
#include <ble/ble.h>
#include <furi.h>
#include <furi_hal_power.h>
#include <m-list.h>
#define TAG "BtBatterySvc"
enum {
// Common states
/* Common states */
BatterySvcPowerStateUnknown = 0b00,
BatterySvcPowerStateUnsupported = 0b01,
// Level states
/* Level states */
BatterySvcPowerStateGoodLevel = 0b10,
BatterySvcPowerStateCriticallyLowLevel = 0b11,
// Charging states
/* Charging states */
BatterySvcPowerStateNotCharging = 0b10,
BatterySvcPowerStateCharging = 0b11,
// Discharging states
/* Discharging states */
BatterySvcPowerStateNotDischarging = 0b10,
BatterySvcPowerStateDischarging = 0b11,
// Battery states
/* Battery states */
BatterySvcPowerStateBatteryNotPresent = 0b10,
BatterySvcPowerStateBatteryPresent = 0b11,
};
@@ -46,96 +48,110 @@ typedef enum {
BatterySvcGattCharacteristicCount,
} BatterySvcGattCharacteristicId;
static const FlipperGattCharacteristicParams battery_svc_chars[BatterySvcGattCharacteristicCount] =
{[BatterySvcGattCharacteristicBatteryLevel] =
{.name = "Battery Level",
.data_prop_type = FlipperGattCharacteristicDataFixed,
.data.fixed.length = 1,
.uuid.Char_UUID_16 = BATTERY_LEVEL_CHAR_UUID,
.uuid_type = UUID_TYPE_16,
.char_properties = CHAR_PROP_READ | CHAR_PROP_NOTIFY,
.security_permissions = ATTR_PERMISSION_AUTHEN_READ,
.gatt_evt_mask = GATT_DONT_NOTIFY_EVENTS,
.is_variable = CHAR_VALUE_LEN_CONSTANT},
[BatterySvcGattCharacteristicPowerState] = {
.name = "Power State",
static const BleGattCharacteristicParams battery_svc_chars[BatterySvcGattCharacteristicCount] = {
[BatterySvcGattCharacteristicBatteryLevel] =
{.name = "Battery Level",
.data_prop_type = FlipperGattCharacteristicDataFixed,
.data.fixed.length = 1,
.uuid.Char_UUID_16 = BATTERY_POWER_STATE,
.uuid.Char_UUID_16 = BATTERY_LEVEL_CHAR_UUID,
.uuid_type = UUID_TYPE_16,
.char_properties = CHAR_PROP_READ | CHAR_PROP_NOTIFY,
.security_permissions = ATTR_PERMISSION_AUTHEN_READ,
.gatt_evt_mask = GATT_DONT_NOTIFY_EVENTS,
.is_variable = CHAR_VALUE_LEN_CONSTANT}};
.is_variable = CHAR_VALUE_LEN_CONSTANT},
[BatterySvcGattCharacteristicPowerState] = {
.name = "Power State",
.data_prop_type = FlipperGattCharacteristicDataFixed,
.data.fixed.length = 1,
.uuid.Char_UUID_16 = BATTERY_POWER_STATE,
.uuid_type = UUID_TYPE_16,
.char_properties = CHAR_PROP_READ | CHAR_PROP_NOTIFY,
.security_permissions = ATTR_PERMISSION_AUTHEN_READ,
.gatt_evt_mask = GATT_DONT_NOTIFY_EVENTS,
.is_variable = CHAR_VALUE_LEN_CONSTANT}};
typedef struct {
struct BleServiceBattery {
uint16_t svc_handle;
FlipperGattCharacteristicInstance chars[BatterySvcGattCharacteristicCount];
} BatterySvc;
BleGattCharacteristicInstance chars[BatterySvcGattCharacteristicCount];
bool auto_update;
};
static BatterySvc* battery_svc = NULL;
LIST_DEF(BatterySvcInstanceList, BleServiceBattery*, M_POD_OPLIST);
void battery_svc_start() {
battery_svc = malloc(sizeof(BatterySvc));
tBleStatus status;
/* We need to keep track of all battery service instances so that we can update
* them when the battery state changes. */
static BatterySvcInstanceList_t instances;
static bool instances_initialized = false;
// Add Battery service
status = aci_gatt_add_service(
UUID_TYPE_16, (Service_UUID_t*)&service_uuid, PRIMARY_SERVICE, 8, &battery_svc->svc_handle);
if(status) {
FURI_LOG_E(TAG, "Failed to add Battery service: %d", status);
BleServiceBattery* ble_svc_battery_start(bool auto_update) {
BleServiceBattery* battery_svc = malloc(sizeof(BleServiceBattery));
if(!ble_gatt_service_add(
UUID_TYPE_16,
(Service_UUID_t*)&service_uuid,
PRIMARY_SERVICE,
8,
&battery_svc->svc_handle)) {
free(battery_svc);
return NULL;
}
for(size_t i = 0; i < BatterySvcGattCharacteristicCount; i++) {
flipper_gatt_characteristic_init(
ble_gatt_characteristic_init(
battery_svc->svc_handle, &battery_svc_chars[i], &battery_svc->chars[i]);
}
battery_svc_update_power_state();
}
void battery_svc_stop() {
tBleStatus status;
if(battery_svc) {
for(size_t i = 0; i < BatterySvcGattCharacteristicCount; i++) {
flipper_gatt_characteristic_delete(battery_svc->svc_handle, &battery_svc->chars[i]);
battery_svc->auto_update = auto_update;
if(auto_update) {
if(!instances_initialized) {
BatterySvcInstanceList_init(instances);
instances_initialized = true;
}
// Delete Battery service
status = aci_gatt_del_service(battery_svc->svc_handle);
if(status) {
FURI_LOG_E(TAG, "Failed to delete Battery service: %d", status);
BatterySvcInstanceList_push_back(instances, battery_svc);
}
return battery_svc;
}
void ble_svc_battery_stop(BleServiceBattery* battery_svc) {
furi_assert(battery_svc);
if(battery_svc->auto_update) {
BatterySvcInstanceList_it_t it;
for(BatterySvcInstanceList_it(it, instances); !BatterySvcInstanceList_end_p(it);
BatterySvcInstanceList_next(it)) {
if(*BatterySvcInstanceList_ref(it) == battery_svc) {
BatterySvcInstanceList_remove(instances, it);
break;
}
}
free(battery_svc);
battery_svc = NULL;
}
for(size_t i = 0; i < BatterySvcGattCharacteristicCount; i++) {
ble_gatt_characteristic_delete(battery_svc->svc_handle, &battery_svc->chars[i]);
}
/* Delete Battery service */
ble_gatt_service_delete(battery_svc->svc_handle);
free(battery_svc);
}
bool battery_svc_is_started() {
return battery_svc != NULL;
}
bool battery_svc_update_level(uint8_t battery_charge) {
// Check if service was started
if(battery_svc == NULL) {
return false;
}
// Update battery level characteristic
return flipper_gatt_characteristic_update(
bool ble_svc_battery_update_level(BleServiceBattery* battery_svc, uint8_t battery_charge) {
furi_check(battery_svc);
/* Update battery level characteristic */
return ble_gatt_characteristic_update(
battery_svc->svc_handle,
&battery_svc->chars[BatterySvcGattCharacteristicBatteryLevel],
&battery_charge);
}
bool battery_svc_update_power_state() {
// Check if service was started
if(battery_svc == NULL) {
return false;
}
// Update power state characteristic
bool ble_svc_battery_update_power_state(BleServiceBattery* battery_svc, bool charging) {
furi_check(battery_svc);
/* Update power state characteristic */
BattrySvcPowerState power_state = {
.level = BatterySvcPowerStateUnsupported,
.present = BatterySvcPowerStateBatteryPresent,
};
if(furi_hal_power_is_charging()) {
if(charging) {
power_state.charging = BatterySvcPowerStateCharging;
power_state.discharging = BatterySvcPowerStateNotDischarging;
} else {
@@ -143,8 +159,29 @@ bool battery_svc_update_power_state() {
power_state.discharging = BatterySvcPowerStateDischarging;
}
return flipper_gatt_characteristic_update(
return ble_gatt_characteristic_update(
battery_svc->svc_handle,
&battery_svc->chars[BatterySvcGattCharacteristicPowerState],
&power_state);
}
void ble_svc_battery_state_update(uint8_t* battery_level, bool* charging) {
if(!instances_initialized) {
#ifdef FURI_BLE_EXTRA_LOG
FURI_LOG_W(TAG, "Battery service not initialized");
#endif
return;
}
BatterySvcInstanceList_it_t it;
for(BatterySvcInstanceList_it(it, instances); !BatterySvcInstanceList_end_p(it);
BatterySvcInstanceList_next(it)) {
BleServiceBattery* battery_svc = *BatterySvcInstanceList_ref(it);
if(battery_level) {
ble_svc_battery_update_level(battery_svc, *battery_level);
}
if(charging) {
ble_svc_battery_update_power_state(battery_svc, *charging);
}
}
}