1#ifndef BLUETOE_ATTRIBUTE_HPP
2#define BLUETOE_ATTRIBUTE_HPP
5#include <bluetoe/client_characteristic_configuration.hpp>
6#include <bluetoe/pairing_status.hpp>
7#include <bluetoe/attribute_handle.hpp>
20 enum class attribute_access_result : std::int_fast16_t {
40 enum class attribute_access_type {
47 struct attribute_access_arguments
49 attribute_access_type type;
51 std::size_t buffer_size;
52 std::size_t buffer_offset;
53 client_characteristic_configuration client_config;
54 connection_security_attributes connection_security;
57 template < std::
size_t N >
58 static constexpr attribute_access_arguments read(
59 std::uint8_t(&buffer)[N],
61 const client_characteristic_configuration& cc = client_characteristic_configuration(),
62 const connection_security_attributes& cs = connection_security_attributes() )
64 return attribute_access_arguments{
65 attribute_access_type::read,
75 static attribute_access_arguments read(
76 std::uint8_t* begin, std::uint8_t* end, std::size_t offset,
77 const client_characteristic_configuration& cc,
78 const connection_security_attributes& cs,
81 assert( end >= begin );
83 return attribute_access_arguments{
84 attribute_access_type::read,
86 static_cast< std::size_t
>( end - begin ),
94 template < std::
size_t N >
95 static constexpr attribute_access_arguments write(
const std::uint8_t(&buffer)[N], std::size_t offset = 0,
96 const client_characteristic_configuration& cc = client_characteristic_configuration(),
97 const connection_security_attributes& cs = connection_security_attributes() )
99 return attribute_access_arguments{
100 attribute_access_type::write,
101 const_cast< std::uint8_t*
>( &buffer[ 0 ] ),
110 static attribute_access_arguments write(
const std::uint8_t* begin,
const std::uint8_t* end, std::size_t offset,
111 const client_characteristic_configuration& cc,
112 const connection_security_attributes& cs,
115 assert( end >= begin );
117 return attribute_access_arguments{
118 attribute_access_type::write,
119 const_cast< std::uint8_t*
>( begin ),
120 static_cast< std::size_t
>( end - begin ),
128 static constexpr attribute_access_arguments check_write(
void* server )
130 return attribute_access_arguments{
131 attribute_access_type::write,
135 client_characteristic_configuration(),
136 connection_security_attributes(),
141 static constexpr attribute_access_arguments compare_128bit_uuid(
const std::uint8_t* uuid )
143 return attribute_access_arguments{
144 attribute_access_type::compare_128bit_uuid,
145 const_cast< std::uint8_t*
>( uuid ),
148 client_characteristic_configuration(),
149 connection_security_attributes(),
154 static attribute_access_arguments compare_value(
const std::uint8_t* begin,
const std::uint8_t* end,
void* )
156 assert( end >= begin );
158 return attribute_access_arguments{
159 attribute_access_type::compare_value,
160 const_cast< std::uint8_t*
>( begin ),
161 static_cast< std::size_t
>( end - begin ),
163 client_characteristic_configuration(),
164 connection_security_attributes(),
170 typedef attribute_access_result ( *attribute_access )( attribute_access_arguments&, std::size_t attribute_index );
184 attribute_access access;
191 template <
typename T,
typename CCCDIndices, std::
size_t ClientCharacteristicIndex,
typename Service,
typename Server >
192 struct attribute_at_list;
194 template <
typename CCCDIndices, std::
size_t ClientCharacteristicIndex,
typename Service,
typename Server >
195 struct attribute_at_list< std::tuple<>, CCCDIndices, ClientCharacteristicIndex, Service, Server >
197 static details::attribute attribute_at( std::size_t )
199 assert( !
"index out of bound" );
200 return details::attribute();
207 typename CCCDIndices,
208 std::size_t ClientCharacteristicIndex,
211 struct attribute_at_list< std::tuple< T, Ts... >, CCCDIndices, ClientCharacteristicIndex, Service, Server >
213 static details::attribute attribute_at( std::size_t index )
215 if ( index < T::number_of_attributes )
216 return T::template attribute_at< CCCDIndices, ClientCharacteristicIndex, Service, Server >( index );
218 typedef details::attribute_at_list< std::tuple< Ts... >, CCCDIndices, ClientCharacteristicIndex + T::number_of_client_configs, Service, Server > remaining_characteristics;
220 return remaining_characteristics::attribute_at( index - T::number_of_attributes );
227 template <
typename Services,
typename Server,
typename CCCDIndices, std::
size_t ClientCharacteristicIndex = 0,
typename AllServices = Services >
228 struct attribute_from_service_list;
230 template <
typename Server,
typename CCCDIndices, std::
size_t ClientCharacteristicIndex,
typename AllServices >
231 struct attribute_from_service_list< std::tuple<>, Server, CCCDIndices, ClientCharacteristicIndex, AllServices >
233 static details::attribute attribute_at( std::size_t )
235 assert( !
"index out of bound" );
236 return details::attribute();
244 typename CCCDIndices,
245 std::size_t ClientCharacteristicIndex,
246 typename AllServices >
247 struct attribute_from_service_list< std::tuple< T, Ts... >, Server, CCCDIndices, ClientCharacteristicIndex, AllServices >
249 static details::attribute attribute_at( std::size_t index )
251 if ( index < T::number_of_attributes )
252 return T::template attribute_at< CCCDIndices, ClientCharacteristicIndex, AllServices, Server >( index );
254 typedef details::attribute_from_service_list<
258 ClientCharacteristicIndex + T::number_of_client_configs,
259 AllServices > remaining_characteristics;
261 return remaining_characteristics::attribute_at( index - T::number_of_attributes );
268 enum class notification_type {
277 class notification_data
281 : attribute_table_index_( details::invalid_attribute_index )
282 , client_characteristic_configuration_index_( 0 )
287 notification_data( std::size_t value_attribute_index, std::size_t client_characteristic_configuration_index )
288 : attribute_table_index_( value_attribute_index )
289 , client_characteristic_configuration_index_( client_characteristic_configuration_index )
296 return attribute_table_index_ != details::invalid_attribute_index;
302 std::size_t attribute_table_index()
const
304 return attribute_table_index_;
310 std::size_t client_characteristic_configuration_index()
const
312 return client_characteristic_configuration_index_;
320 attribute_table_index_ = details::invalid_attribute_index;
321 client_characteristic_configuration_index_ = 0;
325 std::size_t attribute_table_index_;
326 std::size_t client_characteristic_configuration_index_;
332 template <
typename CharacteristicList,
typename UUID >
333 struct find_characteristic_data_by_uuid_in_characteristic_list;
335 template <
typename UUID >
336 struct find_characteristic_data_by_uuid_in_characteristic_list< std::tuple<>, UUID >
338 typedef details::no_such_type type;
342 typename Characteristic,
343 typename ... Characteristics,
345 struct find_characteristic_data_by_uuid_in_characteristic_list< std::tuple< Characteristic, Characteristics...>, UUID >
347 using found = std::is_same< typename Characteristic::configured_uuid, UUID >;
349 using next =
typename find_characteristic_data_by_uuid_in_characteristic_list<
350 std::tuple< Characteristics... >,
355 static constexpr bool has_indication = Characteristic::value_type::has_indication;
356 static constexpr bool has_notification = Characteristic::value_type::has_notification;
357 using characteristic_t = Characteristic;
360 typedef typename details::select_type<
370 template <
typename ServiceList,
typename UUID >
371 struct find_characteristic_data_by_uuid_in_service_list;
373 template <
typename UUID >
374 struct find_characteristic_data_by_uuid_in_service_list< std::tuple<>, UUID >
376 typedef details::no_such_type type;
379 struct wrap_search_in_service_list {
382 typename ... Services >
383 using f =
typename find_characteristic_data_by_uuid_in_service_list<
384 std::tuple< Services... >, UUID >::type;
387 template <
typename Result >
388 struct wrap_result_found_in_service {
391 typename ... Services >
397 typename ... Services,
399 struct find_characteristic_data_by_uuid_in_service_list< std::tuple< Service, Services...>, UUID >
403 using c_type =
typename find_characteristic_data_by_uuid_in_characteristic_list<
404 typename Service::characteristics, UUID >::type;
408 std::is_same< c_type, no_such_type >::value,
409 wrap_search_in_service_list,
410 wrap_result_found_in_service< c_type >
413 using type =
typename next_path::template f<
419 inline attribute_access_result attribute_value_read_access( attribute_access_arguments& args,
const std::uint8_t* memory, std::size_t size )
421 if ( args.type == attribute_access_type::compare_value )
423 return size == args.buffer_size && std::equal( memory, memory + size, args.buffer )
424 ? attribute_access_result::value_equal
425 : attribute_access_result::read_not_permitted;
428 if ( args.buffer_offset > size )
429 return details::attribute_access_result::invalid_offset;
431 args.buffer_size = std::min< std::size_t >( args.buffer_size, size - args.buffer_offset );
432 const std::uint8_t*
const ptr = memory + args.buffer_offset;
434 std::copy( ptr, ptr + args.buffer_size, args.buffer );
436 return details::attribute_access_result::success;
439 inline attribute_access_result attribute_value_read_only_access( attribute_access_arguments& args,
const std::uint8_t* memory, std::size_t size )
441 if ( args.type != attribute_access_type::read && args.type != attribute_access_type::compare_value )
442 return attribute_access_result::write_not_permitted;
444 return attribute_value_read_access( args, memory, size );
@ insufficient_authentication
Definition: codes.hpp:179
@ request_not_supported
Definition: codes.hpp:184
@ invalid_offset
Definition: codes.hpp:189
@ success
Definition: codes.hpp:154
@ write_not_permitted
Definition: codes.hpp:169
@ attribute_not_long
Definition: codes.hpp:209
@ invalid_attribute_value_length
Definition: codes.hpp:219
@ read_not_permitted
Definition: codes.hpp:164
@ insufficient_encryption
Definition: codes.hpp:230