BlueToe
an alternative GATT/BLE implementation
Loading...
Searching...
No Matches
io_capabilities.hpp
1#ifndef BLUETOE_SM_INCLUDE_IO_CAPABILTIES_HPP
2#define BLUETOE_SM_INCLUDE_IO_CAPABILTIES_HPP
3
5#include <bluetoe/ll_meta_types.hpp>
6#include <bluetoe/bits.hpp>
7
8namespace bluetoe
9{
10 namespace details {
11 struct pairing_input_capabilty_meta_type {};
12 struct pairing_output_capabilty_meta_type {};
13 struct pairing_just_works_meta_type {};
14
15 enum class io_capabilities : std::uint8_t {
16 display_only = 0x00,
17 display_yes_no = 0x01,
18 keyboard_only = 0x02,
19 no_input_no_output = 0x03,
20 keyboard_display = 0x04,
21 last = keyboard_display
22 };
23
24 enum class legacy_pairing_algorithm : std::uint8_t {
25 just_works,
26 oob_authentication,
27 passkey_entry_display,
28 passkey_entry_input
29 };
30
31 enum class lesc_pairing_algorithm : std::uint8_t {
32 just_works,
33 oob_authentication,
34 passkey_entry_display,
35 passkey_entry_input,
36 numeric_comparison
37 };
38
39 }
40
50 {
52 static std::array< std::uint8_t, 16 > sm_pairing_passkey()
53 {
54 return {{0}};
55 }
56
57 template < class S >
58 static bool sm_pairing_request_yes_no( const S& )
59 {
60 return true;
61 }
62
63 struct meta_type :
64 details::pairing_input_capabilty_meta_type,
65 link_layer::details::valid_link_layer_option_meta_type {};
67 };
68
76 {
77 public:
79 virtual void yes_no_response( bool ) = 0;
81 protected:
82 ~pairing_yes_no_response() = default;
83 };
84
101 template < typename T, T& Obj >
103 {
105 static std::array< std::uint8_t, 16 > sm_pairing_passkey()
106 {
107 return {{0}};
108 }
109
110 template < class S >
111 static void sm_pairing_request_yes_no( S& state )
112 {
113 state.wait_for_user_response();
114 Obj.sm_pairing_yes_no( state );
115 }
116
117 struct meta_type :
118 details::pairing_input_capabilty_meta_type,
119 link_layer::details::valid_link_layer_option_meta_type {};
121 };
122
138 template < typename T, T& Obj >
140 {
142 static std::array< std::uint8_t, 16 > sm_pairing_passkey()
143 {
144 std::array< std::uint8_t, 16 > result = {{ 0 }};
145 details::write_32bit( result.data(), Obj.sm_pairing_passkey() );
146
147 return result;
148 }
149
150 struct meta_type :
151 details::pairing_input_capabilty_meta_type,
152 link_layer::details::valid_link_layer_option_meta_type {};
154 };
155
160 {
162 static details::io_capabilities get_io_capabilities( const pairing_no_input& )
163 {
164 return details::io_capabilities::no_input_no_output;
165 }
166
167 template < typename T, T& Obj >
168 static details::io_capabilities get_io_capabilities( const pairing_yes_no< T, Obj >& )
169 {
170 return details::io_capabilities::no_input_no_output;
171 }
172
173 template < typename T, T& Obj >
174 static details::io_capabilities get_io_capabilities( const pairing_keyboard< T, Obj >& )
175 {
176 return details::io_capabilities::keyboard_only;
177 }
178
179 static details::legacy_pairing_algorithm select_legacy_pairing_algorithm( const pairing_no_input&, details::io_capabilities /* io_capability */ )
180 {
181 return details::legacy_pairing_algorithm::just_works;
182 }
183
184 template < typename T, T& Obj >
185 static details::legacy_pairing_algorithm select_legacy_pairing_algorithm( const pairing_yes_no< T, Obj >&, details::io_capabilities /* io_capability */ )
186 {
187 return details::legacy_pairing_algorithm::just_works;
188 }
189
190 template < typename T, T& Obj >
191 static details::legacy_pairing_algorithm select_legacy_pairing_algorithm( const pairing_keyboard< T, Obj >&, details::io_capabilities io_capability )
192 {
193 if ( io_capability == details::io_capabilities::no_input_no_output )
194 return details::legacy_pairing_algorithm::just_works;
195
196 return details::legacy_pairing_algorithm::passkey_entry_input;
197 }
198
199 static details::lesc_pairing_algorithm select_lesc_pairing_algorithm( const pairing_no_input&, details::io_capabilities )
200 {
201 return details::lesc_pairing_algorithm::just_works;
202 }
203
204 template < typename T, T& Obj >
205 static details::lesc_pairing_algorithm select_lesc_pairing_algorithm( const pairing_yes_no< T, Obj >&, details::io_capabilities )
206 {
207 return details::lesc_pairing_algorithm::just_works;
208 }
209
210 template < typename T, T& Obj >
211 static details::lesc_pairing_algorithm select_lesc_pairing_algorithm( const pairing_keyboard< T, Obj >&, details::io_capabilities io_capability )
212 {
213 if ( io_capability == details::io_capabilities::no_input_no_output )
214 return details::lesc_pairing_algorithm::just_works;
215
216 return details::lesc_pairing_algorithm::passkey_entry_input;
217 }
218
219 static void sm_pairing_numeric_output( const std::array< std::uint8_t, 16 >& )
220 {
221 }
222
223 template < class S, class F >
224 static void sm_pairing_numeric_compare_output( const S&, F& )
225 {
226 }
227
228 struct meta_type :
229 details::pairing_output_capabilty_meta_type,
230 link_layer::details::valid_link_layer_option_meta_type {};
232 };
233
245 template < typename T, T& Obj >
247 {
249 static details::io_capabilities get_io_capabilities( const pairing_no_input& )
250 {
251 return details::io_capabilities::display_only;
252 }
253
254 template < typename O, O& Other >
255 static details::io_capabilities get_io_capabilities( const pairing_yes_no< O, Other >& )
256 {
257 return details::io_capabilities::display_yes_no;
258 }
259
260 template < typename O, O& Other >
261 static details::io_capabilities get_io_capabilities( const pairing_keyboard< O, Other >& )
262 {
263 return details::io_capabilities::keyboard_display;
264 }
265
266 static details::legacy_pairing_algorithm select_legacy_pairing_algorithm( const pairing_no_input&, details::io_capabilities io_capability )
267 {
268 if ( io_capability == details::io_capabilities::keyboard_only || io_capability == details::io_capabilities::keyboard_display )
269 return details::legacy_pairing_algorithm::passkey_entry_display;
270
271 return details::legacy_pairing_algorithm::just_works;
272 }
273
274 template < typename O, O& Other >
275 static details::legacy_pairing_algorithm select_legacy_pairing_algorithm( const pairing_yes_no< O, Other >&, details::io_capabilities io_capability )
276 {
277 if ( io_capability == details::io_capabilities::keyboard_only || io_capability == details::io_capabilities::keyboard_display )
278 return details::legacy_pairing_algorithm::passkey_entry_display;
279
280 return details::legacy_pairing_algorithm::just_works;
281 }
282
283 template < typename O, O& Other >
284 static details::legacy_pairing_algorithm select_legacy_pairing_algorithm( const pairing_keyboard< O, Other >&, details::io_capabilities io_capability )
285 {
286 if ( io_capability == details::io_capabilities::no_input_no_output )
287 return details::legacy_pairing_algorithm::just_works;
288
289 if ( io_capability == details::io_capabilities::keyboard_only )
290 return details::legacy_pairing_algorithm::passkey_entry_display;
291
292 return details::legacy_pairing_algorithm::passkey_entry_input;
293 }
294
295 static details::lesc_pairing_algorithm select_lesc_pairing_algorithm( const pairing_no_input&, details::io_capabilities io_capability )
296 {
297 if ( io_capability == details::io_capabilities::keyboard_only || io_capability == details::io_capabilities::keyboard_display )
298 return details::lesc_pairing_algorithm::passkey_entry_display;
299
300 return details::lesc_pairing_algorithm::just_works;
301 }
302
303 template < typename O, O& Other >
304 static details::lesc_pairing_algorithm select_lesc_pairing_algorithm( const pairing_yes_no< O, Other >&, details::io_capabilities io_capability )
305 {
306 if ( io_capability == details::io_capabilities::display_yes_no || io_capability == details::io_capabilities::keyboard_display )
307 return details::lesc_pairing_algorithm::numeric_comparison;
308
309 if ( io_capability == details::io_capabilities::keyboard_only )
310 return details::lesc_pairing_algorithm::passkey_entry_display;
311
312 return details::lesc_pairing_algorithm::just_works;
313 }
314
315 template < typename O, O& Other >
316 static details::lesc_pairing_algorithm select_lesc_pairing_algorithm( const pairing_keyboard< O, Other >&, details::io_capabilities io_capability )
317 {
318 if ( io_capability == details::io_capabilities::display_yes_no || io_capability == details::io_capabilities::keyboard_display )
319 return details::lesc_pairing_algorithm::numeric_comparison;
320
321 if ( io_capability == details::io_capabilities::display_only )
322 return details::lesc_pairing_algorithm::passkey_entry_input;
323
324 if ( io_capability == details::io_capabilities::keyboard_only )
325 return details::lesc_pairing_algorithm::passkey_entry_display;
326
327 return details::lesc_pairing_algorithm::just_works;
328 }
329
330 static void sm_pairing_numeric_output( const std::array< std::uint8_t, 16 >& key )
331 {
332 Obj.sm_pairing_numeric_output( static_cast< int >( details::read_32bit( key.data() ) ) );
333 }
334
335 template < class S, class F >
336 static void sm_pairing_numeric_compare_output( const S& state, F& funcs )
337 {
338 const auto& Na = state.remote_nonce();
339 const auto& Nb = state.local_nonce();
340 const std::uint8_t* Pkax = state.remote_public_key_x();
341 const std::uint8_t* PKbx = state.local_public_key_x();
342
343 const auto pass_key = funcs.g2( Pkax, PKbx, Na, Nb );
344 Obj.sm_pairing_numeric_output( static_cast< int >( pass_key ) );
345 }
346
347 struct meta_type :
348 details::pairing_output_capabilty_meta_type,
349 link_layer::details::valid_link_layer_option_meta_type {};
351 };
352
363 {
365 struct meta_type :
366 details::pairing_just_works_meta_type,
367 link_layer::details::valid_link_layer_option_meta_type {};
369 };
370
378 {
380 struct meta_type :
381 details::pairing_just_works_meta_type,
382 link_layer::details::valid_link_layer_option_meta_type {};
384 };
385
386 namespace details
387 {
388 template < typename ... Options >
389 class io_capabilities_matrix
390 {
391 public:
392 using input_capabilities = typename find_by_meta_type< pairing_input_capabilty_meta_type, Options..., pairing_no_input >::type;
393 using output_capabilities = typename find_by_meta_type< pairing_output_capabilty_meta_type, Options..., pairing_no_output >::type;
394
395 static io_capabilities get_io_capabilities()
396 {
397 return output_capabilities::get_io_capabilities(input_capabilities());
398 }
399
400 static legacy_pairing_algorithm select_legacy_pairing_algorithm( std::uint8_t io_capability )
401 {
402 return select_legacy_pairing_algorithm( static_cast< io_capabilities >( io_capability ) );
403 }
404
405 static legacy_pairing_algorithm select_legacy_pairing_algorithm( io_capabilities io_capability )
406 {
407 return output_capabilities::select_legacy_pairing_algorithm( input_capabilities(), io_capability );
408 }
409
410 static lesc_pairing_algorithm select_lesc_pairing_algorithm( std::uint8_t io_capability )
411 {
412 return select_lesc_pairing_algorithm( static_cast< io_capabilities >( io_capability ) );
413 }
414
415 static lesc_pairing_algorithm select_lesc_pairing_algorithm( io_capabilities io_capability )
416 {
417 return output_capabilities::select_lesc_pairing_algorithm( input_capabilities(), io_capability );
418 }
419
420 static void sm_pairing_numeric_output( const std::array< std::uint8_t, 16 >& temp_key )
421 {
422 output_capabilities::sm_pairing_numeric_output( temp_key );
423 }
424
425 template < class S, class F >
426 static void sm_pairing_numeric_compare_output( const S& state, F& func )
427 {
428 output_capabilities::sm_pairing_numeric_compare_output( state, func );
429 }
430
431 static std::array< std::uint8_t, 16 > sm_pairing_passkey()
432 {
433 return input_capabilities::sm_pairing_passkey();
434 }
435
436 template < class S >
437 static void sm_pairing_request_yes_no( S& state )
438 {
439 input_capabilities::sm_pairing_request_yes_no( state );
440 }
441 };
442 }
443}
444
445#endif // include guard
interface that can be stored to provide response to a yes_no question asynchronously.
Definition: io_capabilities.hpp:76
mark that "just works" pairing is accepted, even when the device have IO capabilities to exchange a p...
Definition: io_capabilities.hpp:378
Device has a numeric keyboard that can input the numbers '0' to '9' and a confirmation.
Definition: io_capabilities.hpp:140
defines that the device has no way to receive input from the user during pairing
Definition: io_capabilities.hpp:50
mark that "just works" pairing is not acceptable
Definition: io_capabilities.hpp:363
defines that the device has no means to output a numeric value
Definition: io_capabilities.hpp:160
the device has a mean to output the 6 digit pass key used during the pairing process.
Definition: io_capabilities.hpp:247
Device has at least two buttons that can be easily mapped to 'yes' and 'no' or the device has a mecha...
Definition: io_capabilities.hpp:103