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