[FL-1722] BLE custom serial service (#685)

* ble: remove heart rate profile
* ble-glue: delete dead code
* ble-glue: dis refactoring
* ble-glue: add battery service
* broken ble_common refactoring
* ble-glue: advertise 128 bit service uid
* ble-glue: remove dead code
* ble: advertise service 16 bit uid depending on flipper color
* ble-glue: remove debug
* ble: intriduce serial service
* ble: serial over ble
* bt: serial echo server
* bt: serial service process indicate acknowledge
* bt: serial service event handler update
* bt: refactore battery service
* bt: add battery level apdate API
* power: update battery level on change
* bt: refactore device information service

Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
gornekich 2021-09-10 00:11:32 +03:00 committed by GitHub
parent 710f33981a
commit 9bce160ca6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 438 additions and 1121 deletions

11
applications/bt/bt_service/bt.c Normal file → Executable file
View file

@ -1,4 +1,5 @@
#include "bt_i.h"
#include "battery_service.h"
#define BT_SERVICE_TAG "BT"
@ -43,6 +44,12 @@ Bt* bt_alloc() {
return bt;
}
bool bt_update_battery_level(Bt* bt, uint8_t battery_level) {
BtMessage message = {
.type = BtMessageTypeUpdateBatteryLevel, .data.battery_level = battery_level};
return osMessageQueuePut(bt->message_queue, &message, 0, osWaitForever) == osOK;
}
int32_t bt_srv() {
Bt* bt = bt_alloc();
furi_record_create("bt", bt);
@ -68,6 +75,10 @@ int32_t bt_srv() {
if(message.type == BtMessageTypeUpdateStatusbar) {
// Update statusbar
view_port_enabled_set(bt->statusbar_view_port, furi_hal_bt_is_alive());
} else if(message.type == BtMessageTypeUpdateBatteryLevel) {
if(furi_hal_bt_is_alive()) {
battery_svc_update_level(message.data.battery_level);
}
}
}
return 0;

View file

@ -1,3 +1,16 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct Bt Bt;
bool bt_update_battery_level(Bt* bt, uint8_t battery_level);
#ifdef __cplusplus
}
#endif

View file

@ -13,11 +13,16 @@
typedef enum {
BtMessageTypeUpdateStatusbar,
BtMessageTypeUpdateBatteryLevel,
} BtMessageType;
typedef union {
uint8_t battery_level;
} BtMessageData;
typedef struct {
BtMessageType type;
void* param;
BtMessageData data;
} BtMessage;
struct Bt {

View file

@ -18,6 +18,7 @@
#include <stm32wbxx.h>
#include <notification/notification-messages.h>
#include <applications/bt/bt_service/bt.h>
#define POWER_OFF_TIMEOUT 30
@ -39,6 +40,7 @@ struct Power {
ValueMutex* menu_vm;
Cli* cli;
Bt* bt;
MenuItem* menu;
PowerState state;
@ -108,6 +110,8 @@ Power* power_alloc() {
power->cli = furi_record_open("cli");
power_cli_init(power->cli, power);
power->bt = furi_record_open("bt");
power->menu = menu_item_alloc_menu("Power", icon_animation_alloc(&A_Power_14));
menu_item_subitem_add(
power->menu, menu_item_alloc_function("Off", NULL, power_menu_off_callback, power));
@ -206,13 +210,15 @@ int32_t power_srv(void* p) {
power->menu_vm, (Menu * menu) { menu_item_add(menu, power->menu); });
furi_record_create("power", power);
uint8_t battery_level = 0;
uint8_t battery_level_prev = 0;
while(1) {
bool battery_low = false;
with_view_model(
power->info_view, (PowerInfoModel * model) {
model->charge = furi_hal_power_get_pct();
battery_level = model->charge;
model->health = furi_hal_power_get_bat_health_pct();
model->capacity_remaining = furi_hal_power_get_battery_remaining_capacity();
model->capacity_full = furi_hal_power_get_battery_full_capacity();
@ -258,6 +264,11 @@ int32_t power_srv(void* p) {
power_charging_indication_handler(power, notifications);
if(battery_level_prev != battery_level) {
battery_level_prev = battery_level;
bt_update_battery_level(power->bt, battery_level);
}
view_port_update(power->battery_view_port);
osDelay(1024);

View file

@ -40,3 +40,11 @@
y = SWAP; \
} while(0)
#endif
#ifndef PLACE_IN_SECTION
#define PLACE_IN_SECTION(x) __attribute__((section(x)))
#endif
#ifndef ALIGN
#define ALIGN(n) __attribute__((aligned(n)))
#endif

View file

@ -10,8 +10,9 @@
#include "cmsis_os.h"
#include "shci.h"
#include "otp.h"
#include "dis_app.h"
#include "hrs_app.h"
#include "dev_info_service.h"
#include "battery_service.h"
#include "serial_service.h"
#include <furi-hal.h>
@ -123,7 +124,6 @@ static void Ble_Tl_Init( void );
static void Ble_Hci_Gap_Gatt_Init();
static const uint8_t* BleGetBdAddress( void );
static void Adv_Request( APP_BLE_ConnStatus_t New_Status );
static void Add_Advertisment_Service_UUID( uint16_t servUUID );
static void Adv_Mgr( void );
static void AdvUpdateProcess(void *argument);
static void Adv_Update( void );
@ -160,6 +160,8 @@ bool APP_BLE_Init() {
return (SHCI_C2_BLE_Init( &ble_init_cmd_packet ) == SHCI_Success);
}
static void set_advertisment_service_uid(uint8_t* uid, uint8_t uin_len);
bool APP_BLE_Start() {
if (APPE_Status() != BleGlueStatusStarted) {
return false;
@ -180,16 +182,18 @@ bool APP_BLE_Start() {
#endif
// Initialize DIS Application
DISAPP_Init();
// Initialize HRS Application
HRSAPP_Init();
dev_info_service_init();
// Initialize BAS Application
battery_svc_init();
// Initialize Serial application
serial_svc_init();
// Create timer to handle the connection state machine
HW_TS_Create(CFG_TIM_PROC_ID_ISR, &(BleApplicationContext.Advertising_mgr_timer_Id), hw_ts_SingleShot, Adv_Mgr);
uint8_t adv_service_uid[2];
adv_service_uid[0] = 0x80 | furi_hal_version_get_hw_color();
adv_service_uid[1] = 0x30;
// Make device discoverable
BleApplicationContext.BleApplicationContext_legacy.advtServUUID[0] = AD_TYPE_16_BIT_SERV_UUID;
BleApplicationContext.BleApplicationContext_legacy.advtServUUIDlen = 1;
Add_Advertisment_Service_UUID(HEART_RATE_SERVICE_UUID);
set_advertisment_service_uid(adv_service_uid, sizeof(adv_service_uid));
/* Initialize intervals for reconnexion without intervals update */
AdvIntervalMin = CFG_FAST_CONN_ADV_INTERVAL_MIN;
AdvIntervalMax = CFG_FAST_CONN_ADV_INTERVAL_MAX;
@ -198,6 +202,11 @@ bool APP_BLE_Start() {
return true;
}
void SVCCTL_SvcInit() {
// Dummy function to prevent unused services initialization
// TODO refactore
}
SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification( void *pckt )
{
hci_event_pckt *event_pckt;
@ -382,56 +391,23 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification( void *pckt )
return (SVCCTL_UserEvtFlowEnable);
}
static void set_advertisment_service_uid(uint8_t* uid, uint8_t uid_len) {
BleApplicationContext.BleApplicationContext_legacy.advtServUUIDlen = 1;
if(uid_len == 2) {
BleApplicationContext.BleApplicationContext_legacy.advtServUUID[0] = AD_TYPE_16_BIT_SERV_UUID;
} else if (uid_len == 4) {
BleApplicationContext.BleApplicationContext_legacy.advtServUUID[0] = AD_TYPE_32_BIT_SERV_UUID;
} else if(uid_len == 16) {
BleApplicationContext.BleApplicationContext_legacy.advtServUUID[0] = AD_TYPE_128_BIT_SERV_UUID_CMPLT_LIST;
}
memcpy(&BleApplicationContext.BleApplicationContext_legacy.advtServUUID[1], uid, uid_len);
BleApplicationContext.BleApplicationContext_legacy.advtServUUIDlen += uid_len;
}
APP_BLE_ConnStatus_t APP_BLE_Get_Server_Connection_Status() {
return BleApplicationContext.Device_Connection_Status;
}
/* USER CODE BEGIN FD*/
void APP_BLE_Key_Button1_Action() {
tBleStatus ret = BLE_STATUS_INVALID_PARAMS;
ret = aci_gap_clear_security_db();
if (ret == BLE_STATUS_SUCCESS) {
APP_DBG_MSG("Successfully aci_gap_clear_security_db()\r\n");
} else {
APP_DBG_MSG("aci_gap_clear_security_db() Failed , result: %d \r\n", ret);
}
}
void APP_BLE_Key_Button2_Action() {
tBleStatus ret = BLE_STATUS_INVALID_PARAMS;
ret = aci_gap_slave_security_req(BleApplicationContext.BleApplicationContext_legacy.connectionHandle);
if (ret == BLE_STATUS_SUCCESS) {
APP_DBG_MSG("Successfully aci_gap_slave_security_req()");
} else {
APP_DBG_MSG("aci_gap_slave_security_req() Failed , result: %d \r\n", ret);
}
}
void APP_BLE_Key_Button3_Action() {
uint8_t TX_PHY, RX_PHY;
tBleStatus ret = BLE_STATUS_INVALID_PARAMS;
ret = hci_le_read_phy(BleApplicationContext.BleApplicationContext_legacy.connectionHandle,&TX_PHY,&RX_PHY);
if (ret == BLE_STATUS_SUCCESS) {
APP_DBG_MSG("Read_PHY success \r\n");
APP_DBG_MSG("PHY Param TX= %d, RX= %d \r\n", TX_PHY, RX_PHY);
if ((TX_PHY == TX_2M) && (RX_PHY == RX_2M)) {
APP_DBG_MSG("hci_le_set_phy PHY Param TX= %d, RX= %d \r\n", TX_1M, RX_1M);
ret = hci_le_set_phy(BleApplicationContext.BleApplicationContext_legacy.connectionHandle,ALL_PHYS_PREFERENCE,TX_1M,RX_1M,0);
} else {
APP_DBG_MSG("hci_le_set_phy PHY Param TX= %d, RX= %d \r\n", TX_2M_PREFERRED, RX_2M_PREFERRED);
ret = hci_le_set_phy(BleApplicationContext.BleApplicationContext_legacy.connectionHandle,ALL_PHYS_PREFERENCE,TX_2M_PREFERRED,RX_2M_PREFERRED,0);
}
} else {
APP_DBG_MSG("Read conf not succeess \r\n");
}
if (ret == BLE_STATUS_SUCCESS) {
APP_DBG_MSG("set PHY cmd ok\r\n");
} else {
APP_DBG_MSG("set PHY cmd NOK\r\n");
}
}
static void Ble_Tl_Init( void ) {
HCI_TL_HciInitConf_t Hci_Tl_Init_Conf;
@ -654,6 +630,9 @@ static void Adv_Request(APP_BLE_ConnStatus_t New_Status)
BleApplicationContext.BleApplicationContext_legacy.advtServUUID,
0,
0);
if(ret) {
FURI_LOG_E("APP ble", "Set discoverable err: %d", ret);
}
/* Update Advertising data */
ret = aci_gap_update_adv_data(sizeof(manuf_data), (uint8_t*) manuf_data);
@ -712,16 +691,6 @@ const uint8_t* BleGetBdAddress( void ) {
*SPECIFIC FUNCTIONS
*
*************************************************************/
static void Add_Advertisment_Service_UUID( uint16_t servUUID ) {
BleApplicationContext.BleApplicationContext_legacy.advtServUUID[BleApplicationContext.BleApplicationContext_legacy.advtServUUIDlen] =
(uint8_t) (servUUID & 0xFF);
BleApplicationContext.BleApplicationContext_legacy.advtServUUIDlen++;
BleApplicationContext.BleApplicationContext_legacy.advtServUUID[BleApplicationContext.BleApplicationContext_legacy.advtServUUIDlen] =
(uint8_t) (servUUID >> 8) & 0xFF;
BleApplicationContext.BleApplicationContext_legacy.advtServUUIDlen++;
}
static void Adv_Mgr( void ) {
/**
* The code shall be executed in the background as an aci command may be sent

View file

@ -22,10 +22,6 @@ bool APP_BLE_Start();
APP_BLE_ConnStatus_t APP_BLE_Get_Server_Connection_Status();
void APP_BLE_Key_Button1_Action();
void APP_BLE_Key_Button2_Action();
void APP_BLE_Key_Button3_Action();
#ifdef __cplusplus
}
#endif

View file

@ -32,81 +32,12 @@ extern "C"{
#include <stdlib.h>
#include <stdarg.h>
#include <furi/common_defines.h>
#include "app_conf.h"
/* -------------------------------- *
* Basic definitions *
* -------------------------------- */
#undef NULL
#define NULL 0
#undef FALSE
#define FALSE 0
#undef TRUE
#define TRUE (!0)
/* -------------------------------- *
* Critical Section definition *
* -------------------------------- */
#define BACKUP_PRIMASK() uint32_t primask_bit= __get_PRIMASK()
#define DISABLE_IRQ() __disable_irq()
#define RESTORE_PRIMASK() __set_PRIMASK(primask_bit)
/* -------------------------------- *
* Macro delimiters *
* -------------------------------- */
#define M_BEGIN do {
#define M_END } while(0)
/* -------------------------------- *
* Some useful macro definitions *
* -------------------------------- */
#define MODINC( a, m ) M_BEGIN (a)++; if ((a)>=(m)) (a)=0; M_END
#define MODDEC( a, m ) M_BEGIN if ((a)==0) (a)=(m); (a)--; M_END
#define MODADD( a, b, m ) M_BEGIN (a)+=(b); if ((a)>=(m)) (a)-=(m); M_END
#define MODSUB( a, b, m ) MODADD( a, (m)-(b), m )
#define PAUSE( t ) M_BEGIN \
__IO int _i; \
for ( _i = t; _i > 0; _i -- ); \
M_END
#define DIVF( x, y ) ((x)/(y))
#define DIVC( x, y ) (((x)+(y)-1)/(y))
#define DIVR( x, y ) (((x)+((y)/2))/(y))
#define SHRR( x, n ) ((((x)>>((n)-1))+1)>>1)
#define BITN( w, n ) (((w)[(n)/32] >> ((n)%32)) & 1)
#define BITNSET( w, n, b ) M_BEGIN (w)[(n)/32] |= ((U32)(b))<<((n)%32); M_END
/* -------------------------------- *
* Compiler *
* -------------------------------- */
#define PLACE_IN_SECTION( __x__ ) __attribute__((section (__x__)))
#ifdef WIN32
#define ALIGN(n)
#else
#define ALIGN(n) __attribute__((aligned(n)))
#endif
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /*APP_COMMON_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
#endif

View file

@ -1,367 +0,0 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* File Name : app_debug.c
* Description : Debug capabilities source file for STM32WPAN Middleware
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "app_common.h"
#include "app_debug.h"
#include "utilities_common.h"
#include "shci.h"
#include "tl.h"
#include "dbg_trace.h"
#include <furi-hal.h>
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
typedef PACKED_STRUCT
{
GPIO_TypeDef* port;
uint16_t pin;
uint8_t enable;
uint8_t reserved;
} APPD_GpioConfig_t;
/* USER CODE END PTD */
/* Private defines -----------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define GPIO_NBR_OF_RF_SIGNALS 9
#define GPIO_CFG_NBR_OF_FEATURES 34
#define NBR_OF_TRACES_CONFIG_PARAMETERS 4
#define NBR_OF_GENERAL_CONFIG_PARAMETERS 4
/**
* THIS SHALL BE SET TO A VALUE DIFFERENT FROM 0 ONLY ON REQUEST FROM ST SUPPORT
*/
#define BLE_DTB_CFG 0
#define SYS_DBG_CFG1 (SHCI_C2_DEBUG_OPTIONS_IPCORE_LP | SHCI_C2_DEBUG_OPTIONS_CPU2_STOP_EN)
/* USER CODE END PD */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static SHCI_C2_DEBUG_TracesConfig_t APPD_TracesConfig={0, 0, 0, 0};
PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static SHCI_C2_DEBUG_GeneralConfig_t APPD_GeneralConfig={BLE_DTB_CFG, SYS_DBG_CFG1, {0, 0}};
/**
* THE DEBUG ON GPIO FOR CPU2 IS INTENDED TO BE USED ONLY ON REQUEST FROM ST SUPPORT
* It provides timing information on the CPU2 activity.
* All configuration of (port, pin) is supported for each features and can be selected by the user
* depending on the availability
*/
static const APPD_GpioConfig_t aGpioConfigList[GPIO_CFG_NBR_OF_FEATURES] =
{
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* BLE_ISR - Set on Entry / Reset on Exit */
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* BLE_STACK_TICK - Set on Entry / Reset on Exit */
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* BLE_CMD_PROCESS - Set on Entry / Reset on Exit */
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* BLE_ACL_DATA_PROCESS - Set on Entry / Reset on Exit */
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* SYS_CMD_PROCESS - Set on Entry / Reset on Exit */
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* RNG_PROCESS - Set on Entry / Reset on Exit */
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* NVM_PROCESS - Set on Entry / Reset on Exit */
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_GENERAL - Set on Entry / Reset on Exit */
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_BLE_CMD_RX - Set on Entry / Reset on Exit */
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_BLE_EVT_TX - Set on Entry / Reset on Exit */
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_BLE_ACL_DATA_RX - Set on Entry / Reset on Exit */
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_SYS_CMD_RX - Set on Entry / Reset on Exit */
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_SYS_EVT_TX - Set on Entry / Reset on Exit */
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_CLI_CMD_RX - Set on Entry / Reset on Exit */
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_OT_CMD_RX - Set on Entry / Reset on Exit */
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_OT_ACK_TX - Set on Entry / Reset on Exit */
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_CLI_ACK_TX - Set on Entry / Reset on Exit */
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_MEM_MANAGER_RX - Set on Entry / Reset on Exit */
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_TRACES_TX - Set on Entry / Reset on Exit */
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* HARD_FAULT - Set on Entry / Reset on Exit */
/* From v1.1.1 */
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IP_CORE_LP_STATUS - Set on Entry / Reset on Exit */
/* From v1.2.0 */
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* END_OF_CONNECTION_EVENT - Set on Entry / Reset on Exit */
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* TIMER_SERVER_CALLBACK - Toggle on Entry */
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* PES_ACTIVITY - Set on Entry / Reset on Exit */
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* MB_BLE_SEND_EVT - Set on Entry / Reset on Exit */
/* From v1.3.0 */
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* BLE_NO_DELAY - Set on Entry / Reset on Exit */
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* BLE_STACK_STORE_NVM_CB - Set on Entry / Reset on Exit */
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* NVMA_WRITE_ONGOING - Set on Entry / Reset on Exit */
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* NVMA_WRITE_COMPLETE - Set on Entry / Reset on Exit */
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* NVMA_CLEANUP - Set on Entry / Reset on Exit */
/* From v1.4.0 */
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* NVMA_START - Set on Entry / Reset on Exit */
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* FLASH_EOP - Set on Entry / Reset on Exit */
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* FLASH_WRITE - Set on Entry / Reset on Exit */
{ GPIOA, LL_GPIO_PIN_0, 0, 0}, /* FLASH_ERASE - Set on Entry / Reset on Exit */
};
/**
* THE DEBUG ON GPIO FOR CPU2 IS INTENDED TO BE USED ONLY ON REQUEST FROM ST SUPPORT
* This table is relevant only for BLE
* It provides timing information on BLE RF activity.
* New signals may be allocated at any location when requested by ST
* The GPIO allocated to each signal depend on the BLE_DTB_CFG value and cannot be changed
*/
#if( BLE_DTB_CFG == 7)
static const APPD_GpioConfig_t aRfConfigList[GPIO_NBR_OF_RF_SIGNALS] =
{
{ GPIOB, LL_GPIO_PIN_2, 0, 0}, /* DTB10 - Tx/Rx SPI */
{ GPIOB, LL_GPIO_PIN_7, 0, 0}, /* DTB11 - Tx/Tx SPI Clk */
{ GPIOA, LL_GPIO_PIN_8, 0, 0}, /* DTB12 - Tx/Rx Ready & SPI Select */
{ GPIOA, LL_GPIO_PIN_9, 0, 0}, /* DTB13 - Tx/Rx Start */
{ GPIOA, LL_GPIO_PIN_10, 0, 0}, /* DTB14 - FSM0 */
{ GPIOA, LL_GPIO_PIN_11, 0, 0}, /* DTB15 - FSM1 */
{ GPIOB, LL_GPIO_PIN_8, 0, 0}, /* DTB16 - FSM2 */
{ GPIOB, LL_GPIO_PIN_11, 0, 0}, /* DTB17 - FSM3 */
{ GPIOB, LL_GPIO_PIN_10, 0, 0}, /* DTB18 - FSM4 */
};
#endif
/* USER CODE END PV */
/* Global variables ----------------------------------------------------------*/
/* USER CODE BEGIN GV */
/* USER CODE END GV */
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN PFP */
static void APPD_SetCPU2GpioConfig( void );
static void APPD_BleDtbCfg( void );
/* USER CODE END PFP */
/* Functions Definition ------------------------------------------------------*/
void APPD_Init( void )
{
/* USER CODE BEGIN APPD_Init */
#if (CFG_DEBUGGER_SUPPORTED == 1)
/**
* Keep debugger enabled while in any low power mode
*/
HAL_DBGMCU_EnableDBGSleepMode();
HAL_DBGMCU_EnableDBGStopMode();
/***************** ENABLE DEBUGGER *************************************/
LL_EXTI_EnableIT_32_63(LL_EXTI_LINE_48);
#else
GPIO_InitTypeDef gpio_config = {0};
gpio_config.Pull = GPIO_NOPULL;
gpio_config.Mode = GPIO_MODE_ANALOG;
gpio_config.Pin = GPIO_PIN_15 | GPIO_PIN_14 | GPIO_PIN_13;
__HAL_RCC_GPIOA_CLK_ENABLE();
HAL_GPIO_Init(GPIOA, &gpio_config);
__HAL_RCC_GPIOA_CLK_DISABLE();
gpio_config.Pin = GPIO_PIN_4 | GPIO_PIN_3;
__HAL_RCC_GPIOB_CLK_ENABLE();
HAL_GPIO_Init(GPIOB, &gpio_config);
__HAL_RCC_GPIOB_CLK_DISABLE();
HAL_DBGMCU_DisableDBGSleepMode();
HAL_DBGMCU_DisableDBGStopMode();
HAL_DBGMCU_DisableDBGStandbyMode();
#endif /* (CFG_DEBUGGER_SUPPORTED == 1) */
#if(CFG_DEBUG_TRACE != 0)
DbgTraceInit();
#endif
APPD_SetCPU2GpioConfig( );
APPD_BleDtbCfg( );
/* USER CODE END APPD_Init */
return;
}
void APPD_EnableCPU2( void )
{
/* USER CODE BEGIN APPD_EnableCPU2 */
SHCI_C2_DEBUG_Init_Cmd_Packet_t DebugCmdPacket =
{
{{0,0,0}}, /**< Does not need to be initialized */
{(uint8_t *)aGpioConfigList,
(uint8_t *)&APPD_TracesConfig,
(uint8_t *)&APPD_GeneralConfig,
GPIO_CFG_NBR_OF_FEATURES,
NBR_OF_TRACES_CONFIG_PARAMETERS,
NBR_OF_GENERAL_CONFIG_PARAMETERS}
};
/**< Traces channel initialization */
TL_TRACES_Init( );
/** GPIO DEBUG Initialization */
SHCI_C2_DEBUG_Init( &DebugCmdPacket );
/* USER CODE END APPD_EnableCPU2 */
return;
}
/*************************************************************
*
* LOCAL FUNCTIONS
*
*************************************************************/
static void APPD_SetCPU2GpioConfig( void )
{
/* USER CODE BEGIN APPD_SetCPU2GpioConfig */
GPIO_InitTypeDef gpio_config = {0};
uint8_t local_loop;
uint16_t gpioa_pin_list;
uint16_t gpiob_pin_list;
uint16_t gpioc_pin_list;
gpioa_pin_list = 0;
gpiob_pin_list = 0;
gpioc_pin_list = 0;
for(local_loop = 0 ; local_loop < GPIO_CFG_NBR_OF_FEATURES; local_loop++)
{
if( aGpioConfigList[local_loop].enable != 0)
{
switch((uint32_t)aGpioConfigList[local_loop].port)
{
case (uint32_t)GPIOA:
gpioa_pin_list |= aGpioConfigList[local_loop].pin;
break;
case (uint32_t)GPIOB:
gpiob_pin_list |= aGpioConfigList[local_loop].pin;
break;
case (uint32_t)GPIOC:
gpioc_pin_list |= aGpioConfigList[local_loop].pin;
break;
default:
break;
}
}
}
gpio_config.Pull = GPIO_NOPULL;
gpio_config.Mode = GPIO_MODE_OUTPUT_PP;
gpio_config.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
if(gpioa_pin_list != 0)
{
gpio_config.Pin = gpioa_pin_list;
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_C2GPIOA_CLK_ENABLE();
HAL_GPIO_Init(GPIOA, &gpio_config);
HAL_GPIO_WritePin(GPIOA, gpioa_pin_list, GPIO_PIN_RESET);
}
if(gpiob_pin_list != 0)
{
gpio_config.Pin = gpiob_pin_list;
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_C2GPIOB_CLK_ENABLE();
HAL_GPIO_Init(GPIOB, &gpio_config);
HAL_GPIO_WritePin(GPIOB, gpiob_pin_list, GPIO_PIN_RESET);
}
if(gpioc_pin_list != 0)
{
gpio_config.Pin = gpioc_pin_list;
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_C2GPIOC_CLK_ENABLE();
HAL_GPIO_Init(GPIOC, &gpio_config);
HAL_GPIO_WritePin(GPIOC, gpioc_pin_list, GPIO_PIN_RESET);
}
/* USER CODE END APPD_SetCPU2GpioConfig */
return;
}
static void APPD_BleDtbCfg( void )
{
/* USER CODE BEGIN APPD_BleDtbCfg */
#if (BLE_DTB_CFG != 0)
GPIO_InitTypeDef gpio_config = {0};
uint8_t local_loop;
uint16_t gpioa_pin_list;
uint16_t gpiob_pin_list;
gpioa_pin_list = 0;
gpiob_pin_list = 0;
for(local_loop = 0 ; local_loop < GPIO_NBR_OF_RF_SIGNALS; local_loop++)
{
if( aRfConfigList[local_loop].enable != 0)
{
switch((uint32_t)aRfConfigList[local_loop].port)
{
case (uint32_t)GPIOA:
gpioa_pin_list |= aRfConfigList[local_loop].pin;
break;
case (uint32_t)GPIOB:
gpiob_pin_list |= aRfConfigList[local_loop].pin;
break;
default:
break;
}
}
}
gpio_config.Pull = GPIO_NOPULL;
gpio_config.Mode = GPIO_MODE_AF_PP;
gpio_config.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
gpio_config.Alternate = GPIO_AF6_RF_DTB7;
if(gpioa_pin_list != 0)
{
gpio_config.Pin = gpioa_pin_list;
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_C2GPIOA_CLK_ENABLE();
HAL_GPIO_Init(GPIOA, &gpio_config);
}
if(gpiob_pin_list != 0)
{
gpio_config.Pin = gpiob_pin_list;
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_C2GPIOB_CLK_ENABLE();
HAL_GPIO_Init(GPIOB, &gpio_config);
}
#endif
/* USER CODE END APPD_BleDtbCfg */
return;
}
/*************************************************************
*
* WRAP FUNCTIONS
*
*************************************************************/
#if(CFG_DEBUG_TRACE != 0)
void DbgOutputInit( void )
{
}
void DbgOutputTraces( uint8_t *p_data, uint16_t size, void (*cb)(void) )
{
furi_hal_console_tx(p_data, size);
cb();
}
#endif
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View file

@ -1,69 +0,0 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* File Name : app_debug.h
* Description : Header for app_debug.c module
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __APP_DEBUG_H
#define __APP_DEBUG_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Exported types ------------------------------------------------------------*/
/* USER CODE BEGIN ET */
/* USER CODE END ET */
/* Exported constants --------------------------------------------------------*/
/* USER CODE BEGIN EC */
/* USER CODE END EC */
/* Exported variables --------------------------------------------------------*/
/* USER CODE BEGIN EV */
/* USER CODE END EV */
/* Exported macros ------------------------------------------------------------*/
/* USER CODE BEGIN EM */
/* USER CODE END EM */
/* Exported functions ---------------------------------------------*/
void APPD_Init( void );
void APPD_EnableCPU2( void );
/* USER CODE BEGIN EF */
/* USER CODE END EF */
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /*__APP_DEBUG_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View file

@ -6,7 +6,6 @@
#include "tl.h"
#include "cmsis_os.h"
#include "shci_tl.h"
#include "app_debug.h"
#include <furi-hal.h>
extern RTC_HandleTypeDef hrtc;
@ -178,3 +177,16 @@ void shci_cmd_resp_wait(uint32_t timeout) {
UNUSED(timeout);
osSemaphoreAcquire( SemShciId, osWaitForever );
}
#if(CFG_DEBUG_TRACE != 0)
void DbgOutputInit( void )
{
}
void DbgOutputTraces( uint8_t *p_data, uint16_t size, void (*cb)(void) )
{
furi_hal_console_tx(p_data, size);
cb();
}
#endif

View file

@ -0,0 +1,55 @@
#include "battery_service.h"
#include "app_common.h"
#include "ble.h"
#include <furi.h>
#define BATTERY_SERVICE_TAG "battery service"
typedef struct {
uint16_t svc_handle;
uint16_t char_level_handle;
} BatterySvc;
static BatterySvc battery_svc;
bool battery_svc_init() {
tBleStatus status;
const uint16_t service_uuid = BATTERY_SERVICE_UUID;
const uint16_t char_battery_level_uuid = BATTERY_LEVEL_CHAR_UUID;
// Add Battery service
status = aci_gatt_add_service(UUID_TYPE_16, (Service_UUID_t*)&service_uuid, PRIMARY_SERVICE, 4, &battery_svc.svc_handle);
if(status) {
FURI_LOG_E(BATTERY_SERVICE_TAG, "Failed to add Battery service: %d", status);
}
// Add Battery level characteristic
status = aci_gatt_add_char(battery_svc.svc_handle,
UUID_TYPE_16,
(Char_UUID_t *) &char_battery_level_uuid,
1,
CHAR_PROP_READ | CHAR_PROP_NOTIFY,
ATTR_PERMISSION_NONE,
GATT_DONT_NOTIFY_EVENTS,
10,
CHAR_VALUE_LEN_CONSTANT,
&battery_svc.char_level_handle);
if(status) {
FURI_LOG_E(BATTERY_SERVICE_TAG, "Failed to add Battery level characteristic: %d", status);
}
return status != BLE_STATUS_SUCCESS;
}
bool battery_svc_update_level(uint8_t battery_charge) {
FURI_LOG_I(BATTERY_SERVICE_TAG, "Updating battery level characteristic");
tBleStatus result = aci_gatt_update_char_value(battery_svc.svc_handle,
battery_svc.char_level_handle,
0,
1,
&battery_charge);
if(result) {
FURI_LOG_E(BATTERY_SERVICE_TAG, "Failed updating RX characteristic: %d", result);
}
return result != BLE_STATUS_SUCCESS;
}

View file

@ -0,0 +1,16 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
bool battery_svc_init();
bool battery_svc_update_level(uint8_t battery_level);
#ifdef __cplusplus
}
#endif

View file

@ -53,47 +53,12 @@
#define BLE_CFG_CLT_MAX_NBR_CB 0
/******************************************************************************
* Device Information Service (DIS)
******************************************************************************/
/**< Options: Supported(1) or Not Supported(0) */
#define BLE_CFG_DIS_MANUFACTURER_NAME_STRING 1
#define BLE_CFG_DIS_MODEL_NUMBER_STRING 1
#define BLE_CFG_DIS_SERIAL_NUMBER_STRING 0
#define BLE_CFG_DIS_HARDWARE_REVISION_STRING 0
#define BLE_CFG_DIS_FIRMWARE_REVISION_STRING 1
#define BLE_CFG_DIS_SOFTWARE_REVISION_STRING 1
#define BLE_CFG_DIS_SYSTEM_ID 0
#define BLE_CFG_DIS_IEEE_CERTIFICATION 0
#define BLE_CFG_DIS_PNP_ID 0
/**
* device information service characteristic lengths
*/
#define BLE_CFG_DIS_SYSTEM_ID_LEN_MAX (8)
#define BLE_CFG_DIS_MODEL_NUMBER_STRING_LEN_MAX (32)
#define BLE_CFG_DIS_SERIAL_NUMBER_STRING_LEN_MAX (32)
#define BLE_CFG_DIS_FIRMWARE_REVISION_STRING_LEN_MAX (32)
#define BLE_CFG_DIS_HARDWARE_REVISION_STRING_LEN_MAX (32)
#define BLE_CFG_DIS_SOFTWARE_REVISION_STRING_LEN_MAX (64)
#define BLE_CFG_DIS_MANUFACTURER_NAME_STRING_LEN_MAX (32)
#define BLE_CFG_DIS_IEEE_CERTIFICATION_LEN_MAX (32)
#define BLE_CFG_DIS_PNP_ID_LEN_MAX (7)
/******************************************************************************
* Heart Rate Service (HRS)
******************************************************************************/
#define BLE_CFG_HRS_BODY_SENSOR_LOCATION_CHAR 1/**< BODY SENSOR LOCATION CHARACTERISTIC */
#define BLE_CFG_HRS_ENERGY_EXPENDED_INFO_FLAG 1/**< ENERGY EXTENDED INFO FLAG */
#define BLE_CFG_HRS_ENERGY_RR_INTERVAL_FLAG 1/**< Max number of RR interval values - Shall not be greater than 9 */
/******************************************************************************
* GAP Service - Apprearance
******************************************************************************/
#define BLE_CFG_UNKNOWN_APPEARANCE (0)
#define BLE_CFG_HR_SENSOR_APPEARANCE (832)
#define BLE_CFG_GAP_APPEARANCE (BLE_CFG_HR_SENSOR_APPEARANCE)
#define BLE_CFG_GAP_APPEARANCE (0x0086)
/******************************************************************************
* Over The Air Feature (OTA) - STM Proprietary

View file

@ -0,0 +1,121 @@
#include "dev_info_service.h"
#include "app_common.h"
#include "ble.h"
#include <furi.h>
#define DEV_INFO_SERVICE_TAG "dev info service"
typedef struct {
uint16_t service_handle;
uint16_t man_name_char_handle;
uint16_t serial_num_char_handle;
uint16_t firmware_rev_char_handle;
uint16_t software_rev_char_handle;
} DevInfoSvc;
bool dev_info_service_init() {
tBleStatus status;
DevInfoSvc dev_info_svc;
// Add Device Information Service
uint16_t uuid = DEVICE_INFORMATION_SERVICE_UUID;
status = aci_gatt_add_service(UUID_TYPE_16, (Service_UUID_t*)&uuid, PRIMARY_SERVICE, 9, &dev_info_svc.service_handle);
if(status) {
FURI_LOG_E(DEV_INFO_SERVICE_TAG, "Failed to add Device Information Service: %d", status);
}
// Add characteristics
uuid = MANUFACTURER_NAME_UUID;
status = aci_gatt_add_char(dev_info_svc.service_handle,
UUID_TYPE_16,
(Char_UUID_t*)&uuid,
strlen(DEV_INFO_MANUFACTURER_NAME),
CHAR_PROP_READ,
ATTR_PERMISSION_NONE,
GATT_DONT_NOTIFY_EVENTS,
10,
CHAR_VALUE_LEN_CONSTANT,
&dev_info_svc.man_name_char_handle);
if(status) {
FURI_LOG_E(DEV_INFO_SERVICE_TAG, "Failed to add manufacturer name char: %d", status);
}
uuid = SERIAL_NUMBER_UUID;
status = aci_gatt_add_char(dev_info_svc.service_handle,
UUID_TYPE_16,
(Char_UUID_t*)&uuid,
strlen(DEV_INFO_SERIAL_NUMBER),
CHAR_PROP_READ,
ATTR_PERMISSION_NONE,
GATT_DONT_NOTIFY_EVENTS,
10,
CHAR_VALUE_LEN_CONSTANT,
&dev_info_svc.serial_num_char_handle);
if(status) {
FURI_LOG_E(DEV_INFO_SERVICE_TAG, "Failed to add serial number char: %d", status);
}
uuid = FIRMWARE_REVISION_UUID;
status = aci_gatt_add_char(dev_info_svc.service_handle,
UUID_TYPE_16,
(Char_UUID_t*)&uuid,
strlen(DEV_INFO_FIRMWARE_REVISION_NUMBER),
CHAR_PROP_READ,
ATTR_PERMISSION_NONE,
GATT_DONT_NOTIFY_EVENTS,
10,
CHAR_VALUE_LEN_CONSTANT,
&dev_info_svc.firmware_rev_char_handle);
if(status) {
FURI_LOG_E(DEV_INFO_SERVICE_TAG, "Failed to add firmware revision char: %d", status);
}
uuid = SOFTWARE_REVISION_UUID;
status = aci_gatt_add_char(dev_info_svc.service_handle,
UUID_TYPE_16,
(Char_UUID_t*)&uuid,
strlen(DEV_INFO_SOFTWARE_REVISION_NUMBER),
CHAR_PROP_READ,
ATTR_PERMISSION_NONE,
GATT_DONT_NOTIFY_EVENTS,
10,
CHAR_VALUE_LEN_CONSTANT,
&dev_info_svc.software_rev_char_handle);
if(status) {
FURI_LOG_E(DEV_INFO_SERVICE_TAG, "Failed to add software revision char: %d", status);
}
// Update characteristics
status = aci_gatt_update_char_value(dev_info_svc.service_handle,
dev_info_svc.man_name_char_handle,
0,
strlen(DEV_INFO_MANUFACTURER_NAME),
(uint8_t*)DEV_INFO_MANUFACTURER_NAME);
if(status) {
FURI_LOG_E(DEV_INFO_SERVICE_TAG, "Failed to update manufacturer name char: %d", status);
}
status = aci_gatt_update_char_value(dev_info_svc.service_handle,
dev_info_svc.serial_num_char_handle,
0,
strlen(DEV_INFO_SERIAL_NUMBER),
(uint8_t*)DEV_INFO_SERIAL_NUMBER);
if(status) {
FURI_LOG_E(DEV_INFO_SERVICE_TAG, "Failed to update serial number char: %d", status);
}
status = aci_gatt_update_char_value(dev_info_svc.service_handle,
dev_info_svc.firmware_rev_char_handle,
0,
strlen(DEV_INFO_FIRMWARE_REVISION_NUMBER),
(uint8_t*)DEV_INFO_FIRMWARE_REVISION_NUMBER);
if(status) {
FURI_LOG_E(DEV_INFO_SERVICE_TAG, "Failed to update firmware revision char: %d", status);
}
status = aci_gatt_update_char_value(dev_info_svc.service_handle,
dev_info_svc.software_rev_char_handle,
0,
strlen(DEV_INFO_SOFTWARE_REVISION_NUMBER),
(uint8_t*)DEV_INFO_SOFTWARE_REVISION_NUMBER);
if(status) {
FURI_LOG_E(DEV_INFO_SERVICE_TAG, "Failed to update software revision char: %d", status);
}
return status != BLE_STATUS_SUCCESS;
}

View file

@ -0,0 +1,20 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
#define DEV_INFO_MANUFACTURER_NAME "Flipper Devices Inc."
#define DEV_INFO_SERIAL_NUMBER "1.0"
#define DEV_INFO_FIRMWARE_REVISION_NUMBER TARGET
#define DEV_INFO_SOFTWARE_REVISION_NUMBER GIT_COMMIT " " GIT_BRANCH " " GIT_BRANCH_NUM " " BUILD_DATE
bool dev_info_service_init();
#ifdef __cplusplus
}
#endif

View file

@ -1,157 +0,0 @@
#include "app_common.h"
#include "ble.h"
#include "dis_app.h"
#include <furi-hal-version.h>
#if ((BLE_CFG_DIS_SYSTEM_ID != 0) || (CFG_MENU_DEVICE_INFORMATION != 0))
static const uint8_t system_id[BLE_CFG_DIS_SYSTEM_ID_LEN_MAX] = {
(uint8_t)((DISAPP_MANUFACTURER_ID & 0xFF0000) >> 16),
(uint8_t)((DISAPP_MANUFACTURER_ID & 0x00FF00) >> 8),
(uint8_t)(DISAPP_MANUFACTURER_ID & 0x0000FF),
0xFE,
0xFF,
(uint8_t)((DISAPP_OUI & 0xFF0000) >> 16),
(uint8_t)((DISAPP_OUI & 0x00FF00) >> 8),
(uint8_t)(DISAPP_OUI & 0x0000FF)
};
#endif
#if ((BLE_CFG_DIS_IEEE_CERTIFICATION != 0) || (CFG_MENU_DEVICE_INFORMATION != 0))
static const uint8_t ieee_id[BLE_CFG_DIS_IEEE_CERTIFICATION_LEN_MAX] = {
0xFE, 0xCA, 0xFE, 0xCA, 0xFE, 0xCA, 0xFE, 0xCA,
0xFE, 0xCA, 0xFE, 0xCA, 0xFE, 0xCA, 0xFE, 0xCA,
0xFE, 0xCA, 0xFE, 0xCA, 0xFE, 0xCA, 0xFE, 0xCA,
0xFE, 0xCA, 0xFE, 0xCA, 0xFE, 0xCA, 0xFE, 0xCA,
};
#endif
#if ((BLE_CFG_DIS_PNP_ID != 0) || (CFG_MENU_DEVICE_INFORMATION != 0))
static const uint8_t pnp_id[BLE_CFG_DIS_PNP_ID_LEN_MAX] = {
0x1,
0xAD, 0xDE,
0xDE, 0xDA,
0x01, 0x00
};
#endif
void DISAPP_Init(void) {
DIS_Data_t dis_information_data;
#if ((BLE_CFG_DIS_MANUFACTURER_NAME_STRING != 0) || (CFG_MENU_DEVICE_INFORMATION != 0))
/**
* Update MANUFACTURER NAME Information
*
* @param UUID
* @param pPData
* @return
*/
dis_information_data.pPayload = (uint8_t*)DISAPP_MANUFACTURER_NAME;
dis_information_data.Length = sizeof(DISAPP_MANUFACTURER_NAME);
DIS_UpdateChar(MANUFACTURER_NAME_UUID, &dis_information_data);
#endif
#if ((BLE_CFG_DIS_MODEL_NUMBER_STRING != 0) || (CFG_MENU_DEVICE_INFORMATION != 0))
/**
* Update MODEL NUMBERInformation
*
* @param UUID
* @param pPData
* @return
*/
const char* name = furi_hal_version_get_device_name_ptr();
dis_information_data.pPayload = (uint8_t*)name;
dis_information_data.Length = strlen(name) + 1;
DIS_UpdateChar(MODEL_NUMBER_UUID, &dis_information_data);
#endif
#if ((BLE_CFG_DIS_SERIAL_NUMBER_STRING != 0) || (CFG_MENU_DEVICE_INFORMATION != 0))
/**
* Update SERIAL NUMBERInformation
*
* @param UUID
* @param pPData
* @return
*/
dis_information_data.pPayload = (uint8_t*)DISAPP_SERIAL_NUMBER;
dis_information_data.Length = sizeof(DISAPP_SERIAL_NUMBER);
DIS_UpdateChar(SERIAL_NUMBER_UUID, &dis_information_data);
#endif
#if ((BLE_CFG_DIS_HARDWARE_REVISION_STRING != 0) || (CFG_MENU_DEVICE_INFORMATION != 0))
/**
* Update HARDWARE REVISION NUMBERInformation
*
* @param UUID
* @param pPData
* @return
*/
dis_information_data.pPayload = (uint8_t*)DISAPP_HARDWARE_REVISION_NUMBER;
dis_information_data.Length = sizeof(DISAPP_HARDWARE_REVISION_NUMBER);
DIS_UpdateChar(HARDWARE_REVISION_UUID, &dis_information_data);
#endif
#if ((BLE_CFG_DIS_FIRMWARE_REVISION_STRING != 0) || (CFG_MENU_DEVICE_INFORMATION != 0))
/**
* Update FIRMWARE REVISION NUMBERInformation
*
* @param UUID
* @param pPData
* @return
*/
dis_information_data.pPayload = (uint8_t*)DISAPP_FIRMWARE_REVISION_NUMBER;
dis_information_data.Length = sizeof(DISAPP_FIRMWARE_REVISION_NUMBER);
DIS_UpdateChar(FIRMWARE_REVISION_UUID, &dis_information_data);
#endif
#if ((BLE_CFG_DIS_SOFTWARE_REVISION_STRING != 0) || (CFG_MENU_DEVICE_INFORMATION != 0))
/**
* Update SOFTWARE REVISION NUMBERInformation
*
* @param UUID
* @param pPData
* @return
*/
dis_information_data.pPayload = (uint8_t*)DISAPP_SOFTWARE_REVISION_NUMBER;
dis_information_data.Length = sizeof(DISAPP_SOFTWARE_REVISION_NUMBER);
DIS_UpdateChar(SOFTWARE_REVISION_UUID, &dis_information_data);
#endif
#if ((BLE_CFG_DIS_SYSTEM_ID != 0) || (CFG_MENU_DEVICE_INFORMATION != 0))
/**
* Update SYSTEM ID Information
*
* @param UUID
* @param pPData
* @return
*/
dis_information_data.pPayload = (uint8_t *)system_id;
dis_information_data.Length = BLE_CFG_DIS_SYSTEM_ID_LEN_MAX;
DIS_UpdateChar(SYSTEM_ID_UUID, &dis_information_data);
#endif
#if ((BLE_CFG_DIS_IEEE_CERTIFICATION != 0) || (CFG_MENU_DEVICE_INFORMATION != 0))
/**
* Update IEEE CERTIFICATION ID Information
*
* @param UUID
* @param pPData
* @return
*/
dis_information_data.pPayload = (uint8_t *)ieee_id;
dis_information_data.Length = BLE_CFG_DIS_IEEE_CERTIFICATION_LEN_MAX;
DIS_UpdateChar(IEEE_CERTIFICATION_UUID, &dis_information_data);
#endif
#if ((BLE_CFG_DIS_PNP_ID != 0) || (CFG_MENU_DEVICE_INFORMATION != 0))
/**
* Update PNP ID Information
*
* @param UUID
* @param pPData
* @return
*/
dis_information_data.pPayload = (uint8_t *)pnp_id;
dis_information_data.Length = BLE_CFG_DIS_PNP_ID_LEN_MAX;
DIS_UpdateChar(PNP_ID_UUID, &dis_information_data);
#endif
}

View file

@ -1,20 +0,0 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#define DISAPP_MANUFACTURER_NAME "Flipperdevice Inc."
//#define DISAPP_MODEL_NUMBER "FlipperZero"
#define DISAPP_SERIAL_NUMBER "1.0"
#define DISAPP_HARDWARE_REVISION_NUMBER "1.0"
#define DISAPP_FIRMWARE_REVISION_NUMBER TARGET
#define DISAPP_SOFTWARE_REVISION_NUMBER GIT_COMMIT " " GIT_BRANCH " " GIT_BRANCH_NUM " " BUILD_DATE
#define DISAPP_OUI 0x123456
#define DISAPP_MANUFACTURER_ID 0x9ABCDE
void DISAPP_Init(void);
#ifdef __cplusplus
}
#endif

View file

@ -1,256 +0,0 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file hrs_app.c
* @author MCD Application Team
* @brief Heart Rate Service Application
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "app_common.h"
#include "ble.h"
#include "hrs_app.h"
#include "cmsis_os.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
typedef struct
{
HRS_BodySensorLocation_t BodySensorLocationChar;
HRS_MeasVal_t MeasurementvalueChar;
uint8_t ResetEnergyExpended;
uint8_t TimerMeasurement_Id;
} HRSAPP_Context_t;
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private defines ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macros ------------------------------------------------------------*/
#define HRSAPP_MEASUREMENT_INTERVAL (1000000/CFG_TS_TICK_VAL) /**< 1s */
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/**
* START of Section BLE_APP_CONTEXT
*/
PLACE_IN_SECTION("BLE_APP_CONTEXT") static HRSAPP_Context_t HRSAPP_Context;
/**
* END of Section BLE_APP_CONTEXT
*/
osThreadId_t HrsProcessId;
const osThreadAttr_t HrsProcess_attr = {
.name = CFG_HRS_PROCESS_NAME,
.attr_bits = CFG_HRS_PROCESS_ATTR_BITS,
.cb_mem = CFG_HRS_PROCESS_CB_MEM,
.cb_size = CFG_HRS_PROCESS_CB_SIZE,
.stack_mem = CFG_HRS_PROCESS_STACK_MEM,
.priority = CFG_HRS_PROCESS_PRIORITY,
.stack_size = CFG_HRS_PROCESS_STACK_SIZE
};
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private functions prototypes-----------------------------------------------*/
static void HrMeas( void );
static void HrsProcess(void *argument);
static void HRSAPP_Measurement(void);
static uint32_t HRSAPP_Read_RTC_SSR_SS ( void );
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Functions Definition ------------------------------------------------------*/
void HRS_Notification(HRS_App_Notification_evt_t *pNotification)
{
/* USER CODE BEGIN HRS_Notification_1 */
/* USER CODE END HRS_Notification_1 */
switch(pNotification->HRS_Evt_Opcode)
{
/* USER CODE BEGIN HRS_Notification_HRS_Evt_Opcode */
/* USER CODE END HRS_Notification_HRS_Evt_Opcode */
#if (BLE_CFG_HRS_ENERGY_EXPENDED_INFO_FLAG != 0)
case HRS_RESET_ENERGY_EXPENDED_EVT:
/* USER CODE BEGIN HRS_RESET_ENERGY_EXPENDED_EVT */
HRSAPP_Context.MeasurementvalueChar.EnergyExpended = 0;
HRSAPP_Context.ResetEnergyExpended = 1;
/* USER CODE END HRS_RESET_ENERGY_EXPENDED_EVT */
break;
#endif
case HRS_NOTIFICATION_ENABLED:
/* USER CODE BEGIN HRS_NOTIFICATION_ENABLED */
/**
* It could be the enable notification is received twice without the disable notification in between
*/
HW_TS_Stop(HRSAPP_Context.TimerMeasurement_Id);
HW_TS_Start(HRSAPP_Context.TimerMeasurement_Id, HRSAPP_MEASUREMENT_INTERVAL);
/* USER CODE END HRS_NOTIFICATION_ENABLED */
break;
case HRS_NOTIFICATION_DISABLED:
/* USER CODE BEGIN HRS_NOTIFICATION_DISABLED */
HW_TS_Stop(HRSAPP_Context.TimerMeasurement_Id);
/* USER CODE END HRS_NOTIFICATION_DISABLED */
break;
#if (BLE_CFG_OTA_REBOOT_CHAR != 0)
case HRS_STM_BOOT_REQUEST_EVT:
/* USER CODE BEGIN HRS_STM_BOOT_REQUEST_EVT */
*(uint32_t*)SRAM1_BASE = *(uint32_t*)pNotification->DataTransfered.pPayload;
NVIC_SystemReset();
/* USER CODE END HRS_STM_BOOT_REQUEST_EVT */
break;
#endif
default:
/* USER CODE BEGIN HRS_Notification_Default */
/* USER CODE END HRS_Notification_Default */
break;
}
/* USER CODE BEGIN HRS_Notification_2 */
/* USER CODE END HRS_Notification_2 */
return;
}
void HRSAPP_Init(void)
{
HrsProcessId = osThreadNew(HrsProcess, NULL, &HrsProcess_attr);
/* USER CODE BEGIN HRSAPP_Init */
/**
* Set Body Sensor Location
*/
HRSAPP_Context.ResetEnergyExpended = 0;
HRSAPP_Context.BodySensorLocationChar = HRS_BODY_SENSOR_LOCATION_HAND;
HRS_UpdateChar(SENSOR_LOCATION_UUID, (uint8_t *)&HRSAPP_Context.BodySensorLocationChar);
/**
* Set Flags for measurement value
*/
HRSAPP_Context.MeasurementvalueChar.Flags = ( HRS_HRM_VALUE_FORMAT_UINT16 |
HRS_HRM_SENSOR_CONTACTS_PRESENT |
HRS_HRM_SENSOR_CONTACTS_SUPPORTED |
HRS_HRM_ENERGY_EXPENDED_PRESENT |
HRS_HRM_RR_INTERVAL_PRESENT );
#if (BLE_CFG_HRS_ENERGY_EXPENDED_INFO_FLAG != 0)
if(HRSAPP_Context.MeasurementvalueChar.Flags & HRS_HRM_ENERGY_EXPENDED_PRESENT)
HRSAPP_Context.MeasurementvalueChar.EnergyExpended = 10;
#endif
#if (BLE_CFG_HRS_ENERGY_RR_INTERVAL_FLAG != 0)
if(HRSAPP_Context.MeasurementvalueChar.Flags & HRS_HRM_RR_INTERVAL_PRESENT)
{
uint8_t i;
HRSAPP_Context.MeasurementvalueChar.NbreOfValidRRIntervalValues = BLE_CFG_HRS_ENERGY_RR_INTERVAL_FLAG;
for(i = 0; i < BLE_CFG_HRS_ENERGY_RR_INTERVAL_FLAG; i++)
HRSAPP_Context.MeasurementvalueChar.aRRIntervalValues[i] = 1024;
}
#endif
/**
* Create timer for Heart Rate Measurement
*/
HW_TS_Create(CFG_TIM_PROC_ID_ISR, &(HRSAPP_Context.TimerMeasurement_Id), hw_ts_Repeated, HrMeas);
/* USER CODE END HRSAPP_Init */
return;
}
static void HrsProcess(void *argument)
{
UNUSED(argument);
for(;;)
{
osThreadFlagsWait( 1, osFlagsWaitAny, osWaitForever);
HRSAPP_Measurement( );
}
}
static void HRSAPP_Measurement(void)
{
/* USER CODE BEGIN HRSAPP_Measurement */
uint32_t measurement;
measurement = ((HRSAPP_Read_RTC_SSR_SS()) & 0x07) + 65;
HRSAPP_Context.MeasurementvalueChar.MeasurementValue = measurement;
#if (BLE_CFG_HRS_ENERGY_EXPENDED_INFO_FLAG != 0)
if((HRSAPP_Context.MeasurementvalueChar.Flags & HRS_HRM_ENERGY_EXPENDED_PRESENT) &&
(HRSAPP_Context.ResetEnergyExpended == 0))
HRSAPP_Context.MeasurementvalueChar.EnergyExpended += 5;
else if(HRSAPP_Context.ResetEnergyExpended == 1)
HRSAPP_Context.ResetEnergyExpended = 0;
#endif
HRS_UpdateChar(HEART_RATE_MEASURMENT_UUID, (uint8_t *)&HRSAPP_Context.MeasurementvalueChar);
/* USER CODE END HRSAPP_Measurement */
return;
}
static void HrMeas( void )
{
/**
* The code shall be executed in the background as aci command may be sent
* The background is the only place where the application can make sure a new aci command
* is not sent if there is a pending one
*/
osThreadFlagsSet( HrsProcessId, 1 );
/* USER CODE BEGIN HrMeas */
/* USER CODE END HrMeas */
return;
}
static uint32_t HRSAPP_Read_RTC_SSR_SS ( void )
{
return ((uint32_t)(READ_BIT(RTC->SSR, RTC_SSR_SS)));
}
/* USER CODE BEGIN FD */
/* USER CODE END FD */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View file

@ -1,69 +0,0 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file hrs_app.h
* @author MCD Application Team
* @brief Header for hrs_application.c module
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __HRS_APP_H
#define __HRS_APP_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Exported types ------------------------------------------------------------*/
/* USER CODE BEGIN ET */
/* USER CODE END ET */
/* Exported constants --------------------------------------------------------*/
/* USER CODE BEGIN EC */
/* USER CODE END EC */
/* External variables --------------------------------------------------------*/
/* USER CODE BEGIN EV */
/* USER CODE END EV */
/* Exported macros ------------------------------------------------------------*/
/* USER CODE BEGIN EM */
/* USER CODE END EM */
/* Exported functions ---------------------------------------------*/
void HRSAPP_Init( void );
/* USER CODE BEGIN EF */
/* USER CODE END EF */
#ifdef __cplusplus
}
#endif
#endif /*__HRS_APP_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View file

@ -0,0 +1,102 @@
#include "serial_service.h"
#include "app_common.h"
#include "ble.h"
#include <furi.h>
#define SERIAL_SERVICE_TAG "serial service"
typedef struct {
uint16_t svc_handle;
uint16_t rx_char_handle;
uint16_t tx_char_handle;
} SerialSvc;
static SerialSvc serial_svc;
static SVCCTL_EvtAckStatus_t serial_svc_event_handler(void *event) {
SVCCTL_EvtAckStatus_t ret = SVCCTL_EvtNotAck;
hci_event_pckt* event_pckt = (hci_event_pckt *)(((hci_uart_pckt*)event)->data);
evt_blecore_aci* blecore_evt = (evt_blecore_aci*)event_pckt->data;
aci_gatt_attribute_modified_event_rp0* attribute_modified;
if(event_pckt->evt == HCI_VENDOR_SPECIFIC_DEBUG_EVT_CODE) {
if(blecore_evt->ecode == ACI_GATT_ATTRIBUTE_MODIFIED_VSEVT_CODE) {
attribute_modified = (aci_gatt_attribute_modified_event_rp0*)blecore_evt->data;
if(attribute_modified->Attr_Handle == serial_svc.tx_char_handle + 2) {
// Descriptor handle
ret = SVCCTL_EvtAckFlowEnable;
FURI_LOG_D(SERIAL_SERVICE_TAG, "TX descriptor event");
} else if(attribute_modified->Attr_Handle == serial_svc.tx_char_handle + 1) {
FURI_LOG_I(SERIAL_SERVICE_TAG, "Data len: %d", attribute_modified->Attr_Data_Length);
for(uint8_t i = 0; i < attribute_modified->Attr_Data_Length; i++) {
printf("%02X ", attribute_modified->Attr_Data[i]);
}
printf("\r\n");
serial_svc_update_rx(attribute_modified->Attr_Data, attribute_modified->Attr_Data_Length);
ret = SVCCTL_EvtAckFlowEnable;
}
} else if(blecore_evt->ecode == ACI_GATT_SERVER_CONFIRMATION_VSEVT_CODE) {
FURI_LOG_I(SERIAL_SERVICE_TAG, "Ack received", blecore_evt->ecode);
ret = SVCCTL_EvtAckFlowEnable;
}
}
return ret;
}
bool serial_svc_init() {
tBleStatus status;
const uint8_t service_uuid[] = {SERIAL_SVC_UUID_128};
const uint8_t char_rx_uuid[] = {SERIAL_CHAR_RX_UUID_128};
const uint8_t char_tx_uuid[] = {SERIAL_CHAR_TX_UUID_128};
// Register event handler
SVCCTL_RegisterSvcHandler(serial_svc_event_handler);
// Add service
status = aci_gatt_add_service(UUID_TYPE_128, (Service_UUID_t *)service_uuid, PRIMARY_SERVICE, 6, &serial_svc.svc_handle);
if(status) {
FURI_LOG_E(SERIAL_SERVICE_TAG, "Failed to add Serial service: %d", status);
}
// Add TX characteristics
status = aci_gatt_add_char(serial_svc.svc_handle, UUID_TYPE_128, (const Char_UUID_t*)char_tx_uuid ,
SERIAL_SVC_DATA_LEN_MAX,
CHAR_PROP_WRITE_WITHOUT_RESP | CHAR_PROP_WRITE | CHAR_PROP_READ,
ATTR_PERMISSION_NONE,
GATT_NOTIFY_ATTRIBUTE_WRITE,
10,
CHAR_VALUE_LEN_VARIABLE,
&serial_svc.tx_char_handle);
if(status) {
FURI_LOG_E(SERIAL_SERVICE_TAG, "Failed to add TX characteristic: %d", status);
}
// Add RX characteristic
status = aci_gatt_add_char(serial_svc.svc_handle, UUID_TYPE_128, (const Char_UUID_t*)char_rx_uuid ,
SERIAL_SVC_DATA_LEN_MAX,
CHAR_PROP_READ | CHAR_PROP_INDICATE,
ATTR_PERMISSION_NONE,
GATT_DONT_NOTIFY_EVENTS,
10,
CHAR_VALUE_LEN_VARIABLE,
&serial_svc.rx_char_handle);
if(status) {
FURI_LOG_E(SERIAL_SERVICE_TAG, "Failed to add RX characteristic: %d", status);
}
return status != BLE_STATUS_SUCCESS;
}
bool serial_svc_update_rx(uint8_t* data, uint8_t data_len) {
furi_assert(data_len < SERIAL_SVC_DATA_LEN_MAX);
tBleStatus result = aci_gatt_update_char_value(serial_svc.svc_handle,
serial_svc.rx_char_handle,
0,
data_len,
data);
if(result) {
FURI_LOG_E(SERIAL_SERVICE_TAG, "Failed updating RX characteristic: %d", result);
}
return result != BLE_STATUS_SUCCESS;
}

View file

@ -0,0 +1,22 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
#define SERIAL_SVC_DATA_LEN_MAX 255
#define SERIAL_SVC_UUID_128 0x00, 0x00, 0xfe, 0x60, 0xcc, 0x7a, 0x48, 0x2a, 0x98, 0x4a, 0x7f, 0x2e, 0xd5, 0xb3, 0xe5, 0x8f
#define SERIAL_CHAR_RX_UUID_128 0x00, 0x00, 0xfe, 0x61, 0x8e, 0x22, 0x45, 0x41, 0x9d, 0x4c, 0x21, 0xed, 0xae, 0x82, 0xed, 0x19
#define SERIAL_CHAR_TX_UUID_128 0x00, 0x00, 0xfe, 0x62, 0x8e, 0x22, 0x45, 0x41, 0x9d, 0x4c, 0x21, 0xed, 0xae, 0x82, 0xed, 0x19
bool serial_svc_init();
bool serial_svc_update_rx(uint8_t* data, uint8_t data_len);
#ifdef __cplusplus
}
#endif

View file

@ -108,8 +108,6 @@ C_SOURCES += \
$(CUBE_DIR)/Middlewares/ST/STM32_WPAN/utilities/stm_list.c \
$(CUBE_DIR)/Middlewares/ST/STM32_WPAN/utilities/dbg_trace.c \
$(CUBE_DIR)/Middlewares/ST/STM32_WPAN/ble/svc/Src/svc_ctl.c \
$(CUBE_DIR)/Middlewares/ST/STM32_WPAN/ble/svc/Src/dis.c \
$(CUBE_DIR)/Middlewares/ST/STM32_WPAN/ble/svc/Src/hrs.c \
$(CUBE_DIR)/Middlewares/ST/STM32_WPAN/ble/core/template/osal.c \
$(CUBE_DIR)/Middlewares/ST/STM32_WPAN/ble/core/auto/ble_hci_le.c \
$(CUBE_DIR)/Middlewares/ST/STM32_WPAN/ble/core/auto/ble_gap_aci.c \