1 // Copyright 2023 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 use std::cell::RefCell;
16 use std::collections::VecDeque;
17 use std::convert::{TryFrom, TryInto};
18 use std::future::Future;
19 use std::pin::Pin;
20 use std::task::{self, Poll};
21 
22 use crate::lmp::ec::PrivateKey;
23 use crate::packets::{hci, lmp};
24 
25 use crate::lmp::procedure::Context;
26 
27 #[derive(Default)]
28 pub struct TestContext {
29     pub in_lmp_packets: RefCell<VecDeque<lmp::LmpPacket>>,
30     pub out_lmp_packets: RefCell<VecDeque<lmp::LmpPacket>>,
31     pub hci_events: RefCell<VecDeque<hci::Event>>,
32     pub hci_commands: RefCell<VecDeque<hci::Command>>,
33     private_key: RefCell<Option<PrivateKey>>,
34     features_pages: [u64; 3],
35     peer_features_pages: [u64; 3],
36 }
37 
38 impl TestContext {
new() -> Self39     pub fn new() -> Self {
40         Self::default()
41             .with_page_1_feature(hci::LMPFeaturesPage1Bits::SecureSimplePairingHostSupport)
42             .with_peer_page_1_feature(hci::LMPFeaturesPage1Bits::SecureSimplePairingHostSupport)
43     }
44 
with_page_1_feature(mut self, feature: hci::LMPFeaturesPage1Bits) -> Self45     pub fn with_page_1_feature(mut self, feature: hci::LMPFeaturesPage1Bits) -> Self {
46         self.features_pages[1] |= u64::from(feature);
47         self
48     }
49 
with_page_2_feature(mut self, feature: hci::LMPFeaturesPage2Bits) -> Self50     pub fn with_page_2_feature(mut self, feature: hci::LMPFeaturesPage2Bits) -> Self {
51         self.features_pages[2] |= u64::from(feature);
52         self
53     }
54 
with_peer_page_1_feature(mut self, feature: hci::LMPFeaturesPage1Bits) -> Self55     pub fn with_peer_page_1_feature(mut self, feature: hci::LMPFeaturesPage1Bits) -> Self {
56         self.peer_features_pages[1] |= u64::from(feature);
57         self
58     }
59 
with_peer_page_2_feature(mut self, feature: hci::LMPFeaturesPage2Bits) -> Self60     pub fn with_peer_page_2_feature(mut self, feature: hci::LMPFeaturesPage2Bits) -> Self {
61         self.peer_features_pages[2] |= u64::from(feature);
62         self
63     }
64 }
65 
66 impl Context for TestContext {
poll_hci_command<C: TryFrom<hci::Command>>(&self) -> Poll<C>67     fn poll_hci_command<C: TryFrom<hci::Command>>(&self) -> Poll<C> {
68         let command =
69             self.hci_commands.borrow().front().and_then(|command| command.clone().try_into().ok());
70 
71         if let Some(command) = command {
72             self.hci_commands.borrow_mut().pop_front();
73             Poll::Ready(command)
74         } else {
75             Poll::Pending
76         }
77     }
78 
poll_lmp_packet<P: TryFrom<lmp::LmpPacket>>(&self) -> Poll<P>79     fn poll_lmp_packet<P: TryFrom<lmp::LmpPacket>>(&self) -> Poll<P> {
80         let packet =
81             self.in_lmp_packets.borrow().front().and_then(|packet| packet.clone().try_into().ok());
82 
83         if let Some(packet) = packet {
84             self.in_lmp_packets.borrow_mut().pop_front();
85             Poll::Ready(packet)
86         } else {
87             Poll::Pending
88         }
89     }
90 
send_hci_event<E: Into<hci::Event>>(&self, event: E)91     fn send_hci_event<E: Into<hci::Event>>(&self, event: E) {
92         self.hci_events.borrow_mut().push_back(event.into());
93     }
94 
send_lmp_packet<P: Into<lmp::LmpPacket>>(&self, packet: P)95     fn send_lmp_packet<P: Into<lmp::LmpPacket>>(&self, packet: P) {
96         self.out_lmp_packets.borrow_mut().push_back(packet.into());
97     }
98 
peer_address(&self) -> hci::Address99     fn peer_address(&self) -> hci::Address {
100         hci::Address::try_from(0).unwrap()
101     }
102 
peer_handle(&self) -> u16103     fn peer_handle(&self) -> u16 {
104         0x42
105     }
106 
peer_extended_features(&self, features_page: u8) -> Option<u64>107     fn peer_extended_features(&self, features_page: u8) -> Option<u64> {
108         Some(self.peer_features_pages[features_page as usize])
109     }
110 
extended_features(&self, features_page: u8) -> u64111     fn extended_features(&self, features_page: u8) -> u64 {
112         self.features_pages[features_page as usize]
113     }
114 
get_private_key(&self) -> Option<PrivateKey>115     fn get_private_key(&self) -> Option<PrivateKey> {
116         self.private_key.borrow().clone()
117     }
118 
set_private_key(&self, key: &PrivateKey)119     fn set_private_key(&self, key: &PrivateKey) {
120         *self.private_key.borrow_mut() = Some(key.clone())
121     }
122 }
123 
poll(future: Pin<&mut impl Future<Output = ()>>) -> Poll<()>124 pub fn poll(future: Pin<&mut impl Future<Output = ()>>) -> Poll<()> {
125     let waker = crate::future::noop_waker();
126     future.poll(&mut task::Context::from_waker(&waker))
127 }
128