1#ifndef BLUETOE_LINK_LAYER_ADVERTISING_HPP
2#define BLUETOE_LINK_LAYER_ADVERTISING_HPP
5#include <bluetoe/default_pdu_layout.hpp>
6#include <bluetoe/address.hpp>
7#include <bluetoe/buffer.hpp>
8#include <bluetoe/delta_time.hpp>
9#include <bluetoe/ll_meta_types.hpp>
25 struct advertising_type_meta_type {};
26 struct advertising_startup_meta_type {};
27 struct advertising_interval_meta_type {};
28 struct advertising_channel_map_meta_type {};
30 template <
unsigned long long AdvertisingIntervalMilliSeconds >
31 struct check_advertising_interval_parameter {
32 static_assert( AdvertisingIntervalMilliSeconds >= 20,
"the advertising interval must be greater than or equal to 20ms." );
33 static_assert( AdvertisingIntervalMilliSeconds <= 10240,
"the advertising interval must be smaller than or equal to 10.24s." );
38 struct advertising_type_base {
39 static constexpr std::uint8_t header_txaddr_field = 0x40;
40 static constexpr std::uint8_t header_rxaddr_field = 0x80;
41 static constexpr std::size_t advertising_pdu_header_size = 2;
42 static constexpr std::uint8_t adv_ind_pdu_type_code = 0;
43 static constexpr std::uint8_t adv_direct_ind_pdu_type_code= 1;
44 static constexpr std::uint8_t adv_nonconn_ind_pdu_type_code= 2;
45 static constexpr std::uint8_t adv_scan_ind_pdu_type_code = 6;
46 static constexpr std::uint8_t scan_response_pdu_type_code = 4;
47 static constexpr std::size_t address_length = 6;
48 static constexpr std::size_t maximum_adv_request_size = 34;
50 static constexpr std::size_t max_advertising_data_size = 31;
51 static constexpr std::size_t max_scan_response_data_size = 31;
53 static constexpr std::size_t max_advertising_pdu_size = max_advertising_data_size + address_length;
54 static constexpr std::size_t max_scan_response_pdu_size = max_scan_response_data_size + address_length;
56 template <
typename Layout >
57 static bool is_valid_scan_request(
const read_buffer& receive,
const device_address& addr )
59 static constexpr std::size_t scan_request_size = 2 * address_length;
60 static constexpr std::uint8_t scan_request_code = 0x03;
62 const std::uint16_t header = Layout::header( receive );
64 bool result = receive.size == Layout::data_channel_pdu_memory_size( scan_request_size )
65 && ( ( header >> 8 ) & 0x3f ) == scan_request_size
66 && ( header & 0x0f ) == scan_request_code;
70 const auto body = Layout::body( receive );
71 result = result && std::equal( &body.begin[ address_length ], &body.begin[ 2 * address_length ], addr.begin() );
72 result = result && addr.is_random() == ( ( header & header_rxaddr_field ) != 0 );
78 template <
typename Layout >
79 static bool is_valid_connect_request(
const read_buffer& receive,
const device_address& addr )
81 static constexpr std::size_t connect_request_size = 34;
82 static constexpr std::uint8_t connect_request_code = 0x05;
84 if ( receive.size != Layout::data_channel_pdu_memory_size( connect_request_size ) )
87 const std::uint16_t header = Layout::header( receive );
88 const auto body = Layout::body( receive ).first;
90 bool result = ( ( header >> 8 ) & 0x3f ) == connect_request_size
91 && ( header & 0x0f ) == connect_request_code;
93 result = result && std::equal( &body[ address_length ], &body[ 2 * address_length ], addr.begin() );
94 result = result && addr.is_random() == ( ( header & header_rxaddr_field ) != 0 );
99 template <
typename Layout >
100 static std::size_t fill_empty_scan_response_data(
const device_address& addr, read_buffer adv_response_buffer )
102 std::uint16_t header = scan_response_pdu_type_code;
104 if ( addr.is_random() )
105 header |= header_txaddr_field;
107 static constexpr std::size_t empty_ad_size = 2;
108 std::size_t adv_response_size = advertising_pdu_header_size + address_length + empty_ad_size;
109 header |= ( adv_response_size - advertising_pdu_header_size ) << 8;
111 const auto body = Layout::body( adv_response_buffer );
113 std::copy( addr.begin(), addr.end(), body.first );
117 body.first[ adv_response_size - 2 ] = 0;
118 body.first[ adv_response_size - 1 ] = 0;
120 Layout::header( adv_response_buffer, header );
122 return adv_response_size;
160 template <
typename Type >
165 details::advertising_type_meta_type,
166 details::valid_link_layer_option_meta_type {};
168 template <
typename LinkLayer,
typename Advertiser >
169 class impl :
protected details::advertising_type_base
178 adv_size_ = address_length;
180 const auto buffer = advertiser().advertising_buffer();
181 std::uint16_t header = adv_ind_pdu_type_code;
182 std::uint8_t* body = layout_t::body( buffer ).first;
185 header |= header_txaddr_field;
187 const std::size_t size =
192 adv_size_ = layout_t::data_channel_pdu_memory_size( size );
194 std::copy( addr.
begin(), addr.
end(), body );
195 layout_t::header( buffer, header );
197 fill_scan_response_data();
201 read_buffer get_advertising_data()
203 return advertiser().advertising_buffer();
206 read_buffer get_scan_response_data()
208 return advertiser().scan_response_buffer();
211 bool is_valid_scan_request(
const read_buffer& receive )
const
213 using layout_t =
typename pdu_layout_by_radio< typename LinkLayer::radio_t >::pdu_layout;
214 return details::advertising_type_base::is_valid_scan_request< layout_t >( receive, link_layer().local_address() );
217 bool is_valid_connect_request(
const read_buffer& receive )
const
219 using layout_t =
typename pdu_layout_by_radio< typename LinkLayer::radio_t >::pdu_layout;
220 return details::advertising_type_base::is_valid_connect_request< layout_t >( receive, link_layer().local_address() );
225 static constexpr std::size_t maximum_adv_send_size = max_advertising_data_size + address_length;
227 void fill_scan_response_data()
229 using layout_t =
typename pdu_layout_by_radio< typename LinkLayer::radio_t >::pdu_layout;
230 const device_address& addr = link_layer().local_address();
232 const auto buffer = advertiser().scan_response_buffer();
234 std::uint16_t header = scan_response_pdu_type_code;
235 std::uint8_t* body = layout_t::body( buffer ).first;
237 if ( addr.is_random() )
238 header |= header_txaddr_field;
240 const std::size_t size =
242 + link_layer().fill_l2cap_scan_response_data( &body[ address_length ], max_scan_response_data_size );
245 adv_response_size_ = layout_t::data_channel_pdu_memory_size( size );
247 std::copy( addr.begin(), addr.end(), body );
248 layout_t::header( buffer, header );
251 LinkLayer& link_layer()
253 return static_cast< LinkLayer&
>( *this );
256 const LinkLayer& link_layer()
const
258 return static_cast< const LinkLayer&
>( *this );
261 Advertiser& advertiser()
263 return static_cast< Advertiser&
>( *this );
266 std::size_t adv_size_;
267 std::size_t adv_response_size_;
298 template <
typename Type >
311 details::advertising_type_meta_type,
312 details::valid_link_layer_option_meta_type {};
314 template <
typename LinkLayer,
typename Advertiser >
315 class impl :
protected details::advertising_type_base
321 bool start_advertising = !addr_valid_ && address_valid;
324 addr_valid_ = address_valid;
326 if ( start_advertising && started_ )
327 advertiser().handle_start_advertising();
332 : addr_valid_( false )
337 read_buffer fill_advertising_data()
342 return read_buffer{
nullptr, 0 };
345 const device_address& addr = link_layer().local_address();
346 using layout_t =
typename pdu_layout_by_radio< typename LinkLayer::radio_t >::pdu_layout;
348 const auto buffer = advertiser().advertising_buffer();
350 std::uint8_t*
const adv_data = buffer.buffer;
351 std::uint16_t header = adv_direct_ind_pdu_type_code;
353 if ( addr.is_random() )
354 header |= header_txaddr_field;
356 if ( addr_.is_random() )
357 header |= header_rxaddr_field;
359 header |= ( 2 * address_length ) << 8;
361 layout_t::header( adv_data, header );
363 const auto body = layout_t::body( buffer );
364 std::copy( addr.begin(), addr.end(), &body.first[ 0 ] );
365 std::copy( addr_.begin(), addr_.end(), &body.first[ address_length ] );
370 read_buffer get_advertising_data()
372 return addr_valid_ ? advertiser().advertising_buffer() : read_buffer{
nullptr, 0 };
375 read_buffer get_scan_response_data()
const
377 return read_buffer{
nullptr, 0 };
380 bool is_valid_scan_request(
const read_buffer& )
const
385 bool is_valid_connect_request(
const read_buffer& receive )
const
387 using layout_t =
typename pdu_layout_by_radio< typename LinkLayer::radio_t >::pdu_layout;
389 bool result = details::advertising_type_base::is_valid_connect_request< layout_t >( receive, link_layer().local_address() );
390 const auto body = layout_t::body( receive ).first;
391 const auto header = layout_t::header( receive );
393 result = result && std::equal( &body[ 0 ], &body[ address_length ], addr_.begin() ) && addr_valid_;
394 result = result && addr_.is_random() == ( ( header & header_txaddr_field ) != 0 );
401 static constexpr std::size_t max_advertising_data_size = 2 * address_length;
403 LinkLayer& link_layer()
405 return static_cast< LinkLayer&
>( *this );
408 const LinkLayer& link_layer()
const
410 return static_cast< const LinkLayer&
>( *this );
413 Advertiser& advertiser()
415 return static_cast< Advertiser&
>( *this );
418 device_address addr_;
445 template <
typename Type >
450 details::advertising_type_meta_type,
451 details::valid_link_layer_option_meta_type {};
453 template <
typename LinkLayer,
typename Advertiser >
454 class impl :
protected details::advertising_type_base
462 fill_scan_response_data();
465 const auto buffer = advertiser().advertising_buffer();
467 std::uint16_t header = adv_scan_ind_pdu_type_code;
468 std::uint8_t* body = layout_t::body( buffer ).first;
471 header |= header_txaddr_field;
473 const std::size_t size =
478 adv_size_ = layout_t::data_channel_pdu_memory_size( size );
480 layout_t::header( buffer, header );
481 std::copy( addr.
begin(), addr.
end(), body );
486 read_buffer get_advertising_data()
488 return read_buffer{ advertiser().advertising_buffer().buffer, adv_size_ };
491 read_buffer get_scan_response_data()
493 return read_buffer{ advertiser().scan_response_buffer().buffer, adv_response_size_ };
496 bool is_valid_scan_request(
const read_buffer& receive )
const
498 return details::advertising_type_base::is_valid_scan_request( receive, link_layer().local_address() );
501 bool is_valid_connect_request(
const read_buffer& )
const
507 static constexpr std::size_t max_advertising_data_size = 31;
508 static constexpr std::size_t maximum_adv_send_size = max_advertising_data_size + address_length;
510 void fill_scan_response_data()
512 using layout_t =
typename pdu_layout_by_radio< typename LinkLayer::radio_t >::pdu_layout;
514 adv_response_size_ = fill_empty_scan_response_data< layout_t >(
515 link_layer().local_address(), advertiser().scan_response_buffer() );
518 LinkLayer& link_layer()
520 return static_cast< LinkLayer&
>( *this );
523 const LinkLayer& link_layer()
const
525 return static_cast< const LinkLayer&
>( *this );
528 Advertiser& advertiser()
530 return static_cast< Advertiser&
>( *this );
533 std::size_t adv_size_;
534 std::size_t adv_response_size_;
559 template <
typename Type >
564 details::advertising_type_meta_type,
565 details::valid_link_layer_option_meta_type {};
567 template <
typename LinkLayer,
typename Advertiser >
568 class impl :
protected details::advertising_type_base
576 const auto buffer = advertiser().advertising_buffer();
578 std::uint16_t header = adv_nonconn_ind_pdu_type_code;
579 std::uint8_t* body = layout_t::body( buffer ).first;
582 header |= header_txaddr_field;
584 const std::size_t size =
590 adv_size_ = layout_t::data_channel_pdu_memory_size( size );
592 layout_t::header( buffer, header );
593 std::copy( addr.
begin(), addr.
end(), body );
598 read_buffer get_advertising_data()
600 return advertiser().advertising_buffer();
603 read_buffer get_scan_response_data()
const
605 return read_buffer{
nullptr, 0 };
608 bool is_valid_scan_request(
const read_buffer& )
const
613 bool is_valid_connect_request(
const read_buffer& )
const
619 static constexpr std::size_t max_advertising_data_size = 31;
621 LinkLayer& link_layer()
623 return static_cast< LinkLayer&
>( *this );
626 Advertiser& advertiser()
628 return static_cast< Advertiser&
>( *this );
631 std::size_t adv_size_;
649 details::advertising_startup_meta_type,
650 details::valid_link_layer_option_meta_type {};
652 template <
typename Advertiser >
655 bool begin_of_advertising_events()
const
660 bool continued_advertising_events()
const
665 void end_of_advertising_events()
707 details::advertising_startup_meta_type,
708 details::valid_link_layer_option_meta_type {};
710 template <
typename Advertiser >
720 void start_advertising()
722 const bool start = !enabled_;
727 if ( start && started_ )
728 static_cast< Advertiser&
>( *this ).handle_start_advertising();
735 void start_advertising(
unsigned count )
739 const bool start = !enabled_;
744 if ( start && started_ )
745 static_cast< Advertiser&
>( *this ).handle_start_advertising();
751 void stop_advertising()
758 bool begin_of_advertising_events()
760 bool result = enabled_;
773 bool continued_advertising_events()
775 bool result = enabled_ && started_;
787 void end_of_advertising_events()
793 volatile bool started_;
794 volatile bool enabled_;
795 volatile unsigned count_;
803 template < std::uint16_t AdvertisingIntervalMilliSeconds, typename = typename details::check_advertising_interval_parameter< AdvertisingIntervalMilliSeconds >::type >
808 details::advertising_interval_meta_type,
809 details::valid_link_layer_option_meta_type {};
818 return delta_time( AdvertisingIntervalMilliSeconds * 1000 );
841 if ( interval_ms >= 20 and interval_ms <= 10240 )
851 interval_ = interval;
864 details::advertising_interval_meta_type,
865 details::valid_link_layer_option_meta_type {};
867 delta_time interval_;
872 struct advertising_channel_map_base {
873 static constexpr unsigned first_advertising_channel = 37;
874 static constexpr unsigned last_advertising_channel = 39;
896 assert( channel >= first_advertising_channel );
897 assert( channel <= last_advertising_channel );
899 channel -= first_advertising_channel;
900 map_ = map_ | ( 1 << channel );
902 current_channel_index_ = first_channel_index();
912 assert( channel >= first_advertising_channel );
913 assert( channel <= last_advertising_channel );
915 channel -= first_advertising_channel;
916 map_ = map_ & ~( 1 << channel );
919 current_channel_index_ = first_channel_index();
924 details::advertising_channel_map_meta_type,
925 details::valid_link_layer_option_meta_type {};
927 variable_advertising_channel_map()
928 : current_channel_index_( 0 )
932 unsigned current_channel()
const
934 return current_channel_index_ + first_advertising_channel;
941 ++current_channel_index_;
944 for ( ; ( 1u << current_channel_index_ ) == 0 && ( 1u << current_channel_index_ ) <= map_; ++current_channel_index_ )
947 if ( ( 1u << current_channel_index_ ) > map_ )
948 current_channel_index_ = first_channel_index();
951 bool first_channel_selected()
const
953 return current_channel_index_ == first_channel_index();
957 unsigned first_channel_index()
const
960 for ( ; ( map_ & ( 1 << result ) ) == 0; ++result )
966 unsigned current_channel_index_;
980 details::advertising_channel_map_meta_type,
981 details::valid_link_layer_option_meta_type {};
985 : current_channel_index_( first_advertising_channel )
988 unsigned current_channel()
const
990 return current_channel_index_;
995 current_channel_index_ = current_channel_index_ == last_advertising_channel
996 ? first_advertising_channel
997 : current_channel_index_ + 1;
1000 bool first_channel_selected()
const
1002 return current_channel_index_ == this->first_advertising_channel;
1006 unsigned current_channel_index_;
1014 template <
typename LinkLayer,
typename Options,
typename ... Advertisings >
1017 struct advertiser_base_base
1019 static constexpr std::uint32_t advertising_radio_access_address = 0x8E89BED6;
1020 static constexpr std::uint32_t advertising_crc_init = 0x555555;
1023 template <
typename LinkLayer,
typename ... Options >
1024 class advertiser_base :
1025 public advertiser_base_base,
1026 public bluetoe::details::find_by_meta_type<
1027 details::advertising_interval_meta_type,
1028 Options..., advertising_interval< 100 > >::type,
1029 public bluetoe::details::find_by_meta_type<
1030 details::advertising_channel_map_meta_type,
1031 Options..., all_advertising_channel_map >::type
1040 read_buffer advertising_buffer()
1045 base_link_layer().raw_pdu_buffer(),
1046 layout_t::data_channel_pdu_memory_size( advertising_type_base::max_advertising_pdu_size ) };
1049 read_buffer scan_response_buffer()
1054 base_link_layer().raw_pdu_buffer()
1055 + layout_t::data_channel_pdu_memory_size( advertising_type_base::max_advertising_pdu_size ),
1056 layout_t::data_channel_pdu_memory_size( advertising_type_base::max_scan_response_pdu_size ) };
1059 read_buffer advertising_receive_buffer()
1064 base_link_layer().raw_pdu_buffer()
1065 + layout_t::data_channel_pdu_memory_size( advertising_type_base::max_advertising_pdu_size )
1066 + layout_t::data_channel_pdu_memory_size( advertising_type_base::max_scan_response_pdu_size ),
1067 layout_t::data_channel_pdu_memory_size( advertising_type_base::maximum_adv_request_size ) };
1070 static constexpr std::size_t maximum_required_advertising_buffer()
1074 return layout_t::data_channel_pdu_memory_size( advertising_type_base::max_advertising_pdu_size )
1075 + layout_t::data_channel_pdu_memory_size( advertising_type_base::max_scan_response_pdu_size )
1076 + layout_t::data_channel_pdu_memory_size( advertising_type_base::maximum_adv_request_size );
1081 : adv_perturbation_( 0 )
1085 delta_time next_adv_event()
1087 if ( !this->first_channel_selected() )
1090 adv_perturbation_ = ( adv_perturbation_ + 7 ) % ( max_adv_perturbation_ + 1 );
1092 return this->current_advertising_interval() +
delta_time::msec( adv_perturbation_ );
1095 LinkLayer& base_link_layer()
1097 return static_cast< LinkLayer&
>( *this );
1101 static constexpr unsigned max_adv_perturbation_ = 10;
1103 unsigned adv_perturbation_;
1106 template <
typename LinkLayer,
typename Advertising,
typename ... Options >
1107 struct start_stop_implementation :
1108 bluetoe::details::find_by_meta_type<
1109 advertising_startup_meta_type,
1111 auto_start_advertising
1112 >::type::template impl<
1115 std::tuple< Options... >,
1123 template <
typename LinkLayer,
typename ... Options,
typename Advertising >
1124 class advertiser< LinkLayer, std::tuple< Options... >, std::tuple< Advertising > > :
1125 public Advertising::template impl< LinkLayer, advertiser< LinkLayer, std::tuple< Options... >, std::tuple< Advertising > > >,
1126 public advertiser_base< LinkLayer, Options... >,
1127 public start_stop_implementation< LinkLayer, std::tuple< Advertising >, Options... >
1134 void handle_start_advertising()
1136 const read_buffer advertising_data = this->fill_advertising_data();
1137 const read_buffer response_data = this->get_scan_response_data();
1139 if ( !advertising_data.empty() && this->begin_of_advertising_events() )
1141 this->base_link_layer().set_access_address_and_crc_init(
1142 this->advertising_radio_access_address,
1143 this->advertising_crc_init );
1145 this->base_link_layer().schedule_advertisment(
1146 this->current_channel(),
1147 write_buffer( advertising_data ),
1148 write_buffer( response_data ),
1150 this->advertising_receive_buffer() );
1154 void handle_stop_advertising()
1156 this->end_of_advertising_events();
1162 bool handle_adv_receive( read_buffer receive, device_address& remote_address )
1164 if ( this->is_valid_connect_request( receive ) )
1168 const std::uint8_t*
const body = layout_t::body( receive ).first;
1169 const std::uint16_t header = layout_t::header( receive );
1171 remote_address = device_address( &body[ 0 ], header & 0x40 );
1173 if ( this->base_link_layer().is_connection_request_in_filter( remote_address ) )
1177 handle_adv_timeout();
1182 void handle_adv_timeout()
1184 const read_buffer advertising_data = this->base_link_layer().l2cap_adverting_data_or_scan_response_data_changed()
1185 ? this->fill_advertising_data()
1186 : this->get_advertising_data();
1188 const read_buffer response_data = this->get_scan_response_data();
1190 if ( !advertising_data.empty() && this->continued_advertising_events() )
1192 this->next_channel();
1194 this->base_link_layer().schedule_advertisment(
1195 this->current_channel(),
1196 write_buffer( advertising_data ),
1197 write_buffer( response_data ),
1198 this->next_adv_event(),
1199 this->advertising_receive_buffer() );
1208 template <
typename LinkLayer,
typename ... Options >
1209 class advertiser< LinkLayer, std::tuple< Options... >, std::tuple<> > :
1210 public advertiser< LinkLayer, std::tuple< Options... >, std::tuple< connectable_undirected_advertising > >
1214 template <
typename LinkLayer,
typename Options,
typename Advertiser,
typename ... Types >
1215 class multipl_advertiser_base;
1217 template <
typename LinkLayer,
typename Options,
typename Advertiser >
1218 class multipl_advertiser_base< LinkLayer, Options, Advertiser >
1221 read_buffer fill_advertising_data(
unsigned )
1223 return read_buffer{
nullptr, 0 };
1226 read_buffer get_advertising_data(
unsigned )
1228 return read_buffer{
nullptr, 0 };
1231 read_buffer get_scan_response_data(
unsigned )
1233 return read_buffer{
nullptr, 0 };
1236 bool is_valid_scan_request(
const read_buffer&,
unsigned )
const
1241 bool is_valid_connect_request(
const read_buffer&,
unsigned )
const
1247 template <
typename LinkLayer,
typename Options,
typename Advertiser,
typename Type,
typename ... Types >
1248 class multipl_advertiser_base< LinkLayer, Options, Advertiser, Type, Types... > :
1249 public Type::template impl< LinkLayer, Advertiser >,
1250 public multipl_advertiser_base< LinkLayer, Options, Advertiser, Types... >
1254 read_buffer fill_advertising_data(
unsigned selected )
1256 return selected == 0
1257 ? adv_type::fill_advertising_data()
1258 : tail_type::fill_advertising_data( selected -1 );
1261 read_buffer get_advertising_data(
unsigned selected )
1263 return selected == 0
1264 ? adv_type::get_advertising_data()
1265 : tail_type::get_advertising_data( selected -1 );
1268 read_buffer get_scan_response_data(
unsigned selected )
1270 return selected == 0
1271 ? adv_type::get_scan_response_data()
1272 : tail_type::get_scan_response_data( selected -1 );
1275 bool is_valid_scan_request(
const read_buffer& b,
unsigned selected )
const
1277 return selected == 0
1278 ? adv_type::is_valid_scan_request( b )
1279 : tail_type::is_valid_scan_request( b, selected -1 );
1282 bool is_valid_connect_request(
const read_buffer& b,
unsigned selected )
const
1284 return selected == 0
1285 ? adv_type::is_valid_connect_request( b )
1286 : tail_type::is_valid_connect_request( b, selected -1 );
1290 using adv_type =
typename Type::template impl< LinkLayer, Advertiser >;
1291 using tail_type = multipl_advertiser_base< LinkLayer, Options, Advertiser, Types... >;
1297 template <
typename LinkLayer,
typename ... Options,
typename FirstAdv,
typename SecondAdv,
typename ... Advertisings >
1298 class advertiser< LinkLayer, std::tuple< Options... >, std::tuple< FirstAdv, SecondAdv, Advertisings... > > :
1299 public advertiser_base< LinkLayer, Options... >,
1300 public multipl_advertiser_base<
1302 std::tuple< Options... >,
1303 advertiser< LinkLayer, std::tuple< Options... >, std::tuple< FirstAdv, SecondAdv, Advertisings... > >,
1304 FirstAdv, SecondAdv, Advertisings...
1306 public start_stop_implementation< LinkLayer, std::tuple< FirstAdv, SecondAdv, Advertisings... >, Options... >
1315 void handle_start_advertising()
1317 selected_ = proposal_;
1318 const read_buffer advertising_data = this->fill_advertising_data( selected_ );
1319 const read_buffer response_data = this->get_scan_response_data( selected_ );
1321 if ( !advertising_data.empty() && this->begin_of_advertising_events() )
1323 this->base_link_layer().set_access_address_and_crc_init(
1324 this->advertising_radio_access_address,
1325 this->advertising_crc_init );
1327 this->base_link_layer().schedule_advertisment(
1328 this->current_channel(),
1329 write_buffer( advertising_data ),
1330 write_buffer( response_data ),
1332 this->advertising_receive_buffer() );
1336 void handle_stop_advertising()
1338 this->end_of_advertising_events();
1341 bool handle_adv_receive( read_buffer receive, device_address& remote_address )
1343 if ( this->is_valid_connect_request( receive, selected_ ) )
1347 const std::uint8_t*
const body = layout_t::body( receive ).first;
1348 const std::uint16_t header = layout_t::header( receive );
1350 remote_address = device_address( &body[ 0 ], header & 0x40 );
1352 if ( this->base_link_layer().is_connection_request_in_filter( remote_address ) )
1356 handle_adv_timeout();
1361 void handle_adv_timeout()
1363 const bool fill_data = selected_ != proposal_
1364 || this->base_link_layer().l2cap_adverting_data_or_scan_response_data_changed();
1366 selected_ = proposal_;
1367 const read_buffer advertising_data = fill_data
1368 ? this->fill_advertising_data( selected_ )
1369 : this->get_advertising_data( selected_ );
1371 const read_buffer response_data = this->get_scan_response_data( selected_ );
1373 if ( !advertising_data.empty() && this->continued_advertising_events() )
1375 this->next_channel();
1377 this->base_link_layer().schedule_advertisment(
1378 this->current_channel(),
1379 write_buffer( advertising_data ),
1380 write_buffer( response_data ),
1381 this->next_adv_event(),
1382 this->advertising_receive_buffer() );
1389 template <
typename Type >
1390 void change_advertising()
1392 proposal_ = bluetoe::details::index_of< Type, FirstAdv, SecondAdv, Advertisings... >::value;
1393 assert( proposal_ !=
sizeof...(Advertisings) + 2 );
1403 template <
typename LinkLayer,
typename ... Options >
1404 using select_advertiser_implementation =
1407 std::tuple< Options... >,
1408 typename bluetoe::details::find_all_by_meta_type< advertising_type_meta_type,
1409 Options... >::type >;
const_iterator begin() const
returns an iterator to the first byte (LSB) of the address
const_iterator end() const
returns an iterator one behind the last byte of the address
if this options is given to the link layer, the link layer will start to advertise automatically,...
Definition: advertising.hpp:645
enables low duty connectable directed advertising
Definition: advertising.hpp:285
void directed_advertising_address(const device_address &addr)
sets the address to be used in the advertising PDU.
void change_advertising()
change type of advertisment
enables connectable undirected advertising
Definition: advertising.hpp:147
void change_advertising()
change type of advertisment
positiv time quantum used to express distance in time.
Definition: delta_time.hpp:14
static delta_time msec(std::uint32_t msec)
creates a delta_time from a positive number of ms (milliseconds).
static delta_time now()
creates a delta_time denoting the distance from now to now. Aka 0.
data type containing a device address and the address type (public or random).
Definition: address.hpp:107
bool is_random() const
returns true, if this device address is a random device address.
Definition: address.hpp:114
link layer implementation
Definition: link_layer.hpp:489
const device_address & local_address() const
returns the own local device address
std::size_t fill_l2cap_advertising_data(std::uint8_t *buffer, std::size_t buffer_size) const
fills the given buffer with l2cap advertising payload
if this options is given to the link layer, the link layer will not start to advertise automatically,...
Definition: advertising.hpp:684
void stop_advertising()
stop advertising
void start_advertising()
starts to advertise.
void start_advertising(unsigned count)
same as start_advertising(), but the link layer will automatically stop to advertise after count adve...
advertising interval in ms in the range 20ms to 10.24s
Definition: advertising.hpp:805
delta_time current_advertising_interval() const
Definition: advertising.hpp:816
channel map that contains all three advertising channels
Definition: advertising.hpp:977
implements a PDU layout, where in memory and over the air layout are equal.
Definition: default_pdu_layout.hpp:42
enables non-connectable undirected advertising
Definition: advertising.hpp:547
void change_advertising()
change type of advertisment
default_pdu_layout pdu_layout
the layout to be applied when Radio is used
Definition: default_pdu_layout.hpp:108
type suitable to store the location and size of a chunk of memory that can be used to receive from th...
Definition: buffer.hpp:18
enables scannable undirected advertising
Definition: advertising.hpp:433
void change_advertising()
change type of advertisment
adds the abillity to set a channel map for advertising
Definition: advertising.hpp:890
void remove_channel_from_advertsing_channel_map(unsigned channel)
removes the channel from the map.
Definition: advertising.hpp:910
void add_channel_to_advertising_channel_map(unsigned channel)
adds the given channel to the map
Definition: advertising.hpp:894
adds the abillity to change the advertising interval
Definition: advertising.hpp:829
void advertising_interval_ms(unsigned interval_ms)
sets the advertising interval in ms in the range 20ms to 10.24s
Definition: advertising.hpp:839
void advertising_interval(delta_time interval)
sets the advertising interval in ms in the range 20ms to 10.24s
Definition: advertising.hpp:848
delta_time current_advertising_interval() const
currently used advertising interval
Definition: advertising.hpp:857