ELEC-C7222
Libraries for ELEC C7222 Course Work
Loading...
Searching...
No Matches
c7222::AttributeServer Class Reference

Encapsulates the ATT attribute server for the Pico W BLE stack. More...

#include <attribute_server.hpp>

Inheritance diagram for c7222::AttributeServer:
Inheritance graph
Collaboration diagram for c7222::AttributeServer:
Collaboration graph

Classes

struct  ReadResult
 

Public Member Functions

Initialization and State
BleError Init (const void *context)
 Initialize the ATT server from a platform context.
 
bool IsInitialized () const
 Check whether the server was initialized.
 
const void * GetContext () const
 Get the stored platform context pointer.
 
bool HasContext () const
 Check whether a platform context has been stored.
 
Service and Characteristic Lookup
size_t GetServiceCount () const
 Get the number of parsed services.
 
ServiceGetService (size_t index)
 Get a service by index.
 
const std::list< Service > & GetServices () const
 Get the list of services.
 
std::list< Service > & GetServices ()
 Get the list of services.
 
const ServiceGetService (size_t index) const
 Get a service by index (const version).
 
ServiceFindServiceByUuid (const Uuid &uuid)
 Find a service by UUID.
 
const ServiceFindServiceByUuid (const Uuid &uuid) const
 Find a service by UUID (const version).
 
bool HasServicesRequiringAuthentication () const
 Check whether any service contains characteristics requiring authentication.
 
bool HasServicesRequiringEncryption () const
 Check whether any service contains characteristics requiring encryption.
 
bool HasServicesRequiringAuthorization () const
 Check whether any service contains characteristics requiring authorization.
 
std::list< Characteristic * > FindCharacteristicByUuid (const Uuid &uuid)
 Find characteristics by UUID.
 
std::list< const Characteristic * > FindCharacteristicByUuid (const Uuid &uuid) const
 Find characteristics by UUID (const version).
 
CharacteristicFindCharacteristicByHandle (uint16_t handle)
 Find a characteristic by attribute handle.
 
const CharacteristicFindCharacteristicByHandle (uint16_t handle) const
 Find a characteristic by attribute handle (const version).
 
Iteration
auto begin ()
 Get iterator to first service.
 
auto end ()
 Get iterator to end of services.
 
auto begin () const
 Get const iterator to first service.
 
auto end () const
 Get const iterator to end of services.
 
auto cbegin () const
 Get const iterator to first service.
 
auto cend () const
 Get const iterator to end of services.
 
Connection and Event Routing
void SetConnectionHandle (uint16_t connection_handle)
 Set the active connection handle for all characteristics.
 
void SetSecurityLevel (uint16_t connection_handle, uint8_t security_level)
 Update cached security level for the active connection.
 
uint8_t GetSecurityLevel (uint16_t connection_handle) const
 Get cached security level for the active connection.
 
void SetAuthorizationGranted (uint16_t connection_handle, bool granted)
 Update cached authorization result for the active connection.
 
bool IsAuthorizationGranted (uint16_t connection_handle) const
 Get cached authorization result for the active connection.
 
uint16_t GetConnectionHandle () const
 Get the current connection handle.
 
void SetDisconnected ()
 
bool HasConnectionHandle () const
 Check whether a connection handle is set.
 
bool IsConnected () const
 Queries whether a client is connected to the server.
 
BleError DispatchBleHciPacket (uint8_t packet_type, const uint8_t *packet_data, uint16_t packet_data_size)
 Dispatch HCI ATT events to all characteristics.
 
ATT Callbacks (Internal Use)
ReadResult ReadAttribute (uint16_t attribute_handle, uint16_t offset, uint8_t *buffer, uint16_t buffer_size)
 Handle an ATT read request (internal use).
 
BleError WriteAttribute (uint16_t attribute_handle, uint16_t offset, const uint8_t *data, uint16_t size)
 Handle an ATT write request (internal use).
 
Service Parsing Helpers
void InitServices (std::list< Attribute > &attributes)
 Initialize services from a parsed attribute list.
 
- Public Member Functions inherited from c7222::NonCopyable
 NonCopyable (const NonCopyable &)=delete
 
NonCopyableoperator= (const NonCopyable &)=delete
 
 NonCopyable (NonCopyable &&)=default
 
NonCopyableoperator= (NonCopyable &&)=default
 
- Public Member Functions inherited from c7222::NonMovable
 NonMovable (const NonMovable &)=default
 
NonMovableoperator= (const NonMovable &)=default
 
 NonMovable (NonMovable &&)=delete
 
NonMovableoperator= (NonMovable &&)=delete
 

Static Public Member Functions

Construction and Lifetime
static AttributeServerGetInstance ()
 Get the singleton instance.
 

Friends

Stream Output
std::ostream & operator<< (std::ostream &os, const AttributeServer &server)
 Stream insertion operator for attribute server information.
 

Additional Inherited Members

- Protected Member Functions inherited from c7222::NonCopyableNonMovable
 NonCopyableNonMovable ()=default
 
 ~NonCopyableNonMovable ()=default
 
- Protected Member Functions inherited from c7222::NonCopyable
 NonCopyable ()=default
 
 ~NonCopyable ()=default
 
- Protected Member Functions inherited from c7222::NonMovable
 NonMovable ()=default
 
 ~NonMovable ()=default
 

Detailed Description

Encapsulates the ATT attribute server for the Pico W BLE stack.

This class parses the compiled ATT database into GATT Service/Characteristic objects and routes ATT read/write requests to the appropriate handlers. It also forwards HCI ATT events to characteristics for indications and flow-control callbacks.

Note
This implementation supports a single client connection at a time. If more than one client attempts to connect, the server will accept all of them but use only the last connection handle in its responses. So, it is not recommended for use cases requiring multiple concurrent connections.

Responsibilities

  • ATT DB parsing: Platform-specific code converts the ATT database blob into Attribute objects, then InitServices() builds Service and Characteristic objects in discovery order.
  • ATT routing: Dispatches ATT read/write requests to the correct Characteristic or service-level Attribute handlers.
  • HCI event fan-out: Forwards ATT-related HCI events (e.g. indication completion, can-send-now) to characteristics so they can drive notifications/indications.

Security Queries (Planning Before Connections)

The server now exposes aggregate security checks across all parsed services:

These helpers are intended to guide SecurityManager enablement and configuration before connections are established.


Connection Security State (Runtime)

The server caches the active connection handle and the security state associated with that connection:

Platform glue (e.g., BTstack packet handlers) should update these values when GAP/SM events are received so characteristic descriptor writes can be validated consistently.


BTstack Integration Details

BTstack exposes the ATT server through a C API:

  • att_server_init(att_db, read_cb, write_cb) registers the database and callbacks used when a client reads/writes an attribute.
  • Read callbacks return a byte count on success or an ATT error code.
  • Write callbacks return 0 on success or an ATT error code.

This class wraps that model as follows:

The class itself is platform-agnostic; the BTstack binding and ATT DB parsing live in the platform implementation (platform/rpi_pico/attribute_server.cpp).


RPi Pico W (BTstack) Implementation

On RP2040/Pico W, Init() treats the context pointer as the BTstack ATT DB blob (att_db.h/att_db.c) and:

  • Registers BTstack callbacks via att_server_init().
  • Parses the ATT DB into Attribute objects and calls InitServices().

The context pointer is cached the first time Init() is called. Subsequent calls reuse the stored context pointer so the ATT DB remains stable.

The ATT DB blob must remain valid for the lifetime of the server because parsed static attributes point directly into the DB memory.


Typical Usage

server->Init(att_db); // att_db from BTstack-generated files
// Route connection handle for notifications/indications
server->SetConnectionHandle(connection_handle);
// Look up a characteristic and install handlers
auto* ch = server->FindCharacteristicByUuid(c7222::Uuid(0x2A19));
if(ch != nullptr) {
ch->AddEventHandler(my_handler);
}
static AttributeServer * GetInstance()
Get the singleton instance.
Definition attribute_server.hpp:160
UUID storage for 16-bit and 128-bit UUIDs.
Definition uuid.hpp:53

Design Assumptions

  • The platform provides an immutable ATT database blob whose lifetime exceeds the AttributeServer instance lifetime.
  • Parsed static attributes point into the ATT DB memory and must not outlive it.
  • Services/characteristics are rebuilt from the ATT DB each time Init() runs.

Internal/Reserved APIs (do not call from application code)

The following methods exist to integrate with the BLE stack and platform glue. They are not part of the public application API and should be considered reserved for internal use:

Member Function Documentation

◆ begin() [1/2]

auto c7222::AttributeServer::begin ( )
inline

Get iterator to first service.

Returns
Iterator to begin of services list

◆ begin() [2/2]

auto c7222::AttributeServer::begin ( ) const
inline

Get const iterator to first service.

Returns
Const iterator to begin of services list

◆ cbegin()

auto c7222::AttributeServer::cbegin ( ) const
inline

Get const iterator to first service.

Returns
Const iterator to begin of services list

◆ cend()

auto c7222::AttributeServer::cend ( ) const
inline

Get const iterator to end of services.

Returns
Const iterator to end of services list

◆ DispatchBleHciPacket()

BleError c7222::AttributeServer::DispatchBleHciPacket ( uint8_t  packet_type,
const uint8_t *  packet_data,
uint16_t  packet_data_size 
)

Dispatch HCI ATT events to all characteristics.

This should be called from the BLE packet handler so that ATT indication completion and can-send-now flow control are handled by characteristics.

◆ end() [1/2]

auto c7222::AttributeServer::end ( )
inline

Get iterator to end of services.

Returns
Iterator to end of services list

◆ end() [2/2]

auto c7222::AttributeServer::end ( ) const
inline

Get const iterator to end of services.

Returns
Const iterator to end of services list

◆ FindCharacteristicByHandle() [1/2]

Characteristic * c7222::AttributeServer::FindCharacteristicByHandle ( uint16_t  handle)

Find a characteristic by attribute handle.

Parameters
handleATT handle to search for (value, declaration, or descriptor).
Returns
Pointer to the characteristic, or nullptr if not found.
Here is the caller graph for this function:

◆ FindCharacteristicByHandle() [2/2]

const Characteristic * c7222::AttributeServer::FindCharacteristicByHandle ( uint16_t  handle) const

Find a characteristic by attribute handle (const version).

Parameters
handleATT handle to search for (value, declaration, or descriptor).
Returns
Const pointer to the characteristic, or nullptr if not found.

◆ FindCharacteristicByUuid() [1/2]

std::list< Characteristic * > c7222::AttributeServer::FindCharacteristicByUuid ( const Uuid uuid)

Find characteristics by UUID.

Multiple characteristics can share a UUID (e.g., replicated instances), so this returns all matches in discovery order.

Parameters
uuidCharacteristic UUID to search for.
Returns
List of matching characteristics (may be empty).

◆ FindCharacteristicByUuid() [2/2]

std::list< const Characteristic * > c7222::AttributeServer::FindCharacteristicByUuid ( const Uuid uuid) const

Find characteristics by UUID (const version).

Multiple characteristics can share a UUID (e.g., replicated instances), so this returns all matches in discovery order.

Parameters
uuidCharacteristic UUID to search for.
Returns
List of matching characteristics (may be empty).

◆ FindServiceByUuid() [1/2]

Service * c7222::AttributeServer::FindServiceByUuid ( const Uuid uuid)

Find a service by UUID.

Parameters
uuidService UUID to search for.
Returns
Pointer to the service, or nullptr if not found.
Here is the caller graph for this function:

◆ FindServiceByUuid() [2/2]

const Service * c7222::AttributeServer::FindServiceByUuid ( const Uuid uuid) const

Find a service by UUID (const version).

Parameters
uuidService UUID to search for.
Returns
Const pointer to the service, or nullptr if not found.

◆ GetConnectionHandle()

uint16_t c7222::AttributeServer::GetConnectionHandle ( ) const
inline

Get the current connection handle.

Returns 0 when disconnected or not set.

◆ GetContext()

const void * c7222::AttributeServer::GetContext ( ) const
inline

Get the stored platform context pointer.

On Pico W this is the ATT DB blob pointer; other platforms may store different context data.

◆ GetInstance()

static AttributeServer * c7222::AttributeServer::GetInstance ( )
inlinestatic

Get the singleton instance.

The server is a process-wide singleton because BTstack exposes a single global ATT server for the device.

◆ GetSecurityLevel()

uint8_t c7222::AttributeServer::GetSecurityLevel ( uint16_t  connection_handle) const

Get cached security level for the active connection.

◆ GetService() [1/2]

Service & c7222::AttributeServer::GetService ( size_t  index)

Get a service by index.

Parameters
indexService index in discovery order.
Returns
Reference to the service.

◆ GetService() [2/2]

const Service & c7222::AttributeServer::GetService ( size_t  index) const

Get a service by index (const version).

Parameters
indexService index in discovery order.
Returns
Const reference to the service.

◆ GetServiceCount()

size_t c7222::AttributeServer::GetServiceCount ( ) const
inline

Get the number of parsed services.

Returns the count of services parsed from the ATT DB in discovery order.

◆ GetServices() [1/2]

std::list< Service > & c7222::AttributeServer::GetServices ( )
inline

Get the list of services.

Returns
Reference to the service list.

◆ GetServices() [2/2]

const std::list< Service > & c7222::AttributeServer::GetServices ( ) const
inline

Get the list of services.

Returns
Const reference to the service list.

◆ HasConnectionHandle()

bool c7222::AttributeServer::HasConnectionHandle ( ) const
inline

Check whether a connection handle is set.

◆ HasContext()

bool c7222::AttributeServer::HasContext ( ) const
inline

Check whether a platform context has been stored.

◆ HasServicesRequiringAuthentication()

bool c7222::AttributeServer::HasServicesRequiringAuthentication ( ) const

Check whether any service contains characteristics requiring authentication.

This aggregates the per-service checks and is intended to guide SecurityManager configuration before connections are established.

◆ HasServicesRequiringAuthorization()

bool c7222::AttributeServer::HasServicesRequiringAuthorization ( ) const

Check whether any service contains characteristics requiring authorization.

Authorization implies authentication and typically requires application-level approval.

◆ HasServicesRequiringEncryption()

bool c7222::AttributeServer::HasServicesRequiringEncryption ( ) const

Check whether any service contains characteristics requiring encryption.

◆ Init()

BleError c7222::AttributeServer::Init ( const void *  context)

Initialize the ATT server from a platform context.

On the Pico W BLE stack, the context is the BTstack ATT database blob (att_db.h). Other platforms may treat the context differently.

When called the first time, the context pointer is cached in the instance. The Pico W implementation parses the ATT DB and registers BTstack read/write callbacks. Subsequent calls reuse the cached context.

RPi Pico (BTstack) steps:

  1. Cache the ATT DB pointer if not already stored.
  2. Parse the ATT DB into Attribute objects.
  3. Call InitServices() to build services/characteristics.
  4. Register BTstack callbacks via att_server_init().
  5. Mark the server initialized.
Parameters
contextPlatform-specific context pointer.
Returns
BleError::kSuccess on success.

◆ InitServices()

void c7222::AttributeServer::InitServices ( std::list< Attribute > &  attributes)

Initialize services from a parsed attribute list.

This method consumes the ordered attribute list to construct services and characteristics in discovery order. The list is modified in place and may be emptied by the parsing process.

Parameters
attributesParsed attributes in DB order.

◆ IsAuthorizationGranted()

bool c7222::AttributeServer::IsAuthorizationGranted ( uint16_t  connection_handle) const

Get cached authorization result for the active connection.

◆ IsConnected()

bool c7222::AttributeServer::IsConnected ( ) const
inline

Queries whether a client is connected to the server.

An attribute server is connected if it has a non-zero connection handle.

Here is the caller graph for this function:

◆ IsInitialized()

bool c7222::AttributeServer::IsInitialized ( ) const
inline

Check whether the server was initialized.

◆ ReadAttribute()

ReadResult c7222::AttributeServer::ReadAttribute ( uint16_t  attribute_handle,
uint16_t  offset,
uint8_t *  buffer,
uint16_t  buffer_size 
)

Handle an ATT read request (internal use).

Used by the platform binding to service BTstack read callbacks.

◆ SetAuthorizationGranted()

void c7222::AttributeServer::SetAuthorizationGranted ( uint16_t  connection_handle,
bool  granted 
)

Update cached authorization result for the active connection.

◆ SetConnectionHandle()

void c7222::AttributeServer::SetConnectionHandle ( uint16_t  connection_handle)

Set the active connection handle for all characteristics.

This value is propagated into each service/characteristic so that notifications/indications can be sent from Characteristic::UpdateValue().

Here is the caller graph for this function:

◆ SetDisconnected()

void c7222::AttributeServer::SetDisconnected ( )

◆ SetSecurityLevel()

void c7222::AttributeServer::SetSecurityLevel ( uint16_t  connection_handle,
uint8_t  security_level 
)

Update cached security level for the active connection.

◆ WriteAttribute()

BleError c7222::AttributeServer::WriteAttribute ( uint16_t  attribute_handle,
uint16_t  offset,
const uint8_t *  data,
uint16_t  size 
)

Handle an ATT write request (internal use).

Used by the platform binding to service BTstack write callbacks.

Friends And Related Symbol Documentation

◆ operator<<

std::ostream & operator<< ( std::ostream &  os,
const AttributeServer server 
)
friend

Stream insertion operator for attribute server information.

Outputs summary details including:

  • Initialization state
  • Service count
  • Connection handle

The documentation for this class was generated from the following file: