Loading system/bta/gatt/bta_gattc_act.cc +0 −8 Original line number Diff line number Diff line Loading @@ -965,14 +965,6 @@ void bta_gattc_op_cmpl(tBTA_GATTC_CLCB* p_clcb, tBTA_GATTC_DATA* p_data) { } } /** operation completed */ void bta_gattc_ignore_op_cmpl(UNUSED_ATTR tBTA_GATTC_CLCB* p_clcb, tBTA_GATTC_DATA* p_data) { /* receive op complete when discovery is started, ignore the response, and wait for discovery finish and resent */ VLOG(1) << __func__ << ": op = " << +p_data->hdr.layer_specific; } /** start a search in the local server cache */ void bta_gattc_search(tBTA_GATTC_CLCB* p_clcb, tBTA_GATTC_DATA* p_data) { tGATT_STATUS status = GATT_INTERNAL_ERROR; Loading system/bta/gatt/bta_gattc_cache.cc +111 −7 Original line number Diff line number Diff line Loading @@ -46,6 +46,8 @@ #include "sdpdefs.h" #include "utl.h" #include <base/strings/string_number_conversions.h> using base::StringPrintf; using bluetooth::Uuid; using gatt::Characteristic; Loading @@ -70,7 +72,7 @@ static void bta_gattc_explore_srvc_finished(uint16_t conn_id, #define BTA_GATT_SDP_DB_SIZE 4096 #define GATT_CACHE_PREFIX "/data/misc/bluetooth/gatt_cache_" #define GATT_CACHE_VERSION 5 #define GATT_CACHE_VERSION 6 static void bta_gattc_generate_cache_file_name(char* buffer, size_t buffer_len, const RawAddress& bda) { Loading Loading @@ -153,16 +155,52 @@ static void bta_gattc_explore_next_service(uint16_t conn_id, return; } if (!p_srvc_cb->pending_discovery.StartNextServiceExploration()) { bta_gattc_explore_srvc_finished(conn_id, p_srvc_cb); return; } const auto& service = p_srvc_cb->pending_discovery.CurrentlyExploredService(); if (p_srvc_cb->pending_discovery.StartNextServiceExploration()) { const auto& service = p_srvc_cb->pending_discovery.CurrentlyExploredService(); VLOG(1) << "Start service discovery"; /* start discovering included services */ GATTC_Discover(conn_id, GATT_DISC_INC_SRVC, service.first, service.second); return; } // No more services to discover // As part of service discovery, read the values of "Characteristic Extended // Properties" descriptor const auto& descriptors = p_srvc_cb->pending_discovery.DescriptorHandlesToRead(); if (!descriptors.empty()) { if (p_srvc_cb->read_multiple_not_supported) { tGATT_READ_PARAM read_param{ .by_handle = {.handle = descriptors.front(), .auth_req = GATT_AUTH_REQ_NONE}}; GATTC_Read(conn_id, GATT_READ_BY_HANDLE, &read_param); // asynchronous continuation in bta_gattc_op_cmpl_during_discovery return; } // TODO(jpawlowski): as a limit we should use MTU/2 rather than // GATT_MAX_READ_MULTI_HANDLES /* each descriptor contains just 2 bytes, so response size is same as * request size */ size_t num_handles = std::min(descriptors.size(), (size_t)GATT_MAX_READ_MULTI_HANDLES); tGATT_READ_PARAM read_param; memset(&read_param, 0, sizeof(tGATT_READ_PARAM)); read_param.read_multiple.num_handles = num_handles; read_param.read_multiple.auth_req = GATT_AUTH_REQ_NONE; memcpy(&read_param.read_multiple.handles, descriptors.data(), sizeof(uint16_t) * num_handles); GATTC_Read(conn_id, GATT_READ_MULTIPLE, &read_param); // asynchronous continuation in bta_gattc_op_cmpl_during_discovery return; } bta_gattc_explore_srvc_finished(conn_id, p_srvc_cb); } static void bta_gattc_explore_srvc_finished(uint16_t conn_id, Loading Loading @@ -315,6 +353,66 @@ static tGATT_STATUS bta_gattc_sdp_service_disc(uint16_t conn_id, return GATT_SUCCESS; } /** operation completed */ void bta_gattc_op_cmpl_during_discovery(UNUSED_ATTR tBTA_GATTC_CLCB* p_clcb, tBTA_GATTC_DATA* p_data) { uint8_t op = (uint8_t)p_data->op_cmpl.op_code; if (op != GATTC_OPTYPE_READ) { /* receive op complete when discovery is started, ignore the response, and wait for discovery finish and resent */ VLOG(1) << __func__ << ": op = " << +p_data->hdr.layer_specific; return; } // our read operation is finished. // TODO: check if we can get here when any other read operation i.e. initiated // by upper layer apps, can get us there. tBTA_GATTC_SERV* p_srvc_cb = p_clcb->p_srcb; const uint8_t status = p_data->op_cmpl.status; if (status == GATT_REQ_NOT_SUPPORTED && !p_srvc_cb->read_multiple_not_supported) { // can't do "read multiple request", fall back to "read request" p_srvc_cb->read_multiple_not_supported = true; bta_gattc_explore_next_service(p_clcb->bta_conn_id, p_srvc_cb); return; } if (status != GATT_SUCCESS) { LOG(WARNING) << "Discovery on server failed: " << loghex(status); bta_gattc_reset_discover_st(p_clcb->p_srcb, GATT_ERROR); } const tGATT_VALUE& att_value = p_data->op_cmpl.p_cmpl->att_value; if (!p_srvc_cb->read_multiple_not_supported && att_value.len != 2) { // Just one Characteristic Extended Properties value at a time in Read // Response LOG(WARNING) << __func__ << " Read Response should be just 2 bytes!"; bta_gattc_reset_discover_st(p_clcb->p_srcb, GATT_ERROR); } // Parsing is same for "Read Multiple Response", and for "Read Response" const uint8_t* p = att_value.value; std::vector<uint16_t> value_of_descriptors; while (p < att_value.value + att_value.len) { uint16_t extended_properties; STREAM_TO_UINT16(extended_properties, p); value_of_descriptors.push_back(extended_properties); } bool ret = p_srvc_cb->pending_discovery.SetValueOfDescriptors(value_of_descriptors); if (!ret) { LOG(WARNING) << __func__ << " Problem setting Extended Properties descriptors values"; bta_gattc_reset_discover_st(p_clcb->p_srcb, GATT_ERROR); } // Continue service discovery bta_gattc_explore_next_service(p_clcb->bta_conn_id, p_srvc_cb); } /** callback function to GATT client stack */ void bta_gattc_disc_res_cback(uint16_t conn_id, tGATT_DISC_TYPE disc_type, tGATT_DISC_RES* p_data) { Loading Loading @@ -633,12 +731,18 @@ static void bta_gattc_get_gatt_db_impl(tBTA_GATTC_SERV* p_srvc_cb, charac.value_handle, 0 /* s_handle */, 0 /* e_handle */, charac.value_handle, charac.uuid, charac.properties); btgatt_db_element_t* characteristic = curr_db_attr; curr_db_attr++; for (const Descriptor& desc : charac.descriptors) { bta_gattc_fill_gatt_db_el( curr_db_attr, BTGATT_DB_DESCRIPTOR, desc.handle, 0 /* s_handle */, 0 /* e_handle */, desc.handle, desc.uuid, 0 /* property */); if (desc.uuid == Uuid::From16Bit(GATT_UUID_CHAR_EXT_PROP)) { characteristic->extended_properties = desc.characteristic_extended_properties; } curr_db_attr++; } } Loading system/bta/gatt/bta_gattc_int.h +6 −2 Original line number Diff line number Diff line Loading @@ -214,6 +214,10 @@ typedef struct { gatt::DatabaseBuilder pending_discovery; /* used only during service discovery, when reading Extended Characteristic * Properties */ bool read_multiple_not_supported; uint8_t srvc_hdl_chg; /* service handle change indication pending */ uint16_t attr_index; /* cahce NV saving/loading attribute index */ Loading Loading @@ -363,7 +367,7 @@ extern void bta_gattc_read_multi(tBTA_GATTC_CLCB* p_clcb, extern void bta_gattc_ci_open(tBTA_GATTC_CLCB* p_clcb, tBTA_GATTC_DATA* p_data); extern void bta_gattc_ci_close(tBTA_GATTC_CLCB* p_clcb, tBTA_GATTC_DATA* p_data); extern void bta_gattc_ignore_op_cmpl(tBTA_GATTC_CLCB* p_clcb, extern void bta_gattc_op_cmpl_during_discovery(tBTA_GATTC_CLCB* p_clcb, tBTA_GATTC_DATA* p_data); extern void bta_gattc_restart_discover(tBTA_GATTC_CLCB* p_clcb, tBTA_GATTC_DATA* p_msg); Loading system/bta/gatt/bta_gattc_main.cc +26 −26 Original line number Diff line number Diff line Loading @@ -57,7 +57,7 @@ enum { BTA_GATTC_CONFIRM, BTA_GATTC_EXEC, BTA_GATTC_READ_MULTI, BTA_GATTC_IGNORE_OP_CMPL, BTA_GATTC_OP_CMPL_DURING_DISCOVERY, BTA_GATTC_DISC_CLOSE, BTA_GATTC_RESTART_DISCOVER, BTA_GATTC_CFG_MTU, Loading Loading @@ -90,7 +90,7 @@ const tBTA_GATTC_ACTION bta_gattc_action[] = { bta_gattc_confirm, /* BTA_GATTC_CONFIRM */ bta_gattc_execute, /* BTA_GATTC_EXEC */ bta_gattc_read_multi, /* BTA_GATTC_READ_MULTI */ bta_gattc_ignore_op_cmpl, /* BTA_GATTC_IGNORE_OP_CMPL */ bta_gattc_op_cmpl_during_discovery, /* BTA_GATTC_OP_CMPL_DURING_DISCOVERY */ bta_gattc_disc_close, /* BTA_GATTC_DISC_CLOSE */ bta_gattc_restart_discover, /* BTA_GATTC_RESTART_DISCOVER */ bta_gattc_cfg_mtu /* BTA_GATTC_CFG_MTU */ Loading Loading @@ -256,7 +256,7 @@ static const uint8_t bta_gattc_st_discover[][BTA_GATTC_NUM_COLS] = { BTA_GATTC_DISCOVER_ST}, /* BTA_GATTC_DISCOVER_CMPL_EVT */ {BTA_GATTC_DISC_CMPL, BTA_GATTC_CONN_ST}, /* BTA_GATTC_OP_CMPL_EVT */ {BTA_GATTC_IGNORE_OP_CMPL, /* BTA_GATTC_OP_CMPL_EVT */ {BTA_GATTC_OP_CMPL_DURING_DISCOVERY, BTA_GATTC_DISCOVER_ST}, /* BTA_GATTC_INT_DISCONN_EVT */ {BTA_GATTC_CLOSE, BTA_GATTC_IDLE_ST}, Loading system/bta/gatt/database.cc +21 −3 Original line number Diff line number Diff line Loading @@ -35,6 +35,8 @@ const Uuid PRIMARY_SERVICE = Uuid::From16Bit(GATT_UUID_PRI_SERVICE); const Uuid SECONDARY_SERVICE = Uuid::From16Bit(GATT_UUID_SEC_SERVICE); const Uuid INCLUDE = Uuid::From16Bit(GATT_UUID_INCLUDE_SERVICE); const Uuid CHARACTERISTIC = Uuid::From16Bit(GATT_UUID_CHAR_DECLARE); const Uuid CHARACTERISTIC_EXTENDED_PROPERTIES = Uuid::From16Bit(GATT_UUID_CHAR_EXT_PROP); bool HandleInRange(const Service& svc, uint16_t handle) { return handle >= svc.handle && handle <= svc.end_handle; Loading Loading @@ -116,10 +118,17 @@ std::vector<StoredAttribute> Database::Serialize() const { .uuid = charac.uuid}}}); for (const Descriptor& desc : charac.descriptors) { if (desc.uuid == CHARACTERISTIC_EXTENDED_PROPERTIES) { nv_attr.push_back({desc.handle, desc.uuid, {.characteristic_extended_properties = desc.characteristic_extended_properties}}); } else { nv_attr.push_back({desc.handle, desc.uuid, {}}); } } } } return nv_attr; } Loading Loading @@ -182,11 +191,20 @@ Database Database::Deserialize(const std::vector<StoredAttribute>& nv_attr, .properties = attr.value.characteristic.properties, }); } else { if (attr.type == CHARACTERISTIC_EXTENDED_PROPERTIES) { current_service_it->characteristics.back().descriptors.emplace_back( Descriptor{.handle = attr.handle, .uuid = attr.type, .characteristic_extended_properties = attr.value.characteristic_extended_properties}); } else { current_service_it->characteristics.back().descriptors.emplace_back( Descriptor{.handle = attr.handle, .uuid = attr.type}); } } } *success = true; return result; } Loading Loading
system/bta/gatt/bta_gattc_act.cc +0 −8 Original line number Diff line number Diff line Loading @@ -965,14 +965,6 @@ void bta_gattc_op_cmpl(tBTA_GATTC_CLCB* p_clcb, tBTA_GATTC_DATA* p_data) { } } /** operation completed */ void bta_gattc_ignore_op_cmpl(UNUSED_ATTR tBTA_GATTC_CLCB* p_clcb, tBTA_GATTC_DATA* p_data) { /* receive op complete when discovery is started, ignore the response, and wait for discovery finish and resent */ VLOG(1) << __func__ << ": op = " << +p_data->hdr.layer_specific; } /** start a search in the local server cache */ void bta_gattc_search(tBTA_GATTC_CLCB* p_clcb, tBTA_GATTC_DATA* p_data) { tGATT_STATUS status = GATT_INTERNAL_ERROR; Loading
system/bta/gatt/bta_gattc_cache.cc +111 −7 Original line number Diff line number Diff line Loading @@ -46,6 +46,8 @@ #include "sdpdefs.h" #include "utl.h" #include <base/strings/string_number_conversions.h> using base::StringPrintf; using bluetooth::Uuid; using gatt::Characteristic; Loading @@ -70,7 +72,7 @@ static void bta_gattc_explore_srvc_finished(uint16_t conn_id, #define BTA_GATT_SDP_DB_SIZE 4096 #define GATT_CACHE_PREFIX "/data/misc/bluetooth/gatt_cache_" #define GATT_CACHE_VERSION 5 #define GATT_CACHE_VERSION 6 static void bta_gattc_generate_cache_file_name(char* buffer, size_t buffer_len, const RawAddress& bda) { Loading Loading @@ -153,16 +155,52 @@ static void bta_gattc_explore_next_service(uint16_t conn_id, return; } if (!p_srvc_cb->pending_discovery.StartNextServiceExploration()) { bta_gattc_explore_srvc_finished(conn_id, p_srvc_cb); return; } const auto& service = p_srvc_cb->pending_discovery.CurrentlyExploredService(); if (p_srvc_cb->pending_discovery.StartNextServiceExploration()) { const auto& service = p_srvc_cb->pending_discovery.CurrentlyExploredService(); VLOG(1) << "Start service discovery"; /* start discovering included services */ GATTC_Discover(conn_id, GATT_DISC_INC_SRVC, service.first, service.second); return; } // No more services to discover // As part of service discovery, read the values of "Characteristic Extended // Properties" descriptor const auto& descriptors = p_srvc_cb->pending_discovery.DescriptorHandlesToRead(); if (!descriptors.empty()) { if (p_srvc_cb->read_multiple_not_supported) { tGATT_READ_PARAM read_param{ .by_handle = {.handle = descriptors.front(), .auth_req = GATT_AUTH_REQ_NONE}}; GATTC_Read(conn_id, GATT_READ_BY_HANDLE, &read_param); // asynchronous continuation in bta_gattc_op_cmpl_during_discovery return; } // TODO(jpawlowski): as a limit we should use MTU/2 rather than // GATT_MAX_READ_MULTI_HANDLES /* each descriptor contains just 2 bytes, so response size is same as * request size */ size_t num_handles = std::min(descriptors.size(), (size_t)GATT_MAX_READ_MULTI_HANDLES); tGATT_READ_PARAM read_param; memset(&read_param, 0, sizeof(tGATT_READ_PARAM)); read_param.read_multiple.num_handles = num_handles; read_param.read_multiple.auth_req = GATT_AUTH_REQ_NONE; memcpy(&read_param.read_multiple.handles, descriptors.data(), sizeof(uint16_t) * num_handles); GATTC_Read(conn_id, GATT_READ_MULTIPLE, &read_param); // asynchronous continuation in bta_gattc_op_cmpl_during_discovery return; } bta_gattc_explore_srvc_finished(conn_id, p_srvc_cb); } static void bta_gattc_explore_srvc_finished(uint16_t conn_id, Loading Loading @@ -315,6 +353,66 @@ static tGATT_STATUS bta_gattc_sdp_service_disc(uint16_t conn_id, return GATT_SUCCESS; } /** operation completed */ void bta_gattc_op_cmpl_during_discovery(UNUSED_ATTR tBTA_GATTC_CLCB* p_clcb, tBTA_GATTC_DATA* p_data) { uint8_t op = (uint8_t)p_data->op_cmpl.op_code; if (op != GATTC_OPTYPE_READ) { /* receive op complete when discovery is started, ignore the response, and wait for discovery finish and resent */ VLOG(1) << __func__ << ": op = " << +p_data->hdr.layer_specific; return; } // our read operation is finished. // TODO: check if we can get here when any other read operation i.e. initiated // by upper layer apps, can get us there. tBTA_GATTC_SERV* p_srvc_cb = p_clcb->p_srcb; const uint8_t status = p_data->op_cmpl.status; if (status == GATT_REQ_NOT_SUPPORTED && !p_srvc_cb->read_multiple_not_supported) { // can't do "read multiple request", fall back to "read request" p_srvc_cb->read_multiple_not_supported = true; bta_gattc_explore_next_service(p_clcb->bta_conn_id, p_srvc_cb); return; } if (status != GATT_SUCCESS) { LOG(WARNING) << "Discovery on server failed: " << loghex(status); bta_gattc_reset_discover_st(p_clcb->p_srcb, GATT_ERROR); } const tGATT_VALUE& att_value = p_data->op_cmpl.p_cmpl->att_value; if (!p_srvc_cb->read_multiple_not_supported && att_value.len != 2) { // Just one Characteristic Extended Properties value at a time in Read // Response LOG(WARNING) << __func__ << " Read Response should be just 2 bytes!"; bta_gattc_reset_discover_st(p_clcb->p_srcb, GATT_ERROR); } // Parsing is same for "Read Multiple Response", and for "Read Response" const uint8_t* p = att_value.value; std::vector<uint16_t> value_of_descriptors; while (p < att_value.value + att_value.len) { uint16_t extended_properties; STREAM_TO_UINT16(extended_properties, p); value_of_descriptors.push_back(extended_properties); } bool ret = p_srvc_cb->pending_discovery.SetValueOfDescriptors(value_of_descriptors); if (!ret) { LOG(WARNING) << __func__ << " Problem setting Extended Properties descriptors values"; bta_gattc_reset_discover_st(p_clcb->p_srcb, GATT_ERROR); } // Continue service discovery bta_gattc_explore_next_service(p_clcb->bta_conn_id, p_srvc_cb); } /** callback function to GATT client stack */ void bta_gattc_disc_res_cback(uint16_t conn_id, tGATT_DISC_TYPE disc_type, tGATT_DISC_RES* p_data) { Loading Loading @@ -633,12 +731,18 @@ static void bta_gattc_get_gatt_db_impl(tBTA_GATTC_SERV* p_srvc_cb, charac.value_handle, 0 /* s_handle */, 0 /* e_handle */, charac.value_handle, charac.uuid, charac.properties); btgatt_db_element_t* characteristic = curr_db_attr; curr_db_attr++; for (const Descriptor& desc : charac.descriptors) { bta_gattc_fill_gatt_db_el( curr_db_attr, BTGATT_DB_DESCRIPTOR, desc.handle, 0 /* s_handle */, 0 /* e_handle */, desc.handle, desc.uuid, 0 /* property */); if (desc.uuid == Uuid::From16Bit(GATT_UUID_CHAR_EXT_PROP)) { characteristic->extended_properties = desc.characteristic_extended_properties; } curr_db_attr++; } } Loading
system/bta/gatt/bta_gattc_int.h +6 −2 Original line number Diff line number Diff line Loading @@ -214,6 +214,10 @@ typedef struct { gatt::DatabaseBuilder pending_discovery; /* used only during service discovery, when reading Extended Characteristic * Properties */ bool read_multiple_not_supported; uint8_t srvc_hdl_chg; /* service handle change indication pending */ uint16_t attr_index; /* cahce NV saving/loading attribute index */ Loading Loading @@ -363,7 +367,7 @@ extern void bta_gattc_read_multi(tBTA_GATTC_CLCB* p_clcb, extern void bta_gattc_ci_open(tBTA_GATTC_CLCB* p_clcb, tBTA_GATTC_DATA* p_data); extern void bta_gattc_ci_close(tBTA_GATTC_CLCB* p_clcb, tBTA_GATTC_DATA* p_data); extern void bta_gattc_ignore_op_cmpl(tBTA_GATTC_CLCB* p_clcb, extern void bta_gattc_op_cmpl_during_discovery(tBTA_GATTC_CLCB* p_clcb, tBTA_GATTC_DATA* p_data); extern void bta_gattc_restart_discover(tBTA_GATTC_CLCB* p_clcb, tBTA_GATTC_DATA* p_msg); Loading
system/bta/gatt/bta_gattc_main.cc +26 −26 Original line number Diff line number Diff line Loading @@ -57,7 +57,7 @@ enum { BTA_GATTC_CONFIRM, BTA_GATTC_EXEC, BTA_GATTC_READ_MULTI, BTA_GATTC_IGNORE_OP_CMPL, BTA_GATTC_OP_CMPL_DURING_DISCOVERY, BTA_GATTC_DISC_CLOSE, BTA_GATTC_RESTART_DISCOVER, BTA_GATTC_CFG_MTU, Loading Loading @@ -90,7 +90,7 @@ const tBTA_GATTC_ACTION bta_gattc_action[] = { bta_gattc_confirm, /* BTA_GATTC_CONFIRM */ bta_gattc_execute, /* BTA_GATTC_EXEC */ bta_gattc_read_multi, /* BTA_GATTC_READ_MULTI */ bta_gattc_ignore_op_cmpl, /* BTA_GATTC_IGNORE_OP_CMPL */ bta_gattc_op_cmpl_during_discovery, /* BTA_GATTC_OP_CMPL_DURING_DISCOVERY */ bta_gattc_disc_close, /* BTA_GATTC_DISC_CLOSE */ bta_gattc_restart_discover, /* BTA_GATTC_RESTART_DISCOVER */ bta_gattc_cfg_mtu /* BTA_GATTC_CFG_MTU */ Loading Loading @@ -256,7 +256,7 @@ static const uint8_t bta_gattc_st_discover[][BTA_GATTC_NUM_COLS] = { BTA_GATTC_DISCOVER_ST}, /* BTA_GATTC_DISCOVER_CMPL_EVT */ {BTA_GATTC_DISC_CMPL, BTA_GATTC_CONN_ST}, /* BTA_GATTC_OP_CMPL_EVT */ {BTA_GATTC_IGNORE_OP_CMPL, /* BTA_GATTC_OP_CMPL_EVT */ {BTA_GATTC_OP_CMPL_DURING_DISCOVERY, BTA_GATTC_DISCOVER_ST}, /* BTA_GATTC_INT_DISCONN_EVT */ {BTA_GATTC_CLOSE, BTA_GATTC_IDLE_ST}, Loading
system/bta/gatt/database.cc +21 −3 Original line number Diff line number Diff line Loading @@ -35,6 +35,8 @@ const Uuid PRIMARY_SERVICE = Uuid::From16Bit(GATT_UUID_PRI_SERVICE); const Uuid SECONDARY_SERVICE = Uuid::From16Bit(GATT_UUID_SEC_SERVICE); const Uuid INCLUDE = Uuid::From16Bit(GATT_UUID_INCLUDE_SERVICE); const Uuid CHARACTERISTIC = Uuid::From16Bit(GATT_UUID_CHAR_DECLARE); const Uuid CHARACTERISTIC_EXTENDED_PROPERTIES = Uuid::From16Bit(GATT_UUID_CHAR_EXT_PROP); bool HandleInRange(const Service& svc, uint16_t handle) { return handle >= svc.handle && handle <= svc.end_handle; Loading Loading @@ -116,10 +118,17 @@ std::vector<StoredAttribute> Database::Serialize() const { .uuid = charac.uuid}}}); for (const Descriptor& desc : charac.descriptors) { if (desc.uuid == CHARACTERISTIC_EXTENDED_PROPERTIES) { nv_attr.push_back({desc.handle, desc.uuid, {.characteristic_extended_properties = desc.characteristic_extended_properties}}); } else { nv_attr.push_back({desc.handle, desc.uuid, {}}); } } } } return nv_attr; } Loading Loading @@ -182,11 +191,20 @@ Database Database::Deserialize(const std::vector<StoredAttribute>& nv_attr, .properties = attr.value.characteristic.properties, }); } else { if (attr.type == CHARACTERISTIC_EXTENDED_PROPERTIES) { current_service_it->characteristics.back().descriptors.emplace_back( Descriptor{.handle = attr.handle, .uuid = attr.type, .characteristic_extended_properties = attr.value.characteristic_extended_properties}); } else { current_service_it->characteristics.back().descriptors.emplace_back( Descriptor{.handle = attr.handle, .uuid = attr.type}); } } } *success = true; return result; } Loading