1#ifndef BLUETOE_LINK_LAYER_LINK_LAYER_HPP
2#define BLUETOE_LINK_LAYER_LINK_LAYER_HPP
4#include <bluetoe/buffer.hpp>
5#include <bluetoe/delta_time.hpp>
6#include <bluetoe/ll_l2cap_sdu_buffer.hpp>
7#include <bluetoe/ll_options.hpp>
8#include <bluetoe/phy_encodings.hpp>
9#include <bluetoe/address.hpp>
10#include <bluetoe/channel_map.hpp>
11#include <bluetoe/notification_queue.hpp>
12#include <bluetoe/connection_callbacks.hpp>
13#include <bluetoe/connection_event_callback.hpp>
14#include <bluetoe/l2cap_signaling_channel.hpp>
15#include <bluetoe/white_list.hpp>
17#include <bluetoe/attribute.hpp>
18#include <bluetoe/meta_types.hpp>
20#include <bluetoe/security_manager.hpp>
21#include <bluetoe/codes.hpp>
22#include <bluetoe/encryption.hpp>
23#include <bluetoe/l2cap.hpp>
24#include <bluetoe/connection_events.hpp>
32 class notification_data;
40 std::size_t TransmitSize,
41 std::size_t ReceiveSize,
50 template <
typename ... Options >
53 typedef typename ::bluetoe::details::find_by_meta_type<
54 buffer_sizes_meta_type,
59 static constexpr std::size_t tx_size = s_type::transmit_buffer_size;
60 static constexpr std::size_t rx_size = s_type::receive_buffer_size;
63 template <
typename SecurityFunctions,
typename Server,
typename ... Options >
64 struct security_manager {
66 bluetoe::details::requires_encryption_support_t< Server >::value,
71 using impl =
typename bluetoe::details::find_by_meta_type<
72 bluetoe::details::security_manager_meta_type,
76 using type =
typename impl::template impl< SecurityFunctions, Options... >;
79 template <
typename ... Options >
80 struct signaling_channel {
81 typedef typename bluetoe::details::find_by_meta_type<
82 bluetoe::details::signaling_channel_meta_type,
87 template <
typename LinkLayer,
typename ... Options >
88 struct connection_callbacks
90 typedef typename bluetoe::details::find_by_meta_type<
91 connection_callbacks_meta_type,
93 no_connection_callbacks >::type callbacks;
95 typedef typename callbacks::impl type;
98 template <
typename Radio,
typename LinkLayer,
typename ... Options >
101 typedef typename bluetoe::details::find_by_meta_type<
102 white_list_meta_type,
104 no_white_list >::type list;
106 typedef typename list::template impl< Radio, LinkLayer > type;
114 struct link_layer_security_impl
116 template <
class LinkLayer >
122 , encryption_in_progress_( false )
127 return static_cast< LinkLayer&
>( *this );
130 bool handle_encryption_pdus( std::uint8_t opcode, std::uint8_t size,
const write_buffer& pdu, read_buffer write,
bool& commit )
132 using namespace ::bluetoe::details;
136 bool encryption_changed =
false;
138 if ( opcode == LinkLayer::LL_ENC_REQ && size == 23 )
140 encryption_in_progress_ =
true;
141 fill< layout_t >( write, { LinkLayer::ll_control_pdu_code, 1 + 8 + 4, LinkLayer::LL_ENC_RSP } );
143 const std::uint8_t*
const pdu_body = layout_t::body( pdu ).first;
145 const std::uint64_t rand = read_64bit( pdu_body +1 );
146 const std::uint16_t ediv = read_16bit( pdu_body +9 );
147 const std::uint64_t skdm = read_64bit( pdu_body +11 );
148 const std::uint32_t ivm = read_32bit( pdu_body +19 );
149 std::uint64_t skds = 0;
150 std::uint32_t ivs = 0;
152 bluetoe::details::uint128_t key;
153 std::tie( has_key_, key ) = that().connection_data_.find_key( ediv, rand );
156 std::tie( skds, ivs ) = that().setup_encryption( key, skdm, ivm );
158 std::uint8_t* write_body = layout_t::body( write ).first;
159 bluetoe::details::write_64bit( &write_body[ 1 ], skds );
160 bluetoe::details::write_32bit( &write_body[ 9 ], ivs );
162 else if ( opcode == LinkLayer::LL_START_ENC_RSP && size == 1 )
164 fill< layout_t >( write, { LinkLayer::ll_control_pdu_code, 1, LinkLayer::LL_START_ENC_RSP } );
165 that().start_transmit_encrypted();
166 encryption_changed = that().connection_data_.is_encrypted(
true );
168 if ( encryption_changed )
169 that().connection_data_.restore_bonded_cccds( that().connection_data_ );
172 else if ( opcode == LinkLayer::LL_PAUSE_ENC_REQ && size == 1 )
174 fill< layout_t >( write, { LinkLayer::ll_control_pdu_code, 1, LinkLayer::LL_PAUSE_ENC_RSP } );
175 that().stop_receive_encrypted();
176 encryption_changed = that().connection_data_.is_encrypted(
false );
178 else if ( opcode == LinkLayer::LL_PAUSE_ENC_RSP && size == 1 )
180 that().stop_transmit_encrypted();
181 encryption_changed = that().connection_data_.is_encrypted(
false );
190 if ( encryption_changed )
192 that().connection_data_.pairing_status(that().connection_data_.local_device_pairing_status());
193 that().connection_changed( that().details(), that().connection_data_,
static_cast< typename LinkLayer::radio_t&
>( that() ) );
199 void transmit_pending_security_pdus()
203 if ( !encryption_in_progress_ )
206 auto out_buffer = that().allocate_ll_transmit_buffer( LinkLayer::maximum_ll_payload_size );
207 if ( out_buffer.empty() )
212 fill< layout_t >( out_buffer, {
213 LinkLayer::ll_control_pdu_code, 1, LinkLayer::LL_START_ENC_REQ } );
215 that().start_receive_encrypted();
216 that().commit_ll_transmit_buffer( out_buffer );
220 that().reject( LinkLayer::LL_ENC_REQ, LinkLayer::err_pin_or_key_missing, out_buffer );
221 that().commit_ll_transmit_buffer( out_buffer );
224 encryption_in_progress_ =
false;
227 void reset_encryption()
229 that().connection_data_.is_encrypted(
false );
230 that().stop_receive_encrypted();
231 that().stop_transmit_encrypted();
236 bool encryption_in_progress_;
239 using link_state = bluetoe::details::link_state;
242 struct link_layer_no_security_impl
244 template <
class LinkLayer >
247 bool handle_encryption_pdus( std::uint8_t, std::uint8_t, write_buffer, read_buffer,
bool& )
252 void transmit_pending_security_pdus()
256 void reset_encryption()
261 using link_state = bluetoe::details::link_state_no_security;
267 struct phy_update_request_impl
269 template <
class LL >
270 bool handle_phy_request( std::uint8_t opcode, std::uint8_t size,
const write_buffer& pdu, read_buffer& write, LL& link_layer,
bool& commit )
272 assert( link_layer.defered_ll_control_pdu_.buffer ==
nullptr );
276 if ( opcode == LL::LL_PHY_REQ && size == 3 )
278 fill< layout_t >( write, {
279 LL::ll_control_pdu_code, 3,
281 phy_ll_encoding::le_1m_phy | phy_ll_encoding::le_2m_phy,
282 phy_ll_encoding::le_1m_phy | phy_ll_encoding::le_2m_phy } );
287 if ( opcode == LL::LL_PHY_UPDATE_IND && size == 5 )
289 const std::uint8_t*
const pdu_body = layout_t::body( pdu ).first;
291 const std::uint8_t c_to_p = pdu_body[ 1 ];
292 const std::uint8_t p_to_c = pdu_body[ 2 ];
294 if ( !valid_phy_encoding( c_to_p ) || !valid_phy_encoding( p_to_c ) )
299 if ( c_to_p == details::phy_ll_encoding::le_unchanged_coding
300 && p_to_c == details::phy_ll_encoding::le_unchanged_coding )
303 link_layer.defered_ll_control_pdu_ = pdu;
304 link_layer.defered_conn_event_counter_ = ::bluetoe::details::read_16bit( pdu_body + 3 );
312 template <
class LL >
313 bool handle_pending_phy_request( std::uint8_t opcode, LL& link_layer )
315 assert( link_layer.defered_ll_control_pdu_.buffer );
319 if ( opcode == LL::LL_PHY_UPDATE_IND )
321 const std::uint8_t*
const pdu_body = layout_t::body( link_layer.defered_ll_control_pdu_ ).first;
323 const auto c_to_p =
static_cast< phy_ll_encoding::phy_ll_encoding_t
>( pdu_body[ 1 ] );
324 const auto p_to_c =
static_cast< phy_ll_encoding::phy_ll_encoding_t
>( pdu_body[ 2 ] );
325 link_layer.defered_ll_control_pdu_ = {
nullptr, 0 };
326 link_layer.radio_set_phy( c_to_p, p_to_c );
334 template <
class LL >
335 void reset_phy( LL& link_layer )
337 link_layer.radio_set_phy( phy_ll_encoding::le_1m_phy, phy_ll_encoding::le_1m_phy );
341 bool valid_phy_encoding( std::uint8_t c )
const
344 || c == phy_ll_encoding::le_1m_phy
345 || c == phy_ll_encoding::le_2m_phy;
349 struct no_phy_update_request_impl
351 template <
class LL >
352 bool handle_phy_request( std::uint8_t, std::uint8_t,
const write_buffer&, read_buffer, LL&,
bool& )
357 template <
class LL >
358 bool handle_pending_phy_request( std::uint8_t, LL& )
363 template <
class LL >
364 void reset_phy( LL& )
368 template <
class Server,
class LinkLayer >
369 using select_link_layer_security_impl =
371 bluetoe::details::requires_encryption_support_t< Server >::value,
372 link_layer_security_impl,
373 link_layer_no_security_impl
374 >::type::template impl< LinkLayer >;
376 template <
class Server >
377 using select_link_layer_security_link_state =
379 bluetoe::details::requires_encryption_support_t< Server >::value,
380 link_layer_security_impl,
381 link_layer_no_security_impl
384 template <
class Radio >
385 using select_phy_update_impl =
387 Radio::hardware_supports_2mbit,
388 phy_update_request_impl,
389 no_phy_update_request_impl
395 std::size_t TransmitSize,
396 std::size_t ReceiveSize,
399 class ScheduledRadio,
403 using impl = bluetoe::details::l2cap<
404 link_layer< Server, ScheduledRadio, Options... >,
405 details::select_link_layer_security_link_state< Server >,
407 typename details::signaling_channel< Options... >::type,
408 typename details::security_manager<
409 link_layer< Server, ScheduledRadio, Options... >,
414 static constexpr std::size_t required_minimum_l2cap_buffer_size = impl::maximum_mtu_size;
417 template <
typename ...Options >
418 using connection_latency_state_t = peripheral_latency_state<
419 typename bluetoe::details::find_by_meta_type<
420 peripheral_latency_meta_type,
425 template <
class Base,
typename ...Options >
426 using select_user_timer_impl =
typename bluetoe::details::find_by_meta_type<
427 synchronized_connection_event_callback_meta_type,
429 no_synchronized_connection_event_callback
430 >::type::template impl< Base >;
448 std::size_t TransmitSize,
449 std::size_t ReceiveSize,
452 class ScheduledRadio,
458 details::buffer_sizes< Options... >::tx_size,
459 details::buffer_sizes< Options... >::rx_size,
460 link_layer< Server, ScheduledRadio, Options... >
462 details::l2cap_layer< Server, ScheduledRadio, Options... >::required_minimum_l2cap_buffer_size
464 public details::white_list<
465 bluetoe::link_layer::ll_l2cap_sdu_buffer<
467 details::buffer_sizes< Options... >::tx_size,
468 details::buffer_sizes< Options... >::rx_size,
469 link_layer< Server, ScheduledRadio, Options... >
471 details::l2cap_layer< Server, ScheduledRadio, Options... >::required_minimum_l2cap_buffer_size
473 link_layer< Server, ScheduledRadio, Options... >,
475 public details::select_advertiser_implementation<
476 link_layer< Server, ScheduledRadio, Options... >,
478 public details::l2cap_layer< Server, ScheduledRadio, Options... >::impl,
479 private details::connection_callbacks< link_layer< Server, ScheduledRadio, Options... >, Options... >::type,
480 private details::select_link_layer_security_impl< Server, link_layer< Server, ScheduledRadio, Options... > >,
481 public details::connection_latency_state_t< Options... >,
482 private details::select_phy_update_impl< ScheduledRadio<
483 details::buffer_sizes< Options... >::tx_size,
484 details::buffer_sizes< Options... >::rx_size,
485 link_layer< Server, ScheduledRadio, Options... >
487 public details::select_user_timer_impl<
488 link_layer< Server, ScheduledRadio, Options... >, Options ... >
602 using radio_t = ScheduledRadio<
603 details::buffer_sizes< Options... >::tx_size,
604 details::buffer_sizes< Options... >::rx_size,
605 link_layer< Server, ScheduledRadio, Options... >
609 using l2cap_t =
typename details::l2cap_layer< Server, ScheduledRadio, Options... >::impl;
612 using connection_data_t =
typename l2cap_t::connection_data_t;
615 static bool queue_lcap_notification( const ::bluetoe::details::notification_data& item,
void* usr_arg, ::bluetoe::details::notification_type type );
618 std::pair< std::size_t, std::uint8_t* > allocate_l2cap_output_buffer( std::size_t size );
619 void commit_l2cap_output_buffer( std::pair< std::size_t, std::uint8_t* > buffer );
622 void restart_user_timer();
628 friend details::select_link_layer_security_impl< Server,
link_layer< Server, ScheduledRadio, Options... > >;
629 friend details::select_phy_update_impl< ScheduledRadio<
630 details::buffer_sizes< Options... >::tx_size,
631 details::buffer_sizes< Options... >::rx_size,
632 link_layer< Server, ScheduledRadio, Options... >
637 typename ::bluetoe::details::find_by_not_meta_type<
638 details::valid_link_layer_option_meta_type,
640 >::type, ::bluetoe::details::no_such_type >::value,
641 "Option passed to the link layer, that is not a valid link_layer option." );
644 static constexpr bool encryption_required = bluetoe::details::requires_encryption_support_t< Server >::value;
645 static_assert( !encryption_required || ( encryption_required && radio_t::hardware_supports_encryption ),
646 "The GATT server requires encryption while the selecte hardware binding doesn't provide support for encryption!" );
648 using security_manager_t =
typename details::security_manager<
649 link_layer< Server, ScheduledRadio, Options... >,
653 using signaling_channel_t =
typename details::signaling_channel< Options... >::type;
655 using advertising_t = details::select_advertiser_implementation<
656 link_layer< Server, ScheduledRadio, Options... >, Options... >;
658 unsigned sleep_clock_accuracy(
const std::uint8_t* received_body )
const;
659 bool check_timing_paremeters()
const;
660 bool parse_timing_parameters_from_connect_request(
const std::uint8_t* valid_connect_request_body );
661 bool parse_timing_parameters_from_connection_update_request(
const std::uint8_t* valid_connect_request );
662 void force_disconnect();
663 void start_advertising_impl();
665 void transmit_pending_control_pdus();
666 void reject( std::uint8_t opcode, std::uint8_t error_code,
read_buffer& output );
668 enum class ll_result {
673 ll_result handle_received_data();
674 ll_result send_control_pdus();
677 ll_result handle_pending_ll_control( std::uint16_t instance );
681 static constexpr unsigned first_advertising_channel = 37;
682 static constexpr unsigned num_windows_til_timeout = 6;
683 static constexpr auto us_per_digits = 1250;
685 static constexpr std::uint8_t ll_control_pdu_code = 3;
686 static constexpr std::uint8_t lld_data_pdu_code = 2;
688 static constexpr std::uint8_t LL_CONNECTION_UPDATE_REQ = 0x00;
689 static constexpr std::uint8_t LL_CHANNEL_MAP_REQ = 0x01;
690 static constexpr std::uint8_t LL_TERMINATE_IND = 0x02;
691 static constexpr std::uint8_t LL_ENC_REQ = 0x03;
692 static constexpr std::uint8_t LL_ENC_RSP = 0x04;
693 static constexpr std::uint8_t LL_START_ENC_REQ = 0x05;
694 static constexpr std::uint8_t LL_START_ENC_RSP = 0x06;
695 static constexpr std::uint8_t LL_UNKNOWN_RSP = 0x07;
696 static constexpr std::uint8_t LL_FEATURE_REQ = 0x08;
697 static constexpr std::uint8_t LL_FEATURE_RSP = 0x09;
698 static constexpr std::uint8_t LL_PAUSE_ENC_REQ = 0x0A;
699 static constexpr std::uint8_t LL_PAUSE_ENC_RSP = 0x0B;
700 static constexpr std::uint8_t LL_VERSION_IND = 0x0C;
701 static constexpr std::uint8_t LL_REJECT_IND = 0x0D;
702 static constexpr std::uint8_t LL_CONNECTION_PARAM_REQ = 0x0F;
703 static constexpr std::uint8_t LL_CONNECTION_PARAM_RSP = 0x10;
704 static constexpr std::uint8_t LL_REJECT_IND_EXT = 0x11;
705 static constexpr std::uint8_t LL_PING_REQ = 0x12;
706 static constexpr std::uint8_t LL_PING_RSP = 0x13;
707 static constexpr std::uint8_t LL_PHY_REQ = 0x16;
708 static constexpr std::uint8_t LL_PHY_RSP = 0x17;
709 static constexpr std::uint8_t LL_PHY_UPDATE_IND = 0x18;
711 static constexpr std::uint8_t LL_VERSION_NR = 0x09;
712 static constexpr std::uint8_t LL_VERSION_40 = 0x06;
714 static constexpr std::uint8_t err_pin_or_key_missing = 0x06;
715 static constexpr std::uint16_t company_identifier = 0x0269;
717 struct link_layer_feature {
718 enum : std::uint16_t {
719 le_encryption = 0x001,
720 connection_parameters_request_procedure = 0x002,
721 extended_reject_indication = 0x004,
722 peripheral_initiated_features_exchange = 0x008,
724 le_data_packet_length_extension = 0x020,
726 extended_scanner_filter_policies = 0x080,
727 le_2m_phy_support = 0x100
731 static constexpr std::uint16_t supported_features =
732 link_layer_feature::connection_parameters_request_procedure |
733 link_layer_feature::extended_reject_indication |
734 link_layer_feature::le_ping |
735 ( bluetoe::details::requires_encryption_support_t< Server >::value
736 ? link_layer_feature::le_encryption
738 ( radio_t::hardware_supports_2mbit
739 ? link_layer_feature::le_2m_phy_support
743 static_assert( radio_t::size >= advertising_t::maximum_required_advertising_buffer(),
"buffer to small" );
746 static constexpr std::size_t maximum_ll_payload_size = 27u;
748 device_address address_;
749 channel_map channels_;
750 unsigned cumulated_sleep_clock_accuracy_;
751 delta_time transmit_window_offset_;
752 delta_time transmit_window_size_;
753 delta_time connection_interval_;
754 std::uint16_t peripheral_latency_;
755 std::uint16_t timeout_value_;
756 delta_time connection_timeout_;
757 std::uint16_t defered_conn_event_counter_;
758 write_buffer defered_ll_control_pdu_;
759 connection_data_t connection_data_;
760 bool termination_send_;
761 std::uint16_t used_features_;
763 volatile bool restart_user_timer_requested_;
775 std::uint16_t proposed_interval_min_;
776 std::uint16_t proposed_interval_max_;
777 std::uint16_t proposed_latency_;
778 std::uint16_t proposed_timeout_;
779 bool connection_parameters_request_pending_;
780 bool connection_parameters_request_running_;
781 bool phy_update_request_pending_;
784 typedef advertising_interval< 100 > default_advertising_interval;
785 typedef sleep_clock_accuracy_ppm< 500 > default_sleep_clock_accuracy;
786 typedef random_static_address default_device_address;
788 typedef typename ::bluetoe::details::find_by_meta_type<
789 details::device_address_meta_type,
790 Options..., default_device_address >::type local_device_address;
792 typedef typename ::bluetoe::details::find_by_meta_type<
793 details::sleep_clock_accuracy_meta_type,
794 Options..., default_sleep_clock_accuracy >::type device_sleep_clock_accuracy;
796 typedef typename ::bluetoe::details::find_by_meta_type<
797 details::connection_event_callback_meta_type,
798 Options..., details::default_connection_event_callback
799 >::type connection_event_callback;
804 template <
class Server,
template < std::
size_t, std::
size_t,
class >
class ScheduledRadio,
typename ... Options >
805 link_layer< Server, ScheduledRadio, Options... >::link_layer()
806 : address_( local_device_address::address( *this ) )
807 , defered_ll_control_pdu_{ nullptr, 0 }
808 , used_features_( supported_features )
809 , restart_user_timer_requested_( false )
810 , state_( state::initial )
811 , connection_parameters_request_pending_( false )
812 , connection_parameters_request_running_( false )
813 , phy_update_request_pending_( false )
815 using user_timer_t =
typename bluetoe::details::find_by_meta_type<
816 details::synchronized_connection_event_callback_meta_type,
818 no_synchronized_connection_event_callback
821 using compile_time_check_user_timer_parameters_t = typename ::bluetoe::details::find_by_meta_type<
822 details::check_synchronized_connection_event_callback_meta_type,
823 Options..., no_check_synchronized_connection_event_callback
826 compile_time_check_user_timer_parameters_t::template check< link_layer< Server, ScheduledRadio, Options... > >( user_timer_t() );
828 this->notification_callback( queue_lcap_notification,
this );
831 template <
class Server,
template < std::
size_t, std::
size_t,
class >
class ScheduledRadio,
typename ... Options >
835 if ( state_ == state::initial )
837 start_advertising_impl();
843 template <
class Server,
template < std::
size_t, std::
size_t,
class >
class ScheduledRadio,
typename ... Options >
846 using namespace ::bluetoe::details;
848 assert( state_ == state::advertising );
850 device_address remote_address;
851 const bool connection_request_received = this->handle_adv_receive( receive, remote_address );
853 if ( connection_request_received )
855 const std::uint8_t*
const body = layout_t::body( receive ).first;
857 if ( channels_.reset( &body[ 28 ], body[ 33 ] & 0x1f )
858 && parse_timing_parameters_from_connect_request( body ) )
860 this->reset_connection_state();
862 state_ = state::connecting;
863 cumulated_sleep_clock_accuracy_ = sleep_clock_accuracy( body ) + device_sleep_clock_accuracy::accuracy_ppm;
864 used_features_ = supported_features;
865 connection_parameters_request_pending_ =
false;
866 connection_parameters_request_running_ =
false;
867 phy_update_request_pending_ =
false;
868 pending_event_ =
false;
870 this->set_access_address_and_crc_init( read_32bit( &body[ 12 ] ), read_24bit( &body[ 16 ] ) );
872 this->reset_pdu_buffer();
873 setup_next_connection_event();
875 this->connection_request( connection_addresses( address_, remote_address ) );
876 this->handle_stop_advertising();
878 connection_data_ = connection_data_t();
879 connection_data_.remote_connection_created( remote_address );
884 template <
class Server,
template < std::
size_t, std::
size_t,
class >
class ScheduledRadio,
typename ... Options >
887 assert( state_ == state::advertising );
889 this->handle_adv_timeout();
892 template <
class Server,
template < std::
size_t, std::
size_t,
class >
class ScheduledRadio,
typename ... Options >
895 pending_event_ =
false;
897 assert( state_ == state::connecting || state_ == state::connected || state_ == state::disconnecting || state_ == state::connection_changed );
899 const auto time_since_last_event = this->time_since_last_event();
901 if ( time_since_last_event <= connection_timeout_
902 && !( state_ == state::connecting && time_since_last_event >= ( num_windows_til_timeout - 1 ) * connection_interval_ ) )
904 this->plan_next_connection_event_after_timeout( connection_interval_ );
906 if ( handle_pending_ll_control( this->connection_event_counter() ) == ll_result::disconnect )
912 setup_next_connection_event();
920 this->
template handle_connection_events< link_layer< Server, ScheduledRadio, Options... > >();
923 template <
class Server,
template < std::
size_t, std::
size_t,
class >
class ScheduledRadio,
typename ... Options >
926 pending_event_ =
false;
928 assert( state_ == state::connecting || state_ == state::connected || state_ == state::disconnecting || state_ == state::connection_changed );
930 if ( state_ == state::connecting || restart_user_timer_requested_ )
932 this->synchronized_connection_event_callback_new_connection( connection_interval_ );
933 restart_user_timer_requested_ =
false;
936 if ( state_ == state::connecting )
938 this->connection_established( details(), connection_data_,
static_cast< radio_t&
>( *
this ) );
940 else if ( state_ == state::connection_changed )
942 this->synchronized_connection_event_callback_connection_changed( connection_interval_ );
945 if ( state_ != state::disconnecting )
947 state_ = state::connected;
948 transmit_window_size_ = delta_time();
957 if ( handle_received_data() == ll_result::disconnect || send_control_pdus() == ll_result::disconnect )
963 this->transmit_pending_security_pdus();
965 const std::pair< bool, std::uint16_t > pending_instant = { !defered_ll_control_pdu_.empty(), defered_conn_event_counter_ };
967 evts.pending_outgoing_data = evts.pending_outgoing_data || this->pending_outgoing_data_available();
968 this->plan_next_connection_event(
969 peripheral_latency_, evts, connection_interval_, pending_instant );
972 if ( handle_pending_ll_control( this->connection_event_counter() ) == ll_result::disconnect )
978 const delta_time time_till_next_event = setup_next_connection_event();
979 connection_event_callback::call_connection_event_callback( time_till_next_event );
984 if ( state_ == state::connected || state_ == state::connecting )
986 transmit_pending_control_pdus();
987 this->transmit_pending_l2cap_output( connection_data_ );
990 this->
template handle_connection_events< link_layer< Server, ScheduledRadio, Options... > >();
993 template <
class Server,
template < std::
size_t, std::
size_t,
class >
class ScheduledRadio,
typename ... Options >
994 void link_layer< Server, ScheduledRadio, Options... >::restart_user_timer()
996 restart_user_timer_requested_ =
true;
999 template <
class Server,
template < std::
size_t, std::
size_t,
class >
class ScheduledRadio,
typename ... Options >
1002 this->synchronized_connection_event_callback_timeout( anchor_moved );
1005 template <
class Server,
template < std::
size_t, std::
size_t,
class >
class ScheduledRadio,
typename ... Options >
1008 if ( ( state_ == state::connected || state_ == state::connecting )
1009 && pending_event_ && this->reschedule_on_pending_data( *
this, connection_interval_ ) )
1011 setup_next_connection_event();
1015 template <
class Server,
template < std::
size_t, std::
size_t,
class >
class ScheduledRadio,
typename ... Options >
1018 if ( used_features_ & link_layer_feature::connection_parameters_request_procedure )
1020 if ( connection_parameters_request_pending_ )
1023 proposed_interval_min_ = interval_min;
1024 proposed_interval_max_ = interval_max;
1025 proposed_latency_ = latency;
1026 proposed_timeout_ = timeout;
1027 connection_parameters_request_pending_ =
true;
1034 const bool result =
static_cast< signaling_channel_t&
>( *this ).connection_parameter_update_request( interval_min, interval_max, latency, timeout );
1042 template <
class Server,
template < std::
size_t, std::
size_t,
class >
class ScheduledRadio,
typename ... Options >
1045 if ( phy_update_request_pending_ )
1048 phy_update_request_pending_ =
true;
1055 template <
class Server,
template < std::
size_t, std::
size_t,
class >
class ScheduledRadio,
typename ... Options >
1058 state_ = state::disconnecting;
1059 termination_send_ =
false;
1061 this->synchronized_connection_event_callback_disconnect();
1062 this->reset_encryption();
1065 template <
class Server,
template < std::
size_t, std::
size_t,
class >
class ScheduledRadio,
typename ... Options >
1066 delta_time link_layer< Server, ScheduledRadio, Options... >::setup_next_connection_event()
1068 pending_event_ =
true;
1070 delta_time window_start;
1071 delta_time window_end;
1073 const delta_time time_since_last_event = this->time_since_last_event();
1076 if ( !transmit_window_size_.zero() )
1078 window_start = time_since_last_event + transmit_window_offset_;
1079 window_end = window_start + transmit_window_size_;
1081 window_start -= window_start.ppm( cumulated_sleep_clock_accuracy_ );
1082 window_end += window_end.ppm( cumulated_sleep_clock_accuracy_ );
1086 const delta_time window_size = time_since_last_event.ppm( cumulated_sleep_clock_accuracy_ );
1088 window_start = time_since_last_event - window_size;
1089 window_end = time_since_last_event + window_size;
1092 return this->schedule_connection_event(
1093 channels_.data_channel( this->current_channel_index() ),
1096 connection_interval_ );
1099 template <
class Server,
template < std::
size_t, std::
size_t,
class >
class ScheduledRadio,
typename ... Options >
1100 void link_layer< Server, ScheduledRadio, Options... >::transmit_pending_control_pdus()
1102 static constexpr std::uint8_t connection_param_req_size = 24u;
1104 if ( !connection_parameters_request_pending_ && !phy_update_request_pending_ )
1108 auto out_buffer = this->allocate_ll_transmit_buffer( connection_param_req_size );
1110 if ( out_buffer.empty() )
1116 if ( connection_parameters_request_pending_ )
1118 connection_parameters_request_pending_ =
false;
1119 connection_parameters_request_running_ =
true;
1121 fill< layout_t >( out_buffer, {
1122 ll_control_pdu_code, connection_param_req_size, LL_CONNECTION_PARAM_REQ,
1123 static_cast< std::uint8_t
>( proposed_interval_min_ ),
1124 static_cast< std::uint8_t
>( proposed_interval_min_ >> 8 ),
1125 static_cast< std::uint8_t
>( proposed_interval_max_ ),
1126 static_cast< std::uint8_t
>( proposed_interval_max_ >> 8 ),
1127 static_cast< std::uint8_t
>( proposed_latency_ ),
1128 static_cast< std::uint8_t
>( proposed_latency_ >> 8 ),
1129 static_cast< std::uint8_t
>( proposed_timeout_ ),
1130 static_cast< std::uint8_t
>( proposed_timeout_ >> 8 ),
1133 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1134 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } );
1136 this->commit_ll_transmit_buffer( out_buffer );
1138 else if ( phy_update_request_pending_ )
1140 phy_update_request_pending_ =
false;
1142 fill< layout_t >( out_buffer, {
1143 ll_control_pdu_code, 3, LL_PHY_REQ,
1144 details::phy_ll_encoding::le_2m_phy, details::phy_ll_encoding::le_2m_phy } );
1146 this->commit_ll_transmit_buffer( out_buffer );
1150 template <
class Server,
template < std::
size_t, std::
size_t,
class >
class ScheduledRadio,
typename ... Options >
1151 void link_layer< Server, ScheduledRadio, Options... >::reject( std::uint8_t opcode, std::uint8_t error_code, read_buffer& output )
1153 if ( used_features_ & link_layer_feature::extended_reject_indication )
1155 fill< layout_t >( output, {
1156 ll_control_pdu_code, 3, LL_REJECT_IND_EXT, opcode, error_code } );
1160 fill< layout_t >( output, {
1161 ll_control_pdu_code, 2, LL_REJECT_IND, error_code } );
1165 template <
class Server,
template < std::
size_t, std::
size_t,
class >
class ScheduledRadio,
typename ... Options >
1166 bool link_layer< Server, ScheduledRadio, Options... >::queue_lcap_notification( const ::bluetoe::details::notification_data& item,
void* that, ::bluetoe::details::notification_type type )
1168 auto& connection =
static_cast< link_layer< Server, ScheduledRadio, Options...
>* >( that )->connection_data_;
1170 bool new_data =
false;
1174 case bluetoe::details::notification_type::notification:
1175 new_data = connection.queue_notification( item.client_characteristic_configuration_index() );
1177 case bluetoe::details::notification_type::indication:
1178 new_data = connection.queue_indication( item.client_characteristic_configuration_index() );
1180 case bluetoe::details::notification_type::confirmation:
1181 connection.indication_confirmed();
1187 static_cast< link_layer< Server, ScheduledRadio, Options...
>* >( that )->request_event_cancelation();
1192 template <
class Server,
template < std::
size_t, std::
size_t,
class >
class ScheduledRadio,
typename ... Options >
1193 unsigned link_layer< Server, ScheduledRadio, Options... >::sleep_clock_accuracy(
const std::uint8_t* received_body )
const
1195 static constexpr std::uint16_t inaccuracy_ppm[ 8 ] = {
1196 500, 250, 150, 100, 75, 50, 30, 20
1199 return inaccuracy_ppm[ ( received_body[ 33 ] >> 5 & 0x7 ) ];
1202 template <
class Server,
template < std::
size_t, std::
size_t,
class >
class ScheduledRadio,
typename ... Options >
1203 bool link_layer< Server, ScheduledRadio, Options... >::check_timing_paremeters()
const
1205 static constexpr delta_time maximum_transmit_window_offset( 10 * 1000 );
1206 static constexpr delta_time maximum_connection_timeout( 32 * 1000 * 1000 );
1207 static constexpr delta_time minimum_connection_timeout( 100 * 1000 );
1209 return transmit_window_size_ <= maximum_transmit_window_offset
1210 && transmit_window_size_ <= connection_interval_
1211 && connection_timeout_ >= minimum_connection_timeout
1212 && connection_timeout_ <= maximum_connection_timeout
1213 && connection_timeout_ >= ( peripheral_latency_ + 1 ) * 2 * connection_interval_
1214 && peripheral_latency_ <= maximum_link_layer_peripheral_latency;
1217 template <
class Server,
template < std::
size_t, std::
size_t,
class >
class ScheduledRadio,
typename ... Options >
1218 bool link_layer< Server, ScheduledRadio, Options... >::parse_timing_parameters_from_connect_request(
const std::uint8_t* valid_connect_request_body )
1220 using namespace ::bluetoe::details;
1222 const delta_time transmit_window_offset = delta_time( read_16bit( &valid_connect_request_body[ 20 ] ) * us_per_digits );
1224 transmit_window_size_ = delta_time( valid_connect_request_body[ 19 ] * us_per_digits );
1225 transmit_window_offset_ = delta_time( read_16bit( &valid_connect_request_body[ 20 ] ) * us_per_digits + us_per_digits );
1226 connection_interval_ = delta_time( read_16bit( &valid_connect_request_body[ 22 ] ) * us_per_digits );
1227 peripheral_latency_ = read_16bit( &valid_connect_request_body[ 24 ] );
1228 timeout_value_ = read_16bit( &valid_connect_request_body[ 26 ] );
1229 connection_timeout_ = delta_time( timeout_value_ * 10000 );
1231 return transmit_window_offset <= connection_interval_ && check_timing_paremeters();
1234 template <
class Server,
template < std::
size_t, std::
size_t,
class >
class ScheduledRadio,
typename ... Options >
1235 bool link_layer< Server, ScheduledRadio, Options... >::parse_timing_parameters_from_connection_update_request(
const std::uint8_t* valid_update_request )
1237 using namespace ::bluetoe::details;
1239 transmit_window_size_ = delta_time( valid_update_request[ 1 ] * us_per_digits );
1240 transmit_window_offset_ = delta_time( read_16bit( &valid_update_request[ 2 ] ) * us_per_digits );
1241 connection_interval_ = delta_time( read_16bit( &valid_update_request[ 4 ] ) * us_per_digits );
1242 peripheral_latency_ = read_16bit( &valid_update_request[ 6 ] );
1243 timeout_value_ = read_16bit( &valid_update_request[ 8 ] );
1244 connection_timeout_ = delta_time( timeout_value_ * 10000 );
1246 return transmit_window_offset_ <= connection_interval_ && check_timing_paremeters();
1249 template <
class Server,
template < std::
size_t, std::
size_t,
class >
class ScheduledRadio,
typename ... Options >
1250 void link_layer< Server, ScheduledRadio, Options... >::force_disconnect()
1252 this->reset_encryption();
1253 this->reset_phy( *
this );
1255 if ( state_ != state::connecting )
1257 this->synchronized_connection_event_callback_disconnect();
1258 this->connection_closed( connection_data_,
static_cast< radio_t&
>( *
this ) );
1261 start_advertising_impl();
1264 template <
class Server,
template < std::
size_t, std::
size_t,
class >
class ScheduledRadio,
typename ... Options >
1265 void link_layer< Server, ScheduledRadio, Options... >::start_advertising_impl()
1267 state_ = state::advertising;
1269 defered_ll_control_pdu_ = write_buffer{
nullptr, 0 };
1271 this->handle_start_advertising();
1274 template <
class Server,
template < std::
size_t, std::
size_t,
class >
class ScheduledRadio,
typename ... Options >
1275 typename link_layer< Server, ScheduledRadio, Options... >::ll_result link_layer< Server, ScheduledRadio, Options... >::handle_received_data()
1277 ll_result result = ll_result::go_ahead;
1279 if ( !defered_ll_control_pdu_.empty() )
1282 for (
auto pdu = this->next_ll_l2cap_received(); pdu.size != 0 && result == ll_result::go_ahead && defered_ll_control_pdu_.empty(); )
1284 const auto llid = layout_t::header( pdu ) & 0x03;
1285 const auto body = layout_t::body( pdu );
1287 if ( llid == ll_control_pdu_code )
1289 const read_buffer output = this->allocate_ll_transmit_buffer( maximum_ll_payload_size );
1293 result = handle_ll_control_data( pdu, output );
1294 this->free_ll_l2cap_received();
1295 pdu = this->next_ll_l2cap_received();
1302 else if ( llid == lld_data_pdu_code && state_ != state::disconnecting
1303 && this->handle_l2cap_input( body.first, body.second - body.first, connection_data_ ) )
1305 this->free_ll_l2cap_received();
1306 pdu = this->next_ll_l2cap_received();
1317 template <
class Server,
template < std::
size_t, std::
size_t,
class >
class ScheduledRadio,
typename ... Options >
1318 typename link_layer< Server, ScheduledRadio, Options... >::ll_result link_layer< Server, ScheduledRadio, Options... >::send_control_pdus()
1320 static constexpr std::uint8_t connection_terminated_by_local_host = 0x16;
1322 if ( state_ == state::disconnecting && !termination_send_ )
1324 auto output = this->allocate_ll_transmit_buffer( maximum_ll_payload_size );
1328 fill< layout_t >( output, {
1329 ll_control_pdu_code, 2,
1330 LL_TERMINATE_IND, connection_terminated_by_local_host
1333 this->commit_ll_transmit_buffer( output );
1334 termination_send_ =
true;
1338 return ll_result::go_ahead;
1341 template <
class Server,
template < std::
size_t, std::
size_t,
class >
class ScheduledRadio,
typename ... Options >
1342 typename link_layer< Server, ScheduledRadio, Options... >::ll_result link_layer< Server, ScheduledRadio, Options... >::handle_ll_control_data(
const write_buffer& pdu, read_buffer write )
1344 using namespace ::bluetoe::details;
1346 ll_result result = ll_result::go_ahead;
1349 assert( write.size >= radio_t::min_buffer_size );
1351 const std::uint8_t*
const body = layout_t::body( pdu ).first;
1352 const std::uint16_t header = layout_t::header( pdu );
1354 if ( ( header & 0x3 ) == ll_control_pdu_code )
1356 const std::uint8_t size = header >> 8;
1357 const std::uint8_t opcode = size > 0 ? *body : 0xff;
1359 if ( opcode == LL_CONNECTION_UPDATE_REQ && size == 12 )
1361 defered_conn_event_counter_ = read_16bit( &body[ 10 ] );
1364 if (
static_cast< std::uint16_t
>( defered_conn_event_counter_ - this->connection_event_counter() + 1 ) & 0x8000
1365 || defered_conn_event_counter_ == this->connection_event_counter() + 1 )
1367 result = ll_result::disconnect;
1371 defered_ll_control_pdu_ = pdu;
1374 else if ( opcode == LL_TERMINATE_IND && size == 2 )
1377 result = ll_result::disconnect;
1379 else if ( opcode == LL_VERSION_IND && size == 6 )
1381 if ( body[ 1 ] <= LL_VERSION_40 )
1382 used_features_ = used_features_ & ~link_layer_feature::connection_parameters_request_procedure;
1384 fill< layout_t >( write, {
1385 ll_control_pdu_code, 6, LL_VERSION_IND,
1387 static_cast< std::uint8_t
>( company_identifier ),
1388 static_cast< std::uint8_t
>( company_identifier >> 8 ),
1392 else if ( opcode == LL_CHANNEL_MAP_REQ && size == 8 )
1394 defered_conn_event_counter_ = read_16bit( &body[ 6 ] );
1397 if (
static_cast< std::uint16_t
>( defered_conn_event_counter_ - this->connection_event_counter() ) & 0x8000 )
1399 result = ll_result::disconnect;
1403 defered_ll_control_pdu_ = pdu;
1406 else if ( opcode == LL_PING_REQ && size == 1 )
1408 fill< layout_t >( write, { ll_control_pdu_code, 1, LL_PING_RSP } );
1410 else if ( opcode == LL_FEATURE_REQ && size == 9 )
1412 std::uint16_t remote_features = read_16bit( & body[ 1 ] );
1413 used_features_ = used_features_ & remote_features;
1418 fill< layout_t >( write, {
1419 ll_control_pdu_code, 9,
1421 static_cast< std::uint8_t
>( used_features_ ),
1422 static_cast< std::uint8_t
>( supported_features >> 8 ),
1423 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1427 else if ( ( opcode == LL_UNKNOWN_RSP && size == 2 && body[ 1 ] == LL_CONNECTION_PARAM_REQ )
1428 || opcode == LL_REJECT_IND
1429 || ( opcode == LL_REJECT_IND_EXT && body[ 1 ] == LL_CONNECTION_PARAM_REQ ) )
1431 if ( connection_parameters_request_running_ )
1433 connection_parameters_request_running_ =
false;
1435 if ( signaling_channel_t::connection_parameter_update_request(
1436 proposed_interval_min_,
1437 proposed_interval_max_,
1439 proposed_timeout_ ) )
1445 if ( opcode == LL_UNKNOWN_RSP )
1446 used_features_ = used_features_ & ~link_layer_feature::connection_parameters_request_procedure;
1450 else if ( opcode == LL_CONNECTION_PARAM_REQ && size == 24 )
1452 using connection_param_responder =
typename bluetoe::details::find_by_meta_type<
1453 bluetoe::link_layer::details::desired_connection_parameters_meta_type,
1455 no_desired_connection_parameters >::type;
1457 connection_param_responder::template fill_response< layout_t >( pdu, write );
1459 else if ( this->handle_encryption_pdus( opcode, size, pdu, write, commit ) )
1463 else if ( this->handle_phy_request( opcode, size, pdu, write, *
this, commit ) )
1467 else if ( opcode != LL_UNKNOWN_RSP )
1469 fill< layout_t >( write, { ll_control_pdu_code, 2, LL_UNKNOWN_RSP, opcode } );
1477 this->commit_ll_transmit_buffer( write );
1483 template <
class Server,
template < std::
size_t, std::
size_t,
class >
class ScheduledRadio,
typename ... Options >
1484 typename link_layer< Server, ScheduledRadio, Options... >::ll_result link_layer< Server, ScheduledRadio, Options... >::handle_pending_ll_control( std::uint16_t instance )
1486 ll_result result = ll_result::go_ahead;
1488 if ( !defered_ll_control_pdu_.empty() && defered_conn_event_counter_ == instance )
1490 const std::uint8_t* body = layout_t::body( defered_ll_control_pdu_ ).first;
1491 const std::uint8_t opcode = body[ 0 ];
1493 if ( opcode == LL_CHANNEL_MAP_REQ )
1495 channels_.reset( &body[ 1 ] );
1497 else if ( opcode == LL_CONNECTION_UPDATE_REQ )
1499 if ( parse_timing_parameters_from_connection_update_request( body ) )
1501 state_ = state::connection_changed;
1502 this->synchronized_connection_event_callback_start_changing_connection();
1503 this->connection_changed( details(), connection_data_,
static_cast< radio_t&
>( *
this ) );
1507 result = ll_result::disconnect;
1510 else if ( this->handle_pending_phy_request( opcode, *
this ) )
1516 assert( !
"invalid opcode" );
1519 defered_ll_control_pdu_ = write_buffer{
nullptr, 0 };
1525 template <
class Server,
template < std::
size_t, std::
size_t,
class >
class ScheduledRadio,
typename ... Options >
1526 connection_details link_layer< Server, ScheduledRadio, Options... >::details()
const
1528 return connection_details(
1530 connection_interval_.usec() / us_per_digits,
1531 peripheral_latency_,
1533 cumulated_sleep_clock_accuracy_ );
1536 template <
class Server,
template < std::
size_t, std::
size_t,
class >
class ScheduledRadio,
typename ... Options >
1539 return this->advertising_data( buffer, buffer_size );
1542 template <
class Server,
template < std::
size_t, std::
size_t,
class >
class ScheduledRadio,
typename ... Options >
1545 return this->scan_response_data( buffer, buffer_size );
1548 template <
class Server,
template < std::
size_t, std::
size_t,
class >
class ScheduledRadio,
typename ... Options >
1551 return this->advertising_or_scan_response_data_has_been_changed();
1554 template <
class Server,
template < std::
size_t, std::
size_t,
class >
class ScheduledRadio,
typename ... Options >
1560 template <
class Server,
template < std::
size_t, std::
size_t,
class >
class ScheduledRadio,
typename ... Options >
1563 address_ = new_address;
1566 template <
class Server,
template < std::
size_t, std::
size_t,
class >
class ScheduledRadio,
typename ... Options >
1569 return supported_features;
1572 template <
class Server,
template < std::
size_t, std::
size_t,
class >
class ScheduledRadio,
typename ... Options >
1575 return LL_VERSION_NR;
1578 template <
class Server,
template < std::
size_t, std::
size_t,
class >
class ScheduledRadio,
typename ... Options >
1581 return company_identifier;
1584 template <
class Server,
template < std::
size_t, std::
size_t,
class >
class ScheduledRadio,
typename ... Options >
1585 std::pair< std::size_t, std::uint8_t* > link_layer< Server, ScheduledRadio, Options... >::allocate_l2cap_output_buffer( std::size_t size )
1587 const auto buffer = this->allocate_l2cap_transmit_buffer( size );
1589 if ( buffer.size == 0 )
1590 return { 0,
nullptr };
1593 const auto body = layout_t::body( buffer );
1595 return { body.second - body.first, body.first };
1598 template <
class Server,
template < std::
size_t, std::
size_t,
class >
class ScheduledRadio,
typename ... Options >
1599 void link_layer< Server, ScheduledRadio, Options... >::commit_l2cap_output_buffer( std::pair< std::size_t, std::uint8_t* > buffer )
1601 assert( buffer.first );
1602 assert( buffer.second );
1605 static constexpr std::size_t overhead = layout_t::data_channel_pdu_memory_size( 0 );
1607 const read_buffer out_buffer{ buffer.second - overhead, buffer.first + overhead };
1611 fill< layout_t >( out_buffer, {
1613 static_cast< std::uint8_t
>( buffer.first & 0xff ) } );
1615 this->commit_l2cap_transmit_buffer( out_buffer );
signaling channel implementations that does simply nothing
Definition: l2cap_signaling_channel.hpp:93
A Security manager that implements only LESC pairing.
Definition: security_manager.hpp:482
data type to store details of an established link layer connection
Definition: connection_details.hpp:15
positiv time quantum used to express distance in time.
Definition: delta_time.hpp:14
data type containing a device address and the address type (public or random).
Definition: address.hpp:107
link layer implementation
Definition: link_layer.hpp:489
void user_timer(bool anchor_moved)
call back that will be called on expired user timer.
void disconnect()
terminates the give connection
void local_address(const device_address &new_address)
set the local address
bool phy_update_request_to_2mbit()
initiates a PHY Update Procedure to request to upgrade the PHY to 2MBit.
bool l2cap_adverting_data_or_scan_response_data_changed()
returns true, if advertising or scan response data might have changed.
std::uint64_t supported_link_layer_features() const
returns the feature mask of supported link layer features
std::uint16_t link_layer_company_identifier() const
returns the Company_Identifier field of the LL_VERSION_IND PDU
std::size_t fill_l2cap_scan_response_data(std::uint8_t *buffer, std::size_t buffer_size) const
fills the given buffer with l2cap scan response payload
void adv_received(const read_buffer &receive)
call back that will be called when the central responds to an advertising PDU
void end_event(connection_event_events evts)
call back that will be called after a connect event was closed.
void timeout()
call back that will be called when connect event times out
void try_event_cancelation()
call back that will try to reschedule the connection event
void run()
this function passes the CPU to the link layer implementation
bool connection_parameter_update_request(std::uint16_t interval_min, std::uint16_t interval_max, std::uint16_t latency, std::uint16_t timeout)
initiating the change of communication parameters of an established connection
const device_address & local_address() const
returns the own local device address
void adv_timeout()
call back that will be called when the central does not respond to an advertising PDU
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
std::uint8_t supported_link_layer_version() const
returns the Version field of the LL_VERSION_IND PDU
buffer responsible for fragment or defragment L2CAP SDUs
Definition: ll_l2cap_sdu_buffer.hpp:19
implementation of the security manager, that actievly rejects every pairing attempt.
Definition: security_manager.hpp:533
peripheral_latency_configuration< peripheral_latency::listen_if_pending_transmit_data, peripheral_latency::listen_if_unacknowledged_data, peripheral_latency::listen_if_last_received_not_empty, peripheral_latency::listen_if_last_transmitted_not_empty, peripheral_latency::listen_if_last_received_had_more_data > periperal_latency_default_configuration
Default peripheral latency configuration.
Definition: peripheral_latency.hpp:265
defines link layer transmit and receive buffer sizes
Definition: ll_options.hpp:124
set of events, that could have happend during a connection event
Definition: connection_events.hpp:14
implements a PDU layout, where in memory and over the air layout are equal.
Definition: default_pdu_layout.hpp:42
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
type suitable to store the location and size of a chunk of memory that can be used to transmit to the...
Definition: buffer.hpp:85