fuchsia_bluetooth/types/
pairing_options.rs

1// Copyright 2020 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4use fidl_fuchsia_bluetooth_sys as sys;
5
6use crate::types::Technology;
7
8/// Configuration Options for a Pairing Request
9#[derive(Clone, Debug, PartialEq)]
10pub struct PairingOptions {
11    pub le_security_level: SecurityLevel,
12    pub bondable: BondableMode,
13    pub transport: Technology,
14}
15
16/// The security level required for this pairing - corresponds to the security
17/// levels defined in the Security Manager Protocol in Vol 3, Part H, Section 2.3.1
18#[derive(Clone, Copy, Debug, PartialEq)]
19pub enum SecurityLevel {
20    /// Encrypted without MITM protection (unauthenticated)
21    Encrypted,
22    /// Encrypted with MITM protection (authenticated), although this level of security does not
23    /// fully protect against passive eavesdroppers
24    Authenticated,
25}
26
27/// Bondable Mode - whether to accept bonding initiated by a remote peer
28/// As described in Core Spec v5.2 | Vol 3, Part C, Sec 4.3
29#[derive(Clone, Copy, Debug, PartialEq)]
30pub enum BondableMode {
31    Bondable,
32    NonBondable,
33}
34
35impl From<sys::PairingSecurityLevel> for SecurityLevel {
36    fn from(level: sys::PairingSecurityLevel) -> Self {
37        match level {
38            sys::PairingSecurityLevel::Encrypted => SecurityLevel::Encrypted,
39            sys::PairingSecurityLevel::Authenticated => SecurityLevel::Authenticated,
40        }
41    }
42}
43
44impl From<SecurityLevel> for sys::PairingSecurityLevel {
45    fn from(level: SecurityLevel) -> Self {
46        match level {
47            SecurityLevel::Encrypted => sys::PairingSecurityLevel::Encrypted,
48            SecurityLevel::Authenticated => sys::PairingSecurityLevel::Authenticated,
49        }
50    }
51}
52
53impl From<sys::PairingOptions> for PairingOptions {
54    fn from(opts: sys::PairingOptions) -> Self {
55        (&opts).into()
56    }
57}
58
59impl From<&sys::PairingOptions> for PairingOptions {
60    fn from(opts: &sys::PairingOptions) -> Self {
61        let bondable = match opts.bondable_mode {
62            Some(sys::BondableMode::NonBondable) => BondableMode::NonBondable,
63            Some(sys::BondableMode::Bondable) | None => BondableMode::Bondable,
64        };
65        let le_security_level =
66            opts.le_security_level.map_or(SecurityLevel::Encrypted, SecurityLevel::from);
67        let transport = opts.transport.map_or(Technology::DualMode, Technology::from);
68        PairingOptions { le_security_level, bondable, transport }
69    }
70}
71
72impl From<&PairingOptions> for sys::PairingOptions {
73    fn from(opts: &PairingOptions) -> Self {
74        let bondable_mode = match opts.bondable {
75            BondableMode::NonBondable => Some(sys::BondableMode::NonBondable),
76            BondableMode::Bondable => Some(sys::BondableMode::Bondable),
77        };
78        let le_security_level = Some(opts.le_security_level.into());
79        let transport = Some(opts.transport.into());
80        sys::PairingOptions { le_security_level, bondable_mode, transport, ..Default::default() }
81    }
82}
83
84impl From<PairingOptions> for sys::PairingOptions {
85    fn from(opts: PairingOptions) -> Self {
86        (&opts).into()
87    }
88}
89
90#[cfg(test)]
91pub mod tests {
92    use super::*;
93    use proptest::prelude::*;
94
95    fn any_technology() -> impl Strategy<Value = Technology> {
96        prop_oneof![Just(Technology::LE), Just(Technology::Classic), Just(Technology::DualMode)]
97    }
98    fn any_bondable() -> impl Strategy<Value = BondableMode> {
99        prop_oneof![Just(BondableMode::Bondable), Just(BondableMode::NonBondable)]
100    }
101    fn any_security() -> impl Strategy<Value = SecurityLevel> {
102        prop_oneof![Just(SecurityLevel::Encrypted), Just(SecurityLevel::Authenticated)]
103    }
104
105    prop_compose! {
106        fn any_pairing_options()(
107            le_security_level in any_security(),
108            bondable in  any_bondable(),
109            transport in any_technology()) -> PairingOptions {
110            PairingOptions{ le_security_level, bondable, transport }
111        }
112    }
113
114    proptest! {
115        #[test]
116        fn roundtrip(opts in any_pairing_options()) {
117            let sys: sys::PairingOptions = (&opts).into();
118            assert_eq!(opts, sys.into());
119        }
120    }
121}