From e0e4e3044eba1eb0f7d68f51166ca9b842950f5c Mon Sep 17 00:00:00 2001 From: hedger Date: Sat, 15 Apr 2023 05:26:19 +0400 Subject: [PATCH 01/14] ble: refactored bt gatt characteristics setup --- applications/services/bt/bt_service/bt.c | 2 +- firmware/targets/f7/ble_glue/app_debug.c | 4 +- firmware/targets/f7/ble_glue/ble_app.c | 79 +++-- .../targets/f7/ble_glue/dev_info_service.c | 220 ------------ firmware/targets/f7/ble_glue/hid_service.c | 332 ------------------ .../ble_glue/{ => services}/battery_service.c | 118 +++---- .../ble_glue/{ => services}/battery_service.h | 0 .../f7/ble_glue/services/dev_info_service.c | 185 ++++++++++ .../{ => services}/dev_info_service.h | 0 .../targets/f7/ble_glue/services/gatt_char.c | 125 +++++++ .../targets/f7/ble_glue/services/gatt_char.h | 86 +++++ .../f7/ble_glue/services/hid_service.c | 274 +++++++++++++++ .../f7/ble_glue/{ => services}/hid_service.h | 0 .../ble_glue/{ => services}/serial_service.c | 256 ++++++++------ .../ble_glue/{ => services}/serial_service.h | 0 firmware/targets/f7/furi_hal/furi_hal_bt.c | 2 +- .../targets/f7/furi_hal/furi_hal_bt_hid.c | 8 +- .../targets/f7/furi_hal/furi_hal_bt_serial.c | 6 +- .../targets/furi_hal_include/furi_hal_bt.h | 2 +- .../furi_hal_include/furi_hal_bt_serial.h | 2 +- site_scons/extapps.scons | 1 - 21 files changed, 919 insertions(+), 783 deletions(-) delete mode 100644 firmware/targets/f7/ble_glue/dev_info_service.c delete mode 100644 firmware/targets/f7/ble_glue/hid_service.c rename firmware/targets/f7/ble_glue/{ => services}/battery_service.c (53%) rename firmware/targets/f7/ble_glue/{ => services}/battery_service.h (100%) create mode 100644 firmware/targets/f7/ble_glue/services/dev_info_service.c rename firmware/targets/f7/ble_glue/{ => services}/dev_info_service.h (100%) create mode 100644 firmware/targets/f7/ble_glue/services/gatt_char.c create mode 100644 firmware/targets/f7/ble_glue/services/gatt_char.h create mode 100644 firmware/targets/f7/ble_glue/services/hid_service.c rename firmware/targets/f7/ble_glue/{ => services}/hid_service.h (100%) rename firmware/targets/f7/ble_glue/{ => services}/serial_service.c (57%) rename firmware/targets/f7/ble_glue/{ => services}/serial_service.h (100%) diff --git a/applications/services/bt/bt_service/bt.c b/applications/services/bt/bt_service/bt.c index 16b60231b244..19ddea8909e7 100644 --- a/applications/services/bt/bt_service/bt.c +++ b/applications/services/bt/bt_service/bt.c @@ -1,7 +1,7 @@ #include "bt_i.h" -#include "battery_service.h" #include "bt_keys_storage.h" +#include #include #include #include diff --git a/firmware/targets/f7/ble_glue/app_debug.c b/firmware/targets/f7/ble_glue/app_debug.c index d84588540a08..2324fb70282c 100644 --- a/firmware/targets/f7/ble_glue/app_debug.c +++ b/firmware/targets/f7/ble_glue/app_debug.c @@ -195,14 +195,14 @@ static void APPD_SetCPU2GpioConfig(void) { gpio_config.Pin = gpiob_pin_list; LL_C2_AHB2_GRP1_EnableClock(LL_C2_AHB2_GRP1_PERIPH_GPIOB); LL_GPIO_Init(GPIOB, &gpio_config); - LL_GPIO_ResetOutputPin(GPIOB, gpioa_pin_list); + LL_GPIO_ResetOutputPin(GPIOB, gpiob_pin_list); } if(gpioc_pin_list != 0) { gpio_config.Pin = gpioc_pin_list; LL_C2_AHB2_GRP1_EnableClock(LL_C2_AHB2_GRP1_PERIPH_GPIOC); LL_GPIO_Init(GPIOC, &gpio_config); - LL_GPIO_ResetOutputPin(GPIOC, gpioa_pin_list); + LL_GPIO_ResetOutputPin(GPIOC, gpioc_pin_list); } } diff --git a/firmware/targets/f7/ble_glue/ble_app.c b/firmware/targets/f7/ble_glue/ble_app.c index 30be3c7ceca7..25ca0da2c847 100644 --- a/firmware/targets/f7/ble_glue/ble_app.c +++ b/firmware/targets/f7/ble_glue/ble_app.c @@ -33,6 +33,45 @@ static int32_t ble_app_hci_thread(void* context); static void ble_app_hci_event_handler(void* pPayload); static void ble_app_hci_status_not_handler(HCI_TL_CmdStatus_t status); +static const HCI_TL_HciInitConf_t hci_tl_config = { + .p_cmdbuffer = (uint8_t*)&ble_app_cmd_buffer, + .StatusNotCallBack = ble_app_hci_status_not_handler, +}; + +static const SHCI_C2_CONFIG_Cmd_Param_t config_param = { + .PayloadCmdSize = SHCI_C2_CONFIG_PAYLOAD_CMD_SIZE, + .Config1 = SHCI_C2_CONFIG_CONFIG1_BIT0_BLE_NVM_DATA_TO_SRAM, + .BleNvmRamAddress = (uint32_t)ble_app_nvm, + .EvtMask1 = SHCI_C2_CONFIG_EVTMASK1_BIT1_BLE_NVM_RAM_UPDATE_ENABLE, +}; + +static const SHCI_C2_Ble_Init_Cmd_Packet_t ble_init_cmd_packet = { + .Header = {{0, 0, 0}}, // Header unused + .Param = { + .pBleBufferAddress = 0, // pBleBufferAddress not used + .BleBufferSize = 0, // BleBufferSize not used + .NumAttrRecord = CFG_BLE_NUM_GATT_ATTRIBUTES, + .NumAttrServ = CFG_BLE_NUM_GATT_SERVICES, + .AttrValueArrSize = CFG_BLE_ATT_VALUE_ARRAY_SIZE, + .NumOfLinks = CFG_BLE_NUM_LINK, + .ExtendedPacketLengthEnable = CFG_BLE_DATA_LENGTH_EXTENSION, + .PrWriteListSize = CFG_BLE_PREPARE_WRITE_LIST_SIZE, + .MblockCount = CFG_BLE_MBLOCK_COUNT, + .AttMtu = CFG_BLE_MAX_ATT_MTU, + .SlaveSca = CFG_BLE_SLAVE_SCA, + .MasterSca = CFG_BLE_MASTER_SCA, + .LsSource = CFG_BLE_LSE_SOURCE, + .MaxConnEventLength = CFG_BLE_MAX_CONN_EVENT_LENGTH, + .HsStartupTime = CFG_BLE_HSE_STARTUP_TIME, + .ViterbiEnable = CFG_BLE_VITERBI_MODE, + .Options = CFG_BLE_OPTIONS, + .HwVersion = 0, + .max_coc_initiator_nbr = 32, + .min_tx_power = 0, + .max_tx_power = 0, + .rx_model_config = 1, + }}; + bool ble_app_init() { SHCI_CmdStatus_t status; ble_app = malloc(sizeof(BleApp)); @@ -44,52 +83,16 @@ bool ble_app_init() { furi_thread_start(ble_app->thread); // Initialize Ble Transport Layer - HCI_TL_HciInitConf_t hci_tl_config = { - .p_cmdbuffer = (uint8_t*)&ble_app_cmd_buffer, - .StatusNotCallBack = ble_app_hci_status_not_handler, - }; hci_init(ble_app_hci_event_handler, (void*)&hci_tl_config); // Configure NVM store for pairing data - SHCI_C2_CONFIG_Cmd_Param_t config_param = { - .PayloadCmdSize = SHCI_C2_CONFIG_PAYLOAD_CMD_SIZE, - .Config1 = SHCI_C2_CONFIG_CONFIG1_BIT0_BLE_NVM_DATA_TO_SRAM, - .BleNvmRamAddress = (uint32_t)ble_app_nvm, - .EvtMask1 = SHCI_C2_CONFIG_EVTMASK1_BIT1_BLE_NVM_RAM_UPDATE_ENABLE, - }; - status = SHCI_C2_Config(&config_param); + status = SHCI_C2_Config((SHCI_C2_CONFIG_Cmd_Param_t*)&config_param); if(status) { FURI_LOG_E(TAG, "Failed to configure 2nd core: %d", status); } // Start ble stack on 2nd core - SHCI_C2_Ble_Init_Cmd_Packet_t ble_init_cmd_packet = { - .Header = {{0, 0, 0}}, // Header unused - .Param = { - .pBleBufferAddress = 0, // pBleBufferAddress not used - .BleBufferSize = 0, // BleBufferSize not used - .NumAttrRecord = CFG_BLE_NUM_GATT_ATTRIBUTES, - .NumAttrServ = CFG_BLE_NUM_GATT_SERVICES, - .AttrValueArrSize = CFG_BLE_ATT_VALUE_ARRAY_SIZE, - .NumOfLinks = CFG_BLE_NUM_LINK, - .ExtendedPacketLengthEnable = CFG_BLE_DATA_LENGTH_EXTENSION, - .PrWriteListSize = CFG_BLE_PREPARE_WRITE_LIST_SIZE, - .MblockCount = CFG_BLE_MBLOCK_COUNT, - .AttMtu = CFG_BLE_MAX_ATT_MTU, - .SlaveSca = CFG_BLE_SLAVE_SCA, - .MasterSca = CFG_BLE_MASTER_SCA, - .LsSource = CFG_BLE_LSE_SOURCE, - .MaxConnEventLength = CFG_BLE_MAX_CONN_EVENT_LENGTH, - .HsStartupTime = CFG_BLE_HSE_STARTUP_TIME, - .ViterbiEnable = CFG_BLE_VITERBI_MODE, - .Options = CFG_BLE_OPTIONS, - .HwVersion = 0, - .max_coc_initiator_nbr = 32, - .min_tx_power = 0, - .max_tx_power = 0, - .rx_model_config = 1, - }}; - status = SHCI_C2_BLE_Init(&ble_init_cmd_packet); + status = SHCI_C2_BLE_Init((SHCI_C2_Ble_Init_Cmd_Packet_t*)&ble_init_cmd_packet); if(status) { FURI_LOG_E(TAG, "Failed to start ble stack: %d", status); } diff --git a/firmware/targets/f7/ble_glue/dev_info_service.c b/firmware/targets/f7/ble_glue/dev_info_service.c deleted file mode 100644 index 8bdb2eea84c7..000000000000 --- a/firmware/targets/f7/ble_glue/dev_info_service.c +++ /dev/null @@ -1,220 +0,0 @@ -#include "dev_info_service.h" -#include "app_common.h" -#include - -#include -#include -#include - -#define TAG "BtDevInfoSvc" - -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; - uint16_t rpc_version_char_handle; - FuriString* version_string; - char hardware_revision[4]; -} DevInfoSvc; - -static DevInfoSvc* dev_info_svc = NULL; - -static const char dev_info_man_name[] = "Flipper Devices Inc."; -static const char dev_info_serial_num[] = "1.0"; -static const char dev_info_rpc_version[] = TOSTRING(PROTOBUF_MAJOR_VERSION.PROTOBUF_MINOR_VERSION); - -static const uint8_t dev_info_rpc_version_uuid[] = - {0x33, 0xa9, 0xb5, 0x3e, 0x87, 0x5d, 0x1a, 0x8e, 0xc8, 0x47, 0x5e, 0xae, 0x6d, 0x66, 0xf6, 0x03}; - -void dev_info_svc_start() { - dev_info_svc = malloc(sizeof(DevInfoSvc)); - dev_info_svc->version_string = furi_string_alloc_printf( - "%s %s %s %s", - version_get_githash(NULL), - version_get_gitbranch(NULL), - version_get_gitbranchnum(NULL), - version_get_builddate(NULL)); - snprintf( - dev_info_svc->hardware_revision, - sizeof(dev_info_svc->hardware_revision), - "%d", - version_get_target(NULL)); - tBleStatus status; - - // 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, 11, &dev_info_svc->service_handle); - if(status) { - FURI_LOG_E(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_man_name), - CHAR_PROP_READ, - ATTR_PERMISSION_AUTHEN_READ, - GATT_DONT_NOTIFY_EVENTS, - 10, - CHAR_VALUE_LEN_CONSTANT, - &dev_info_svc->man_name_char_handle); - if(status) { - FURI_LOG_E(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_num), - CHAR_PROP_READ, - ATTR_PERMISSION_AUTHEN_READ, - GATT_DONT_NOTIFY_EVENTS, - 10, - CHAR_VALUE_LEN_CONSTANT, - &dev_info_svc->serial_num_char_handle); - if(status) { - FURI_LOG_E(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_svc->hardware_revision), - CHAR_PROP_READ, - ATTR_PERMISSION_AUTHEN_READ, - GATT_DONT_NOTIFY_EVENTS, - 10, - CHAR_VALUE_LEN_CONSTANT, - &dev_info_svc->firmware_rev_char_handle); - if(status) { - FURI_LOG_E(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, - furi_string_size(dev_info_svc->version_string), - CHAR_PROP_READ, - ATTR_PERMISSION_AUTHEN_READ, - GATT_DONT_NOTIFY_EVENTS, - 10, - CHAR_VALUE_LEN_CONSTANT, - &dev_info_svc->software_rev_char_handle); - if(status) { - FURI_LOG_E(TAG, "Failed to add software revision char: %d", status); - } - status = aci_gatt_add_char( - dev_info_svc->service_handle, - UUID_TYPE_128, - (const Char_UUID_t*)dev_info_rpc_version_uuid, - strlen(dev_info_rpc_version), - CHAR_PROP_READ, - ATTR_PERMISSION_AUTHEN_READ, - GATT_DONT_NOTIFY_EVENTS, - 10, - CHAR_VALUE_LEN_CONSTANT, - &dev_info_svc->rpc_version_char_handle); - if(status) { - FURI_LOG_E(TAG, "Failed to add rpc version characteristic: %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_man_name), - (uint8_t*)dev_info_man_name); - if(status) { - FURI_LOG_E(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_num), - (uint8_t*)dev_info_serial_num); - if(status) { - FURI_LOG_E(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_svc->hardware_revision), - (uint8_t*)dev_info_svc->hardware_revision); - if(status) { - FURI_LOG_E(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, - furi_string_size(dev_info_svc->version_string), - (uint8_t*)furi_string_get_cstr(dev_info_svc->version_string)); - if(status) { - FURI_LOG_E(TAG, "Failed to update software revision char: %d", status); - } - status = aci_gatt_update_char_value( - dev_info_svc->service_handle, - dev_info_svc->rpc_version_char_handle, - 0, - strlen(dev_info_rpc_version), - (uint8_t*)dev_info_rpc_version); - if(status) { - FURI_LOG_E(TAG, "Failed to update rpc version char: %d", status); - } -} - -void dev_info_svc_stop() { - tBleStatus status; - if(dev_info_svc) { - furi_string_free(dev_info_svc->version_string); - // Delete service characteristics - status = - aci_gatt_del_char(dev_info_svc->service_handle, dev_info_svc->man_name_char_handle); - if(status) { - FURI_LOG_E(TAG, "Failed to delete manufacturer name char: %d", status); - } - status = - aci_gatt_del_char(dev_info_svc->service_handle, dev_info_svc->serial_num_char_handle); - if(status) { - FURI_LOG_E(TAG, "Failed to delete serial number char: %d", status); - } - status = aci_gatt_del_char( - dev_info_svc->service_handle, dev_info_svc->firmware_rev_char_handle); - if(status) { - FURI_LOG_E(TAG, "Failed to delete firmware revision char: %d", status); - } - status = aci_gatt_del_char( - dev_info_svc->service_handle, dev_info_svc->software_rev_char_handle); - if(status) { - FURI_LOG_E(TAG, "Failed to delete software revision char: %d", status); - } - status = - aci_gatt_del_char(dev_info_svc->service_handle, dev_info_svc->rpc_version_char_handle); - if(status) { - FURI_LOG_E(TAG, "Failed to delete rpc version char: %d", status); - } - // Delete service - status = aci_gatt_del_service(dev_info_svc->service_handle); - if(status) { - FURI_LOG_E(TAG, "Failed to delete device info service: %d", status); - } - free(dev_info_svc); - dev_info_svc = NULL; - } -} - -bool dev_info_svc_is_started() { - return dev_info_svc != NULL; -} diff --git a/firmware/targets/f7/ble_glue/hid_service.c b/firmware/targets/f7/ble_glue/hid_service.c deleted file mode 100644 index 47d242d4dff8..000000000000 --- a/firmware/targets/f7/ble_glue/hid_service.c +++ /dev/null @@ -1,332 +0,0 @@ -#include "hid_service.h" -#include "app_common.h" -#include - -#include - -#define TAG "BtHid" - -typedef struct { - uint16_t svc_handle; - uint16_t protocol_mode_char_handle; - uint16_t report_char_handle[HID_SVC_REPORT_COUNT]; - uint16_t report_ref_desc_handle[HID_SVC_REPORT_COUNT]; - uint16_t report_map_char_handle; - uint16_t info_char_handle; - uint16_t ctrl_point_char_handle; -} HIDSvc; - -static HIDSvc* hid_svc = NULL; - -static SVCCTL_EvtAckStatus_t hid_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) { - // Process modification events - ret = SVCCTL_EvtAckFlowEnable; - } else if(blecore_evt->ecode == ACI_GATT_SERVER_CONFIRMATION_VSEVT_CODE) { - // Process notification confirmation - ret = SVCCTL_EvtAckFlowEnable; - } - } - return ret; -} - -void hid_svc_start() { - tBleStatus status; - hid_svc = malloc(sizeof(HIDSvc)); - Service_UUID_t svc_uuid = {}; - Char_Desc_Uuid_t desc_uuid = {}; - Char_UUID_t char_uuid = {}; - - // Register event handler - SVCCTL_RegisterSvcHandler(hid_svc_event_handler); - // Add service - svc_uuid.Service_UUID_16 = HUMAN_INTERFACE_DEVICE_SERVICE_UUID; - /** - * Add Human Interface Device Service - */ - status = aci_gatt_add_service( - UUID_TYPE_16, - &svc_uuid, - PRIMARY_SERVICE, - 2 + /* protocol mode */ - (4 * HID_SVC_INPUT_REPORT_COUNT) + (3 * HID_SVC_OUTPUT_REPORT_COUNT) + - (3 * HID_SVC_FEATURE_REPORT_COUNT) + 1 + 2 + 2 + - 2, /* Service + Report Map + HID Information + HID Control Point */ - &hid_svc->svc_handle); - if(status) { - FURI_LOG_E(TAG, "Failed to add HID service: %d", status); - } - // Add Protocol mode characteristics - char_uuid.Char_UUID_16 = PROTOCOL_MODE_CHAR_UUID; - status = aci_gatt_add_char( - hid_svc->svc_handle, - UUID_TYPE_16, - &char_uuid, - 1, - CHAR_PROP_READ | CHAR_PROP_WRITE_WITHOUT_RESP, - ATTR_PERMISSION_NONE, - GATT_NOTIFY_ATTRIBUTE_WRITE, - 10, - CHAR_VALUE_LEN_CONSTANT, - &hid_svc->protocol_mode_char_handle); - if(status) { - FURI_LOG_E(TAG, "Failed to add protocol mode characteristic: %d", status); - } - // Update Protocol mode characteristic - uint8_t protocol_mode = 1; - status = aci_gatt_update_char_value( - hid_svc->svc_handle, hid_svc->protocol_mode_char_handle, 0, 1, &protocol_mode); - if(status) { - FURI_LOG_E(TAG, "Failed to update protocol mode characteristic: %d", status); - } - -#if(HID_SVC_REPORT_COUNT != 0) - for(uint8_t i = 0; i < HID_SVC_REPORT_COUNT; i++) { - if(i < HID_SVC_INPUT_REPORT_COUNT) { //-V547 - uint8_t buf[2] = {i + 1, 1}; // 1 input - char_uuid.Char_UUID_16 = REPORT_CHAR_UUID; - status = aci_gatt_add_char( - hid_svc->svc_handle, - UUID_TYPE_16, - &char_uuid, - HID_SVC_REPORT_MAX_LEN, - CHAR_PROP_READ | CHAR_PROP_NOTIFY, - ATTR_PERMISSION_NONE, - GATT_DONT_NOTIFY_EVENTS, - 10, - CHAR_VALUE_LEN_VARIABLE, - &(hid_svc->report_char_handle[i])); - if(status) { - FURI_LOG_E(TAG, "Failed to add report characteristic: %d", status); - } - - desc_uuid.Char_UUID_16 = REPORT_REFERENCE_DESCRIPTOR_UUID; - status = aci_gatt_add_char_desc( - hid_svc->svc_handle, - hid_svc->report_char_handle[i], - UUID_TYPE_16, - &desc_uuid, - HID_SVC_REPORT_REF_LEN, - HID_SVC_REPORT_REF_LEN, - buf, - ATTR_PERMISSION_NONE, - ATTR_ACCESS_READ_WRITE, - GATT_DONT_NOTIFY_EVENTS, - MIN_ENCRY_KEY_SIZE, - CHAR_VALUE_LEN_CONSTANT, - &(hid_svc->report_ref_desc_handle[i])); - if(status) { - FURI_LOG_E(TAG, "Failed to add report reference descriptor: %d", status); - } - } else if((i - HID_SVC_INPUT_REPORT_COUNT) < HID_SVC_OUTPUT_REPORT_COUNT) { - uint8_t buf[2] = {i + 1, 2}; // 2 output - char_uuid.Char_UUID_16 = REPORT_CHAR_UUID; - status = aci_gatt_add_char( - hid_svc->svc_handle, - UUID_TYPE_16, - &char_uuid, - HID_SVC_REPORT_MAX_LEN, - CHAR_PROP_READ | CHAR_PROP_NOTIFY, - ATTR_PERMISSION_NONE, - GATT_DONT_NOTIFY_EVENTS, - 10, - CHAR_VALUE_LEN_VARIABLE, - &(hid_svc->report_char_handle[i])); - if(status) { - FURI_LOG_E(TAG, "Failed to add report characteristic: %d", status); - } - - desc_uuid.Char_UUID_16 = REPORT_REFERENCE_DESCRIPTOR_UUID; - status = aci_gatt_add_char_desc( - hid_svc->svc_handle, - hid_svc->report_char_handle[i], - UUID_TYPE_16, - &desc_uuid, - HID_SVC_REPORT_REF_LEN, - HID_SVC_REPORT_REF_LEN, - buf, - ATTR_PERMISSION_NONE, - ATTR_ACCESS_READ_WRITE, - GATT_DONT_NOTIFY_EVENTS, - MIN_ENCRY_KEY_SIZE, - CHAR_VALUE_LEN_CONSTANT, - &(hid_svc->report_ref_desc_handle[i])); - if(status) { - FURI_LOG_E(TAG, "Failed to add report reference descriptor: %d", status); - } - } else { - uint8_t buf[2] = {i + 1, 3}; // 3 feature - char_uuid.Char_UUID_16 = REPORT_CHAR_UUID; - status = aci_gatt_add_char( - hid_svc->svc_handle, - UUID_TYPE_16, - &char_uuid, - HID_SVC_REPORT_MAX_LEN, - CHAR_PROP_READ | CHAR_PROP_NOTIFY, - ATTR_PERMISSION_NONE, - GATT_DONT_NOTIFY_EVENTS, - 10, - CHAR_VALUE_LEN_VARIABLE, - &(hid_svc->report_char_handle[i])); - if(status) { - FURI_LOG_E(TAG, "Failed to add report characteristic: %d", status); - } - - desc_uuid.Char_UUID_16 = REPORT_REFERENCE_DESCRIPTOR_UUID; - status = aci_gatt_add_char_desc( - hid_svc->svc_handle, - hid_svc->report_char_handle[i], - UUID_TYPE_16, - &desc_uuid, - HID_SVC_REPORT_REF_LEN, - HID_SVC_REPORT_REF_LEN, - buf, - ATTR_PERMISSION_NONE, - ATTR_ACCESS_READ_WRITE, - GATT_DONT_NOTIFY_EVENTS, - MIN_ENCRY_KEY_SIZE, - CHAR_VALUE_LEN_CONSTANT, - &(hid_svc->report_ref_desc_handle[i])); - if(status) { - FURI_LOG_E(TAG, "Failed to add report reference descriptor: %d", status); - } - } - } -#endif - // Add Report Map characteristic - char_uuid.Char_UUID_16 = REPORT_MAP_CHAR_UUID; - status = aci_gatt_add_char( - hid_svc->svc_handle, - UUID_TYPE_16, - &char_uuid, - HID_SVC_REPORT_MAP_MAX_LEN, - CHAR_PROP_READ, - ATTR_PERMISSION_NONE, - GATT_DONT_NOTIFY_EVENTS, - 10, - CHAR_VALUE_LEN_VARIABLE, - &hid_svc->report_map_char_handle); - if(status) { - FURI_LOG_E(TAG, "Failed to add report map characteristic: %d", status); - } - - // Add Information characteristic - char_uuid.Char_UUID_16 = HID_INFORMATION_CHAR_UUID; - status = aci_gatt_add_char( - hid_svc->svc_handle, - UUID_TYPE_16, - &char_uuid, - HID_SVC_INFO_LEN, - CHAR_PROP_READ, - ATTR_PERMISSION_NONE, - GATT_DONT_NOTIFY_EVENTS, - 10, - CHAR_VALUE_LEN_CONSTANT, - &hid_svc->info_char_handle); - if(status) { - FURI_LOG_E(TAG, "Failed to add information characteristic: %d", status); - } - // Add Control Point characteristic - char_uuid.Char_UUID_16 = HID_CONTROL_POINT_CHAR_UUID; - status = aci_gatt_add_char( - hid_svc->svc_handle, - UUID_TYPE_16, - &char_uuid, - HID_SVC_CONTROL_POINT_LEN, - CHAR_PROP_WRITE_WITHOUT_RESP, - ATTR_PERMISSION_NONE, - GATT_NOTIFY_ATTRIBUTE_WRITE, - 10, - CHAR_VALUE_LEN_CONSTANT, - &hid_svc->ctrl_point_char_handle); - if(status) { - FURI_LOG_E(TAG, "Failed to add control point characteristic: %d", status); - } -} - -bool hid_svc_update_report_map(const uint8_t* data, uint16_t len) { - furi_assert(data); - furi_assert(hid_svc); - - tBleStatus status = aci_gatt_update_char_value( - hid_svc->svc_handle, hid_svc->report_map_char_handle, 0, len, data); - if(status) { - FURI_LOG_E(TAG, "Failed updating report map characteristic: %d", status); - return false; - } - return true; -} - -bool hid_svc_update_input_report(uint8_t input_report_num, uint8_t* data, uint16_t len) { - furi_assert(data); - furi_assert(hid_svc); - - tBleStatus status = aci_gatt_update_char_value( - hid_svc->svc_handle, hid_svc->report_char_handle[input_report_num], 0, len, data); - if(status) { - FURI_LOG_E(TAG, "Failed updating report characteristic: %d", status); - return false; - } - return true; -} - -bool hid_svc_update_info(uint8_t* data, uint16_t len) { - furi_assert(data); - furi_assert(hid_svc); - - tBleStatus status = - aci_gatt_update_char_value(hid_svc->svc_handle, hid_svc->info_char_handle, 0, len, data); - if(status) { - FURI_LOG_E(TAG, "Failed updating info characteristic: %d", status); - return false; - } - return true; -} - -bool hid_svc_is_started() { - return hid_svc != NULL; -} - -void hid_svc_stop() { - tBleStatus status; - if(hid_svc) { - // Delete characteristics - status = aci_gatt_del_char(hid_svc->svc_handle, hid_svc->report_map_char_handle); - if(status) { - FURI_LOG_E(TAG, "Failed to delete Report Map characteristic: %d", status); - } -#if(HID_SVC_INPUT_REPORT_COUNT != 0) - for(uint8_t i = 0; i < HID_SVC_REPORT_COUNT; i++) { - status = aci_gatt_del_char(hid_svc->svc_handle, hid_svc->report_char_handle[i]); - if(status) { - FURI_LOG_E(TAG, "Failed to delete Report characteristic: %d", status); - } - } -#endif - status = aci_gatt_del_char(hid_svc->svc_handle, hid_svc->protocol_mode_char_handle); - if(status) { - FURI_LOG_E(TAG, "Failed to delete Protocol Mode characteristic: %d", status); - } - status = aci_gatt_del_char(hid_svc->svc_handle, hid_svc->info_char_handle); - if(status) { - FURI_LOG_E(TAG, "Failed to delete Information characteristic: %d", status); - } - status = aci_gatt_del_char(hid_svc->svc_handle, hid_svc->ctrl_point_char_handle); - if(status) { - FURI_LOG_E(TAG, "Failed to delete Control Point characteristic: %d", status); - } - // Delete service - status = aci_gatt_del_service(hid_svc->svc_handle); - if(status) { - FURI_LOG_E(TAG, "Failed to delete HID service: %d", status); - } - // Delete buffer size mutex - free(hid_svc); - hid_svc = NULL; - } -} diff --git a/firmware/targets/f7/ble_glue/battery_service.c b/firmware/targets/f7/ble_glue/services/battery_service.c similarity index 53% rename from firmware/targets/f7/ble_glue/battery_service.c rename to firmware/targets/f7/ble_glue/services/battery_service.c index 8c371efadba0..37770be97eab 100644 --- a/firmware/targets/f7/ble_glue/battery_service.c +++ b/firmware/targets/f7/ble_glue/services/battery_service.c @@ -1,5 +1,7 @@ #include "battery_service.h" #include "app_common.h" +#include "gatt_char.h" + #include #include @@ -7,12 +9,6 @@ #define TAG "BtBatterySvc" -typedef struct { - uint16_t svc_handle; - uint16_t battery_level_char_handle; - uint16_t power_state_char_handle; -} BatterySvc; - enum { // Common states BatterySvcPowerStateUnknown = 0b00, @@ -40,13 +36,44 @@ typedef struct { _Static_assert(sizeof(BattrySvcPowerState) == 1, "Incorrect structure size"); -static BatterySvc* battery_svc = NULL; - #define BATTERY_POWER_STATE (0x2A1A) static const uint16_t service_uuid = BATTERY_SERVICE_UUID; -static const uint16_t battery_level_char_uuid = BATTERY_LEVEL_CHAR_UUID; -static const uint16_t power_state_char_uuid = BATTERY_POWER_STATE; + +typedef enum { + BatterySvcGattCharacteristicBatteryLevel = 0, + BatterySvcGattCharacteristicPowerState, + BatterySvcGattCharacteristicCount, +} BatterySvcGattCharacteristicId; + +static const FlipperGattCharacteristicParams battery_svc_chars[BatterySvcGattCharacteristicCount] = + {[BatterySvcGattCharacteristicBatteryLevel] = + {.name = "Battery Level", + .data_prop_type = FlipperGattCharacteristicDataPropsFixed, + .data_prop.fixed.length = 1, + .uuid.Char_UUID_16 = BATTERY_LEVEL_CHAR_UUID, + .uuid_type = UUID_TYPE_16, + .properties = CHAR_PROP_READ | CHAR_PROP_NOTIFY, + .permissions = ATTR_PERMISSION_AUTHEN_READ, + .evt_mask = GATT_DONT_NOTIFY_EVENTS, + .is_variable = CHAR_VALUE_LEN_CONSTANT}, + [BatterySvcGattCharacteristicPowerState] = { + .name = "Power State", + .data_prop_type = FlipperGattCharacteristicDataPropsFixed, + .data_prop.fixed.length = 1, + .uuid.Char_UUID_16 = BATTERY_POWER_STATE, + .uuid_type = UUID_TYPE_16, + .properties = CHAR_PROP_READ | CHAR_PROP_NOTIFY, + .permissions = ATTR_PERMISSION_AUTHEN_READ, + .evt_mask = GATT_DONT_NOTIFY_EVENTS, + .is_variable = CHAR_VALUE_LEN_CONSTANT}}; + +typedef struct { + uint16_t svc_handle; + FlipperGattCharacteristicInstance chars[BatterySvcGattCharacteristicCount]; +} BatterySvc; + +static BatterySvc* battery_svc = NULL; void battery_svc_start() { battery_svc = malloc(sizeof(BatterySvc)); @@ -58,53 +85,19 @@ void battery_svc_start() { if(status) { FURI_LOG_E(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*)&battery_level_char_uuid, - 1, - CHAR_PROP_READ | CHAR_PROP_NOTIFY, - ATTR_PERMISSION_AUTHEN_READ, - GATT_DONT_NOTIFY_EVENTS, - 10, - CHAR_VALUE_LEN_CONSTANT, - &battery_svc->battery_level_char_handle); - if(status) { - FURI_LOG_E(TAG, "Failed to add Battery level characteristic: %d", status); + for(size_t i = 0; i < BatterySvcGattCharacteristicCount; i++) { + flipper_gatt_characteristic_init( + battery_svc->svc_handle, &battery_svc_chars[i], &battery_svc->chars[i]); } - // Add Power state characteristic - status = aci_gatt_add_char( - battery_svc->svc_handle, - UUID_TYPE_16, - (Char_UUID_t*)&power_state_char_uuid, - 1, - CHAR_PROP_READ | CHAR_PROP_NOTIFY, - ATTR_PERMISSION_AUTHEN_READ, - GATT_DONT_NOTIFY_EVENTS, - 10, - CHAR_VALUE_LEN_CONSTANT, - &battery_svc->power_state_char_handle); - if(status) { - FURI_LOG_E(TAG, "Failed to add Battery level characteristic: %d", status); - } - // Update power state charachteristic + battery_svc_update_power_state(); } void battery_svc_stop() { tBleStatus status; if(battery_svc) { - // Delete Battery level characteristic - status = - aci_gatt_del_char(battery_svc->svc_handle, battery_svc->battery_level_char_handle); - if(status) { - FURI_LOG_E(TAG, "Failed to delete Battery level characteristic: %d", status); - } - // Delete Power state characteristic - status = aci_gatt_del_char(battery_svc->svc_handle, battery_svc->power_state_char_handle); - if(status) { - FURI_LOG_E(TAG, "Failed to delete Battery level characteristic: %d", status); + for(size_t i = 0; i < BatterySvcGattCharacteristicCount; i++) { + flipper_gatt_characteristic_deinit(battery_svc->svc_handle, &battery_svc->chars[i]); } // Delete Battery service status = aci_gatt_del_service(battery_svc->svc_handle); @@ -126,13 +119,10 @@ bool battery_svc_update_level(uint8_t battery_charge) { return false; } // Update battery level characteristic - FURI_LOG_D(TAG, "Updating battery level characteristic"); - tBleStatus result = aci_gatt_update_char_value( - battery_svc->svc_handle, battery_svc->battery_level_char_handle, 0, 1, &battery_charge); - if(result) { - FURI_LOG_E(TAG, "Failed updating RX characteristic: %d", result); - } - return result != BLE_STATUS_SUCCESS; + return flipper_gatt_characteristic_update( + battery_svc->svc_handle, + &battery_svc->chars[BatterySvcGattCharacteristicBatteryLevel], + &battery_charge); } bool battery_svc_update_power_state() { @@ -152,15 +142,9 @@ bool battery_svc_update_power_state() { power_state.charging = BatterySvcPowerStateNotCharging; power_state.discharging = BatterySvcPowerStateDischarging; } - FURI_LOG_D(TAG, "Updating power state characteristic"); - tBleStatus result = aci_gatt_update_char_value( + + return flipper_gatt_characteristic_update( battery_svc->svc_handle, - battery_svc->power_state_char_handle, - 0, - 1, - (uint8_t*)&power_state); - if(result) { - FURI_LOG_E(TAG, "Failed updating Power state characteristic: %d", result); - } - return result != BLE_STATUS_SUCCESS; + &battery_svc->chars[BatterySvcGattCharacteristicPowerState], + &power_state); } diff --git a/firmware/targets/f7/ble_glue/battery_service.h b/firmware/targets/f7/ble_glue/services/battery_service.h similarity index 100% rename from firmware/targets/f7/ble_glue/battery_service.h rename to firmware/targets/f7/ble_glue/services/battery_service.h diff --git a/firmware/targets/f7/ble_glue/services/dev_info_service.c b/firmware/targets/f7/ble_glue/services/dev_info_service.c new file mode 100644 index 000000000000..26611b14d355 --- /dev/null +++ b/firmware/targets/f7/ble_glue/services/dev_info_service.c @@ -0,0 +1,185 @@ +#include "dev_info_service.h" +#include "app_common.h" +#include "gatt_char.h" +#include + +#include +#include +#include + +#define TAG "BtDevInfoSvc" + +typedef enum { + DevInfoSvcGattCharacteristicMfgName = 0, + DevInfoSvcGattCharacteristicSerial, + DevInfoSvcGattCharacteristicFirmwareRev, + DevInfoSvcGattCharacteristicSoftwareRev, + DevInfoSvcGattCharacteristicRpcVersion, + DevInfoSvcGattCharacteristicCount, +} DevInfoSvcGattCharacteristicId; + +typedef struct { + uint16_t service_handle; + FlipperGattCharacteristicInstance characteristics[DevInfoSvcGattCharacteristicCount]; + FuriString* version_string; + char hardware_revision[4]; +} DevInfoSvc; + +static DevInfoSvc* dev_info_svc = NULL; + +static const char dev_info_man_name[] = "Flipper Devices Inc."; +static const char dev_info_serial_num[] = "1.0"; +static const char dev_info_rpc_version[] = TOSTRING(PROTOBUF_MAJOR_VERSION.PROTOBUF_MINOR_VERSION); + +static bool dev_info_char_firmware_rev_callback( + const void* context, + const uint8_t** data, + uint16_t* data_len) { + const DevInfoSvc* dev_info_svc = *(DevInfoSvc**)context; + *data = (const uint8_t*)&dev_info_svc->hardware_revision; + *data_len = sizeof(dev_info_svc->hardware_revision); + return false; +} + +static bool dev_info_char_software_rev_callback( + const void* context, + const uint8_t** data, + uint16_t* data_len) { + const DevInfoSvc* dev_info_svc = *(DevInfoSvc**)context; + *data = (const uint8_t*)furi_string_get_cstr(dev_info_svc->version_string); + *data_len = furi_string_size(dev_info_svc->version_string); + return false; +} + +static const FlipperGattCharacteristicParams dev_info_svc_chars[DevInfoSvcGattCharacteristicCount] = + {[DevInfoSvcGattCharacteristicMfgName] = + {.name = "Manufacturer Name", + .data_prop_type = FlipperGattCharacteristicDataPropsCallback, + .data_prop.callback.context = dev_info_man_name, + .data_prop.callback.fn = flipper_gatt_characteristic_props_const_char, + .uuid.Char_UUID_16 = MANUFACTURER_NAME_UUID, + .uuid_type = UUID_TYPE_16, + .properties = CHAR_PROP_READ, + .permissions = ATTR_PERMISSION_AUTHEN_READ, + .evt_mask = GATT_DONT_NOTIFY_EVENTS, + .is_variable = CHAR_VALUE_LEN_CONSTANT}, + [DevInfoSvcGattCharacteristicSerial] = + {.name = "Serial Number", + .data_prop_type = FlipperGattCharacteristicDataPropsCallback, + .data_prop.callback.context = dev_info_serial_num, + .data_prop.callback.fn = flipper_gatt_characteristic_props_const_char, + .uuid.Char_UUID_16 = SERIAL_NUMBER_UUID, + .uuid_type = UUID_TYPE_16, + .properties = CHAR_PROP_READ, + .permissions = ATTR_PERMISSION_AUTHEN_READ, + .evt_mask = GATT_DONT_NOTIFY_EVENTS, + .is_variable = CHAR_VALUE_LEN_CONSTANT}, + [DevInfoSvcGattCharacteristicFirmwareRev] = + {.name = "Firmware Revision", + .data_prop_type = FlipperGattCharacteristicDataPropsCallback, + .data_prop.callback.context = &dev_info_svc, + .data_prop.callback.fn = dev_info_char_firmware_rev_callback, + .uuid.Char_UUID_16 = FIRMWARE_REVISION_UUID, + .uuid_type = UUID_TYPE_16, + .properties = CHAR_PROP_READ, + .permissions = ATTR_PERMISSION_AUTHEN_READ, + .evt_mask = GATT_DONT_NOTIFY_EVENTS, + .is_variable = CHAR_VALUE_LEN_CONSTANT}, + [DevInfoSvcGattCharacteristicSoftwareRev] = + {.name = "Software Revision", + .data_prop_type = FlipperGattCharacteristicDataPropsCallback, + .data_prop.callback.context = &dev_info_svc, + .data_prop.callback.fn = dev_info_char_software_rev_callback, + .uuid.Char_UUID_16 = SOFTWARE_REVISION_UUID, + .uuid_type = UUID_TYPE_16, + .properties = CHAR_PROP_READ, + .permissions = ATTR_PERMISSION_AUTHEN_READ, + .evt_mask = GATT_DONT_NOTIFY_EVENTS, + .is_variable = CHAR_VALUE_LEN_CONSTANT}, + [DevInfoSvcGattCharacteristicRpcVersion] = { + .name = "RPC Version", + .data_prop_type = FlipperGattCharacteristicDataPropsCallback, + .data_prop.callback.context = dev_info_rpc_version, + .data_prop.callback.fn = flipper_gatt_characteristic_props_const_char, + .uuid.Char_UUID_128 = + {0x33, + 0xa9, + 0xb5, + 0x3e, + 0x87, + 0x5d, + 0x1a, + 0x8e, + 0xc8, + 0x47, + 0x5e, + 0xae, + 0x6d, + 0x66, + 0xf6, + 0x03}, + .uuid_type = UUID_TYPE_128, + .properties = CHAR_PROP_READ, + .permissions = ATTR_PERMISSION_AUTHEN_READ, + .evt_mask = GATT_DONT_NOTIFY_EVENTS, + .is_variable = CHAR_VALUE_LEN_CONSTANT}}; + +void dev_info_svc_start() { + dev_info_svc = malloc(sizeof(DevInfoSvc)); + dev_info_svc->version_string = furi_string_alloc_printf( + "%s %s %s %s", + version_get_githash(NULL), + version_get_gitbranch(NULL), + version_get_gitbranchnum(NULL), + version_get_builddate(NULL)); + snprintf( + dev_info_svc->hardware_revision, + sizeof(dev_info_svc->hardware_revision), + "%d", + version_get_target(NULL)); + tBleStatus status; + + // 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, + 1 + 2 * DevInfoSvcGattCharacteristicCount, + &dev_info_svc->service_handle); + if(status) { + FURI_LOG_E(TAG, "Failed to add Device Information Service: %d", status); + } + + for(size_t i = 0; i < DevInfoSvcGattCharacteristicCount; i++) { + flipper_gatt_characteristic_init( + dev_info_svc->service_handle, + &dev_info_svc_chars[i], + &dev_info_svc->characteristics[i]); + flipper_gatt_characteristic_update( + dev_info_svc->service_handle, &dev_info_svc->characteristics[i], NULL); + } +} + +void dev_info_svc_stop() { + tBleStatus status; + if(dev_info_svc) { + furi_string_free(dev_info_svc->version_string); + // Delete service characteristics + for(size_t i = 0; i < DevInfoSvcGattCharacteristicCount; i++) { + flipper_gatt_characteristic_deinit( + dev_info_svc->service_handle, &dev_info_svc->characteristics[i]); + } + // Delete service + status = aci_gatt_del_service(dev_info_svc->service_handle); + if(status) { + FURI_LOG_E(TAG, "Failed to delete device info service: %d", status); + } + free(dev_info_svc); + dev_info_svc = NULL; + } +} + +bool dev_info_svc_is_started() { + return dev_info_svc != NULL; +} diff --git a/firmware/targets/f7/ble_glue/dev_info_service.h b/firmware/targets/f7/ble_glue/services/dev_info_service.h similarity index 100% rename from firmware/targets/f7/ble_glue/dev_info_service.h rename to firmware/targets/f7/ble_glue/services/dev_info_service.h diff --git a/firmware/targets/f7/ble_glue/services/gatt_char.c b/firmware/targets/f7/ble_glue/services/gatt_char.c new file mode 100644 index 000000000000..d83d7c4f599d --- /dev/null +++ b/firmware/targets/f7/ble_glue/services/gatt_char.c @@ -0,0 +1,125 @@ +#include "gatt_char.h" + +#include + +#define TAG "BLE_CHAR" + +bool flipper_gatt_characteristic_props_const_char( + const void* context, + const uint8_t** data, + uint16_t* data_len) { + const char* str = (const char*)context; + *data = (const uint8_t*)str; + *data_len = strlen(str); + return false; +} + +void flipper_gatt_characteristic_init( + uint16_t svc_handle, + const FlipperGattCharacteristicParams* char_descriptor, + FlipperGattCharacteristicInstance* char_instance) { + furi_assert(char_descriptor); + furi_assert(char_instance); + + char_instance->characteristic = char_descriptor; + + uint8_t const* char_data = NULL; + uint16_t char_data_size = 0; + bool release_data = false; + if(char_descriptor->data_prop_type == FlipperGattCharacteristicDataPropsFixed) { + char_data = char_descriptor->data_prop.fixed.ptr; + char_data_size = char_descriptor->data_prop.fixed.length; + } else if(char_descriptor->data_prop_type == FlipperGattCharacteristicDataPropsCallback) { + release_data = char_descriptor->data_prop.callback.fn( + char_descriptor->data_prop.callback.context, &char_data, &char_data_size); + } + + tBleStatus status = aci_gatt_add_char( + svc_handle, + char_descriptor->uuid_type, + &char_descriptor->uuid, + char_data_size, + char_descriptor->properties, + char_descriptor->permissions, + char_descriptor->evt_mask, + 10, + char_descriptor->is_variable, + &char_instance->handle); + if(status) { + FURI_LOG_E(TAG, "Failed to add %s char: %d", char_descriptor->name, status); + } + if(release_data) { + free((void*)char_data); + } + + char_instance->descriptor_handle = 0; + if((status == 0) && char_descriptor->descriptor_params) { + const FlipperGattCharacteristicDescriptorParams* char_data_descriptor = + char_descriptor->descriptor_params; + release_data = char_data_descriptor->value_callback.fn( + char_data_descriptor->value_callback.context, &char_data, &char_data_size); + + status = aci_gatt_add_char_desc( + svc_handle, + char_instance->handle, + char_data_descriptor->uuid_type, + &char_data_descriptor->uuid, + char_data_descriptor->max_length, + char_data_size, + char_data, + char_data_descriptor->security_permissions, + char_data_descriptor->access_permissions, + char_data_descriptor->evt_mask, + 7, + char_data_descriptor->is_variable, + &char_instance->descriptor_handle); + if(status) { + FURI_LOG_E(TAG, "Failed to add %s char descriptor: %d", char_descriptor->name, status); + } + if(release_data) { + free((void*)char_data); + } + } +} + +void flipper_gatt_characteristic_deinit( + uint16_t svc_handle, + FlipperGattCharacteristicInstance* char_instance) { + tBleStatus status = aci_gatt_del_char(svc_handle, char_instance->handle); + if(status) { + FURI_LOG_E( + TAG, "Failed to delete %s char: %d", char_instance->characteristic->name, status); + } +} + +bool flipper_gatt_characteristic_update( + uint16_t svc_handle, + FlipperGattCharacteristicInstance* char_instance, + const void* source) { + furi_assert(char_instance); + const FlipperGattCharacteristicParams* char_descriptor = char_instance->characteristic; + FURI_LOG_D(TAG, "Updating %s char", char_descriptor->name); + + uint8_t const* char_data = NULL; + uint16_t char_data_size = 0; + if(char_descriptor->data_prop_type == FlipperGattCharacteristicDataPropsFixed) { + char_data = char_descriptor->data_prop.fixed.ptr; + if(source) { + char_data = (uint8_t*)source; + } + char_data_size = char_descriptor->data_prop.fixed.length; + } else if(char_descriptor->data_prop_type == FlipperGattCharacteristicDataPropsCallback) { + const void* context = char_descriptor->data_prop.callback.context; + if(source) { + context = source; + } + char_descriptor->data_prop.callback.fn(context, &char_data, &char_data_size); + } + + tBleStatus result = aci_gatt_update_char_value( + svc_handle, char_instance->handle, 0, char_data_size, char_data); + if(result) { + FURI_LOG_E(TAG, "Failed updating %s characteristic: %d", char_descriptor->name, result); + } + return result != BLE_STATUS_SUCCESS; +} \ No newline at end of file diff --git a/firmware/targets/f7/ble_glue/services/gatt_char.h b/firmware/targets/f7/ble_glue/services/gatt_char.h new file mode 100644 index 000000000000..cbba153bf405 --- /dev/null +++ b/firmware/targets/f7/ble_glue/services/gatt_char.h @@ -0,0 +1,86 @@ +#pragma once + +#include +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// returns true if you own the data pointer now and must free() it +typedef bool (*FlipperGattCharacteristicPropsCallback)( + const void* context, + const uint8_t** data, + uint16_t* data_len); + +typedef enum { + FlipperGattCharacteristicDataPropsFixed, + FlipperGattCharacteristicDataPropsCallback, +} FlipperGattCharacteristicDataType; + +typedef struct { + Char_Desc_Uuid_t uuid; + uint8_t uuid_type; + uint8_t max_length; + struct { + FlipperGattCharacteristicPropsCallback fn; + const void* context; + } value_callback; + uint8_t security_permissions; + uint8_t access_permissions; + uint8_t evt_mask; + uint8_t is_variable; +} FlipperGattCharacteristicDescriptorParams; + +typedef struct { + const char* name; + FlipperGattCharacteristicDescriptorParams* descriptor_params; + FlipperGattCharacteristicDataType data_prop_type; + union { + struct { + const uint8_t* ptr; + uint16_t length; + } fixed; + struct { + FlipperGattCharacteristicPropsCallback fn; + const void* context; + } callback; + } data_prop; + Char_UUID_t uuid; + uint8_t uuid_type; + uint8_t properties; + uint8_t permissions; + uint8_t evt_mask; + uint8_t is_variable; +} FlipperGattCharacteristicParams; + +typedef struct { + const FlipperGattCharacteristicParams* characteristic; + uint16_t handle; + uint16_t descriptor_handle; +} FlipperGattCharacteristicInstance; + +bool flipper_gatt_characteristic_props_const_char( + const void* context, + const uint8_t** data, + uint16_t* data_len); + +void flipper_gatt_characteristic_init( + uint16_t svc_handle, + const FlipperGattCharacteristicParams* char_descriptor, + FlipperGattCharacteristicInstance* char_instance); + +void flipper_gatt_characteristic_deinit( + uint16_t svc_handle, + FlipperGattCharacteristicInstance* char_instance); + +bool flipper_gatt_characteristic_update( + uint16_t svc_handle, + FlipperGattCharacteristicInstance* char_instance, + const void* source); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/firmware/targets/f7/ble_glue/services/hid_service.c b/firmware/targets/f7/ble_glue/services/hid_service.c new file mode 100644 index 000000000000..ab157ab591ef --- /dev/null +++ b/firmware/targets/f7/ble_glue/services/hid_service.c @@ -0,0 +1,274 @@ +#include "hid_service.h" +#include "app_common.h" +#include +#include "gatt_char.h" + +#include + +#define TAG "BtHid" + +typedef enum { + HidSvcGattCharacteristicProtocolMode = 0, + HidSvcGattCharacteristicReportMap, + HidSvcGattCharacteristicInfo, + HidSvcGattCharacteristicCtrlPoint, + HidSvcGattCharacteristicCount, +} HidSvcGattCharacteristicId; + +typedef struct { + uint8_t report_idx; + uint8_t report_type; +} HidSvcReportId; + +static_assert(sizeof(HidSvcReportId) == sizeof(uint16_t), "HidSvcReportId must be 2 bytes"); + +bool hid_svc_char_desc_data_callback(const void* context, const uint8_t** data, uint16_t* data_len) { + const HidSvcReportId* report_id = context; + *data = (const uint8_t*)report_id; + *data_len = sizeof(HidSvcReportId); + return false; +} + +static const FlipperGattCharacteristicParams hid_svc_chars[HidSvcGattCharacteristicCount] = { + [HidSvcGattCharacteristicProtocolMode] = + {.name = "Protocol Mode", + .data_prop_type = FlipperGattCharacteristicDataPropsFixed, + .data_prop.fixed.length = 1, + .uuid.Char_UUID_16 = PROTOCOL_MODE_CHAR_UUID, + .uuid_type = UUID_TYPE_16, + .properties = CHAR_PROP_READ | CHAR_PROP_WRITE_WITHOUT_RESP, + .permissions = ATTR_PERMISSION_NONE, + .evt_mask = GATT_NOTIFY_ATTRIBUTE_WRITE, + .is_variable = CHAR_VALUE_LEN_CONSTANT}, + [HidSvcGattCharacteristicReportMap] = + {.name = "Report Map", + .data_prop_type = FlipperGattCharacteristicDataPropsFixed, + .data_prop.fixed.length = HID_SVC_REPORT_MAP_MAX_LEN, + .uuid.Char_UUID_16 = REPORT_MAP_CHAR_UUID, + .uuid_type = UUID_TYPE_16, + .properties = CHAR_PROP_READ, + .permissions = ATTR_PERMISSION_NONE, + .evt_mask = GATT_DONT_NOTIFY_EVENTS, + .is_variable = CHAR_VALUE_LEN_VARIABLE}, + [HidSvcGattCharacteristicInfo] = + {.name = "HID Information", + .data_prop_type = FlipperGattCharacteristicDataPropsFixed, + .data_prop.fixed.length = HID_SVC_INFO_LEN, + .uuid.Char_UUID_16 = HID_INFORMATION_CHAR_UUID, + .uuid_type = UUID_TYPE_16, + .properties = CHAR_PROP_READ, + .permissions = ATTR_PERMISSION_NONE, + .evt_mask = GATT_DONT_NOTIFY_EVENTS, + .is_variable = CHAR_VALUE_LEN_CONSTANT}, + [HidSvcGattCharacteristicCtrlPoint] = + {.name = "HID Control Point", + .data_prop_type = FlipperGattCharacteristicDataPropsFixed, + .data_prop.fixed.length = HID_SVC_CONTROL_POINT_LEN, + .uuid.Char_UUID_16 = HID_CONTROL_POINT_CHAR_UUID, + .uuid_type = UUID_TYPE_16, + .properties = CHAR_PROP_WRITE_WITHOUT_RESP, + .permissions = ATTR_PERMISSION_NONE, + .evt_mask = GATT_NOTIFY_ATTRIBUTE_WRITE, + .is_variable = CHAR_VALUE_LEN_CONSTANT}, +}; + +static const FlipperGattCharacteristicDescriptorParams hid_svc_char_descr_template = { + .uuid_type = UUID_TYPE_16, + .uuid.Char_UUID_16 = REPORT_REFERENCE_DESCRIPTOR_UUID, + .max_length = HID_SVC_REPORT_REF_LEN, + .value_callback.fn = hid_svc_char_desc_data_callback, + .security_permissions = ATTR_PERMISSION_NONE, + .access_permissions = ATTR_ACCESS_READ_WRITE, + .evt_mask = GATT_DONT_NOTIFY_EVENTS, + .is_variable = CHAR_VALUE_LEN_CONSTANT, +}; + +static const FlipperGattCharacteristicParams hid_svc_report_template = { + .data_prop_type = FlipperGattCharacteristicDataPropsFixed, + .data_prop.fixed.length = HID_SVC_REPORT_MAX_LEN, + .uuid.Char_UUID_16 = REPORT_CHAR_UUID, + .uuid_type = UUID_TYPE_16, + .properties = CHAR_PROP_READ | CHAR_PROP_NOTIFY, + .permissions = ATTR_PERMISSION_NONE, + .evt_mask = GATT_DONT_NOTIFY_EVENTS, + .is_variable = CHAR_VALUE_LEN_VARIABLE, +}; + +typedef struct { + uint16_t svc_handle; + FlipperGattCharacteristicInstance chars[HidSvcGattCharacteristicCount]; + FlipperGattCharacteristicInstance input_report_chars[HID_SVC_INPUT_REPORT_COUNT]; + FlipperGattCharacteristicInstance output_report_chars[HID_SVC_OUTPUT_REPORT_COUNT]; + FlipperGattCharacteristicInstance feature_report_chars[HID_SVC_FEATURE_REPORT_COUNT]; +} HIDSvc; + +static HIDSvc* hid_svc = NULL; + +static SVCCTL_EvtAckStatus_t hid_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) { + // Process modification events + ret = SVCCTL_EvtAckFlowEnable; + } else if(blecore_evt->ecode == ACI_GATT_SERVER_CONFIRMATION_VSEVT_CODE) { + // Process notification confirmation + ret = SVCCTL_EvtAckFlowEnable; + } + } + return ret; +} + +void hid_svc_start() { + tBleStatus status; + hid_svc = malloc(sizeof(HIDSvc)); + Service_UUID_t svc_uuid = {}; + + // Register event handler + SVCCTL_RegisterSvcHandler(hid_svc_event_handler); + // Add service + svc_uuid.Service_UUID_16 = HUMAN_INTERFACE_DEVICE_SERVICE_UUID; + /** + * Add Human Interface Device Service + */ + status = aci_gatt_add_service( + UUID_TYPE_16, + &svc_uuid, + PRIMARY_SERVICE, + 2 + /* protocol mode */ + (4 * HID_SVC_INPUT_REPORT_COUNT) + (3 * HID_SVC_OUTPUT_REPORT_COUNT) + + (3 * HID_SVC_FEATURE_REPORT_COUNT) + 1 + 2 + 2 + + 2, /* Service + Report Map + HID Information + HID Control Point */ + &hid_svc->svc_handle); + if(status) { + FURI_LOG_E(TAG, "Failed to add HID service: %d", status); + } + + for(size_t i = 0; i < HidSvcGattCharacteristicCount; i++) { + flipper_gatt_characteristic_init( + hid_svc->svc_handle, &hid_svc_chars[i], &hid_svc->chars[i]); + } + uint8_t protocol_mode = 1; + flipper_gatt_characteristic_update( + hid_svc->svc_handle, + &hid_svc->chars[HidSvcGattCharacteristicProtocolMode], + &protocol_mode); + + // reports + FlipperGattCharacteristicDescriptorParams hid_svc_char_descr; + FlipperGattCharacteristicParams report_char; + HidSvcReportId report_id; + + memcpy(&hid_svc_char_descr, &hid_svc_char_descr_template, sizeof(hid_svc_char_descr)); + memcpy(&report_char, &hid_svc_report_template, sizeof(report_char)); + + hid_svc_char_descr.value_callback.context = &report_id; + report_char.descriptor_params = &hid_svc_char_descr; + + typedef struct { + uint8_t report_type; + uint8_t report_count; + FlipperGattCharacteristicInstance* chars; + } HidSvcReportCharProps; + + HidSvcReportCharProps hid_report_chars[] = { + {0x01, HID_SVC_INPUT_REPORT_COUNT, hid_svc->input_report_chars}, + {0x02, HID_SVC_OUTPUT_REPORT_COUNT, hid_svc->output_report_chars}, + {0x03, HID_SVC_FEATURE_REPORT_COUNT, hid_svc->feature_report_chars}, + }; + + for(size_t i = 0; i < COUNT_OF(hid_report_chars); i++) { + report_id.report_type = hid_report_chars[i].report_type; + for(size_t j = 0; j < hid_report_chars[i].report_count; j++) { + report_id.report_idx = j + 1; + flipper_gatt_characteristic_init( + hid_svc->svc_handle, &report_char, &hid_report_chars[i].chars[j]); + } + } +} + +bool hid_svc_update_report_map(const uint8_t* data, uint16_t len) { + furi_assert(data); + furi_assert(hid_svc); + + tBleStatus status = aci_gatt_update_char_value( + hid_svc->svc_handle, + hid_svc->chars[HidSvcGattCharacteristicReportMap].handle, + 0, + len, + data); + if(status) { + FURI_LOG_E(TAG, "Failed updating report map characteristic: %d", status); + return false; + } + return true; +} + +bool hid_svc_update_input_report(uint8_t input_report_num, uint8_t* data, uint16_t len) { + furi_assert(data); + furi_assert(hid_svc); + furi_check(input_report_num < HID_SVC_INPUT_REPORT_COUNT); + + tBleStatus status = aci_gatt_update_char_value( + hid_svc->svc_handle, hid_svc->input_report_chars[input_report_num].handle, 0, len, data); + if(status) { + FURI_LOG_E(TAG, "Failed updating report characteristic: %d", status); + return false; + } + return true; +} + +bool hid_svc_update_info(uint8_t* data, uint16_t len) { + furi_assert(data); + furi_assert(hid_svc); + + tBleStatus status = aci_gatt_update_char_value( + hid_svc->svc_handle, hid_svc->chars[HidSvcGattCharacteristicInfo].handle, 0, len, data); + if(status) { + FURI_LOG_E(TAG, "Failed updating info characteristic: %d", status); + return false; + } + return true; +} + +bool hid_svc_is_started() { + return hid_svc != NULL; +} + +void hid_svc_stop() { + tBleStatus status; + if(hid_svc) { + // Delete characteristics + for(size_t i = 0; i < HidSvcGattCharacteristicCount; i++) { + flipper_gatt_characteristic_deinit(hid_svc->svc_handle, &hid_svc->chars[i]); + } + + typedef struct { + uint8_t report_count; + FlipperGattCharacteristicInstance* chars; + } HidSvcReportCharProps; + + HidSvcReportCharProps hid_report_chars[] = { + {HID_SVC_INPUT_REPORT_COUNT, hid_svc->input_report_chars}, + {HID_SVC_OUTPUT_REPORT_COUNT, hid_svc->output_report_chars}, + {HID_SVC_FEATURE_REPORT_COUNT, hid_svc->feature_report_chars}, + }; + + for(size_t i = 0; i < COUNT_OF(hid_report_chars); i++) { + for(size_t j = 0; j < hid_report_chars[i].report_count; j++) { + flipper_gatt_characteristic_deinit( + hid_svc->svc_handle, &hid_report_chars[i].chars[j]); + } + } + + // Delete service + status = aci_gatt_del_service(hid_svc->svc_handle); + if(status) { + FURI_LOG_E(TAG, "Failed to delete HID service: %d", status); + } + free(hid_svc); + hid_svc = NULL; + } +} diff --git a/firmware/targets/f7/ble_glue/hid_service.h b/firmware/targets/f7/ble_glue/services/hid_service.h similarity index 100% rename from firmware/targets/f7/ble_glue/hid_service.h rename to firmware/targets/f7/ble_glue/services/hid_service.h diff --git a/firmware/targets/f7/ble_glue/serial_service.c b/firmware/targets/f7/ble_glue/services/serial_service.c similarity index 57% rename from firmware/targets/f7/ble_glue/serial_service.c rename to firmware/targets/f7/ble_glue/services/serial_service.c index c6421dc28fee..713114052170 100644 --- a/firmware/targets/f7/ble_glue/serial_service.c +++ b/firmware/targets/f7/ble_glue/services/serial_service.c @@ -1,17 +1,129 @@ #include "serial_service.h" #include "app_common.h" #include +#include "gatt_char.h" #include #define TAG "BtSerialSvc" +typedef enum { + SerialSvcGattCharacteristicTx = 0, + SerialSvcGattCharacteristicRx, + SerialSvcGattCharacteristicFlowCtrl, + SerialSvcGattCharacteristicStatus, + SerialSvcGattCharacteristicCount, +} SerialSvcGattCharacteristicId; + +static const FlipperGattCharacteristicParams serial_svc_chars[SerialSvcGattCharacteristicCount] = { + [SerialSvcGattCharacteristicTx] = + {.name = "TX", + .data_prop_type = FlipperGattCharacteristicDataPropsFixed, + .data_prop.fixed.length = SERIAL_SVC_DATA_LEN_MAX, + .uuid.Char_UUID_128 = + {0x00, + 0x00, + 0xfe, + 0x61, + 0x8e, + 0x22, + 0x45, + 0x41, + 0x9d, + 0x4c, + 0x21, + 0xed, + 0xae, + 0x82, + 0xed, + 0x19}, + .uuid_type = UUID_TYPE_128, + .properties = CHAR_PROP_READ | CHAR_PROP_INDICATE, + .permissions = ATTR_PERMISSION_AUTHEN_READ, + .evt_mask = GATT_DONT_NOTIFY_EVENTS, + .is_variable = CHAR_VALUE_LEN_VARIABLE}, + [SerialSvcGattCharacteristicRx] = + {.name = "RX", + .data_prop_type = FlipperGattCharacteristicDataPropsFixed, + .data_prop.fixed.length = SERIAL_SVC_DATA_LEN_MAX, + .uuid.Char_UUID_128 = + {0x00, + 0x00, + 0xfe, + 0x62, + 0x8e, + 0x22, + 0x45, + 0x41, + 0x9d, + 0x4c, + 0x21, + 0xed, + 0xae, + 0x82, + 0xed, + 0x19}, + .uuid_type = UUID_TYPE_128, + .properties = CHAR_PROP_WRITE_WITHOUT_RESP | CHAR_PROP_WRITE | CHAR_PROP_READ, + .permissions = ATTR_PERMISSION_AUTHEN_READ | ATTR_PERMISSION_AUTHEN_WRITE, + .evt_mask = GATT_NOTIFY_ATTRIBUTE_WRITE, + .is_variable = CHAR_VALUE_LEN_VARIABLE}, + [SerialSvcGattCharacteristicFlowCtrl] = + {.name = "Flow control", + .data_prop_type = FlipperGattCharacteristicDataPropsFixed, + .data_prop.fixed.length = sizeof(uint32_t), + .uuid.Char_UUID_128 = + {0x00, + 0x00, + 0xfe, + 0x63, + 0x8e, + 0x22, + 0x45, + 0x41, + 0x9d, + 0x4c, + 0x21, + 0xed, + 0xae, + 0x82, + 0xed, + 0x19}, + .uuid_type = UUID_TYPE_128, + .properties = CHAR_PROP_READ | CHAR_PROP_NOTIFY, + .permissions = ATTR_PERMISSION_AUTHEN_READ, + .evt_mask = GATT_DONT_NOTIFY_EVENTS, + .is_variable = CHAR_VALUE_LEN_CONSTANT}, + [SerialSvcGattCharacteristicStatus] = { + .name = "RPC status", + .data_prop_type = FlipperGattCharacteristicDataPropsFixed, + .data_prop.fixed.length = sizeof(SerialServiceRpcStatus), + .uuid.Char_UUID_128 = + {0x00, + 0x00, + 0xfe, + 0x64, + 0x8e, + 0x22, + 0x45, + 0x41, + 0x9d, + 0x4c, + 0x21, + 0xed, + 0xae, + 0x82, + 0xed, + 0x19}, + .uuid_type = UUID_TYPE_128, + .properties = CHAR_PROP_READ | CHAR_PROP_WRITE | CHAR_PROP_NOTIFY, + .permissions = ATTR_PERMISSION_AUTHEN_READ | ATTR_PERMISSION_AUTHEN_WRITE, + .evt_mask = GATT_NOTIFY_ATTRIBUTE_WRITE, + .is_variable = CHAR_VALUE_LEN_CONSTANT}}; + typedef struct { uint16_t svc_handle; - uint16_t rx_char_handle; - uint16_t tx_char_handle; - uint16_t flow_ctrl_char_handle; - uint16_t rpc_status_char_handle; + FlipperGattCharacteristicInstance chars[SerialSvcGattCharacteristicCount]; FuriMutex* buff_size_mtx; uint32_t buff_size; uint16_t bytes_ready_to_receive; @@ -19,18 +131,10 @@ typedef struct { void* context; } SerialSvc; -static SerialSvc* serial_svc = NULL; - static const uint8_t service_uuid[] = {0x00, 0x00, 0xfe, 0x60, 0xcc, 0x7a, 0x48, 0x2a, 0x98, 0x4a, 0x7f, 0x2e, 0xd5, 0xb3, 0xe5, 0x8f}; -static const uint8_t char_tx_uuid[] = - {0x00, 0x00, 0xfe, 0x61, 0x8e, 0x22, 0x45, 0x41, 0x9d, 0x4c, 0x21, 0xed, 0xae, 0x82, 0xed, 0x19}; -static const uint8_t char_rx_uuid[] = - {0x00, 0x00, 0xfe, 0x62, 0x8e, 0x22, 0x45, 0x41, 0x9d, 0x4c, 0x21, 0xed, 0xae, 0x82, 0xed, 0x19}; -static const uint8_t flow_ctrl_uuid[] = - {0x00, 0x00, 0xfe, 0x63, 0x8e, 0x22, 0x45, 0x41, 0x9d, 0x4c, 0x21, 0xed, 0xae, 0x82, 0xed, 0x19}; -static const uint8_t rpc_status_uuid[] = - {0x00, 0x00, 0xfe, 0x64, 0x8e, 0x22, 0x45, 0x41, 0x9d, 0x4c, 0x21, 0xed, 0xae, 0x82, 0xed, 0x19}; + +static SerialSvc* serial_svc = NULL; static SVCCTL_EvtAckStatus_t serial_svc_event_handler(void* event) { SVCCTL_EvtAckStatus_t ret = SVCCTL_EvtNotAck; @@ -40,11 +144,14 @@ static SVCCTL_EvtAckStatus_t serial_svc_event_handler(void* event) { 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->rx_char_handle + 2) { + if(attribute_modified->Attr_Handle == + serial_svc->chars[SerialSvcGattCharacteristicRx].handle + 2) { // Descriptor handle ret = SVCCTL_EvtAckFlowEnable; FURI_LOG_D(TAG, "RX descriptor event"); - } else if(attribute_modified->Attr_Handle == serial_svc->rx_char_handle + 1) { + } else if( + attribute_modified->Attr_Handle == + serial_svc->chars[SerialSvcGattCharacteristicRx].handle + 1) { FURI_LOG_D(TAG, "Received %d bytes", attribute_modified->Attr_Data_Length); if(serial_svc->callback) { furi_check( @@ -70,7 +177,9 @@ static SVCCTL_EvtAckStatus_t serial_svc_event_handler(void* event) { furi_check(furi_mutex_release(serial_svc->buff_size_mtx) == FuriStatusOk); } ret = SVCCTL_EvtAckFlowEnable; - } else if(attribute_modified->Attr_Handle == serial_svc->rpc_status_char_handle + 1) { + } else if( + attribute_modified->Attr_Handle == + serial_svc->chars[SerialSvcGattCharacteristicStatus].handle + 1) { SerialServiceRpcStatus* rpc_status = (SerialServiceRpcStatus*)attribute_modified->Attr_Data; if(*rpc_status == SerialServiceRpcStatusNotActive) { @@ -97,18 +206,12 @@ static SVCCTL_EvtAckStatus_t serial_svc_event_handler(void* event) { } static void serial_svc_update_rpc_char(SerialServiceRpcStatus status) { - tBleStatus ble_status = aci_gatt_update_char_value( - serial_svc->svc_handle, - serial_svc->rpc_status_char_handle, - 0, - sizeof(SerialServiceRpcStatus), - (uint8_t*)&status); - if(ble_status) { - FURI_LOG_E(TAG, "Failed to update RPC status char: %d", ble_status); - } + flipper_gatt_characteristic_update( + serial_svc->svc_handle, &serial_svc->chars[SerialSvcGattCharacteristicStatus], &status); } void serial_svc_start() { + UNUSED(serial_svc_chars); tBleStatus status; serial_svc = malloc(sizeof(SerialSvc)); // Register event handler @@ -121,67 +224,12 @@ void serial_svc_start() { FURI_LOG_E(TAG, "Failed to add Serial service: %d", status); } - // Add RX characteristics - 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_WRITE_WITHOUT_RESP | CHAR_PROP_WRITE | CHAR_PROP_READ, - ATTR_PERMISSION_AUTHEN_READ | ATTR_PERMISSION_AUTHEN_WRITE, - GATT_NOTIFY_ATTRIBUTE_WRITE, - 10, - CHAR_VALUE_LEN_VARIABLE, - &serial_svc->rx_char_handle); - if(status) { - FURI_LOG_E(TAG, "Failed to add RX characteristic: %d", status); + // Add characteristics + for(uint8_t i = 0; i < SerialSvcGattCharacteristicCount; i++) { + flipper_gatt_characteristic_init( + serial_svc->svc_handle, &serial_svc_chars[i], &serial_svc->chars[i]); } - // Add TX characteristic - 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_READ | CHAR_PROP_INDICATE, - ATTR_PERMISSION_AUTHEN_READ, - GATT_DONT_NOTIFY_EVENTS, - 10, - CHAR_VALUE_LEN_VARIABLE, - &serial_svc->tx_char_handle); - if(status) { - FURI_LOG_E(TAG, "Failed to add TX characteristic: %d", status); - } - // Add Flow Control characteristic - status = aci_gatt_add_char( - serial_svc->svc_handle, - UUID_TYPE_128, - (const Char_UUID_t*)flow_ctrl_uuid, - sizeof(uint32_t), - CHAR_PROP_READ | CHAR_PROP_NOTIFY, - ATTR_PERMISSION_AUTHEN_READ, - GATT_DONT_NOTIFY_EVENTS, - 10, - CHAR_VALUE_LEN_CONSTANT, - &serial_svc->flow_ctrl_char_handle); - if(status) { - FURI_LOG_E(TAG, "Failed to add Flow Control characteristic: %d", status); - } - // Add RPC status characteristic - status = aci_gatt_add_char( - serial_svc->svc_handle, - UUID_TYPE_128, - (const Char_UUID_t*)rpc_status_uuid, - sizeof(SerialServiceRpcStatus), - CHAR_PROP_READ | CHAR_PROP_WRITE | CHAR_PROP_NOTIFY, - ATTR_PERMISSION_AUTHEN_READ | ATTR_PERMISSION_AUTHEN_WRITE, - GATT_NOTIFY_ATTRIBUTE_WRITE, - 10, - CHAR_VALUE_LEN_CONSTANT, - &serial_svc->rpc_status_char_handle); - if(status) { - FURI_LOG_E(TAG, "Failed to add RPC status characteristic: %d", status); - } serial_svc_update_rpc_char(SerialServiceRpcStatusNotActive); // Allocate buffer size mutex serial_svc->buff_size_mtx = furi_mutex_alloc(FuriMutexTypeNormal); @@ -196,13 +244,12 @@ void serial_svc_set_callbacks( serial_svc->context = context; serial_svc->buff_size = buff_size; serial_svc->bytes_ready_to_receive = buff_size; + uint32_t buff_size_reversed = REVERSE_BYTES_U32(serial_svc->buff_size); - aci_gatt_update_char_value( + flipper_gatt_characteristic_update( serial_svc->svc_handle, - serial_svc->flow_ctrl_char_handle, - 0, - sizeof(uint32_t), - (uint8_t*)&buff_size_reversed); + &serial_svc->chars[SerialSvcGattCharacteristicFlowCtrl], + &buff_size_reversed); } void serial_svc_notify_buffer_is_empty() { @@ -213,13 +260,12 @@ void serial_svc_notify_buffer_is_empty() { if(serial_svc->bytes_ready_to_receive == 0) { FURI_LOG_D(TAG, "Buffer is empty. Notifying client"); serial_svc->bytes_ready_to_receive = serial_svc->buff_size; + uint32_t buff_size_reversed = REVERSE_BYTES_U32(serial_svc->buff_size); - aci_gatt_update_char_value( + flipper_gatt_characteristic_update( serial_svc->svc_handle, - serial_svc->flow_ctrl_char_handle, - 0, - sizeof(uint32_t), - (uint8_t*)&buff_size_reversed); + &serial_svc->chars[SerialSvcGattCharacteristicFlowCtrl], + &buff_size_reversed); } furi_check(furi_mutex_release(serial_svc->buff_size_mtx) == FuriStatusOk); } @@ -227,22 +273,8 @@ void serial_svc_notify_buffer_is_empty() { void serial_svc_stop() { tBleStatus status; if(serial_svc) { - // Delete characteristics - status = aci_gatt_del_char(serial_svc->svc_handle, serial_svc->tx_char_handle); - if(status) { - FURI_LOG_E(TAG, "Failed to delete TX characteristic: %d", status); - } - status = aci_gatt_del_char(serial_svc->svc_handle, serial_svc->rx_char_handle); - if(status) { - FURI_LOG_E(TAG, "Failed to delete RX characteristic: %d", status); - } - status = aci_gatt_del_char(serial_svc->svc_handle, serial_svc->flow_ctrl_char_handle); - if(status) { - FURI_LOG_E(TAG, "Failed to delete Flow Control characteristic: %d", status); - } - status = aci_gatt_del_char(serial_svc->svc_handle, serial_svc->rpc_status_char_handle); - if(status) { - FURI_LOG_E(TAG, "Failed to delete RPC Status characteristic: %d", status); + for(uint8_t i = 0; i < SerialSvcGattCharacteristicCount; i++) { + flipper_gatt_characteristic_deinit(serial_svc->svc_handle, &serial_svc->chars[i]); } // Delete service status = aci_gatt_del_service(serial_svc->svc_handle); @@ -273,7 +305,7 @@ bool serial_svc_update_tx(uint8_t* data, uint16_t data_len) { tBleStatus result = aci_gatt_update_char_value_ext( 0, serial_svc->svc_handle, - serial_svc->tx_char_handle, + serial_svc->chars[SerialSvcGattCharacteristicTx].handle, remained ? 0x00 : 0x02, data_len, value_offset, diff --git a/firmware/targets/f7/ble_glue/serial_service.h b/firmware/targets/f7/ble_glue/services/serial_service.h similarity index 100% rename from firmware/targets/f7/ble_glue/serial_service.h rename to firmware/targets/f7/ble_glue/services/serial_service.h diff --git a/firmware/targets/f7/furi_hal/furi_hal_bt.c b/firmware/targets/f7/furi_hal/furi_hal_bt.c index 0857fe4ee56b..6be4b3964f18 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_bt.c +++ b/firmware/targets/f7/furi_hal/furi_hal_bt.c @@ -7,7 +7,7 @@ #include #include #include -#include "battery_service.h" +#include #include diff --git a/firmware/targets/f7/furi_hal/furi_hal_bt_hid.c b/firmware/targets/f7/furi_hal/furi_hal_bt_hid.c index 8259be2f6cd1..78283700beee 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_bt_hid.c +++ b/firmware/targets/f7/furi_hal/furi_hal_bt_hid.c @@ -1,11 +1,11 @@ #include #include -#include "usb_hid.h" -#include "dev_info_service.h" -#include "battery_service.h" -#include "hid_service.h" +#include +#include +#include #include +#include #define FURI_HAL_BT_INFO_BASE_USB_SPECIFICATION (0x0101) #define FURI_HAL_BT_INFO_COUNTRY_CODE (0x00) diff --git a/firmware/targets/f7/furi_hal/furi_hal_bt_serial.c b/firmware/targets/f7/furi_hal/furi_hal_bt_serial.c index 2539e6bd0e90..2927d946f980 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_bt_serial.c +++ b/firmware/targets/f7/furi_hal/furi_hal_bt_serial.c @@ -1,7 +1,7 @@ #include -#include "dev_info_service.h" -#include "battery_service.h" -#include "serial_service.h" +#include +#include +#include #include diff --git a/firmware/targets/furi_hal_include/furi_hal_bt.h b/firmware/targets/furi_hal_include/furi_hal_bt.h index 196b2edb3ad0..5f863ab2cebb 100644 --- a/firmware/targets/furi_hal_include/furi_hal_bt.h +++ b/firmware/targets/furi_hal_include/furi_hal_bt.h @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include #include diff --git a/firmware/targets/furi_hal_include/furi_hal_bt_serial.h b/firmware/targets/furi_hal_include/furi_hal_bt_serial.h index 1b6e79ab0785..0472d31d1815 100644 --- a/firmware/targets/furi_hal_include/furi_hal_bt_serial.h +++ b/firmware/targets/furi_hal_include/furi_hal_bt_serial.h @@ -1,6 +1,6 @@ #pragma once -#include "serial_service.h" +#include #ifdef __cplusplus extern "C" { diff --git a/site_scons/extapps.scons b/site_scons/extapps.scons index 89ee492429fc..2b590f617200 100644 --- a/site_scons/extapps.scons +++ b/site_scons/extapps.scons @@ -2,7 +2,6 @@ from dataclasses import dataclass, field from SCons.Node import NodeList from SCons.Warnings import warn, WarningOnByDefault -from SCons.Errors import UserError Import("ENV") From 24b1e231a9c1e58fa90c5a443693f1c688010ae3 Mon Sep 17 00:00:00 2001 From: hedger Date: Sat, 15 Apr 2023 06:19:36 +0400 Subject: [PATCH 02/14] ble: naming fixes, small optimizations --- .../f7/ble_glue/services/battery_service.c | 14 ++++---- .../f7/ble_glue/services/dev_info_service.c | 32 ++++++++--------- .../targets/f7/ble_glue/services/gatt_char.c | 12 +++---- .../targets/f7/ble_glue/services/gatt_char.h | 26 ++++++++------ .../f7/ble_glue/services/hid_service.c | 36 +++++++++---------- .../f7/ble_glue/services/serial_service.c | 26 +++++++------- 6 files changed, 76 insertions(+), 70 deletions(-) diff --git a/firmware/targets/f7/ble_glue/services/battery_service.c b/firmware/targets/f7/ble_glue/services/battery_service.c index 37770be97eab..aac14ed3b1ea 100644 --- a/firmware/targets/f7/ble_glue/services/battery_service.c +++ b/firmware/targets/f7/ble_glue/services/battery_service.c @@ -53,9 +53,9 @@ static const FlipperGattCharacteristicParams battery_svc_chars[BatterySvcGattCha .data_prop.fixed.length = 1, .uuid.Char_UUID_16 = BATTERY_LEVEL_CHAR_UUID, .uuid_type = UUID_TYPE_16, - .properties = CHAR_PROP_READ | CHAR_PROP_NOTIFY, - .permissions = ATTR_PERMISSION_AUTHEN_READ, - .evt_mask = GATT_DONT_NOTIFY_EVENTS, + .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", @@ -63,9 +63,9 @@ static const FlipperGattCharacteristicParams battery_svc_chars[BatterySvcGattCha .data_prop.fixed.length = 1, .uuid.Char_UUID_16 = BATTERY_POWER_STATE, .uuid_type = UUID_TYPE_16, - .properties = CHAR_PROP_READ | CHAR_PROP_NOTIFY, - .permissions = ATTR_PERMISSION_AUTHEN_READ, - .evt_mask = GATT_DONT_NOTIFY_EVENTS, + .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 { @@ -97,7 +97,7 @@ void battery_svc_stop() { tBleStatus status; if(battery_svc) { for(size_t i = 0; i < BatterySvcGattCharacteristicCount; i++) { - flipper_gatt_characteristic_deinit(battery_svc->svc_handle, &battery_svc->chars[i]); + flipper_gatt_characteristic_delete(battery_svc->svc_handle, &battery_svc->chars[i]); } // Delete Battery service status = aci_gatt_del_service(battery_svc->svc_handle); diff --git a/firmware/targets/f7/ble_glue/services/dev_info_service.c b/firmware/targets/f7/ble_glue/services/dev_info_service.c index 26611b14d355..607c40998d0b 100644 --- a/firmware/targets/f7/ble_glue/services/dev_info_service.c +++ b/firmware/targets/f7/ble_glue/services/dev_info_service.c @@ -59,9 +59,9 @@ static const FlipperGattCharacteristicParams dev_info_svc_chars[DevInfoSvcGattCh .data_prop.callback.fn = flipper_gatt_characteristic_props_const_char, .uuid.Char_UUID_16 = MANUFACTURER_NAME_UUID, .uuid_type = UUID_TYPE_16, - .properties = CHAR_PROP_READ, - .permissions = ATTR_PERMISSION_AUTHEN_READ, - .evt_mask = GATT_DONT_NOTIFY_EVENTS, + .char_properties = CHAR_PROP_READ, + .security_permissions = ATTR_PERMISSION_AUTHEN_READ, + .gatt_evt_mask = GATT_DONT_NOTIFY_EVENTS, .is_variable = CHAR_VALUE_LEN_CONSTANT}, [DevInfoSvcGattCharacteristicSerial] = {.name = "Serial Number", @@ -70,9 +70,9 @@ static const FlipperGattCharacteristicParams dev_info_svc_chars[DevInfoSvcGattCh .data_prop.callback.fn = flipper_gatt_characteristic_props_const_char, .uuid.Char_UUID_16 = SERIAL_NUMBER_UUID, .uuid_type = UUID_TYPE_16, - .properties = CHAR_PROP_READ, - .permissions = ATTR_PERMISSION_AUTHEN_READ, - .evt_mask = GATT_DONT_NOTIFY_EVENTS, + .char_properties = CHAR_PROP_READ, + .security_permissions = ATTR_PERMISSION_AUTHEN_READ, + .gatt_evt_mask = GATT_DONT_NOTIFY_EVENTS, .is_variable = CHAR_VALUE_LEN_CONSTANT}, [DevInfoSvcGattCharacteristicFirmwareRev] = {.name = "Firmware Revision", @@ -81,9 +81,9 @@ static const FlipperGattCharacteristicParams dev_info_svc_chars[DevInfoSvcGattCh .data_prop.callback.fn = dev_info_char_firmware_rev_callback, .uuid.Char_UUID_16 = FIRMWARE_REVISION_UUID, .uuid_type = UUID_TYPE_16, - .properties = CHAR_PROP_READ, - .permissions = ATTR_PERMISSION_AUTHEN_READ, - .evt_mask = GATT_DONT_NOTIFY_EVENTS, + .char_properties = CHAR_PROP_READ, + .security_permissions = ATTR_PERMISSION_AUTHEN_READ, + .gatt_evt_mask = GATT_DONT_NOTIFY_EVENTS, .is_variable = CHAR_VALUE_LEN_CONSTANT}, [DevInfoSvcGattCharacteristicSoftwareRev] = {.name = "Software Revision", @@ -92,9 +92,9 @@ static const FlipperGattCharacteristicParams dev_info_svc_chars[DevInfoSvcGattCh .data_prop.callback.fn = dev_info_char_software_rev_callback, .uuid.Char_UUID_16 = SOFTWARE_REVISION_UUID, .uuid_type = UUID_TYPE_16, - .properties = CHAR_PROP_READ, - .permissions = ATTR_PERMISSION_AUTHEN_READ, - .evt_mask = GATT_DONT_NOTIFY_EVENTS, + .char_properties = CHAR_PROP_READ, + .security_permissions = ATTR_PERMISSION_AUTHEN_READ, + .gatt_evt_mask = GATT_DONT_NOTIFY_EVENTS, .is_variable = CHAR_VALUE_LEN_CONSTANT}, [DevInfoSvcGattCharacteristicRpcVersion] = { .name = "RPC Version", @@ -119,9 +119,9 @@ static const FlipperGattCharacteristicParams dev_info_svc_chars[DevInfoSvcGattCh 0xf6, 0x03}, .uuid_type = UUID_TYPE_128, - .properties = CHAR_PROP_READ, - .permissions = ATTR_PERMISSION_AUTHEN_READ, - .evt_mask = GATT_DONT_NOTIFY_EVENTS, + .char_properties = CHAR_PROP_READ, + .security_permissions = ATTR_PERMISSION_AUTHEN_READ, + .gatt_evt_mask = GATT_DONT_NOTIFY_EVENTS, .is_variable = CHAR_VALUE_LEN_CONSTANT}}; void dev_info_svc_start() { @@ -167,7 +167,7 @@ void dev_info_svc_stop() { furi_string_free(dev_info_svc->version_string); // Delete service characteristics for(size_t i = 0; i < DevInfoSvcGattCharacteristicCount; i++) { - flipper_gatt_characteristic_deinit( + flipper_gatt_characteristic_delete( dev_info_svc->service_handle, &dev_info_svc->characteristics[i]); } // Delete service diff --git a/firmware/targets/f7/ble_glue/services/gatt_char.c b/firmware/targets/f7/ble_glue/services/gatt_char.c index d83d7c4f599d..293a2c31b792 100644 --- a/firmware/targets/f7/ble_glue/services/gatt_char.c +++ b/firmware/targets/f7/ble_glue/services/gatt_char.c @@ -10,7 +10,7 @@ bool flipper_gatt_characteristic_props_const_char( uint16_t* data_len) { const char* str = (const char*)context; *data = (const uint8_t*)str; - *data_len = strlen(str); + *data_len = (uint16_t)strlen(str); return false; } @@ -39,9 +39,9 @@ void flipper_gatt_characteristic_init( char_descriptor->uuid_type, &char_descriptor->uuid, char_data_size, - char_descriptor->properties, - char_descriptor->permissions, - char_descriptor->evt_mask, + char_descriptor->char_properties, + char_descriptor->security_permissions, + char_descriptor->gatt_evt_mask, 10, char_descriptor->is_variable, &char_instance->handle); @@ -69,7 +69,7 @@ void flipper_gatt_characteristic_init( char_data, char_data_descriptor->security_permissions, char_data_descriptor->access_permissions, - char_data_descriptor->evt_mask, + char_data_descriptor->gatt_evt_mask, 7, char_data_descriptor->is_variable, &char_instance->descriptor_handle); @@ -82,7 +82,7 @@ void flipper_gatt_characteristic_init( } } -void flipper_gatt_characteristic_deinit( +void flipper_gatt_characteristic_delete( uint16_t svc_handle, FlipperGattCharacteristicInstance* char_instance) { tBleStatus status = aci_gatt_del_char(svc_handle, char_instance->handle); diff --git a/firmware/targets/f7/ble_glue/services/gatt_char.h b/firmware/targets/f7/ble_glue/services/gatt_char.h index cbba153bf405..a79bfaa7ce57 100644 --- a/firmware/targets/f7/ble_glue/services/gatt_char.h +++ b/firmware/targets/f7/ble_glue/services/gatt_char.h @@ -2,6 +2,7 @@ #include #include +#include #include @@ -22,22 +23,21 @@ typedef enum { typedef struct { Char_Desc_Uuid_t uuid; - uint8_t uuid_type; - uint8_t max_length; struct { FlipperGattCharacteristicPropsCallback fn; const void* context; } value_callback; + uint8_t uuid_type; + uint8_t max_length; uint8_t security_permissions; uint8_t access_permissions; - uint8_t evt_mask; + uint8_t gatt_evt_mask; uint8_t is_variable; } FlipperGattCharacteristicDescriptorParams; typedef struct { const char* name; FlipperGattCharacteristicDescriptorParams* descriptor_params; - FlipperGattCharacteristicDataType data_prop_type; union { struct { const uint8_t* ptr; @@ -49,13 +49,19 @@ typedef struct { } callback; } data_prop; Char_UUID_t uuid; - uint8_t uuid_type; - uint8_t properties; - uint8_t permissions; - uint8_t evt_mask; - uint8_t is_variable; + // Some packed bitfields to save space + FlipperGattCharacteristicDataType data_prop_type : 1; + uint8_t is_variable : 1; + uint8_t uuid_type : 2; + uint8_t char_properties; + uint8_t security_permissions; + uint8_t gatt_evt_mask; } FlipperGattCharacteristicParams; +_Static_assert( + sizeof(FlipperGattCharacteristicParams) == 36, + "FlipperGattCharacteristicParams size must be 36 bytes"); + typedef struct { const FlipperGattCharacteristicParams* characteristic; uint16_t handle; @@ -72,7 +78,7 @@ void flipper_gatt_characteristic_init( const FlipperGattCharacteristicParams* char_descriptor, FlipperGattCharacteristicInstance* char_instance); -void flipper_gatt_characteristic_deinit( +void flipper_gatt_characteristic_delete( uint16_t svc_handle, FlipperGattCharacteristicInstance* char_instance); diff --git a/firmware/targets/f7/ble_glue/services/hid_service.c b/firmware/targets/f7/ble_glue/services/hid_service.c index ab157ab591ef..964803052b4a 100644 --- a/firmware/targets/f7/ble_glue/services/hid_service.c +++ b/firmware/targets/f7/ble_glue/services/hid_service.c @@ -36,9 +36,9 @@ static const FlipperGattCharacteristicParams hid_svc_chars[HidSvcGattCharacteris .data_prop.fixed.length = 1, .uuid.Char_UUID_16 = PROTOCOL_MODE_CHAR_UUID, .uuid_type = UUID_TYPE_16, - .properties = CHAR_PROP_READ | CHAR_PROP_WRITE_WITHOUT_RESP, - .permissions = ATTR_PERMISSION_NONE, - .evt_mask = GATT_NOTIFY_ATTRIBUTE_WRITE, + .char_properties = CHAR_PROP_READ | CHAR_PROP_WRITE_WITHOUT_RESP, + .security_permissions = ATTR_PERMISSION_NONE, + .gatt_evt_mask = GATT_NOTIFY_ATTRIBUTE_WRITE, .is_variable = CHAR_VALUE_LEN_CONSTANT}, [HidSvcGattCharacteristicReportMap] = {.name = "Report Map", @@ -46,9 +46,9 @@ static const FlipperGattCharacteristicParams hid_svc_chars[HidSvcGattCharacteris .data_prop.fixed.length = HID_SVC_REPORT_MAP_MAX_LEN, .uuid.Char_UUID_16 = REPORT_MAP_CHAR_UUID, .uuid_type = UUID_TYPE_16, - .properties = CHAR_PROP_READ, - .permissions = ATTR_PERMISSION_NONE, - .evt_mask = GATT_DONT_NOTIFY_EVENTS, + .char_properties = CHAR_PROP_READ, + .security_permissions = ATTR_PERMISSION_NONE, + .gatt_evt_mask = GATT_DONT_NOTIFY_EVENTS, .is_variable = CHAR_VALUE_LEN_VARIABLE}, [HidSvcGattCharacteristicInfo] = {.name = "HID Information", @@ -56,9 +56,9 @@ static const FlipperGattCharacteristicParams hid_svc_chars[HidSvcGattCharacteris .data_prop.fixed.length = HID_SVC_INFO_LEN, .uuid.Char_UUID_16 = HID_INFORMATION_CHAR_UUID, .uuid_type = UUID_TYPE_16, - .properties = CHAR_PROP_READ, - .permissions = ATTR_PERMISSION_NONE, - .evt_mask = GATT_DONT_NOTIFY_EVENTS, + .char_properties = CHAR_PROP_READ, + .security_permissions = ATTR_PERMISSION_NONE, + .gatt_evt_mask = GATT_DONT_NOTIFY_EVENTS, .is_variable = CHAR_VALUE_LEN_CONSTANT}, [HidSvcGattCharacteristicCtrlPoint] = {.name = "HID Control Point", @@ -66,9 +66,9 @@ static const FlipperGattCharacteristicParams hid_svc_chars[HidSvcGattCharacteris .data_prop.fixed.length = HID_SVC_CONTROL_POINT_LEN, .uuid.Char_UUID_16 = HID_CONTROL_POINT_CHAR_UUID, .uuid_type = UUID_TYPE_16, - .properties = CHAR_PROP_WRITE_WITHOUT_RESP, - .permissions = ATTR_PERMISSION_NONE, - .evt_mask = GATT_NOTIFY_ATTRIBUTE_WRITE, + .char_properties = CHAR_PROP_WRITE_WITHOUT_RESP, + .security_permissions = ATTR_PERMISSION_NONE, + .gatt_evt_mask = GATT_NOTIFY_ATTRIBUTE_WRITE, .is_variable = CHAR_VALUE_LEN_CONSTANT}, }; @@ -79,7 +79,7 @@ static const FlipperGattCharacteristicDescriptorParams hid_svc_char_descr_templa .value_callback.fn = hid_svc_char_desc_data_callback, .security_permissions = ATTR_PERMISSION_NONE, .access_permissions = ATTR_ACCESS_READ_WRITE, - .evt_mask = GATT_DONT_NOTIFY_EVENTS, + .gatt_evt_mask = GATT_DONT_NOTIFY_EVENTS, .is_variable = CHAR_VALUE_LEN_CONSTANT, }; @@ -88,9 +88,9 @@ static const FlipperGattCharacteristicParams hid_svc_report_template = { .data_prop.fixed.length = HID_SVC_REPORT_MAX_LEN, .uuid.Char_UUID_16 = REPORT_CHAR_UUID, .uuid_type = UUID_TYPE_16, - .properties = CHAR_PROP_READ | CHAR_PROP_NOTIFY, - .permissions = ATTR_PERMISSION_NONE, - .evt_mask = GATT_DONT_NOTIFY_EVENTS, + .char_properties = CHAR_PROP_READ | CHAR_PROP_NOTIFY, + .security_permissions = ATTR_PERMISSION_NONE, + .gatt_evt_mask = GATT_DONT_NOTIFY_EVENTS, .is_variable = CHAR_VALUE_LEN_VARIABLE, }; @@ -242,7 +242,7 @@ void hid_svc_stop() { if(hid_svc) { // Delete characteristics for(size_t i = 0; i < HidSvcGattCharacteristicCount; i++) { - flipper_gatt_characteristic_deinit(hid_svc->svc_handle, &hid_svc->chars[i]); + flipper_gatt_characteristic_delete(hid_svc->svc_handle, &hid_svc->chars[i]); } typedef struct { @@ -258,7 +258,7 @@ void hid_svc_stop() { for(size_t i = 0; i < COUNT_OF(hid_report_chars); i++) { for(size_t j = 0; j < hid_report_chars[i].report_count; j++) { - flipper_gatt_characteristic_deinit( + flipper_gatt_characteristic_delete( hid_svc->svc_handle, &hid_report_chars[i].chars[j]); } } diff --git a/firmware/targets/f7/ble_glue/services/serial_service.c b/firmware/targets/f7/ble_glue/services/serial_service.c index 713114052170..2d0665e16e3b 100644 --- a/firmware/targets/f7/ble_glue/services/serial_service.c +++ b/firmware/targets/f7/ble_glue/services/serial_service.c @@ -38,9 +38,9 @@ static const FlipperGattCharacteristicParams serial_svc_chars[SerialSvcGattChara 0xed, 0x19}, .uuid_type = UUID_TYPE_128, - .properties = CHAR_PROP_READ | CHAR_PROP_INDICATE, - .permissions = ATTR_PERMISSION_AUTHEN_READ, - .evt_mask = GATT_DONT_NOTIFY_EVENTS, + .char_properties = CHAR_PROP_READ | CHAR_PROP_INDICATE, + .security_permissions = ATTR_PERMISSION_AUTHEN_READ, + .gatt_evt_mask = GATT_DONT_NOTIFY_EVENTS, .is_variable = CHAR_VALUE_LEN_VARIABLE}, [SerialSvcGattCharacteristicRx] = {.name = "RX", @@ -64,9 +64,9 @@ static const FlipperGattCharacteristicParams serial_svc_chars[SerialSvcGattChara 0xed, 0x19}, .uuid_type = UUID_TYPE_128, - .properties = CHAR_PROP_WRITE_WITHOUT_RESP | CHAR_PROP_WRITE | CHAR_PROP_READ, - .permissions = ATTR_PERMISSION_AUTHEN_READ | ATTR_PERMISSION_AUTHEN_WRITE, - .evt_mask = GATT_NOTIFY_ATTRIBUTE_WRITE, + .char_properties = CHAR_PROP_WRITE_WITHOUT_RESP | CHAR_PROP_WRITE | CHAR_PROP_READ, + .security_permissions = ATTR_PERMISSION_AUTHEN_READ | ATTR_PERMISSION_AUTHEN_WRITE, + .gatt_evt_mask = GATT_NOTIFY_ATTRIBUTE_WRITE, .is_variable = CHAR_VALUE_LEN_VARIABLE}, [SerialSvcGattCharacteristicFlowCtrl] = {.name = "Flow control", @@ -90,9 +90,9 @@ static const FlipperGattCharacteristicParams serial_svc_chars[SerialSvcGattChara 0xed, 0x19}, .uuid_type = UUID_TYPE_128, - .properties = CHAR_PROP_READ | CHAR_PROP_NOTIFY, - .permissions = ATTR_PERMISSION_AUTHEN_READ, - .evt_mask = GATT_DONT_NOTIFY_EVENTS, + .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}, [SerialSvcGattCharacteristicStatus] = { .name = "RPC status", @@ -116,9 +116,9 @@ static const FlipperGattCharacteristicParams serial_svc_chars[SerialSvcGattChara 0xed, 0x19}, .uuid_type = UUID_TYPE_128, - .properties = CHAR_PROP_READ | CHAR_PROP_WRITE | CHAR_PROP_NOTIFY, - .permissions = ATTR_PERMISSION_AUTHEN_READ | ATTR_PERMISSION_AUTHEN_WRITE, - .evt_mask = GATT_NOTIFY_ATTRIBUTE_WRITE, + .char_properties = CHAR_PROP_READ | CHAR_PROP_WRITE | CHAR_PROP_NOTIFY, + .security_permissions = ATTR_PERMISSION_AUTHEN_READ | ATTR_PERMISSION_AUTHEN_WRITE, + .gatt_evt_mask = GATT_NOTIFY_ATTRIBUTE_WRITE, .is_variable = CHAR_VALUE_LEN_CONSTANT}}; typedef struct { @@ -274,7 +274,7 @@ void serial_svc_stop() { tBleStatus status; if(serial_svc) { for(uint8_t i = 0; i < SerialSvcGattCharacteristicCount; i++) { - flipper_gatt_characteristic_deinit(serial_svc->svc_handle, &serial_svc->chars[i]); + flipper_gatt_characteristic_delete(serial_svc->svc_handle, &serial_svc->chars[i]); } // Delete service status = aci_gatt_del_service(serial_svc->svc_handle); From e4a47a356ce51da6fda27508bb761cfd216880f1 Mon Sep 17 00:00:00 2001 From: hedger Date: Sat, 15 Apr 2023 06:39:30 +0400 Subject: [PATCH 03/14] ble: expanded bitfields; fixed pvs warnings --- firmware/targets/f7/ble_glue/services/gatt_char.c | 2 +- firmware/targets/f7/ble_glue/services/gatt_char.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/firmware/targets/f7/ble_glue/services/gatt_char.c b/firmware/targets/f7/ble_glue/services/gatt_char.c index 293a2c31b792..eecaf916fb32 100644 --- a/firmware/targets/f7/ble_glue/services/gatt_char.c +++ b/firmware/targets/f7/ble_glue/services/gatt_char.c @@ -10,7 +10,7 @@ bool flipper_gatt_characteristic_props_const_char( uint16_t* data_len) { const char* str = (const char*)context; *data = (const uint8_t*)str; - *data_len = (uint16_t)strlen(str); + *data_len = (uint16_t)strlen(str); //-V:static_cast:1029 return false; } diff --git a/firmware/targets/f7/ble_glue/services/gatt_char.h b/firmware/targets/f7/ble_glue/services/gatt_char.h index a79bfaa7ce57..03b2b67cbddc 100644 --- a/firmware/targets/f7/ble_glue/services/gatt_char.h +++ b/firmware/targets/f7/ble_glue/services/gatt_char.h @@ -50,8 +50,8 @@ typedef struct { } data_prop; Char_UUID_t uuid; // Some packed bitfields to save space - FlipperGattCharacteristicDataType data_prop_type : 1; - uint8_t is_variable : 1; + FlipperGattCharacteristicDataType data_prop_type : 2; + uint8_t is_variable : 2; uint8_t uuid_type : 2; uint8_t char_properties; uint8_t security_permissions; From 29045ba1579c95114a72e69c64bf5bb2550a03fb Mon Sep 17 00:00:00 2001 From: hedger Date: Sat, 15 Apr 2023 15:49:11 +0400 Subject: [PATCH 04/14] ble: fixed pvs warnings for real --- firmware/targets/f7/ble_glue/services/gatt_char.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/targets/f7/ble_glue/services/gatt_char.c b/firmware/targets/f7/ble_glue/services/gatt_char.c index eecaf916fb32..19426aebd6e5 100644 --- a/firmware/targets/f7/ble_glue/services/gatt_char.c +++ b/firmware/targets/f7/ble_glue/services/gatt_char.c @@ -10,7 +10,7 @@ bool flipper_gatt_characteristic_props_const_char( uint16_t* data_len) { const char* str = (const char*)context; *data = (const uint8_t*)str; - *data_len = (uint16_t)strlen(str); //-V:static_cast:1029 + *data_len = (uint16_t)strlen(str); //-V::1029 return false; } From 2290d5d79a65b2c2f0374e54963573347f8a618f Mon Sep 17 00:00:00 2001 From: hedger Date: Sun, 16 Apr 2023 17:46:36 +0400 Subject: [PATCH 05/14] ble: using FlipperGattCharacteristicDataPropsFixed for char[] props --- .../f7/ble_glue/services/dev_info_service.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/firmware/targets/f7/ble_glue/services/dev_info_service.c b/firmware/targets/f7/ble_glue/services/dev_info_service.c index 607c40998d0b..abdb72dd805f 100644 --- a/firmware/targets/f7/ble_glue/services/dev_info_service.c +++ b/firmware/targets/f7/ble_glue/services/dev_info_service.c @@ -54,9 +54,9 @@ static bool dev_info_char_software_rev_callback( static const FlipperGattCharacteristicParams dev_info_svc_chars[DevInfoSvcGattCharacteristicCount] = {[DevInfoSvcGattCharacteristicMfgName] = {.name = "Manufacturer Name", - .data_prop_type = FlipperGattCharacteristicDataPropsCallback, - .data_prop.callback.context = dev_info_man_name, - .data_prop.callback.fn = flipper_gatt_characteristic_props_const_char, + .data_prop_type = FlipperGattCharacteristicDataPropsFixed, + .data_prop.fixed.length = sizeof(dev_info_man_name), + .data_prop.fixed.ptr = (const uint8_t*)&dev_info_man_name, .uuid.Char_UUID_16 = MANUFACTURER_NAME_UUID, .uuid_type = UUID_TYPE_16, .char_properties = CHAR_PROP_READ, @@ -65,9 +65,9 @@ static const FlipperGattCharacteristicParams dev_info_svc_chars[DevInfoSvcGattCh .is_variable = CHAR_VALUE_LEN_CONSTANT}, [DevInfoSvcGattCharacteristicSerial] = {.name = "Serial Number", - .data_prop_type = FlipperGattCharacteristicDataPropsCallback, - .data_prop.callback.context = dev_info_serial_num, - .data_prop.callback.fn = flipper_gatt_characteristic_props_const_char, + .data_prop_type = FlipperGattCharacteristicDataPropsFixed, + .data_prop.fixed.length = sizeof(dev_info_serial_num), + .data_prop.fixed.ptr = (const uint8_t*)&dev_info_serial_num, .uuid.Char_UUID_16 = SERIAL_NUMBER_UUID, .uuid_type = UUID_TYPE_16, .char_properties = CHAR_PROP_READ, @@ -98,9 +98,9 @@ static const FlipperGattCharacteristicParams dev_info_svc_chars[DevInfoSvcGattCh .is_variable = CHAR_VALUE_LEN_CONSTANT}, [DevInfoSvcGattCharacteristicRpcVersion] = { .name = "RPC Version", - .data_prop_type = FlipperGattCharacteristicDataPropsCallback, - .data_prop.callback.context = dev_info_rpc_version, - .data_prop.callback.fn = flipper_gatt_characteristic_props_const_char, + .data_prop_type = FlipperGattCharacteristicDataPropsFixed, + .data_prop.fixed.length = sizeof(dev_info_rpc_version), + .data_prop.fixed.ptr = (const uint8_t*)&dev_info_rpc_version, .uuid.Char_UUID_128 = {0x33, 0xa9, From ac9254c081f598b1a73c762d220650b30fa13f68 Mon Sep 17 00:00:00 2001 From: hedger Date: Sun, 16 Apr 2023 17:55:03 +0400 Subject: [PATCH 06/14] ble: removed flipper_gatt_characteristic_props_const_char --- firmware/targets/f7/ble_glue/services/gatt_char.c | 12 +----------- firmware/targets/f7/ble_glue/services/gatt_char.h | 7 +------ 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/firmware/targets/f7/ble_glue/services/gatt_char.c b/firmware/targets/f7/ble_glue/services/gatt_char.c index 19426aebd6e5..2a2d49515586 100644 --- a/firmware/targets/f7/ble_glue/services/gatt_char.c +++ b/firmware/targets/f7/ble_glue/services/gatt_char.c @@ -2,17 +2,7 @@ #include -#define TAG "BLE_CHAR" - -bool flipper_gatt_characteristic_props_const_char( - const void* context, - const uint8_t** data, - uint16_t* data_len) { - const char* str = (const char*)context; - *data = (const uint8_t*)str; - *data_len = (uint16_t)strlen(str); //-V::1029 - return false; -} +#define TAG "GattChar" void flipper_gatt_characteristic_init( uint16_t svc_handle, diff --git a/firmware/targets/f7/ble_glue/services/gatt_char.h b/firmware/targets/f7/ble_glue/services/gatt_char.h index 03b2b67cbddc..ffed0ced2a14 100644 --- a/firmware/targets/f7/ble_glue/services/gatt_char.h +++ b/firmware/targets/f7/ble_glue/services/gatt_char.h @@ -10,7 +10,7 @@ extern "C" { #endif -// returns true if you own the data pointer now and must free() it +// returns true if *data ownership is transferred to the caller typedef bool (*FlipperGattCharacteristicPropsCallback)( const void* context, const uint8_t** data, @@ -68,11 +68,6 @@ typedef struct { uint16_t descriptor_handle; } FlipperGattCharacteristicInstance; -bool flipper_gatt_characteristic_props_const_char( - const void* context, - const uint8_t** data, - uint16_t* data_len); - void flipper_gatt_characteristic_init( uint16_t svc_handle, const FlipperGattCharacteristicParams* char_descriptor, From f7cf00f22257b20f9fc6082c81929851688f3aa9 Mon Sep 17 00:00:00 2001 From: hedger Date: Sun, 16 Apr 2023 18:37:38 +0400 Subject: [PATCH 07/14] ble: gatt: naming changes --- .../f7/ble_glue/services/battery_service.c | 8 ++--- .../f7/ble_glue/services/dev_info_service.c | 30 ++++++++-------- .../targets/f7/ble_glue/services/gatt_char.c | 34 +++++++++++-------- .../targets/f7/ble_glue/services/gatt_char.h | 14 ++++---- .../f7/ble_glue/services/hid_service.c | 24 ++++++------- .../f7/ble_glue/services/serial_service.c | 16 ++++----- 6 files changed, 65 insertions(+), 61 deletions(-) diff --git a/firmware/targets/f7/ble_glue/services/battery_service.c b/firmware/targets/f7/ble_glue/services/battery_service.c index aac14ed3b1ea..63f736b3b7ab 100644 --- a/firmware/targets/f7/ble_glue/services/battery_service.c +++ b/firmware/targets/f7/ble_glue/services/battery_service.c @@ -49,8 +49,8 @@ typedef enum { static const FlipperGattCharacteristicParams battery_svc_chars[BatterySvcGattCharacteristicCount] = {[BatterySvcGattCharacteristicBatteryLevel] = {.name = "Battery Level", - .data_prop_type = FlipperGattCharacteristicDataPropsFixed, - .data_prop.fixed.length = 1, + .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, @@ -59,8 +59,8 @@ static const FlipperGattCharacteristicParams battery_svc_chars[BatterySvcGattCha .is_variable = CHAR_VALUE_LEN_CONSTANT}, [BatterySvcGattCharacteristicPowerState] = { .name = "Power State", - .data_prop_type = FlipperGattCharacteristicDataPropsFixed, - .data_prop.fixed.length = 1, + .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, diff --git a/firmware/targets/f7/ble_glue/services/dev_info_service.c b/firmware/targets/f7/ble_glue/services/dev_info_service.c index abdb72dd805f..98a3eaf4e17f 100644 --- a/firmware/targets/f7/ble_glue/services/dev_info_service.c +++ b/firmware/targets/f7/ble_glue/services/dev_info_service.c @@ -54,9 +54,9 @@ static bool dev_info_char_software_rev_callback( static const FlipperGattCharacteristicParams dev_info_svc_chars[DevInfoSvcGattCharacteristicCount] = {[DevInfoSvcGattCharacteristicMfgName] = {.name = "Manufacturer Name", - .data_prop_type = FlipperGattCharacteristicDataPropsFixed, - .data_prop.fixed.length = sizeof(dev_info_man_name), - .data_prop.fixed.ptr = (const uint8_t*)&dev_info_man_name, + .data_prop_type = FlipperGattCharacteristicDataFixed, + .data.fixed.length = sizeof(dev_info_man_name), + .data.fixed.ptr = (const uint8_t*)&dev_info_man_name, .uuid.Char_UUID_16 = MANUFACTURER_NAME_UUID, .uuid_type = UUID_TYPE_16, .char_properties = CHAR_PROP_READ, @@ -65,9 +65,9 @@ static const FlipperGattCharacteristicParams dev_info_svc_chars[DevInfoSvcGattCh .is_variable = CHAR_VALUE_LEN_CONSTANT}, [DevInfoSvcGattCharacteristicSerial] = {.name = "Serial Number", - .data_prop_type = FlipperGattCharacteristicDataPropsFixed, - .data_prop.fixed.length = sizeof(dev_info_serial_num), - .data_prop.fixed.ptr = (const uint8_t*)&dev_info_serial_num, + .data_prop_type = FlipperGattCharacteristicDataFixed, + .data.fixed.length = sizeof(dev_info_serial_num), + .data.fixed.ptr = (const uint8_t*)&dev_info_serial_num, .uuid.Char_UUID_16 = SERIAL_NUMBER_UUID, .uuid_type = UUID_TYPE_16, .char_properties = CHAR_PROP_READ, @@ -76,9 +76,9 @@ static const FlipperGattCharacteristicParams dev_info_svc_chars[DevInfoSvcGattCh .is_variable = CHAR_VALUE_LEN_CONSTANT}, [DevInfoSvcGattCharacteristicFirmwareRev] = {.name = "Firmware Revision", - .data_prop_type = FlipperGattCharacteristicDataPropsCallback, - .data_prop.callback.context = &dev_info_svc, - .data_prop.callback.fn = dev_info_char_firmware_rev_callback, + .data_prop_type = FlipperGattCharacteristicDataCallback, + .data.callback.context = &dev_info_svc, + .data.callback.fn = dev_info_char_firmware_rev_callback, .uuid.Char_UUID_16 = FIRMWARE_REVISION_UUID, .uuid_type = UUID_TYPE_16, .char_properties = CHAR_PROP_READ, @@ -87,9 +87,9 @@ static const FlipperGattCharacteristicParams dev_info_svc_chars[DevInfoSvcGattCh .is_variable = CHAR_VALUE_LEN_CONSTANT}, [DevInfoSvcGattCharacteristicSoftwareRev] = {.name = "Software Revision", - .data_prop_type = FlipperGattCharacteristicDataPropsCallback, - .data_prop.callback.context = &dev_info_svc, - .data_prop.callback.fn = dev_info_char_software_rev_callback, + .data_prop_type = FlipperGattCharacteristicDataCallback, + .data.callback.context = &dev_info_svc, + .data.callback.fn = dev_info_char_software_rev_callback, .uuid.Char_UUID_16 = SOFTWARE_REVISION_UUID, .uuid_type = UUID_TYPE_16, .char_properties = CHAR_PROP_READ, @@ -98,9 +98,9 @@ static const FlipperGattCharacteristicParams dev_info_svc_chars[DevInfoSvcGattCh .is_variable = CHAR_VALUE_LEN_CONSTANT}, [DevInfoSvcGattCharacteristicRpcVersion] = { .name = "RPC Version", - .data_prop_type = FlipperGattCharacteristicDataPropsFixed, - .data_prop.fixed.length = sizeof(dev_info_rpc_version), - .data_prop.fixed.ptr = (const uint8_t*)&dev_info_rpc_version, + .data_prop_type = FlipperGattCharacteristicDataFixed, + .data.fixed.length = sizeof(dev_info_rpc_version), + .data.fixed.ptr = (const uint8_t*)&dev_info_rpc_version, .uuid.Char_UUID_128 = {0x33, 0xa9, diff --git a/firmware/targets/f7/ble_glue/services/gatt_char.c b/firmware/targets/f7/ble_glue/services/gatt_char.c index 2a2d49515586..31229a138078 100644 --- a/firmware/targets/f7/ble_glue/services/gatt_char.c +++ b/firmware/targets/f7/ble_glue/services/gatt_char.c @@ -16,12 +16,12 @@ void flipper_gatt_characteristic_init( uint8_t const* char_data = NULL; uint16_t char_data_size = 0; bool release_data = false; - if(char_descriptor->data_prop_type == FlipperGattCharacteristicDataPropsFixed) { - char_data = char_descriptor->data_prop.fixed.ptr; - char_data_size = char_descriptor->data_prop.fixed.length; - } else if(char_descriptor->data_prop_type == FlipperGattCharacteristicDataPropsCallback) { - release_data = char_descriptor->data_prop.callback.fn( - char_descriptor->data_prop.callback.context, &char_data, &char_data_size); + if(char_descriptor->data_prop_type == FlipperGattCharacteristicDataFixed) { + char_data = char_descriptor->data.fixed.ptr; + char_data_size = char_descriptor->data.fixed.length; + } else if(char_descriptor->data_prop_type == FlipperGattCharacteristicDataCallback) { + release_data = char_descriptor->data.callback.fn( + char_descriptor->data.callback.context, &char_data, &char_data_size); } tBleStatus status = aci_gatt_add_char( @@ -46,8 +46,8 @@ void flipper_gatt_characteristic_init( if((status == 0) && char_descriptor->descriptor_params) { const FlipperGattCharacteristicDescriptorParams* char_data_descriptor = char_descriptor->descriptor_params; - release_data = char_data_descriptor->value_callback.fn( - char_data_descriptor->value_callback.context, &char_data, &char_data_size); + release_data = char_data_descriptor->data_callback.fn( + char_data_descriptor->data_callback.context, &char_data, &char_data_size); status = aci_gatt_add_char_desc( svc_handle, @@ -90,20 +90,21 @@ bool flipper_gatt_characteristic_update( const FlipperGattCharacteristicParams* char_descriptor = char_instance->characteristic; FURI_LOG_D(TAG, "Updating %s char", char_descriptor->name); - uint8_t const* char_data = NULL; + const uint8_t* char_data = NULL; uint16_t char_data_size = 0; - if(char_descriptor->data_prop_type == FlipperGattCharacteristicDataPropsFixed) { - char_data = char_descriptor->data_prop.fixed.ptr; + bool release_data = false; + if(char_descriptor->data_prop_type == FlipperGattCharacteristicDataFixed) { + char_data = char_descriptor->data.fixed.ptr; if(source) { char_data = (uint8_t*)source; } - char_data_size = char_descriptor->data_prop.fixed.length; - } else if(char_descriptor->data_prop_type == FlipperGattCharacteristicDataPropsCallback) { - const void* context = char_descriptor->data_prop.callback.context; + char_data_size = char_descriptor->data.fixed.length; + } else if(char_descriptor->data_prop_type == FlipperGattCharacteristicDataCallback) { + const void* context = char_descriptor->data.callback.context; if(source) { context = source; } - char_descriptor->data_prop.callback.fn(context, &char_data, &char_data_size); + release_data = char_descriptor->data.callback.fn(context, &char_data, &char_data_size); } tBleStatus result = aci_gatt_update_char_value( @@ -111,5 +112,8 @@ bool flipper_gatt_characteristic_update( if(result) { FURI_LOG_E(TAG, "Failed updating %s characteristic: %d", char_descriptor->name, result); } + if(release_data) { + free((void*)char_data); + } return result != BLE_STATUS_SUCCESS; } \ No newline at end of file diff --git a/firmware/targets/f7/ble_glue/services/gatt_char.h b/firmware/targets/f7/ble_glue/services/gatt_char.h index ffed0ced2a14..7527e5a183b3 100644 --- a/firmware/targets/f7/ble_glue/services/gatt_char.h +++ b/firmware/targets/f7/ble_glue/services/gatt_char.h @@ -11,22 +11,22 @@ extern "C" { #endif // returns true if *data ownership is transferred to the caller -typedef bool (*FlipperGattCharacteristicPropsCallback)( +typedef bool (*cbFlipperGattCharacteristicData)( const void* context, const uint8_t** data, uint16_t* data_len); typedef enum { - FlipperGattCharacteristicDataPropsFixed, - FlipperGattCharacteristicDataPropsCallback, + FlipperGattCharacteristicDataFixed, + FlipperGattCharacteristicDataCallback, } FlipperGattCharacteristicDataType; typedef struct { Char_Desc_Uuid_t uuid; struct { - FlipperGattCharacteristicPropsCallback fn; + cbFlipperGattCharacteristicData fn; const void* context; - } value_callback; + } data_callback; uint8_t uuid_type; uint8_t max_length; uint8_t security_permissions; @@ -44,10 +44,10 @@ typedef struct { uint16_t length; } fixed; struct { - FlipperGattCharacteristicPropsCallback fn; + cbFlipperGattCharacteristicData fn; const void* context; } callback; - } data_prop; + } data; Char_UUID_t uuid; // Some packed bitfields to save space FlipperGattCharacteristicDataType data_prop_type : 2; diff --git a/firmware/targets/f7/ble_glue/services/hid_service.c b/firmware/targets/f7/ble_glue/services/hid_service.c index 964803052b4a..a8fc1f71891a 100644 --- a/firmware/targets/f7/ble_glue/services/hid_service.c +++ b/firmware/targets/f7/ble_glue/services/hid_service.c @@ -32,8 +32,8 @@ bool hid_svc_char_desc_data_callback(const void* context, const uint8_t** data, static const FlipperGattCharacteristicParams hid_svc_chars[HidSvcGattCharacteristicCount] = { [HidSvcGattCharacteristicProtocolMode] = {.name = "Protocol Mode", - .data_prop_type = FlipperGattCharacteristicDataPropsFixed, - .data_prop.fixed.length = 1, + .data_prop_type = FlipperGattCharacteristicDataFixed, + .data.fixed.length = 1, .uuid.Char_UUID_16 = PROTOCOL_MODE_CHAR_UUID, .uuid_type = UUID_TYPE_16, .char_properties = CHAR_PROP_READ | CHAR_PROP_WRITE_WITHOUT_RESP, @@ -42,8 +42,8 @@ static const FlipperGattCharacteristicParams hid_svc_chars[HidSvcGattCharacteris .is_variable = CHAR_VALUE_LEN_CONSTANT}, [HidSvcGattCharacteristicReportMap] = {.name = "Report Map", - .data_prop_type = FlipperGattCharacteristicDataPropsFixed, - .data_prop.fixed.length = HID_SVC_REPORT_MAP_MAX_LEN, + .data_prop_type = FlipperGattCharacteristicDataFixed, + .data.fixed.length = HID_SVC_REPORT_MAP_MAX_LEN, .uuid.Char_UUID_16 = REPORT_MAP_CHAR_UUID, .uuid_type = UUID_TYPE_16, .char_properties = CHAR_PROP_READ, @@ -52,8 +52,8 @@ static const FlipperGattCharacteristicParams hid_svc_chars[HidSvcGattCharacteris .is_variable = CHAR_VALUE_LEN_VARIABLE}, [HidSvcGattCharacteristicInfo] = {.name = "HID Information", - .data_prop_type = FlipperGattCharacteristicDataPropsFixed, - .data_prop.fixed.length = HID_SVC_INFO_LEN, + .data_prop_type = FlipperGattCharacteristicDataFixed, + .data.fixed.length = HID_SVC_INFO_LEN, .uuid.Char_UUID_16 = HID_INFORMATION_CHAR_UUID, .uuid_type = UUID_TYPE_16, .char_properties = CHAR_PROP_READ, @@ -62,8 +62,8 @@ static const FlipperGattCharacteristicParams hid_svc_chars[HidSvcGattCharacteris .is_variable = CHAR_VALUE_LEN_CONSTANT}, [HidSvcGattCharacteristicCtrlPoint] = {.name = "HID Control Point", - .data_prop_type = FlipperGattCharacteristicDataPropsFixed, - .data_prop.fixed.length = HID_SVC_CONTROL_POINT_LEN, + .data_prop_type = FlipperGattCharacteristicDataFixed, + .data.fixed.length = HID_SVC_CONTROL_POINT_LEN, .uuid.Char_UUID_16 = HID_CONTROL_POINT_CHAR_UUID, .uuid_type = UUID_TYPE_16, .char_properties = CHAR_PROP_WRITE_WITHOUT_RESP, @@ -76,7 +76,7 @@ static const FlipperGattCharacteristicDescriptorParams hid_svc_char_descr_templa .uuid_type = UUID_TYPE_16, .uuid.Char_UUID_16 = REPORT_REFERENCE_DESCRIPTOR_UUID, .max_length = HID_SVC_REPORT_REF_LEN, - .value_callback.fn = hid_svc_char_desc_data_callback, + .data_callback.fn = hid_svc_char_desc_data_callback, .security_permissions = ATTR_PERMISSION_NONE, .access_permissions = ATTR_ACCESS_READ_WRITE, .gatt_evt_mask = GATT_DONT_NOTIFY_EVENTS, @@ -84,8 +84,8 @@ static const FlipperGattCharacteristicDescriptorParams hid_svc_char_descr_templa }; static const FlipperGattCharacteristicParams hid_svc_report_template = { - .data_prop_type = FlipperGattCharacteristicDataPropsFixed, - .data_prop.fixed.length = HID_SVC_REPORT_MAX_LEN, + .data_prop_type = FlipperGattCharacteristicDataFixed, + .data.fixed.length = HID_SVC_REPORT_MAX_LEN, .uuid.Char_UUID_16 = REPORT_CHAR_UUID, .uuid_type = UUID_TYPE_16, .char_properties = CHAR_PROP_READ | CHAR_PROP_NOTIFY, @@ -164,7 +164,7 @@ void hid_svc_start() { memcpy(&hid_svc_char_descr, &hid_svc_char_descr_template, sizeof(hid_svc_char_descr)); memcpy(&report_char, &hid_svc_report_template, sizeof(report_char)); - hid_svc_char_descr.value_callback.context = &report_id; + hid_svc_char_descr.data_callback.context = &report_id; report_char.descriptor_params = &hid_svc_char_descr; typedef struct { diff --git a/firmware/targets/f7/ble_glue/services/serial_service.c b/firmware/targets/f7/ble_glue/services/serial_service.c index 2d0665e16e3b..75f9a8f6de42 100644 --- a/firmware/targets/f7/ble_glue/services/serial_service.c +++ b/firmware/targets/f7/ble_glue/services/serial_service.c @@ -18,8 +18,8 @@ typedef enum { static const FlipperGattCharacteristicParams serial_svc_chars[SerialSvcGattCharacteristicCount] = { [SerialSvcGattCharacteristicTx] = {.name = "TX", - .data_prop_type = FlipperGattCharacteristicDataPropsFixed, - .data_prop.fixed.length = SERIAL_SVC_DATA_LEN_MAX, + .data_prop_type = FlipperGattCharacteristicDataFixed, + .data.fixed.length = SERIAL_SVC_DATA_LEN_MAX, .uuid.Char_UUID_128 = {0x00, 0x00, @@ -44,8 +44,8 @@ static const FlipperGattCharacteristicParams serial_svc_chars[SerialSvcGattChara .is_variable = CHAR_VALUE_LEN_VARIABLE}, [SerialSvcGattCharacteristicRx] = {.name = "RX", - .data_prop_type = FlipperGattCharacteristicDataPropsFixed, - .data_prop.fixed.length = SERIAL_SVC_DATA_LEN_MAX, + .data_prop_type = FlipperGattCharacteristicDataFixed, + .data.fixed.length = SERIAL_SVC_DATA_LEN_MAX, .uuid.Char_UUID_128 = {0x00, 0x00, @@ -70,8 +70,8 @@ static const FlipperGattCharacteristicParams serial_svc_chars[SerialSvcGattChara .is_variable = CHAR_VALUE_LEN_VARIABLE}, [SerialSvcGattCharacteristicFlowCtrl] = {.name = "Flow control", - .data_prop_type = FlipperGattCharacteristicDataPropsFixed, - .data_prop.fixed.length = sizeof(uint32_t), + .data_prop_type = FlipperGattCharacteristicDataFixed, + .data.fixed.length = sizeof(uint32_t), .uuid.Char_UUID_128 = {0x00, 0x00, @@ -96,8 +96,8 @@ static const FlipperGattCharacteristicParams serial_svc_chars[SerialSvcGattChara .is_variable = CHAR_VALUE_LEN_CONSTANT}, [SerialSvcGattCharacteristicStatus] = { .name = "RPC status", - .data_prop_type = FlipperGattCharacteristicDataPropsFixed, - .data_prop.fixed.length = sizeof(SerialServiceRpcStatus), + .data_prop_type = FlipperGattCharacteristicDataFixed, + .data.fixed.length = sizeof(SerialServiceRpcStatus), .uuid.Char_UUID_128 = {0x00, 0x00, From c013b12d85b75991b38204ef09b27e9173e82e84 Mon Sep 17 00:00:00 2001 From: hedger Date: Sun, 16 Apr 2023 19:29:58 +0400 Subject: [PATCH 08/14] ble: gatt: fixed device_info service constant attrs sizes --- firmware/targets/f7/ble_glue/services/dev_info_service.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/firmware/targets/f7/ble_glue/services/dev_info_service.c b/firmware/targets/f7/ble_glue/services/dev_info_service.c index 98a3eaf4e17f..cdefa1ea313c 100644 --- a/firmware/targets/f7/ble_glue/services/dev_info_service.c +++ b/firmware/targets/f7/ble_glue/services/dev_info_service.c @@ -55,7 +55,7 @@ static const FlipperGattCharacteristicParams dev_info_svc_chars[DevInfoSvcGattCh {[DevInfoSvcGattCharacteristicMfgName] = {.name = "Manufacturer Name", .data_prop_type = FlipperGattCharacteristicDataFixed, - .data.fixed.length = sizeof(dev_info_man_name), + .data.fixed.length = sizeof(dev_info_man_name) - 1, .data.fixed.ptr = (const uint8_t*)&dev_info_man_name, .uuid.Char_UUID_16 = MANUFACTURER_NAME_UUID, .uuid_type = UUID_TYPE_16, @@ -66,7 +66,7 @@ static const FlipperGattCharacteristicParams dev_info_svc_chars[DevInfoSvcGattCh [DevInfoSvcGattCharacteristicSerial] = {.name = "Serial Number", .data_prop_type = FlipperGattCharacteristicDataFixed, - .data.fixed.length = sizeof(dev_info_serial_num), + .data.fixed.length = sizeof(dev_info_serial_num) - 1, .data.fixed.ptr = (const uint8_t*)&dev_info_serial_num, .uuid.Char_UUID_16 = SERIAL_NUMBER_UUID, .uuid_type = UUID_TYPE_16, @@ -99,7 +99,7 @@ static const FlipperGattCharacteristicParams dev_info_svc_chars[DevInfoSvcGattCh [DevInfoSvcGattCharacteristicRpcVersion] = { .name = "RPC Version", .data_prop_type = FlipperGattCharacteristicDataFixed, - .data.fixed.length = sizeof(dev_info_rpc_version), + .data.fixed.length = sizeof(dev_info_rpc_version) - 1, .data.fixed.ptr = (const uint8_t*)&dev_info_rpc_version, .uuid.Char_UUID_128 = {0x33, From 02c594fe8a0b09883a00c88da318a4ba33b3d8b2 Mon Sep 17 00:00:00 2001 From: hedger Date: Sun, 16 Apr 2023 22:15:59 +0400 Subject: [PATCH 09/14] ble: gatt: copy descriptors to char instances; reworked hid chars to be callback-based; moved max size getter to callback with NULL data; added comments --- .../f7/ble_glue/services/dev_info_service.c | 11 +- .../targets/f7/ble_glue/services/gatt_char.c | 22 ++-- .../targets/f7/ble_glue/services/gatt_char.h | 11 +- .../f7/ble_glue/services/hid_service.c | 112 ++++++++++++------ 4 files changed, 108 insertions(+), 48 deletions(-) diff --git a/firmware/targets/f7/ble_glue/services/dev_info_service.c b/firmware/targets/f7/ble_glue/services/dev_info_service.c index cdefa1ea313c..a1c289d794e7 100644 --- a/firmware/targets/f7/ble_glue/services/dev_info_service.c +++ b/firmware/targets/f7/ble_glue/services/dev_info_service.c @@ -18,11 +18,12 @@ typedef enum { DevInfoSvcGattCharacteristicCount, } DevInfoSvcGattCharacteristicId; +#define DEVICE_INFO_HARDWARE_REV_SIZE 4 typedef struct { uint16_t service_handle; FlipperGattCharacteristicInstance characteristics[DevInfoSvcGattCharacteristicCount]; FuriString* version_string; - char hardware_revision[4]; + char hardware_revision[DEVICE_INFO_HARDWARE_REV_SIZE]; } DevInfoSvc; static DevInfoSvc* dev_info_svc = NULL; @@ -36,8 +37,10 @@ static bool dev_info_char_firmware_rev_callback( const uint8_t** data, uint16_t* data_len) { const DevInfoSvc* dev_info_svc = *(DevInfoSvc**)context; - *data = (const uint8_t*)&dev_info_svc->hardware_revision; *data_len = sizeof(dev_info_svc->hardware_revision); + if(data) { + *data = (const uint8_t*)&dev_info_svc->hardware_revision; + } return false; } @@ -46,8 +49,10 @@ static bool dev_info_char_software_rev_callback( const uint8_t** data, uint16_t* data_len) { const DevInfoSvc* dev_info_svc = *(DevInfoSvc**)context; - *data = (const uint8_t*)furi_string_get_cstr(dev_info_svc->version_string); *data_len = furi_string_size(dev_info_svc->version_string); + if(data) { + *data = (const uint8_t*)furi_string_get_cstr(dev_info_svc->version_string); + } return false; } diff --git a/firmware/targets/f7/ble_glue/services/gatt_char.c b/firmware/targets/f7/ble_glue/services/gatt_char.c index 31229a138078..256696393956 100644 --- a/firmware/targets/f7/ble_glue/services/gatt_char.c +++ b/firmware/targets/f7/ble_glue/services/gatt_char.c @@ -11,17 +11,20 @@ void flipper_gatt_characteristic_init( furi_assert(char_descriptor); furi_assert(char_instance); - char_instance->characteristic = char_descriptor; + // Copy the descriptor to the instance, since it may point to stack memory + // TODO: only copy if really comes from stack + char_instance->characteristic = malloc(sizeof(FlipperGattCharacteristicParams)); + memcpy( + (void*)char_instance->characteristic, + char_descriptor, + sizeof(FlipperGattCharacteristicParams)); - uint8_t const* char_data = NULL; uint16_t char_data_size = 0; - bool release_data = false; if(char_descriptor->data_prop_type == FlipperGattCharacteristicDataFixed) { - char_data = char_descriptor->data.fixed.ptr; char_data_size = char_descriptor->data.fixed.length; } else if(char_descriptor->data_prop_type == FlipperGattCharacteristicDataCallback) { - release_data = char_descriptor->data.callback.fn( - char_descriptor->data.callback.context, &char_data, &char_data_size); + char_descriptor->data.callback.fn( + char_descriptor->data.callback.context, NULL, &char_data_size); } tBleStatus status = aci_gatt_add_char( @@ -38,15 +41,13 @@ void flipper_gatt_characteristic_init( if(status) { FURI_LOG_E(TAG, "Failed to add %s char: %d", char_descriptor->name, status); } - if(release_data) { - free((void*)char_data); - } char_instance->descriptor_handle = 0; if((status == 0) && char_descriptor->descriptor_params) { + uint8_t const* char_data = NULL; const FlipperGattCharacteristicDescriptorParams* char_data_descriptor = char_descriptor->descriptor_params; - release_data = char_data_descriptor->data_callback.fn( + bool release_data = char_data_descriptor->data_callback.fn( char_data_descriptor->data_callback.context, &char_data, &char_data_size); status = aci_gatt_add_char_desc( @@ -80,6 +81,7 @@ void flipper_gatt_characteristic_delete( FURI_LOG_E( TAG, "Failed to delete %s char: %d", char_instance->characteristic->name, status); } + free((void*)char_instance->characteristic); } bool flipper_gatt_characteristic_update( diff --git a/firmware/targets/f7/ble_glue/services/gatt_char.h b/firmware/targets/f7/ble_glue/services/gatt_char.h index 7527e5a183b3..959ab67a49f7 100644 --- a/firmware/targets/f7/ble_glue/services/gatt_char.h +++ b/firmware/targets/f7/ble_glue/services/gatt_char.h @@ -10,7 +10,11 @@ extern "C" { #endif -// returns true if *data ownership is transferred to the caller +// Callback signature for getting characteristic data +// Is called when characteristic is created to get max data length. Data ptr is NULL in this case +// The result is passed to aci_gatt_add_char as "Char_Value_Length" +// For updates, called with a context - see flipper_gatt_characteristic_update +// Returns true if *data ownership is transferred to the caller and will be freed typedef bool (*cbFlipperGattCharacteristicData)( const void* context, const uint8_t** data, @@ -68,15 +72,20 @@ typedef struct { uint16_t descriptor_handle; } FlipperGattCharacteristicInstance; +// Initialize a characteristic instance; copies the characteristic descriptor into the instance void flipper_gatt_characteristic_init( uint16_t svc_handle, const FlipperGattCharacteristicParams* char_descriptor, FlipperGattCharacteristicInstance* char_instance); +// Delete a characteristic instance; frees the copied characteristic descriptor from the instance void flipper_gatt_characteristic_delete( uint16_t svc_handle, FlipperGattCharacteristicInstance* char_instance); +// Update a characteristic instance; if source==NULL, uses the data from the characteristic +// - For fixed data, fixed.ptr is used as the source if source==NULL +// - For callback-based data, collback.context is passed as the context if source==NULL bool flipper_gatt_characteristic_update( uint16_t svc_handle, FlipperGattCharacteristicInstance* char_instance, diff --git a/firmware/targets/f7/ble_glue/services/hid_service.c b/firmware/targets/f7/ble_glue/services/hid_service.c index a8fc1f71891a..d9f52e4675c0 100644 --- a/firmware/targets/f7/ble_glue/services/hid_service.c +++ b/firmware/targets/f7/ble_glue/services/hid_service.c @@ -22,10 +22,45 @@ typedef struct { static_assert(sizeof(HidSvcReportId) == sizeof(uint16_t), "HidSvcReportId must be 2 bytes"); -bool hid_svc_char_desc_data_callback(const void* context, const uint8_t** data, uint16_t* data_len) { +static bool + hid_svc_char_desc_data_callback(const void* context, const uint8_t** data, uint16_t* data_len) { const HidSvcReportId* report_id = context; - *data = (const uint8_t*)report_id; *data_len = sizeof(HidSvcReportId); + if(data) { + *data = (const uint8_t*)report_id; + } + return false; +} + +typedef struct { + const void* data_ptr; + uint16_t data_len; +} HidSvcDataWrapper; + +static bool hid_svc_report_map_data_callback( + const void* context, + const uint8_t** data, + uint16_t* data_len) { + const HidSvcDataWrapper* report_data = context; + if(data) { + *data = report_data->data_ptr; + *data_len = report_data->data_len; + } else { + *data_len = HID_SVC_REPORT_MAP_MAX_LEN; + } + return false; +} + +static bool + hid_svc_hid_info_data_callback(const void* context, const uint8_t** data, uint16_t* data_len) { + const HidSvcDataWrapper* report_data = context; + if(data) { + furi_check(report_data->data_len == HID_SVC_INFO_LEN); + *data = report_data->data_ptr; + *data_len = report_data->data_len; + } else { + *data_len = HID_SVC_INFO_LEN; + } return false; } @@ -42,8 +77,9 @@ static const FlipperGattCharacteristicParams hid_svc_chars[HidSvcGattCharacteris .is_variable = CHAR_VALUE_LEN_CONSTANT}, [HidSvcGattCharacteristicReportMap] = {.name = "Report Map", - .data_prop_type = FlipperGattCharacteristicDataFixed, - .data.fixed.length = HID_SVC_REPORT_MAP_MAX_LEN, + .data_prop_type = FlipperGattCharacteristicDataCallback, + .data.callback.fn = hid_svc_report_map_data_callback, + .data.callback.context = NULL, .uuid.Char_UUID_16 = REPORT_MAP_CHAR_UUID, .uuid_type = UUID_TYPE_16, .char_properties = CHAR_PROP_READ, @@ -52,8 +88,9 @@ static const FlipperGattCharacteristicParams hid_svc_chars[HidSvcGattCharacteris .is_variable = CHAR_VALUE_LEN_VARIABLE}, [HidSvcGattCharacteristicInfo] = {.name = "HID Information", - .data_prop_type = FlipperGattCharacteristicDataFixed, - .data.fixed.length = HID_SVC_INFO_LEN, + .data_prop_type = FlipperGattCharacteristicDataCallback, + .data.callback.fn = hid_svc_hid_info_data_callback, + .data.callback.context = NULL, .uuid.Char_UUID_16 = HID_INFORMATION_CHAR_UUID, .uuid_type = UUID_TYPE_16, .char_properties = CHAR_PROP_READ, @@ -83,9 +120,23 @@ static const FlipperGattCharacteristicDescriptorParams hid_svc_char_descr_templa .is_variable = CHAR_VALUE_LEN_CONSTANT, }; +static bool + hid_svc_report_data_callback(const void* context, const uint8_t** data, uint16_t* data_len) { + const HidSvcDataWrapper* report_data = context; + if(data) { + *data = report_data->data_ptr; + *data_len = report_data->data_len; + } else { + *data_len = HID_SVC_REPORT_MAX_LEN; + } + return false; +} + static const FlipperGattCharacteristicParams hid_svc_report_template = { - .data_prop_type = FlipperGattCharacteristicDataFixed, - .data.fixed.length = HID_SVC_REPORT_MAX_LEN, + .name = "Report", + .data_prop_type = FlipperGattCharacteristicDataCallback, + .data.callback.fn = hid_svc_report_data_callback, + .data.callback.context = NULL, .uuid.Char_UUID_16 = REPORT_CHAR_UUID, .uuid_type = UUID_TYPE_16, .char_properties = CHAR_PROP_READ | CHAR_PROP_NOTIFY, @@ -193,44 +244,37 @@ bool hid_svc_update_report_map(const uint8_t* data, uint16_t len) { furi_assert(data); furi_assert(hid_svc); - tBleStatus status = aci_gatt_update_char_value( - hid_svc->svc_handle, - hid_svc->chars[HidSvcGattCharacteristicReportMap].handle, - 0, - len, - data); - if(status) { - FURI_LOG_E(TAG, "Failed updating report map characteristic: %d", status); - return false; - } - return true; + HidSvcDataWrapper report_data = { + .data_ptr = data, + .data_len = len, + }; + return flipper_gatt_characteristic_update( + hid_svc->svc_handle, &hid_svc->chars[HidSvcGattCharacteristicReportMap], &report_data); } bool hid_svc_update_input_report(uint8_t input_report_num, uint8_t* data, uint16_t len) { furi_assert(data); furi_assert(hid_svc); - furi_check(input_report_num < HID_SVC_INPUT_REPORT_COUNT); + furi_assert(input_report_num < HID_SVC_INPUT_REPORT_COUNT); - tBleStatus status = aci_gatt_update_char_value( - hid_svc->svc_handle, hid_svc->input_report_chars[input_report_num].handle, 0, len, data); - if(status) { - FURI_LOG_E(TAG, "Failed updating report characteristic: %d", status); - return false; - } - return true; + HidSvcDataWrapper report_data = { + .data_ptr = data, + .data_len = len, + }; + return flipper_gatt_characteristic_update( + hid_svc->svc_handle, &hid_svc->input_report_chars[input_report_num], &report_data); } bool hid_svc_update_info(uint8_t* data, uint16_t len) { furi_assert(data); furi_assert(hid_svc); - tBleStatus status = aci_gatt_update_char_value( - hid_svc->svc_handle, hid_svc->chars[HidSvcGattCharacteristicInfo].handle, 0, len, data); - if(status) { - FURI_LOG_E(TAG, "Failed updating info characteristic: %d", status); - return false; - } - return true; + HidSvcDataWrapper report_data = { + .data_ptr = data, + .data_len = len, + }; + return flipper_gatt_characteristic_update( + hid_svc->svc_handle, &hid_svc->chars[HidSvcGattCharacteristicInfo], &report_data); } bool hid_svc_is_started() { From 717a347f457380a783b56dc912df0a19a94e6173 Mon Sep 17 00:00:00 2001 From: hedger Date: Sun, 16 Apr 2023 22:35:38 +0400 Subject: [PATCH 10/14] ble: gatt: removed hid_svc_report_data_callback --- .../f7/ble_glue/services/hid_service.c | 20 +++---------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/firmware/targets/f7/ble_glue/services/hid_service.c b/firmware/targets/f7/ble_glue/services/hid_service.c index d9f52e4675c0..65935b8c7530 100644 --- a/firmware/targets/f7/ble_glue/services/hid_service.c +++ b/firmware/targets/f7/ble_glue/services/hid_service.c @@ -37,10 +37,8 @@ typedef struct { uint16_t data_len; } HidSvcDataWrapper; -static bool hid_svc_report_map_data_callback( - const void* context, - const uint8_t** data, - uint16_t* data_len) { +static bool + hid_svc_report_data_callback(const void* context, const uint8_t** data, uint16_t* data_len) { const HidSvcDataWrapper* report_data = context; if(data) { *data = report_data->data_ptr; @@ -78,7 +76,7 @@ static const FlipperGattCharacteristicParams hid_svc_chars[HidSvcGattCharacteris [HidSvcGattCharacteristicReportMap] = {.name = "Report Map", .data_prop_type = FlipperGattCharacteristicDataCallback, - .data.callback.fn = hid_svc_report_map_data_callback, + .data.callback.fn = hid_svc_report_data_callback, .data.callback.context = NULL, .uuid.Char_UUID_16 = REPORT_MAP_CHAR_UUID, .uuid_type = UUID_TYPE_16, @@ -120,18 +118,6 @@ static const FlipperGattCharacteristicDescriptorParams hid_svc_char_descr_templa .is_variable = CHAR_VALUE_LEN_CONSTANT, }; -static bool - hid_svc_report_data_callback(const void* context, const uint8_t** data, uint16_t* data_len) { - const HidSvcDataWrapper* report_data = context; - if(data) { - *data = report_data->data_ptr; - *data_len = report_data->data_len; - } else { - *data_len = HID_SVC_REPORT_MAX_LEN; - } - return false; -} - static const FlipperGattCharacteristicParams hid_svc_report_template = { .name = "Report", .data_prop_type = FlipperGattCharacteristicDataCallback, From c5b7101cfbc7ddcdc9b024deba975dca8c471f9c Mon Sep 17 00:00:00 2001 From: hedger Date: Sun, 16 Apr 2023 22:48:49 +0400 Subject: [PATCH 11/14] ble: hid svc: better double loop idx naming --- .../f7/ble_glue/services/hid_service.c | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/firmware/targets/f7/ble_glue/services/hid_service.c b/firmware/targets/f7/ble_glue/services/hid_service.c index 65935b8c7530..cc5dddd30a91 100644 --- a/firmware/targets/f7/ble_glue/services/hid_service.c +++ b/firmware/targets/f7/ble_glue/services/hid_service.c @@ -216,12 +216,16 @@ void hid_svc_start() { {0x03, HID_SVC_FEATURE_REPORT_COUNT, hid_svc->feature_report_chars}, }; - for(size_t i = 0; i < COUNT_OF(hid_report_chars); i++) { - report_id.report_type = hid_report_chars[i].report_type; - for(size_t j = 0; j < hid_report_chars[i].report_count; j++) { - report_id.report_idx = j + 1; + for(size_t report_type_idx = 0; report_type_idx < COUNT_OF(hid_report_chars); + report_type_idx++) { + report_id.report_type = hid_report_chars[report_type_idx].report_type; + for(size_t report_idx = 0; report_idx < hid_report_chars[report_type_idx].report_count; + report_idx++) { + report_id.report_idx = report_idx + 1; flipper_gatt_characteristic_init( - hid_svc->svc_handle, &report_char, &hid_report_chars[i].chars[j]); + hid_svc->svc_handle, + &report_char, + &hid_report_chars[report_type_idx].chars[report_idx]); } } } @@ -286,10 +290,12 @@ void hid_svc_stop() { {HID_SVC_FEATURE_REPORT_COUNT, hid_svc->feature_report_chars}, }; - for(size_t i = 0; i < COUNT_OF(hid_report_chars); i++) { - for(size_t j = 0; j < hid_report_chars[i].report_count; j++) { + for(size_t report_type_idx = 0; report_type_idx < COUNT_OF(hid_report_chars); + report_type_idx++) { + for(size_t report_idx = 0; report_idx < hid_report_chars[report_type_idx].report_count; + report_idx++) { flipper_gatt_characteristic_delete( - hid_svc->svc_handle, &hid_report_chars[i].chars[j]); + hid_svc->svc_handle, &hid_report_chars[report_type_idx].chars[report_idx]); } } From a8a131bd294e5f0bf82807ad161abfec5ce9b547 Mon Sep 17 00:00:00 2001 From: hedger Date: Sun, 16 Apr 2023 23:00:55 +0400 Subject: [PATCH 12/14] ble: hid svc: simplified hid_svc_update_info --- .../f7/ble_glue/services/hid_service.c | 25 +++---------------- .../f7/ble_glue/services/hid_service.h | 3 ++- .../targets/f7/furi_hal/furi_hal_bt_hid.c | 2 +- 3 files changed, 7 insertions(+), 23 deletions(-) diff --git a/firmware/targets/f7/ble_glue/services/hid_service.c b/firmware/targets/f7/ble_glue/services/hid_service.c index cc5dddd30a91..60ec67e5dd6f 100644 --- a/firmware/targets/f7/ble_glue/services/hid_service.c +++ b/firmware/targets/f7/ble_glue/services/hid_service.c @@ -49,19 +49,6 @@ static bool return false; } -static bool - hid_svc_hid_info_data_callback(const void* context, const uint8_t** data, uint16_t* data_len) { - const HidSvcDataWrapper* report_data = context; - if(data) { - furi_check(report_data->data_len == HID_SVC_INFO_LEN); - *data = report_data->data_ptr; - *data_len = report_data->data_len; - } else { - *data_len = HID_SVC_INFO_LEN; - } - return false; -} - static const FlipperGattCharacteristicParams hid_svc_chars[HidSvcGattCharacteristicCount] = { [HidSvcGattCharacteristicProtocolMode] = {.name = "Protocol Mode", @@ -87,8 +74,8 @@ static const FlipperGattCharacteristicParams hid_svc_chars[HidSvcGattCharacteris [HidSvcGattCharacteristicInfo] = {.name = "HID Information", .data_prop_type = FlipperGattCharacteristicDataCallback, - .data.callback.fn = hid_svc_hid_info_data_callback, - .data.callback.context = NULL, + .data.fixed.length = HID_SVC_INFO_LEN, + .data.fixed.ptr = NULL, .uuid.Char_UUID_16 = HID_INFORMATION_CHAR_UUID, .uuid_type = UUID_TYPE_16, .char_properties = CHAR_PROP_READ, @@ -255,16 +242,12 @@ bool hid_svc_update_input_report(uint8_t input_report_num, uint8_t* data, uint16 hid_svc->svc_handle, &hid_svc->input_report_chars[input_report_num], &report_data); } -bool hid_svc_update_info(uint8_t* data, uint16_t len) { +bool hid_svc_update_info(uint8_t* data) { furi_assert(data); furi_assert(hid_svc); - HidSvcDataWrapper report_data = { - .data_ptr = data, - .data_len = len, - }; return flipper_gatt_characteristic_update( - hid_svc->svc_handle, &hid_svc->chars[HidSvcGattCharacteristicInfo], &report_data); + hid_svc->svc_handle, &hid_svc->chars[HidSvcGattCharacteristicInfo], &data); } bool hid_svc_is_started() { diff --git a/firmware/targets/f7/ble_glue/services/hid_service.h b/firmware/targets/f7/ble_glue/services/hid_service.h index 723460d496ac..211adcd6c440 100644 --- a/firmware/targets/f7/ble_glue/services/hid_service.h +++ b/firmware/targets/f7/ble_glue/services/hid_service.h @@ -25,4 +25,5 @@ bool hid_svc_update_report_map(const uint8_t* data, uint16_t len); bool hid_svc_update_input_report(uint8_t input_report_num, uint8_t* data, uint16_t len); -bool hid_svc_update_info(uint8_t* data, uint16_t len); +// Expects data to be of length HID_SVC_INFO_LEN (4 bytes) +bool hid_svc_update_info(uint8_t* data); diff --git a/firmware/targets/f7/furi_hal/furi_hal_bt_hid.c b/firmware/targets/f7/furi_hal/furi_hal_bt_hid.c index 78283700beee..7ec712af4dbb 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_bt_hid.c +++ b/firmware/targets/f7/furi_hal/furi_hal_bt_hid.c @@ -153,7 +153,7 @@ void furi_hal_bt_hid_start() { FURI_HAL_BT_HID_INFO_FLAG_REMOTE_WAKE_MSK | FURI_HAL_BT_HID_INFO_FLAG_NORMALLY_CONNECTABLE_MSK, }; - hid_svc_update_info(hid_info_val, sizeof(hid_info_val)); + hid_svc_update_info(hid_info_val); } void furi_hal_bt_hid_stop() { From 4f944f1456d142abccb5db13935106a747ac5349 Mon Sep 17 00:00:00 2001 From: hedger Date: Sun, 16 Apr 2023 23:29:55 +0400 Subject: [PATCH 13/14] ble: gatt: removed magic values; fixed type for HidSvcGattCharacteristicInfo --- firmware/targets/f7/ble_glue/services/gatt_char.c | 6 ++++-- firmware/targets/f7/ble_glue/services/hid_service.c | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/firmware/targets/f7/ble_glue/services/gatt_char.c b/firmware/targets/f7/ble_glue/services/gatt_char.c index 256696393956..9b6a44f61b43 100644 --- a/firmware/targets/f7/ble_glue/services/gatt_char.c +++ b/firmware/targets/f7/ble_glue/services/gatt_char.c @@ -4,6 +4,8 @@ #define TAG "GattChar" +#define GATT_MIN_READ_KEY_SIZE (10) + void flipper_gatt_characteristic_init( uint16_t svc_handle, const FlipperGattCharacteristicParams* char_descriptor, @@ -35,7 +37,7 @@ void flipper_gatt_characteristic_init( char_descriptor->char_properties, char_descriptor->security_permissions, char_descriptor->gatt_evt_mask, - 10, + GATT_MIN_READ_KEY_SIZE, char_descriptor->is_variable, &char_instance->handle); if(status) { @@ -61,7 +63,7 @@ void flipper_gatt_characteristic_init( char_data_descriptor->security_permissions, char_data_descriptor->access_permissions, char_data_descriptor->gatt_evt_mask, - 7, + GATT_MIN_READ_KEY_SIZE, char_data_descriptor->is_variable, &char_instance->descriptor_handle); if(status) { diff --git a/firmware/targets/f7/ble_glue/services/hid_service.c b/firmware/targets/f7/ble_glue/services/hid_service.c index 60ec67e5dd6f..cde26b267ec4 100644 --- a/firmware/targets/f7/ble_glue/services/hid_service.c +++ b/firmware/targets/f7/ble_glue/services/hid_service.c @@ -73,7 +73,7 @@ static const FlipperGattCharacteristicParams hid_svc_chars[HidSvcGattCharacteris .is_variable = CHAR_VALUE_LEN_VARIABLE}, [HidSvcGattCharacteristicInfo] = {.name = "HID Information", - .data_prop_type = FlipperGattCharacteristicDataCallback, + .data_prop_type = FlipperGattCharacteristicDataFixed, .data.fixed.length = HID_SVC_INFO_LEN, .data.fixed.ptr = NULL, .uuid.Char_UUID_16 = HID_INFORMATION_CHAR_UUID, From a85f30f171158f3922357dfdac5433fd7680442e Mon Sep 17 00:00:00 2001 From: hedger Date: Mon, 17 Apr 2023 14:58:49 +0400 Subject: [PATCH 14/14] ble: gatt: moved long uuids to separate files --- .../f7/ble_glue/services/dev_info_service.c | 20 +---- .../services/dev_info_service_uuid.inc | 3 + .../f7/ble_glue/services/serial_service.c | 79 ++----------------- .../ble_glue/services/serial_service_uuid.inc | 12 +++ 4 files changed, 25 insertions(+), 89 deletions(-) create mode 100644 firmware/targets/f7/ble_glue/services/dev_info_service_uuid.inc create mode 100644 firmware/targets/f7/ble_glue/services/serial_service_uuid.inc diff --git a/firmware/targets/f7/ble_glue/services/dev_info_service.c b/firmware/targets/f7/ble_glue/services/dev_info_service.c index a1c289d794e7..cc95bb2fc1c8 100644 --- a/firmware/targets/f7/ble_glue/services/dev_info_service.c +++ b/firmware/targets/f7/ble_glue/services/dev_info_service.c @@ -7,6 +7,8 @@ #include #include +#include "dev_info_service_uuid.inc" + #define TAG "BtDevInfoSvc" typedef enum { @@ -106,23 +108,7 @@ static const FlipperGattCharacteristicParams dev_info_svc_chars[DevInfoSvcGattCh .data_prop_type = FlipperGattCharacteristicDataFixed, .data.fixed.length = sizeof(dev_info_rpc_version) - 1, .data.fixed.ptr = (const uint8_t*)&dev_info_rpc_version, - .uuid.Char_UUID_128 = - {0x33, - 0xa9, - 0xb5, - 0x3e, - 0x87, - 0x5d, - 0x1a, - 0x8e, - 0xc8, - 0x47, - 0x5e, - 0xae, - 0x6d, - 0x66, - 0xf6, - 0x03}, + .uuid.Char_UUID_128 = DEV_INVO_RPC_VERSION_UID, .uuid_type = UUID_TYPE_128, .char_properties = CHAR_PROP_READ, .security_permissions = ATTR_PERMISSION_AUTHEN_READ, diff --git a/firmware/targets/f7/ble_glue/services/dev_info_service_uuid.inc b/firmware/targets/f7/ble_glue/services/dev_info_service_uuid.inc new file mode 100644 index 000000000000..ad520f62e5e0 --- /dev/null +++ b/firmware/targets/f7/ble_glue/services/dev_info_service_uuid.inc @@ -0,0 +1,3 @@ +#define DEV_INVO_RPC_VERSION_UID \ + { 0x33, 0xa9, 0xb5, 0x3e, 0x87, 0x5d, 0x1a, 0x8e, 0xc8, 0x47, 0x5e, 0xae, 0x6d, 0x66, 0xf6, 0x03 } + diff --git a/firmware/targets/f7/ble_glue/services/serial_service.c b/firmware/targets/f7/ble_glue/services/serial_service.c index 75f9a8f6de42..ab009bbfcb03 100644 --- a/firmware/targets/f7/ble_glue/services/serial_service.c +++ b/firmware/targets/f7/ble_glue/services/serial_service.c @@ -5,6 +5,8 @@ #include +#include "serial_service_uuid.inc" + #define TAG "BtSerialSvc" typedef enum { @@ -20,23 +22,7 @@ static const FlipperGattCharacteristicParams serial_svc_chars[SerialSvcGattChara {.name = "TX", .data_prop_type = FlipperGattCharacteristicDataFixed, .data.fixed.length = SERIAL_SVC_DATA_LEN_MAX, - .uuid.Char_UUID_128 = - {0x00, - 0x00, - 0xfe, - 0x61, - 0x8e, - 0x22, - 0x45, - 0x41, - 0x9d, - 0x4c, - 0x21, - 0xed, - 0xae, - 0x82, - 0xed, - 0x19}, + .uuid.Char_UUID_128 = SERIAL_SVC_TX_CHAR_UUID, .uuid_type = UUID_TYPE_128, .char_properties = CHAR_PROP_READ | CHAR_PROP_INDICATE, .security_permissions = ATTR_PERMISSION_AUTHEN_READ, @@ -46,23 +32,7 @@ static const FlipperGattCharacteristicParams serial_svc_chars[SerialSvcGattChara {.name = "RX", .data_prop_type = FlipperGattCharacteristicDataFixed, .data.fixed.length = SERIAL_SVC_DATA_LEN_MAX, - .uuid.Char_UUID_128 = - {0x00, - 0x00, - 0xfe, - 0x62, - 0x8e, - 0x22, - 0x45, - 0x41, - 0x9d, - 0x4c, - 0x21, - 0xed, - 0xae, - 0x82, - 0xed, - 0x19}, + .uuid.Char_UUID_128 = SERIAL_SVC_RX_CHAR_UUID, .uuid_type = UUID_TYPE_128, .char_properties = CHAR_PROP_WRITE_WITHOUT_RESP | CHAR_PROP_WRITE | CHAR_PROP_READ, .security_permissions = ATTR_PERMISSION_AUTHEN_READ | ATTR_PERMISSION_AUTHEN_WRITE, @@ -72,23 +42,7 @@ static const FlipperGattCharacteristicParams serial_svc_chars[SerialSvcGattChara {.name = "Flow control", .data_prop_type = FlipperGattCharacteristicDataFixed, .data.fixed.length = sizeof(uint32_t), - .uuid.Char_UUID_128 = - {0x00, - 0x00, - 0xfe, - 0x63, - 0x8e, - 0x22, - 0x45, - 0x41, - 0x9d, - 0x4c, - 0x21, - 0xed, - 0xae, - 0x82, - 0xed, - 0x19}, + .uuid.Char_UUID_128 = SERIAL_SVC_FLOW_CONTROL_UUID, .uuid_type = UUID_TYPE_128, .char_properties = CHAR_PROP_READ | CHAR_PROP_NOTIFY, .security_permissions = ATTR_PERMISSION_AUTHEN_READ, @@ -98,23 +52,7 @@ static const FlipperGattCharacteristicParams serial_svc_chars[SerialSvcGattChara .name = "RPC status", .data_prop_type = FlipperGattCharacteristicDataFixed, .data.fixed.length = sizeof(SerialServiceRpcStatus), - .uuid.Char_UUID_128 = - {0x00, - 0x00, - 0xfe, - 0x64, - 0x8e, - 0x22, - 0x45, - 0x41, - 0x9d, - 0x4c, - 0x21, - 0xed, - 0xae, - 0x82, - 0xed, - 0x19}, + .uuid.Char_UUID_128 = SERIAL_SVC_RPC_STATUS_UUID, .uuid_type = UUID_TYPE_128, .char_properties = CHAR_PROP_READ | CHAR_PROP_WRITE | CHAR_PROP_NOTIFY, .security_permissions = ATTR_PERMISSION_AUTHEN_READ | ATTR_PERMISSION_AUTHEN_WRITE, @@ -131,9 +69,6 @@ typedef struct { void* context; } SerialSvc; -static const uint8_t service_uuid[] = - {0x00, 0x00, 0xfe, 0x60, 0xcc, 0x7a, 0x48, 0x2a, 0x98, 0x4a, 0x7f, 0x2e, 0xd5, 0xb3, 0xe5, 0x8f}; - static SerialSvc* serial_svc = NULL; static SVCCTL_EvtAckStatus_t serial_svc_event_handler(void* event) { @@ -219,7 +154,7 @@ void serial_svc_start() { // Add service status = aci_gatt_add_service( - UUID_TYPE_128, (Service_UUID_t*)service_uuid, PRIMARY_SERVICE, 12, &serial_svc->svc_handle); + UUID_TYPE_128, &service_uuid, PRIMARY_SERVICE, 12, &serial_svc->svc_handle); if(status) { FURI_LOG_E(TAG, "Failed to add Serial service: %d", status); } diff --git a/firmware/targets/f7/ble_glue/services/serial_service_uuid.inc b/firmware/targets/f7/ble_glue/services/serial_service_uuid.inc new file mode 100644 index 000000000000..a297d9ad604a --- /dev/null +++ b/firmware/targets/f7/ble_glue/services/serial_service_uuid.inc @@ -0,0 +1,12 @@ + +static const Service_UUID_t service_uuid = { .Service_UUID_128 = \ + { 0x00, 0x00, 0xfe, 0x60, 0xcc, 0x7a, 0x48, 0x2a, 0x98, 0x4a, 0x7f, 0x2e, 0xd5, 0xb3, 0xe5, 0x8f }}; + +#define SERIAL_SVC_TX_CHAR_UUID \ + { 0x00, 0x00, 0xfe, 0x61, 0x8e, 0x22, 0x45, 0x41, 0x9d, 0x4c, 0x21, 0xed, 0xae, 0x82, 0xed, 0x19 } +#define SERIAL_SVC_RX_CHAR_UUID \ + { 0x00, 0x00, 0xfe, 0x62, 0x8e, 0x22, 0x45, 0x41, 0x9d, 0x4c, 0x21, 0xed, 0xae, 0x82, 0xed, 0x19 } +#define SERIAL_SVC_FLOW_CONTROL_UUID \ + { 0x00, 0x00, 0xfe, 0x63, 0x8e, 0x22, 0x45, 0x41, 0x9d, 0x4c, 0x21, 0xed, 0xae, 0x82, 0xed, 0x19 } +#define SERIAL_SVC_RPC_STATUS_UUID \ + { 0x00, 0x00, 0xfe, 0x64, 0x8e, 0x22, 0x45, 0x41, 0x9d, 0x4c, 0x21, 0xed, 0xae, 0x82, 0xed, 0x19 }