BlueToe
an alternative GATT/BLE implementation
Loading...
Searching...
No Matches
ll_options.hpp
1#ifndef BLUETOE_LINK_LAYER_OPTIONS_HPP
2#define BLUETOE_LINK_LAYER_OPTIONS_HPP
3
4#include <bluetoe/address.hpp>
5#include <bluetoe/connection_details.hpp>
6#include <bluetoe/ll_meta_types.hpp>
7
8
9namespace bluetoe
10{
11namespace link_layer
12{
13 namespace details {
14 struct device_address_meta_type {};
15 struct buffer_sizes_meta_type {};
16 struct desired_connection_parameters_meta_type {};
17 }
18
26 {
30 static constexpr bool is_random()
31 {
32 return true;
33 }
34
38 template < class Radio >
39 static random_device_address address( const Radio& r )
40 {
41 return address::generate_static_random_address( r.static_random_address_seed() );
42 }
43
45 struct meta_type :
46 details::device_address_meta_type,
47 details::valid_link_layer_option_meta_type {};
49 };
50
56 template < std::uint8_t A, std::uint8_t B, std::uint8_t C, std::uint8_t D, std::uint8_t E, std::uint8_t F >
58 {
62 static constexpr bool is_random()
63 {
64 return true;
65 }
66
70 template < class Radio >
71 static random_device_address address( const Radio& )
72 {
73 static constexpr std::uint8_t addr[] = { F, E, D, C, B, A };
74 return ::bluetoe::link_layer::random_device_address( addr );
75 }
76
78 struct meta_type :
79 details::device_address_meta_type,
80 details::valid_link_layer_option_meta_type {};
82 };
83
84 namespace details {
85 struct sleep_clock_accuracy_meta_type {};
86
87 template < unsigned long long SleepClockAccuracyPPM >
88 struct check_sleep_clock_accuracy_ppm {
89 static_assert( SleepClockAccuracyPPM <= 500, "The highest, possible sleep clock accuracy is 500ppm." );
90
91 typedef void type;
92 };
93
94 }
95
104 template < unsigned long long SleepClockAccuracyPPM, typename = typename details::check_sleep_clock_accuracy_ppm< SleepClockAccuracyPPM >::type >
106 {
110 static constexpr unsigned accuracy_ppm = static_cast< unsigned >( SleepClockAccuracyPPM );
111
113 struct meta_type :
114 details::sleep_clock_accuracy_meta_type,
115 details::valid_link_layer_option_meta_type {};
117 };
118
122 template < std::size_t TransmitSize = 61, std::size_t ReceiveSize = 61 >
124 {
126 struct meta_type :
127 details::buffer_sizes_meta_type,
128 details::valid_link_layer_option_meta_type {};
134 static constexpr std::size_t transmit_buffer_size = TransmitSize;
135
139 static constexpr std::size_t receive_buffer_size = ReceiveSize;
140 };
141
142 namespace details
143 {
144 struct desired_connection_parameters_base
145 {
146 static constexpr std::size_t size = 24;
147 static constexpr std::uint8_t ll_control_pdu_code = 3;
148 static constexpr std::uint8_t LL_CONNECTION_PARAM_RSP = 0x10;
149 };
150 }
151
163 template <
164 std::uint16_t Interval_min,
165 std::uint16_t Interval_max,
166 std::uint16_t Latency_min,
167 std::uint16_t Latency_max,
168 std::uint16_t Timeout_min,
169 std::uint16_t Timeout_max >
170 struct desired_connection_parameters : private details::desired_connection_parameters_base
171 {
173 struct meta_type :
174 details::desired_connection_parameters_meta_type,
175 details::valid_link_layer_option_meta_type {};
176
177 template < class Layout >
178 static void fill_response(
179 const write_buffer& request, read_buffer response )
180 {
181 const std::uint8_t* const body = Layout::body( request ).first;
182 std::uint8_t* const write_body = Layout::body( response ).first;
183
184 using bluetoe::details::read_16bit;
185
186 std::uint16_t min_interval = std::max( read_16bit( body + 1 ), Interval_min );
187 std::uint16_t max_interval = std::min( read_16bit( body + 3 ), Interval_max );
188 std::uint16_t latency = read_16bit( body + 5 );
189 std::uint16_t timeout = read_16bit( body + 7 );
190
191 if ( min_interval > max_interval )
192 {
193 min_interval = Interval_min;
194 max_interval = Interval_max;
195 }
196
197 if ( latency < Latency_min || latency > Latency_max )
198 {
199 latency = ( Latency_min + Latency_max ) / 2;
200 }
201
202 if ( timeout < Timeout_min || timeout > Timeout_max )
203 {
204 timeout = ( Timeout_min + Timeout_max ) / 2;
205 }
206
207 fill< Layout >( response, {
208 ll_control_pdu_code, size,
209 LL_CONNECTION_PARAM_RSP,
210 static_cast< std::uint8_t >( min_interval ),
211 static_cast< std::uint8_t >( min_interval >> 8 ),
212 static_cast< std::uint8_t >( max_interval ),
213 static_cast< std::uint8_t >( max_interval >> 8 ),
214 static_cast< std::uint8_t >( latency ),
215 static_cast< std::uint8_t >( latency >> 8 ),
216 static_cast< std::uint8_t >( timeout ),
217 static_cast< std::uint8_t >( timeout >> 8 )
218 } );
219
220 std::copy( &body[ 9 ], &body[ size ], &write_body[ 9 ] );
221 }
223 };
224
226 struct no_desired_connection_parameters : private details::desired_connection_parameters_base
227 {
228 struct meta_type :
229 details::desired_connection_parameters_meta_type,
230 details::valid_link_layer_option_meta_type {};
231
232 template < class Layout >
233 static void fill_response(
234 const write_buffer& request, read_buffer response )
235 {
236 const std::uint8_t* const body = Layout::body( request ).first;
237 std::uint8_t* const write_body = Layout::body( response ).first;
238
239 fill< Layout >( response, { ll_control_pdu_code, size, LL_CONNECTION_PARAM_RSP } );
240
241 std::copy( &body[ 1 ], &body[ 1 + size - 1 ], &write_body[ 1 ] );
242 }
243 };
246}
247}
248
249#endif