-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add GATT Client (discovery attributes) (#131)
Merged PR 11381: [ECR] GATT Client (discovery attributes) GATT Client (discovery attributes). (cherry picked from commit f128b77ef3378c861caaf9d237c5113bbe9b6440) Co-authored-by: Santos, Gabriel <Gabriel.Santos_1@philips.com>
- Loading branch information
1 parent
201687e
commit 121c351
Showing
6 changed files
with
377 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,235 @@ | ||
#include "hal_st/middlewares/ble_middleware/GattClientSt.hpp" | ||
#include "infra/event/EventDispatcherWithWeakPtr.hpp" | ||
#include "infra/stream/InputStream.hpp" | ||
#include "infra/util/Endian.hpp" | ||
|
||
extern "C" | ||
{ | ||
#include "auto/ble_gatt_aci.h" | ||
#include "ble/ble.h" | ||
#include "ble/core/ble_core.h" | ||
} | ||
|
||
namespace hal | ||
{ | ||
GattClientSt::GattClientSt(hal::HciEventSource& hciEventSource) | ||
: hal::HciEventSink(hciEventSource) | ||
, connectionHandle(invalidConnection) | ||
{} | ||
|
||
void GattClientSt::StartServiceDiscovery() | ||
{ | ||
onDiscoveryCompletion = [](services::GattClientDiscoveryObserver& observer) { observer.ServiceDiscoveryComplete(); }; | ||
|
||
aci_gatt_disc_all_primary_services(connectionHandle); | ||
} | ||
|
||
void GattClientSt::StartCharacteristicDiscovery(const services::GattService& service) | ||
{ | ||
onDiscoveryCompletion = [](services::GattClientDiscoveryObserver& observer) { observer.CharacteristicDiscoveryComplete(); }; | ||
|
||
aci_gatt_disc_all_char_of_service(connectionHandle, service.Handle(), service.EndHandle()); | ||
} | ||
|
||
void GattClientSt::StartDescriptorDiscovery(const services::GattService& service) | ||
{ | ||
onDiscoveryCompletion = [](services::GattClientDiscoveryObserver& observer) { observer.DescriptorDiscoveryComplete(); }; | ||
|
||
aci_gatt_disc_all_char_desc(connectionHandle, service.Handle(), service.EndHandle()); | ||
} | ||
|
||
void GattClientSt::HciEvent(hci_event_pckt& event) | ||
{ | ||
switch (event.evt) | ||
{ | ||
case HCI_DISCONNECTION_COMPLETE_EVT_CODE: | ||
HandleHciDisconnectEvent(event); | ||
break; | ||
case HCI_LE_META_EVT_CODE: | ||
HandleHciLeMetaEvent(event); | ||
break; | ||
case HCI_VENDOR_SPECIFIC_DEBUG_EVT_CODE: | ||
HandleHciVendorSpecificDebugEvent(event); | ||
break; | ||
default: | ||
break; | ||
} | ||
} | ||
|
||
void GattClientSt::HandleHciLeMetaEvent(hci_event_pckt& eventPacket) | ||
{ | ||
auto metaEvent = reinterpret_cast<evt_le_meta_event*>(eventPacket.data); | ||
|
||
switch (metaEvent->subevent) | ||
{ | ||
case HCI_LE_ENHANCED_CONNECTION_COMPLETE_SUBEVT_CODE: | ||
HandleHciLeEnhancedConnectionCompleteEvent(metaEvent); | ||
break; | ||
case HCI_LE_CONNECTION_COMPLETE_SUBEVT_CODE: | ||
HandleHciLeConnectionCompleteEvent(metaEvent); | ||
break; | ||
default: | ||
break; | ||
} | ||
} | ||
|
||
void GattClientSt::HandleHciVendorSpecificDebugEvent(hci_event_pckt& eventPacket) | ||
{ | ||
auto vendorEvent = reinterpret_cast<evt_blecore_aci*>(eventPacket.data); | ||
|
||
switch (vendorEvent->ecode) | ||
{ | ||
case ACI_ATT_READ_BY_GROUP_TYPE_RESP_VSEVT_CODE: | ||
HandleAttReadByGroupTypeResponse(vendorEvent); | ||
break; | ||
case ACI_ATT_READ_BY_TYPE_RESP_VSEVT_CODE: | ||
HandleAttReadByTypeResponse(vendorEvent); | ||
break; | ||
case ACI_ATT_FIND_INFO_RESP_VSEVT_CODE: | ||
HandleAttFindInfoResponse(vendorEvent); | ||
break; | ||
case ACI_GATT_PROC_COMPLETE_VSEVT_CODE: | ||
HandleGattCompleteResponse(vendorEvent); | ||
break; | ||
default: | ||
break; | ||
} | ||
} | ||
|
||
void GattClientSt::HandleAttReadByGroupTypeResponse(evt_blecore_aci* vendorEvent) | ||
{ | ||
const uint8_t uuid16 = 6; | ||
auto attReadByGroupResponse = *reinterpret_cast<aci_att_read_by_group_type_resp_event_rp0*>(vendorEvent->data); | ||
|
||
infra::ByteRange data(&attReadByGroupResponse.Attribute_Data_List[0], &attReadByGroupResponse.Attribute_Data_List[0] + attReadByGroupResponse.Data_Length); | ||
infra::ByteInputStream stream(data, infra::softFail); | ||
|
||
really_assert(attReadByGroupResponse.Connection_Handle == connectionHandle); | ||
|
||
HandleServiceDiscovered(stream, attReadByGroupResponse.Attribute_Data_Length == uuid16); | ||
} | ||
|
||
void GattClientSt::HandleAttReadByTypeResponse(evt_blecore_aci* vendorEvent) | ||
{ | ||
const uint8_t uuid16 = 7; | ||
auto attReadByTypeResponse = *reinterpret_cast<aci_att_read_by_type_resp_event_rp0*>(vendorEvent->data); | ||
|
||
infra::ByteRange data(&attReadByTypeResponse.Handle_Value_Pair_Data[0], &attReadByTypeResponse.Handle_Value_Pair_Data[0] + attReadByTypeResponse.Data_Length); | ||
infra::ByteInputStream stream(data, infra::softFail); | ||
|
||
really_assert(attReadByTypeResponse.Connection_Handle == connectionHandle); | ||
|
||
HandleCharacteristicDiscovered(stream, attReadByTypeResponse.Handle_Value_Pair_Length == uuid16); | ||
} | ||
|
||
void GattClientSt::HandleAttFindInfoResponse(evt_blecore_aci* vendorEvent) | ||
{ | ||
auto attFindInfoResponse = *reinterpret_cast<aci_att_find_info_resp_event_rp0*>(vendorEvent->data); | ||
|
||
infra::ByteRange data(&attFindInfoResponse.Handle_UUID_Pair[0], &attFindInfoResponse.Handle_UUID_Pair[0] + attFindInfoResponse.Event_Data_Length); | ||
infra::ByteInputStream stream(data, infra::softFail); | ||
|
||
really_assert(attFindInfoResponse.Connection_Handle == connectionHandle); | ||
|
||
HandleDescriptorDiscovered(stream, attFindInfoResponse.Format == UUID_TYPE_16); | ||
} | ||
|
||
void GattClientSt::HandleGattCompleteResponse(evt_blecore_aci* vendorEvent) | ||
{ | ||
auto gattProcedureEvent = *reinterpret_cast<aci_gatt_proc_complete_event_rp0*>(vendorEvent->data); | ||
|
||
really_assert(gattProcedureEvent.Connection_Handle == connectionHandle); | ||
really_assert(gattProcedureEvent.Error_Code == BLE_STATUS_SUCCESS); | ||
|
||
if (onDiscoveryCompletion) | ||
infra::Subject<services::GattClientDiscoveryObserver>::NotifyObservers(std::exchange(onDiscoveryCompletion, nullptr)); | ||
} | ||
|
||
void GattClientSt::HandleHciLeConnectionCompleteEvent(evt_le_meta_event* metaEvent) | ||
{ | ||
auto connectionCompleteEvent = *reinterpret_cast<hci_le_connection_complete_event_rp0*>(metaEvent->data); | ||
|
||
really_assert(connectionCompleteEvent.Status == BLE_STATUS_SUCCESS); | ||
|
||
connectionHandle = connectionCompleteEvent.Connection_Handle; | ||
} | ||
|
||
void GattClientSt::HandleHciLeEnhancedConnectionCompleteEvent(evt_le_meta_event* metaEvent) | ||
{ | ||
auto enhancedConnectionCompleteEvent = *reinterpret_cast<hci_le_enhanced_connection_complete_event_rp0*>(metaEvent->data); | ||
|
||
really_assert(enhancedConnectionCompleteEvent.Status == BLE_STATUS_SUCCESS); | ||
|
||
connectionHandle = enhancedConnectionCompleteEvent.Connection_Handle; | ||
} | ||
|
||
void GattClientSt::HandleHciDisconnectEvent(hci_event_pckt& eventPacket) | ||
{ | ||
auto disconnectionCompleteEvent = *reinterpret_cast<hci_disconnection_complete_event_rp0*>(eventPacket.data); | ||
|
||
really_assert(disconnectionCompleteEvent.Connection_Handle == connectionHandle); | ||
really_assert(disconnectionCompleteEvent.Status == BLE_STATUS_SUCCESS); | ||
|
||
connectionHandle = GattClientSt::invalidConnection; | ||
} | ||
|
||
void GattClientSt::HandleServiceDiscovered(infra::DataInputStream& stream, bool isUuid16) | ||
{ | ||
while (!stream.Empty()) | ||
{ | ||
Atttributes attributes; | ||
|
||
stream >> attributes.startHandle >> attributes.endHandle; | ||
|
||
HandleUuidFromDiscovery(stream, isUuid16, attributes.type); | ||
|
||
really_assert(!stream.Failed()); | ||
|
||
infra::Subject<services::GattClientDiscoveryObserver>::NotifyObservers([&attributes](auto& observer) { observer.ServiceDiscovered(attributes.type, attributes.startHandle, attributes.endHandle); }); | ||
} | ||
} | ||
|
||
void GattClientSt::HandleCharacteristicDiscovered(infra::DataInputStream& stream, bool isUuid16) | ||
{ | ||
while (!stream.Empty()) | ||
{ | ||
Atttributes attributes; | ||
|
||
stream >> attributes.startHandle >> attributes.properties >> attributes.endHandle; | ||
|
||
HandleUuidFromDiscovery(stream, isUuid16, attributes.type); | ||
|
||
really_assert(!stream.Failed()); | ||
|
||
infra::Subject<services::GattClientDiscoveryObserver>::NotifyObservers([&attributes](auto& observer) { observer.CharacteristicDiscovered(attributes.type, attributes.startHandle, attributes.endHandle, attributes.properties); }); | ||
} | ||
} | ||
|
||
void GattClientSt::HandleDescriptorDiscovered(infra::DataInputStream& stream, bool isUuid16) | ||
{ | ||
while (!stream.Empty()) | ||
{ | ||
Atttributes attributes; | ||
|
||
stream >> attributes.startHandle; | ||
|
||
HandleUuidFromDiscovery(stream, isUuid16, attributes.type); | ||
|
||
really_assert(!stream.Failed()); | ||
|
||
infra::Subject<services::GattClientDiscoveryObserver>::NotifyObservers([&attributes](auto& observer) { observer.DescriptorDiscovered(attributes.type, attributes.startHandle); }); | ||
} | ||
} | ||
|
||
void GattClientSt::HandleUuidFromDiscovery(infra::DataInputStream& stream, bool isUuid16, services::AttAttribute::Uuid& type) | ||
{ | ||
if (isUuid16) | ||
{ | ||
stream >> type.Emplace<services::AttAttribute::Uuid16>(); | ||
} | ||
else | ||
{ | ||
stream >> type.Emplace<services::AttAttribute::Uuid128>(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
#ifndef HAL_ST_GATT_CLIENT_ST_HPP | ||
#define HAL_ST_GATT_CLIENT_ST_HPP | ||
|
||
#include "ble/ble.h" | ||
#include "hal_st/middlewares/ble_middleware/HciEventObserver.hpp" | ||
#include "infra/util/AutoResetFunction.hpp" | ||
#include "infra/util/BoundedVector.hpp" | ||
#include "infra/stream/ByteInputStream.hpp" | ||
#include "services/ble/GattClient.hpp" | ||
|
||
namespace hal | ||
{ | ||
class GattClientSt | ||
: public services::GattClientDiscovery | ||
, public hal::HciEventSink | ||
{ | ||
public: | ||
explicit GattClientSt(hal::HciEventSource& hciEventSource); | ||
|
||
// Implementation of services::GattClientDiscovery | ||
virtual void StartServiceDiscovery() override; | ||
virtual void StartCharacteristicDiscovery(const services::GattService& service) override; | ||
virtual void StartDescriptorDiscovery(const services::GattService& service) override; | ||
|
||
// Implementation of hal::HciEventSink | ||
virtual void HciEvent(hci_event_pckt& event) override; | ||
|
||
protected: | ||
virtual void HandleHciDisconnectEvent(hci_event_pckt& eventPacket); | ||
virtual void HandleHciLeMetaEvent(hci_event_pckt& eventPacket); | ||
virtual void HandleHciVendorSpecificDebugEvent(hci_event_pckt& eventPacket); | ||
|
||
virtual void HandleHciLeConnectionCompleteEvent(evt_le_meta_event* metaEvent); | ||
virtual void HandleHciLeEnhancedConnectionCompleteEvent(evt_le_meta_event* metaEvent); | ||
|
||
virtual void HandleGattCompleteResponse(evt_blecore_aci* vendorEvent); | ||
|
||
virtual void HandleAttReadByGroupTypeResponse(evt_blecore_aci* vendorEvent); | ||
virtual void HandleAttReadByTypeResponse(evt_blecore_aci* vendorEvent); | ||
virtual void HandleAttFindInfoResponse(evt_blecore_aci* vendorEvent); | ||
|
||
private: | ||
void HandleServiceDiscovered(infra::DataInputStream& stream, bool isUuid16); | ||
void HandleCharacteristicDiscovered(infra::DataInputStream& stream, bool isUuid16); | ||
void HandleDescriptorDiscovered(infra::DataInputStream& stream, bool isUuid16); | ||
void HandleUuidFromDiscovery(infra::DataInputStream& stream, bool isUuid16, services::AttAttribute::Uuid& type); | ||
|
||
private: | ||
struct Atttributes | ||
{ | ||
services::AttAttribute::Uuid type; | ||
services::AttAttribute::Handle startHandle; | ||
services::AttAttribute::Handle endHandle; | ||
services::GattCharacteristic::PropertyFlags properties; | ||
}; | ||
|
||
private: | ||
uint16_t connectionHandle; | ||
|
||
static constexpr uint16_t invalidConnection = 0xffff; | ||
|
||
infra::Function<void(services::GattClientDiscoveryObserver&)> onDiscoveryCompletion; | ||
}; | ||
} | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
#include "hal_st/middlewares/ble_middleware/TracingGattClientSt.hpp" | ||
#include "infra/stream/StringOutputStream.hpp" | ||
|
||
namespace infra | ||
{ | ||
TextOutputStream& operator<<(TextOutputStream& stream, const services::AttAttribute::Uuid& uuid) | ||
{ | ||
if (uuid.Is<services::AttAttribute::Uuid16>()) | ||
stream << "0x" << hex << uuid.Get<services::AttAttribute::Uuid16>(); | ||
else | ||
stream << "[" << AsHex(MakeByteRange(uuid.Get<services::AttAttribute::Uuid128>())) << "]"; | ||
|
||
return stream; | ||
} | ||
} | ||
|
||
namespace hal | ||
{ | ||
TracingGattClientSt::TracingGattClientSt(hal::HciEventSource& hciEventSource, services::Tracer& tracer) | ||
: GattClientSt(hciEventSource) | ||
, tracer(tracer) | ||
{ | ||
tracer.Trace() << "TracingGattClientSt::TracingGattClientSt()"; | ||
} | ||
|
||
void TracingGattClientSt::StartServiceDiscovery() | ||
{ | ||
tracer.Trace() << "TracingGattClientSt::StartServiceDiscovery"; | ||
GattClientSt::StartServiceDiscovery(); | ||
} | ||
|
||
void TracingGattClientSt::StartCharacteristicDiscovery(const services::GattService& service) | ||
{ | ||
tracer.Trace() << "TracingGattClientSt::StartCharacteristicDiscovery"; | ||
GattClientSt::StartCharacteristicDiscovery(service); | ||
} | ||
|
||
void TracingGattClientSt::StartDescriptorDiscovery(const services::GattService& service) | ||
{ | ||
tracer.Trace() << "TracingGattClientSt::StartDescriptorDiscovery"; | ||
GattClientSt::StartDescriptorDiscovery(service); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
#ifndef HAL_ST_TRACING_GATT_CLIENT_ST_HPP | ||
#define HAL_ST_TRACING_GATT_CLIENT_ST_HPP | ||
|
||
#include "hal_st/middlewares/ble_middleware/GattClientSt.hpp" | ||
#include "services/tracer/Tracer.hpp" | ||
|
||
namespace hal | ||
{ | ||
class TracingGattClientSt | ||
: public GattClientSt | ||
{ | ||
public: | ||
explicit TracingGattClientSt(hal::HciEventSource& hciEventSource, services::Tracer& tracer); | ||
|
||
// Implementation of services::GattClientDiscovery | ||
virtual void StartServiceDiscovery() override; | ||
virtual void StartCharacteristicDiscovery(const services::GattService& service) override; | ||
virtual void StartDescriptorDiscovery(const services::GattService& service) override; | ||
|
||
private: | ||
services::Tracer& tracer; | ||
}; | ||
} | ||
|
||
#endif |
Oops, something went wrong.