BlueToe
an alternative GATT/BLE implementation
Loading...
Searching...
No Matches
link_layer.hpp
1#ifndef BLUETOE_LINK_LAYER_LINK_LAYER_HPP
2#define BLUETOE_LINK_LAYER_LINK_LAYER_HPP
3
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>
26
27#include <algorithm>
28#include <cassert>
29
30namespace bluetoe {
31 namespace details {
32 class notification_data;
33 }
34
35namespace link_layer {
36
37 template <
38 class Server,
39 template <
40 std::size_t TransmitSize,
41 std::size_t ReceiveSize,
42 class CallBack
43 >
44 class ScheduledRadio,
45 typename ... Options
46 >
47 class link_layer;
48
49 namespace details {
50 template < typename ... Options >
51 struct buffer_sizes
52 {
53 typedef typename ::bluetoe::details::find_by_meta_type<
54 buffer_sizes_meta_type,
55 Options...,
57 >::type s_type;
58
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;
61 };
62
63 template < typename SecurityFunctions, typename Server, typename ... Options >
64 struct security_manager {
65 using default_sm = typename bluetoe::details::select_type<
66 bluetoe::details::requires_encryption_support_t< Server >::value,
69 >::type;
70
71 using impl = typename bluetoe::details::find_by_meta_type<
72 bluetoe::details::security_manager_meta_type,
73 Options...,
74 default_sm >::type;
75
76 using type = typename impl::template impl< SecurityFunctions, Options... >;
77 };
78
79 template < typename ... Options >
80 struct signaling_channel {
81 typedef typename bluetoe::details::find_by_meta_type<
82 bluetoe::details::signaling_channel_meta_type,
83 Options...,
85 };
86
87 template < typename LinkLayer, typename ... Options >
88 struct connection_callbacks
89 {
90 typedef typename bluetoe::details::find_by_meta_type<
91 connection_callbacks_meta_type,
92 Options...,
93 no_connection_callbacks >::type callbacks;
94
95 typedef typename callbacks::impl type;
96 };
97
98 template < typename Radio, typename LinkLayer, typename ... Options >
99 struct white_list
100 {
101 typedef typename bluetoe::details::find_by_meta_type<
102 white_list_meta_type,
103 Options...,
104 no_white_list >::type list;
105
106 typedef typename list::template impl< Radio, LinkLayer > type;
107 };
108
109 /*
110 * The Part of link layer, that handles security related stuff is
111 * factored out, to not have unnessary code, in case that no
112 * security relevant code is required
113 */
114 struct link_layer_security_impl
115 {
116 template < class LinkLayer >
117 class impl
118 {
119 public:
120 impl()
121 : has_key_( false )
122 , encryption_in_progress_( false )
123 {}
124
125 LinkLayer& that()
126 {
127 return static_cast< LinkLayer& >( *this );
128 }
129
130 bool handle_encryption_pdus( std::uint8_t opcode, std::uint8_t size, const write_buffer& pdu, read_buffer write, bool& commit )
131 {
132 using namespace ::bluetoe::details;
133
135
136 bool encryption_changed = false;
137
138 if ( opcode == LinkLayer::LL_ENC_REQ && size == 23 )
139 {
140 encryption_in_progress_ = true;
141 fill< layout_t >( write, { LinkLayer::ll_control_pdu_code, 1 + 8 + 4, LinkLayer::LL_ENC_RSP } );
142
143 const std::uint8_t* const pdu_body = layout_t::body( pdu ).first;
144
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;
151
152 bluetoe::details::uint128_t key;
153 std::tie( has_key_, key ) = that().connection_data_.find_key( ediv, rand );
154
155 // setup encryption
156 std::tie( skds, ivs ) = that().setup_encryption( key, skdm, ivm );
157
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 );
161 }
162 else if ( opcode == LinkLayer::LL_START_ENC_RSP && size == 1 )
163 {
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 );
167
168 if ( encryption_changed )
169 that().connection_data_.restore_bonded_cccds( that().connection_data_ );
170
171 }
172 else if ( opcode == LinkLayer::LL_PAUSE_ENC_REQ && size == 1 )
173 {
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 );
177 }
178 else if ( opcode == LinkLayer::LL_PAUSE_ENC_RSP && size == 1 )
179 {
180 that().stop_transmit_encrypted();
181 encryption_changed = that().connection_data_.is_encrypted( false );
182
183 commit = false;
184 }
185 else
186 {
187 return false;
188 }
189
190 if ( encryption_changed )
191 {
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() ) );
194 }
195
196 return true;
197 }
198
199 void transmit_pending_security_pdus()
200 {
202
203 if ( !encryption_in_progress_ )
204 return;
205
206 auto out_buffer = that().allocate_ll_transmit_buffer( LinkLayer::maximum_ll_payload_size );
207 if ( out_buffer.empty() )
208 return;
209
210 if ( has_key_ )
211 {
212 fill< layout_t >( out_buffer, {
213 LinkLayer::ll_control_pdu_code, 1, LinkLayer::LL_START_ENC_REQ } );
214
215 that().start_receive_encrypted();
216 that().commit_ll_transmit_buffer( out_buffer );
217 }
218 else
219 {
220 that().reject( LinkLayer::LL_ENC_REQ, LinkLayer::err_pin_or_key_missing, out_buffer );
221 that().commit_ll_transmit_buffer( out_buffer );
222 }
223
224 encryption_in_progress_ = false;
225 }
226
227 void reset_encryption()
228 {
229 that().connection_data_.is_encrypted( false );
230 that().stop_receive_encrypted();
231 that().stop_transmit_encrypted();
232 }
233
234 private:
235 bool has_key_;
236 bool encryption_in_progress_;
237 };
238
239 using link_state = bluetoe::details::link_state;
240 };
241
242 struct link_layer_no_security_impl
243 {
244 template < class LinkLayer >
245 struct impl
246 {
247 bool handle_encryption_pdus( std::uint8_t, std::uint8_t, write_buffer, read_buffer, bool& )
248 {
249 return false;
250 }
251
252 void transmit_pending_security_pdus()
253 {
254 }
255
256 void reset_encryption()
257 {
258 }
259 };
260
261 using link_state = bluetoe::details::link_state_no_security;
262 };
263
264 /*
265 * The Part of link layer, that handles PHY update requests
266 */
267 struct phy_update_request_impl
268 {
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 )
271 {
272 assert( link_layer.defered_ll_control_pdu_.buffer == nullptr );
273
275
276 if ( opcode == LL::LL_PHY_REQ && size == 3 )
277 {
278 fill< layout_t >( write, {
279 LL::ll_control_pdu_code, 3,
280 LL::LL_PHY_RSP,
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 } );
283
284 return true;
285 }
286
287 if ( opcode == LL::LL_PHY_UPDATE_IND && size == 5 )
288 {
289 const std::uint8_t* const pdu_body = layout_t::body( pdu ).first;
290
291 const std::uint8_t c_to_p = pdu_body[ 1 ];
292 const std::uint8_t p_to_c = pdu_body[ 2 ];
293
294 if ( !valid_phy_encoding( c_to_p ) || !valid_phy_encoding( p_to_c ) )
295 return false;
296
297 commit = false;
298
299 if ( c_to_p == details::phy_ll_encoding::le_unchanged_coding
300 && p_to_c == details::phy_ll_encoding::le_unchanged_coding )
301 return true;
302
303 link_layer.defered_ll_control_pdu_ = pdu;
304 link_layer.defered_conn_event_counter_ = ::bluetoe::details::read_16bit( pdu_body + 3 );
305
306 return true;
307 }
308
309 return false;
310 }
311
312 template < class LL >
313 bool handle_pending_phy_request( std::uint8_t opcode, LL& link_layer )
314 {
315 assert( link_layer.defered_ll_control_pdu_.buffer );
316
318
319 if ( opcode == LL::LL_PHY_UPDATE_IND )
320 {
321 const std::uint8_t* const pdu_body = layout_t::body( link_layer.defered_ll_control_pdu_ ).first;
322
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 );
327
328 return true;
329 }
330
331 return false;
332 }
333
334 template < class LL >
335 void reset_phy( LL& link_layer )
336 {
337 link_layer.radio_set_phy( phy_ll_encoding::le_1m_phy, phy_ll_encoding::le_1m_phy );
338 }
339
340 private:
341 bool valid_phy_encoding( std::uint8_t c ) const
342 {
343 return c == 0
344 || c == phy_ll_encoding::le_1m_phy
345 || c == phy_ll_encoding::le_2m_phy;
346 }
347 };
348
349 struct no_phy_update_request_impl
350 {
351 template < class LL >
352 bool handle_phy_request( std::uint8_t, std::uint8_t, const write_buffer&, read_buffer, LL&, bool& )
353 {
354 return false;
355 }
356
357 template < class LL >
358 bool handle_pending_phy_request( std::uint8_t, LL& )
359 {
360 return false;
361 }
362
363 template < class LL >
364 void reset_phy( LL& )
365 {}
366 };
367
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 >;
375
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
382 >::type::link_state;
383
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
390 >::type;
391
392 template <
393 class Server,
394 template <
395 std::size_t TransmitSize,
396 std::size_t ReceiveSize,
397 class CallBack
398 >
399 class ScheduledRadio,
400 typename ... Options
401 >
402 struct l2cap_layer {
403 using impl = bluetoe::details::l2cap<
404 link_layer< Server, ScheduledRadio, Options... >,
405 details::select_link_layer_security_link_state< Server >,
406 Server,
407 typename details::signaling_channel< Options... >::type,
408 typename details::security_manager<
409 link_layer< Server, ScheduledRadio, Options... >,
410 Server, Options...
411 >::type
412 >;
413
414 static constexpr std::size_t required_minimum_l2cap_buffer_size = impl::maximum_mtu_size;
415 };
416
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,
421 Options...,
423 >;
424
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,
428 Options...,
429 no_synchronized_connection_event_callback
430 >::type::template impl< Base >;
431 }
432
445 template <
446 class Server,
447 template <
448 std::size_t TransmitSize,
449 std::size_t ReceiveSize,
450 class CallBack
451 >
452 class ScheduledRadio,
453 typename ... Options
454 >
457 ScheduledRadio<
458 details::buffer_sizes< Options... >::tx_size,
459 details::buffer_sizes< Options... >::rx_size,
460 link_layer< Server, ScheduledRadio, Options... >
461 >,
462 details::l2cap_layer< Server, ScheduledRadio, Options... >::required_minimum_l2cap_buffer_size
463 >,
464 public details::white_list<
465 bluetoe::link_layer::ll_l2cap_sdu_buffer<
466 ScheduledRadio<
467 details::buffer_sizes< Options... >::tx_size,
468 details::buffer_sizes< Options... >::rx_size,
469 link_layer< Server, ScheduledRadio, Options... >
470 >,
471 details::l2cap_layer< Server, ScheduledRadio, Options... >::required_minimum_l2cap_buffer_size
472 >,
473 link_layer< Server, ScheduledRadio, Options... >,
474 Options... >::type,
475 public details::select_advertiser_implementation<
476 link_layer< Server, ScheduledRadio, Options... >,
477 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... >
486 > >,
487 public details::select_user_timer_impl<
488 link_layer< Server, ScheduledRadio, Options... >, Options ... >
489 {
490 public:
491 link_layer();
492
499 void run();
500
505 void adv_received( const read_buffer& receive );
506
512
517 void timeout();
518
524
528 void user_timer( bool anchor_moved );
529
534
541 bool connection_parameter_update_request( std::uint16_t interval_min, std::uint16_t interval_max, std::uint16_t latency, std::uint16_t timeout );
542
549
556
560 std::size_t fill_l2cap_advertising_data( std::uint8_t* buffer, std::size_t buffer_size ) const;
561
565 std::size_t fill_l2cap_scan_response_data( std::uint8_t* buffer, std::size_t buffer_size ) const;
566
571
575 std::uint64_t supported_link_layer_features() const;
576
580 std::uint8_t supported_link_layer_version() const;
581
585 std::uint16_t link_layer_company_identifier() const;
586
591
599 void local_address( const device_address& new_address );
600
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... >
606 >;
607
608 using layout_t = typename pdu_layout_by_radio< radio_t >::pdu_layout;
609 using l2cap_t = typename details::l2cap_layer< Server, ScheduledRadio, Options... >::impl;
610
611 // Data associate with a established connection (beside LL parameters), like key, ATT MTU etc.
612 using connection_data_t = typename l2cap_t::connection_data_t;
613
614 // used by the l2cap layer to queue notifications / indications
615 static bool queue_lcap_notification( const ::bluetoe::details::notification_data& item, void* usr_arg, ::bluetoe::details::notification_type type );
616
617 // Allocate size bytes of L2CAP layer payload
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 );
620
621 // will cause the link layer to inform the user callbacks that a connection event happend
622 void restart_user_timer();
623
626 private:
627
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... >
633 > >;
634
635 static_assert(
636 std::is_same<
637 typename ::bluetoe::details::find_by_not_meta_type<
638 details::valid_link_layer_option_meta_type,
639 Options...
640 >::type, ::bluetoe::details::no_such_type >::value,
641 "Option passed to the link layer, that is not a valid link_layer option." );
642
643 // make sure, that the hardware supports encryption
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!" );
647
648 using security_manager_t = typename details::security_manager<
649 link_layer< Server, ScheduledRadio, Options... >,
650 Server, Options...
651 >::type;
652
653 using signaling_channel_t = typename details::signaling_channel< Options... >::type;
654
655 using advertising_t = details::select_advertiser_implementation<
656 link_layer< Server, ScheduledRadio, Options... >, Options... >;
657
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();
664 delta_time setup_next_connection_event();
665 void transmit_pending_control_pdus();
666 void reject( std::uint8_t opcode, std::uint8_t error_code, read_buffer& output );
667
668 enum class ll_result {
669 go_ahead,
670 disconnect
671 };
672
673 ll_result handle_received_data();
674 ll_result send_control_pdus();
675 ll_result handle_ll_control_data( const write_buffer& pdu, read_buffer output );
676 // TODO Make handle_pending_ll_control() impossible to fail by checking PDUs immediately
677 ll_result handle_pending_ll_control( std::uint16_t instance );
678
679 connection_details details() const;
680
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;
684
685 static constexpr std::uint8_t ll_control_pdu_code = 3;
686 static constexpr std::uint8_t lld_data_pdu_code = 2;
687
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;
710
711 static constexpr std::uint8_t LL_VERSION_NR = 0x09;
712 static constexpr std::uint8_t LL_VERSION_40 = 0x06;
713
714 static constexpr std::uint8_t err_pin_or_key_missing = 0x06;
715 static constexpr std::uint16_t company_identifier = 0x0269;
716
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,
723 le_ping = 0x010,
724 le_data_packet_length_extension = 0x020,
725 ll_privacy = 0x040,
726 extended_scanner_filter_policies = 0x080,
727 le_2m_phy_support = 0x100
728 };
729 };
730
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
737 : 0 ) |
738 ( radio_t::hardware_supports_2mbit
739 ? link_layer_feature::le_2m_phy_support
740 : 0 );
741
742 // TODO: calculate the actual needed buffer size for advertising, not the maximum
743 static_assert( radio_t::size >= advertising_t::maximum_required_advertising_buffer(), "buffer to small" );
744
745 // TODO: calculate the maximum required LL buffer size based on the supported features
746 static constexpr std::size_t maximum_ll_payload_size = 27u;
747
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_;
762 bool pending_event_;
763 volatile bool restart_user_timer_requested_;
764
765 enum class state
766 {
767 initial,
768 advertising,
769 connecting,
770 connected,
771 disconnecting,
772 connection_changed
773 } state_;
774
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_;
782
783 // default configuration parameters
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;
787
788 typedef typename ::bluetoe::details::find_by_meta_type<
789 details::device_address_meta_type,
790 Options..., default_device_address >::type local_device_address;
791
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;
795
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;
800 };
801
802 // implementation
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 )
814 {
815 using user_timer_t = typename bluetoe::details::find_by_meta_type<
816 details::synchronized_connection_event_callback_meta_type,
817 Options...,
818 no_synchronized_connection_event_callback
819 >::type;
820
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
824 >::type;
825
826 compile_time_check_user_timer_parameters_t::template check< link_layer< Server, ScheduledRadio, Options... > >( user_timer_t() );
827
828 this->notification_callback( queue_lcap_notification, this );
829 }
830
831 template < class Server, template < std::size_t, std::size_t, class > class ScheduledRadio, typename ... Options >
833 {
834 // after the initial scheduling, the timeout and receive callback will setup the next scheduling
835 if ( state_ == state::initial )
836 {
837 start_advertising_impl();
838 }
839
840 radio_t::run();
841 }
842
843 template < class Server, template < std::size_t, std::size_t, class > class ScheduledRadio, typename ... Options >
845 {
846 using namespace ::bluetoe::details;
847
848 assert( state_ == state::advertising );
849
850 device_address remote_address;
851 const bool connection_request_received = this->handle_adv_receive( receive, remote_address );
852
853 if ( connection_request_received )
854 {
855 const std::uint8_t* const body = layout_t::body( receive ).first;
856
857 if ( channels_.reset( &body[ 28 ], body[ 33 ] & 0x1f )
858 && parse_timing_parameters_from_connect_request( body ) )
859 {
860 this->reset_connection_state();
861
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;
869
870 this->set_access_address_and_crc_init( read_32bit( &body[ 12 ] ), read_24bit( &body[ 16 ] ) );
871
872 this->reset_pdu_buffer();
873 setup_next_connection_event();
874
875 this->connection_request( connection_addresses( address_, remote_address ) );
876 this->handle_stop_advertising();
877
878 connection_data_ = connection_data_t();
879 connection_data_.remote_connection_created( remote_address );
880 }
881 }
882 }
883
884 template < class Server, template < std::size_t, std::size_t, class > class ScheduledRadio, typename ... Options >
886 {
887 assert( state_ == state::advertising );
888
889 this->handle_adv_timeout();
890 }
891
892 template < class Server, template < std::size_t, std::size_t, class > class ScheduledRadio, typename ... Options >
894 {
895 pending_event_ = false;
896
897 assert( state_ == state::connecting || state_ == state::connected || state_ == state::disconnecting || state_ == state::connection_changed );
898
899 const auto time_since_last_event = this->time_since_last_event();
900
901 if ( time_since_last_event <= connection_timeout_
902 && !( state_ == state::connecting && time_since_last_event >= ( num_windows_til_timeout - 1 ) * connection_interval_ ) )
903 {
904 this->plan_next_connection_event_after_timeout( connection_interval_ );
905
906 if ( handle_pending_ll_control( this->connection_event_counter() ) == ll_result::disconnect )
907 {
908 force_disconnect();
909 }
910 else
911 {
912 setup_next_connection_event();
913 }
914 }
915 else
916 {
917 force_disconnect();
918 }
919
920 this->template handle_connection_events< link_layer< Server, ScheduledRadio, Options... > >();
921 }
922
923 template < class Server, template < std::size_t, std::size_t, class > class ScheduledRadio, typename ... Options >
924 void link_layer< Server, ScheduledRadio, Options... >::end_event( connection_event_events evts )
925 {
926 pending_event_ = false;
927
928 assert( state_ == state::connecting || state_ == state::connected || state_ == state::disconnecting || state_ == state::connection_changed );
929
930 if ( state_ == state::connecting || restart_user_timer_requested_ )
931 {
932 this->synchronized_connection_event_callback_new_connection( connection_interval_ );
933 restart_user_timer_requested_ = false;
934 }
935
936 if ( state_ == state::connecting )
937 {
938 this->connection_established( details(), connection_data_, static_cast< radio_t& >( *this ) );
939 }
940 else if ( state_ == state::connection_changed )
941 {
942 this->synchronized_connection_event_callback_connection_changed( connection_interval_ );
943 }
944
945 if ( state_ != state::disconnecting )
946 {
947 state_ = state::connected;
948 transmit_window_size_ = delta_time();
949 }
950
951 /*
952 * L2CAP and pending LL PDUs are handle first, to get the information whether there is
953 * data to be send. This implies that the connEventCount is not updated at this point
954 * and has to be offset by 1 to see if there is a pending instant at this connection
955 * event.
956 */
957 if ( handle_received_data() == ll_result::disconnect || send_control_pdus() == ll_result::disconnect )
958 {
959 force_disconnect();
960 }
961 else
962 {
963 this->transmit_pending_security_pdus();
964
965 const std::pair< bool, std::uint16_t > pending_instant = { !defered_ll_control_pdu_.empty(), defered_conn_event_counter_ };
966
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 );
970
971 // Handle pending LL control PDUs that will affect the _next_ connection event
972 if ( handle_pending_ll_control( this->connection_event_counter() ) == ll_result::disconnect )
973 {
974 force_disconnect();
975 }
976 else
977 {
978 const delta_time time_till_next_event = setup_next_connection_event();
979 connection_event_callback::call_connection_event_callback( time_till_next_event );
980 }
981
982 }
983
984 if ( state_ == state::connected || state_ == state::connecting )
985 {
986 transmit_pending_control_pdus();
987 this->transmit_pending_l2cap_output( connection_data_ );
988 }
989
990 this->template handle_connection_events< link_layer< Server, ScheduledRadio, Options... > >();
991 }
992
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()
995 {
996 restart_user_timer_requested_ = true;
997 }
998
999 template < class Server, template < std::size_t, std::size_t, class > class ScheduledRadio, typename ... Options >
1001 {
1002 this->synchronized_connection_event_callback_timeout( anchor_moved );
1003 }
1004
1005 template < class Server, template < std::size_t, std::size_t, class > class ScheduledRadio, typename ... Options >
1007 {
1008 if ( ( state_ == state::connected || state_ == state::connecting )
1009 && pending_event_ && this->reschedule_on_pending_data( *this, connection_interval_ ) )
1010 {
1011 setup_next_connection_event();
1012 }
1013 }
1014
1015 template < class Server, template < std::size_t, std::size_t, class > class ScheduledRadio, typename ... Options >
1016 bool link_layer< Server, ScheduledRadio, Options... >::connection_parameter_update_request( std::uint16_t interval_min, std::uint16_t interval_max, std::uint16_t latency, std::uint16_t timeout )
1017 {
1018 if ( used_features_ & link_layer_feature::connection_parameters_request_procedure )
1019 {
1020 if ( connection_parameters_request_pending_ )
1021 return false;
1022
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;
1028
1029 this->wake_up();
1030
1031 return true;
1032 }
1033
1034 const bool result = static_cast< signaling_channel_t& >( *this ).connection_parameter_update_request( interval_min, interval_max, latency, timeout );
1035
1036 if ( result )
1037 this->wake_up();
1038
1039 return result;
1040 }
1041
1042 template < class Server, template < std::size_t, std::size_t, class > class ScheduledRadio, typename ... Options >
1044 {
1045 if ( phy_update_request_pending_ )
1046 return false;
1047
1048 phy_update_request_pending_ = true;
1049 this->wake_up();
1050
1051 return true;
1052
1053 }
1054
1055 template < class Server, template < std::size_t, std::size_t, class > class ScheduledRadio, typename ... Options >
1057 {
1058 state_ = state::disconnecting;
1059 termination_send_ = false;
1060
1061 this->synchronized_connection_event_callback_disconnect();
1062 this->reset_encryption();
1063 }
1064
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()
1067 {
1068 pending_event_ = true;
1069
1070 delta_time window_start;
1071 delta_time window_end;
1072
1073 const delta_time time_since_last_event = this->time_since_last_event();
1074
1075 // optimization to calculate the deviation only once for the symetrical case
1076 if ( !transmit_window_size_.zero() )
1077 {
1078 window_start = time_since_last_event + transmit_window_offset_;
1079 window_end = window_start + transmit_window_size_;
1080
1081 window_start -= window_start.ppm( cumulated_sleep_clock_accuracy_ );
1082 window_end += window_end.ppm( cumulated_sleep_clock_accuracy_ );
1083 }
1084 else
1085 {
1086 const delta_time window_size = time_since_last_event.ppm( cumulated_sleep_clock_accuracy_ );
1087
1088 window_start = time_since_last_event - window_size;
1089 window_end = time_since_last_event + window_size;
1090 }
1091
1092 return this->schedule_connection_event(
1093 channels_.data_channel( this->current_channel_index() ),
1094 window_start,
1095 window_end,
1096 connection_interval_ );
1097 }
1098
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()
1101 {
1102 static constexpr std::uint8_t connection_param_req_size = 24u;
1103
1104 if ( !connection_parameters_request_pending_ && !phy_update_request_pending_ )
1105 return;
1106
1107 // first check if we have memory to transmit the message, or otherwise notifications would get lost
1108 auto out_buffer = this->allocate_ll_transmit_buffer( connection_param_req_size );
1109
1110 if ( out_buffer.empty() )
1111 {
1112 this->wake_up();
1113 return;
1114 }
1115
1116 if ( connection_parameters_request_pending_ )
1117 {
1118 connection_parameters_request_pending_ = false;
1119 connection_parameters_request_running_ = true;
1120
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 ),
1131 0x00, // PreferredPeriodicity (none)
1132 0x00, 0x00, // ReferenceConnEventCount
1133 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1134 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } );
1135
1136 this->commit_ll_transmit_buffer( out_buffer );
1137 }
1138 else if ( phy_update_request_pending_ )
1139 {
1140 phy_update_request_pending_ = false;
1141
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 } );
1145
1146 this->commit_ll_transmit_buffer( out_buffer );
1147 }
1148 }
1149
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 )
1152 {
1153 if ( used_features_ & link_layer_feature::extended_reject_indication )
1154 {
1155 fill< layout_t >( output, {
1156 ll_control_pdu_code, 3, LL_REJECT_IND_EXT, opcode, error_code } );
1157 }
1158 else
1159 {
1160 fill< layout_t >( output, {
1161 ll_control_pdu_code, 2, LL_REJECT_IND, error_code } );
1162 }
1163 }
1164
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 )
1167 {
1168 auto& connection = static_cast< link_layer< Server, ScheduledRadio, Options... >* >( that )->connection_data_;
1169
1170 bool new_data = false;
1171 // TODO: Synchronization required!!!
1172 switch ( type )
1173 {
1174 case bluetoe::details::notification_type::notification:
1175 new_data = connection.queue_notification( item.client_characteristic_configuration_index() );
1176 break;
1177 case bluetoe::details::notification_type::indication:
1178 new_data = connection.queue_indication( item.client_characteristic_configuration_index() );
1179 break;
1180 case bluetoe::details::notification_type::confirmation:
1181 connection.indication_confirmed();
1182 return true;
1183 break;
1184 }
1185
1186 if ( new_data )
1187 static_cast< link_layer< Server, ScheduledRadio, Options... >* >( that )->request_event_cancelation();
1188
1189 return new_data;
1190 }
1191
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
1194 {
1195 static constexpr std::uint16_t inaccuracy_ppm[ 8 ] = {
1196 500, 250, 150, 100, 75, 50, 30, 20
1197 };
1198
1199 return inaccuracy_ppm[ ( received_body[ 33 ] >> 5 & 0x7 ) ];
1200 }
1201
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
1204 {
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 );
1208
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;
1215 }
1216
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 )
1219 {
1220 using namespace ::bluetoe::details;
1221
1222 const delta_time transmit_window_offset = delta_time( read_16bit( &valid_connect_request_body[ 20 ] ) * us_per_digits );
1223
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 );
1230
1231 return transmit_window_offset <= connection_interval_ && check_timing_paremeters();
1232 }
1233
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 )
1236 {
1237 using namespace ::bluetoe::details;
1238
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 );
1245
1246 return transmit_window_offset_ <= connection_interval_ && check_timing_paremeters();
1247 }
1248
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()
1251 {
1252 this->reset_encryption();
1253 this->reset_phy( *this );
1254
1255 if ( state_ != state::connecting )
1256 {
1257 this->synchronized_connection_event_callback_disconnect();
1258 this->connection_closed( connection_data_, static_cast< radio_t& >( *this ) );
1259 }
1260
1261 start_advertising_impl();
1262 }
1263
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()
1266 {
1267 state_ = state::advertising;
1268
1269 defered_ll_control_pdu_ = write_buffer{ nullptr, 0 };
1270
1271 this->handle_start_advertising();
1272 }
1273
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()
1276 {
1277 ll_result result = ll_result::go_ahead;
1278
1279 if ( !defered_ll_control_pdu_.empty() )
1280 return result;
1281
1282 for ( auto pdu = this->next_ll_l2cap_received(); pdu.size != 0 && result == ll_result::go_ahead && defered_ll_control_pdu_.empty(); )
1283 {
1284 const auto llid = layout_t::header( pdu ) & 0x03;
1285 const auto body = layout_t::body( pdu );
1286
1287 if ( llid == ll_control_pdu_code )
1288 {
1289 const read_buffer output = this->allocate_ll_transmit_buffer( maximum_ll_payload_size );
1290
1291 if ( output.size )
1292 {
1293 result = handle_ll_control_data( pdu, output );
1294 this->free_ll_l2cap_received();
1295 pdu = this->next_ll_l2cap_received();
1296 }
1297 else
1298 {
1299 pdu.size = 0;
1300 }
1301 }
1302 else if ( llid == lld_data_pdu_code && state_ != state::disconnecting
1303 && this->handle_l2cap_input( body.first, body.second - body.first, connection_data_ ) )
1304 {
1305 this->free_ll_l2cap_received();
1306 pdu = this->next_ll_l2cap_received();
1307 }
1308 else
1309 {
1310 pdu.size = 0;
1311 }
1312 }
1313
1314 return result;
1315 }
1316
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()
1319 {
1320 static constexpr std::uint8_t connection_terminated_by_local_host = 0x16;
1321
1322 if ( state_ == state::disconnecting && !termination_send_ )
1323 {
1324 auto output = this->allocate_ll_transmit_buffer( maximum_ll_payload_size );
1325
1326 if ( output.size )
1327 {
1328 fill< layout_t >( output, {
1329 ll_control_pdu_code, 2,
1330 LL_TERMINATE_IND, connection_terminated_by_local_host
1331 } );
1332
1333 this->commit_ll_transmit_buffer( output );
1334 termination_send_ = true;
1335 }
1336 }
1337
1338 return ll_result::go_ahead;
1339 }
1340
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 )
1343 {
1344 using namespace ::bluetoe::details;
1345
1346 ll_result result = ll_result::go_ahead;
1347 bool commit = true;
1348
1349 assert( write.size >= radio_t::min_buffer_size );
1350
1351 const std::uint8_t* const body = layout_t::body( pdu ).first;
1352 const std::uint16_t header = layout_t::header( pdu );
1353
1354 if ( ( header & 0x3 ) == ll_control_pdu_code )
1355 {
1356 const std::uint8_t size = header >> 8;
1357 const std::uint8_t opcode = size > 0 ? *body : 0xff;
1358
1359 if ( opcode == LL_CONNECTION_UPDATE_REQ && size == 12 )
1360 {
1361 defered_conn_event_counter_ = read_16bit( &body[ 10 ] );
1362 commit = false;
1363
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 )
1366 {
1367 result = ll_result::disconnect;
1368 }
1369 else
1370 {
1371 defered_ll_control_pdu_ = pdu;
1372 }
1373 }
1374 else if ( opcode == LL_TERMINATE_IND && size == 2 )
1375 {
1376 commit = false;
1377 result = ll_result::disconnect;
1378 }
1379 else if ( opcode == LL_VERSION_IND && size == 6 )
1380 {
1381 if ( body[ 1 ] <= LL_VERSION_40 )
1382 used_features_ = used_features_ & ~link_layer_feature::connection_parameters_request_procedure;
1383
1384 fill< layout_t >( write, {
1385 ll_control_pdu_code, 6, LL_VERSION_IND,
1386 LL_VERSION_NR,
1387 static_cast< std::uint8_t >( company_identifier ),
1388 static_cast< std::uint8_t >( company_identifier >> 8 ),
1389 0x00, 0x00
1390 } );
1391 }
1392 else if ( opcode == LL_CHANNEL_MAP_REQ && size == 8 )
1393 {
1394 defered_conn_event_counter_ = read_16bit( &body[ 6 ] );
1395 commit = false;
1396
1397 if ( static_cast< std::uint16_t >( defered_conn_event_counter_ - this->connection_event_counter() ) & 0x8000 )
1398 {
1399 result = ll_result::disconnect;
1400 }
1401 else
1402 {
1403 defered_ll_control_pdu_ = pdu;
1404 }
1405 }
1406 else if ( opcode == LL_PING_REQ && size == 1 )
1407 {
1408 fill< layout_t >( write, { ll_control_pdu_code, 1, LL_PING_RSP } );
1409 }
1410 else if ( opcode == LL_FEATURE_REQ && size == 9 )
1411 {
1412 std::uint16_t remote_features = read_16bit( & body[ 1 ] );
1413 used_features_ = used_features_ & remote_features;
1414
1415 // the LSB of the feature set has to be the actualy used set,
1416 // while all remaining bytes are to be filled with the supported
1417 // features
1418 fill< layout_t >( write, {
1419 ll_control_pdu_code, 9,
1420 LL_FEATURE_RSP,
1421 static_cast< std::uint8_t >( used_features_ ),
1422 static_cast< std::uint8_t >( supported_features >> 8 ),
1423 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1424 } );
1425
1426 }
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 ) )
1430 {
1431 if ( connection_parameters_request_running_ )
1432 {
1433 connection_parameters_request_running_ = false;
1434
1435 if ( signaling_channel_t::connection_parameter_update_request(
1436 proposed_interval_min_,
1437 proposed_interval_max_,
1438 proposed_latency_,
1439 proposed_timeout_ ) )
1440 {
1441 this->wake_up();
1442 }
1443 }
1444
1445 if ( opcode == LL_UNKNOWN_RSP )
1446 used_features_ = used_features_ & ~link_layer_feature::connection_parameters_request_procedure;
1447
1448 commit = false;
1449 }
1450 else if ( opcode == LL_CONNECTION_PARAM_REQ && size == 24 )
1451 {
1452 using connection_param_responder = typename bluetoe::details::find_by_meta_type<
1453 bluetoe::link_layer::details::desired_connection_parameters_meta_type,
1454 Options...,
1455 no_desired_connection_parameters >::type;
1456
1457 connection_param_responder::template fill_response< layout_t >( pdu, write );
1458 }
1459 else if ( this->handle_encryption_pdus( opcode, size, pdu, write, commit ) )
1460 {
1461 // all encryption PDU handled in handle_encryption_pdus()
1462 }
1463 else if ( this->handle_phy_request( opcode, size, pdu, write, *this, commit ) )
1464 {
1465 // all phy PDU handled in handle_phy_reqest
1466 }
1467 else if ( opcode != LL_UNKNOWN_RSP )
1468 {
1469 fill< layout_t >( write, { ll_control_pdu_code, 2, LL_UNKNOWN_RSP, opcode } );
1470 }
1471 else
1472 {
1473 commit = false;
1474 }
1475
1476 if ( commit )
1477 this->commit_ll_transmit_buffer( write );
1478 }
1479
1480 return result;
1481 }
1482
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 )
1485 {
1486 ll_result result = ll_result::go_ahead;
1487
1488 if ( !defered_ll_control_pdu_.empty() && defered_conn_event_counter_ == instance )
1489 {
1490 const std::uint8_t* body = layout_t::body( defered_ll_control_pdu_ ).first;
1491 const std::uint8_t opcode = body[ 0 ];
1492
1493 if ( opcode == LL_CHANNEL_MAP_REQ )
1494 {
1495 channels_.reset( &body[ 1 ] );
1496 }
1497 else if ( opcode == LL_CONNECTION_UPDATE_REQ )
1498 {
1499 if ( parse_timing_parameters_from_connection_update_request( body ) )
1500 {
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 ) );
1504 }
1505 else
1506 {
1507 result = ll_result::disconnect;
1508 }
1509 }
1510 else if ( this->handle_pending_phy_request( opcode, *this ) )
1511 {
1512 }
1513 else
1514 {
1515 // This is an assert, as the opcode was already checked in handle_ll_control_data()
1516 assert( !"invalid opcode" );
1517 }
1518
1519 defered_ll_control_pdu_ = write_buffer{ nullptr, 0 };
1520 }
1521
1522 return result;
1523 }
1524
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
1527 {
1528 return connection_details(
1529 channels_,
1530 connection_interval_.usec() / us_per_digits,
1531 peripheral_latency_,
1532 timeout_value_,
1533 cumulated_sleep_clock_accuracy_ );
1534 }
1535
1536 template < class Server, template < std::size_t, std::size_t, class > class ScheduledRadio, typename ... Options >
1537 std::size_t link_layer< Server, ScheduledRadio, Options... >::fill_l2cap_advertising_data( std::uint8_t* buffer, std::size_t buffer_size ) const
1538 {
1539 return this->advertising_data( buffer, buffer_size );
1540 }
1541
1542 template < class Server, template < std::size_t, std::size_t, class > class ScheduledRadio, typename ... Options >
1543 std::size_t link_layer< Server, ScheduledRadio, Options... >::fill_l2cap_scan_response_data( std::uint8_t* buffer, std::size_t buffer_size ) const
1544 {
1545 return this->scan_response_data( buffer, buffer_size );
1546 }
1547
1548 template < class Server, template < std::size_t, std::size_t, class > class ScheduledRadio, typename ... Options >
1550 {
1551 return this->advertising_or_scan_response_data_has_been_changed();
1552 }
1553
1554 template < class Server, template < std::size_t, std::size_t, class > class ScheduledRadio, typename ... Options >
1556 {
1557 return address_;
1558 }
1559
1560 template < class Server, template < std::size_t, std::size_t, class > class ScheduledRadio, typename ... Options >
1561 void link_layer< Server, ScheduledRadio, Options... >::local_address( const device_address& new_address )
1562 {
1563 address_ = new_address;
1564 }
1565
1566 template < class Server, template < std::size_t, std::size_t, class > class ScheduledRadio, typename ... Options >
1568 {
1569 return supported_features;
1570 }
1571
1572 template < class Server, template < std::size_t, std::size_t, class > class ScheduledRadio, typename ... Options >
1574 {
1575 return LL_VERSION_NR;
1576 }
1577
1578 template < class Server, template < std::size_t, std::size_t, class > class ScheduledRadio, typename ... Options >
1580 {
1581 return company_identifier;
1582 }
1583
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 )
1586 {
1587 const auto buffer = this->allocate_l2cap_transmit_buffer( size );
1588
1589 if ( buffer.size == 0 )
1590 return { 0, nullptr };
1591
1592
1593 const auto body = layout_t::body( buffer );
1594
1595 return { body.second - body.first, body.first };
1596 }
1597
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 )
1600 {
1601 assert( buffer.first );
1602 assert( buffer.second );
1603
1604 // TODO this type of calculations should be forwardet to the buffer
1605 static constexpr std::size_t overhead = layout_t::data_channel_pdu_memory_size( 0 );
1606
1607 const read_buffer out_buffer{ buffer.second - overhead, buffer.first + overhead };
1608
1609 // TODO In case, that the buffer has to be fragmented, the header has to be rewritten
1610 // by the buffer, so maybe better move that to the buffer too.
1611 fill< layout_t >( out_buffer, {
1612 lld_data_pdu_code,
1613 static_cast< std::uint8_t >( buffer.first & 0xff ) } );
1614
1615 this->commit_l2cap_transmit_buffer( out_buffer );
1616 }
1619}
1620}
1621
1622#endif
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
implementation of the security manager, that actievly rejects every pairing attempt.
Definition: security_manager.hpp:533
wrap< typename select_type_impl< Select >::template f< A, B > > select_type
Select A or B by Select. If Select == true, the result is A; B otherwise.
Definition: meta_tools.hpp:38
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