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::{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::rc::{Rc, Weak};
21 use std::task::{Context, Poll};
22 
23 use pdl_runtime::Packet as _;
24 use thiserror::Error;
25 
26 use crate::ffi::ControllerOps;
27 use crate::future::noop_waker;
28 use crate::lmp::procedure;
29 use crate::num_hci_command_packets;
30 use crate::packets::{hci, lmp};
31 
32 struct Link {
33     peer: Cell<hci::Address>,
34     // Only store one HCI packet as our Num_HCI_Command_Packets
35     // is always 1
36     hci: Cell<Option<hci::Command>>,
37     lmp: RefCell<VecDeque<lmp::LmpPacket>>,
38 }
39 
40 impl Default for Link {
default() -> Self41     fn default() -> Self {
42         Link {
43             peer: Cell::new(hci::EMPTY_ADDRESS),
44             hci: Default::default(),
45             lmp: Default::default(),
46         }
47     }
48 }
49 
50 impl Link {
ingest_lmp(&self, packet: lmp::LmpPacket)51     fn ingest_lmp(&self, packet: lmp::LmpPacket) {
52         self.lmp.borrow_mut().push_back(packet);
53     }
54 
ingest_hci(&self, command: hci::Command)55     fn ingest_hci(&self, command: hci::Command) {
56         assert!(self.hci.replace(Some(command)).is_none(), "HCI flow control violation");
57     }
58 
poll_hci_command<C: TryFrom<hci::Command>>(&self) -> Poll<C>59     fn poll_hci_command<C: TryFrom<hci::Command>>(&self) -> Poll<C> {
60         let command = self.hci.take();
61 
62         if let Some(command) = command.clone().and_then(|c| c.try_into().ok()) {
63             Poll::Ready(command)
64         } else {
65             self.hci.set(command);
66             Poll::Pending
67         }
68     }
69 
poll_lmp_packet<P: TryFrom<lmp::LmpPacket>>(&self) -> Poll<P>70     fn poll_lmp_packet<P: TryFrom<lmp::LmpPacket>>(&self) -> Poll<P> {
71         let mut queue = self.lmp.borrow_mut();
72         let packet = queue.front().and_then(|packet| packet.clone().try_into().ok());
73 
74         if let Some(packet) = packet {
75             queue.pop_front();
76             Poll::Ready(packet)
77         } else {
78             Poll::Pending
79         }
80     }
81 
reset(&self)82     fn reset(&self) {
83         self.peer.set(hci::EMPTY_ADDRESS);
84         self.hci.set(None);
85         self.lmp.borrow_mut().clear();
86     }
87 }
88 
89 #[derive(Error, Debug)]
90 pub enum LinkManagerError {
91     #[error("Unknown peer")]
92     UnknownPeer,
93     #[error("Unhandled HCI packet")]
94     UnhandledHciPacket,
95     #[error("Maximum number of links reached")]
96     MaxNumberOfLink,
97 }
98 
99 /// Max number of Bluetooth Peers
100 pub const MAX_PEER_NUMBER: usize = 7;
101 
102 pub struct LinkManager {
103     ops: ControllerOps,
104     links: [Link; MAX_PEER_NUMBER],
105     procedures: RefCell<[Option<Pin<Box<dyn Future<Output = ()>>>>; MAX_PEER_NUMBER]>,
106 }
107 
108 impl LinkManager {
new(ops: ControllerOps) -> Self109     pub fn new(ops: ControllerOps) -> Self {
110         Self { ops, links: Default::default(), procedures: Default::default() }
111     }
112 
get_link(&self, peer: hci::Address) -> Option<&Link>113     fn get_link(&self, peer: hci::Address) -> Option<&Link> {
114         self.links.iter().find(|link| link.peer.get() == peer)
115     }
116 
ingest_lmp( &self, from: hci::Address, packet: lmp::LmpPacket, ) -> Result<(), LinkManagerError>117     pub fn ingest_lmp(
118         &self,
119         from: hci::Address,
120         packet: lmp::LmpPacket,
121     ) -> Result<(), LinkManagerError> {
122         if let Some(link) = self.get_link(from) {
123             link.ingest_lmp(packet);
124         };
125         Ok(())
126     }
127 
128     /// Send a command complete or command status event
129     /// with the specified error code.
send_command_complete_event( &self, command: &hci::Command, status: hci::ErrorCode, ) -> Result<(), LinkManagerError>130     fn send_command_complete_event(
131         &self,
132         command: &hci::Command,
133         status: hci::ErrorCode,
134     ) -> Result<(), LinkManagerError> {
135         use hci::CommandChild::*;
136         #[allow(unused_imports)]
137         use Option::None; // Overwrite `None` variant of `Child` enum
138 
139         let event: hci::Event = match command.specialize() {
140             LinkKeyRequestReply(packet) => hci::LinkKeyRequestReplyCompleteBuilder {
141                 status,
142                 bd_addr: packet.get_bd_addr(),
143                 num_hci_command_packets,
144             }
145             .into(),
146             LinkKeyRequestNegativeReply(packet) => {
147                 hci::LinkKeyRequestNegativeReplyCompleteBuilder {
148                     status,
149                     bd_addr: packet.get_bd_addr(),
150                     num_hci_command_packets,
151                 }
152                 .into()
153             }
154             PinCodeRequestReply(packet) => hci::PinCodeRequestReplyCompleteBuilder {
155                 status,
156                 bd_addr: packet.get_bd_addr(),
157                 num_hci_command_packets,
158             }
159             .into(),
160             PinCodeRequestNegativeReply(packet) => {
161                 hci::PinCodeRequestNegativeReplyCompleteBuilder {
162                     status,
163                     bd_addr: packet.get_bd_addr(),
164                     num_hci_command_packets,
165                 }
166                 .into()
167             }
168             IoCapabilityRequestReply(packet) => hci::IoCapabilityRequestReplyCompleteBuilder {
169                 status,
170                 bd_addr: packet.get_bd_addr(),
171                 num_hci_command_packets,
172             }
173             .into(),
174             IoCapabilityRequestNegativeReply(packet) => {
175                 hci::IoCapabilityRequestNegativeReplyCompleteBuilder {
176                     status,
177                     bd_addr: packet.get_bd_addr(),
178                     num_hci_command_packets,
179                 }
180                 .into()
181             }
182             UserConfirmationRequestReply(packet) => {
183                 hci::UserConfirmationRequestReplyCompleteBuilder {
184                     status,
185                     bd_addr: packet.get_bd_addr(),
186                     num_hci_command_packets,
187                 }
188                 .into()
189             }
190             UserConfirmationRequestNegativeReply(packet) => {
191                 hci::UserConfirmationRequestNegativeReplyCompleteBuilder {
192                     status,
193                     bd_addr: packet.get_bd_addr(),
194                     num_hci_command_packets,
195                 }
196                 .into()
197             }
198             UserPasskeyRequestReply(packet) => hci::UserPasskeyRequestReplyCompleteBuilder {
199                 status,
200                 bd_addr: packet.get_bd_addr(),
201                 num_hci_command_packets,
202             }
203             .into(),
204             UserPasskeyRequestNegativeReply(packet) => {
205                 hci::UserPasskeyRequestNegativeReplyCompleteBuilder {
206                     status,
207                     bd_addr: packet.get_bd_addr(),
208                     num_hci_command_packets,
209                 }
210                 .into()
211             }
212             RemoteOobDataRequestReply(packet) => hci::RemoteOobDataRequestReplyCompleteBuilder {
213                 status,
214                 bd_addr: packet.get_bd_addr(),
215                 num_hci_command_packets,
216             }
217             .into(),
218             RemoteOobDataRequestNegativeReply(packet) => {
219                 hci::RemoteOobDataRequestNegativeReplyCompleteBuilder {
220                     status,
221                     bd_addr: packet.get_bd_addr(),
222                     num_hci_command_packets,
223                 }
224                 .into()
225             }
226             SendKeypressNotification(packet) => hci::SendKeypressNotificationCompleteBuilder {
227                 status,
228                 bd_addr: packet.get_bd_addr(),
229                 num_hci_command_packets,
230             }
231             .into(),
232             AuthenticationRequested(_) => {
233                 hci::AuthenticationRequestedStatusBuilder { status, num_hci_command_packets }.into()
234             }
235             SetConnectionEncryption(_) => {
236                 hci::SetConnectionEncryptionStatusBuilder { status, num_hci_command_packets }.into()
237             }
238             _ => return Err(LinkManagerError::UnhandledHciPacket),
239         };
240         self.ops.send_hci_event(&event.encode_to_vec().unwrap());
241         Ok(())
242     }
243 
ingest_hci(&self, command: hci::Command) -> Result<(), LinkManagerError>244     pub fn ingest_hci(&self, command: hci::Command) -> Result<(), LinkManagerError> {
245         // Try to find the matching link from the command arguments
246         let link = hci::command_connection_handle(&command)
247             .and_then(|handle| self.ops.get_address(handle))
248             .or_else(|| hci::command_remote_device_address(&command))
249             .and_then(|peer| self.get_link(peer));
250 
251         if let Some(link) = link {
252             link.ingest_hci(command);
253             Ok(())
254         } else {
255             self.send_command_complete_event(&command, hci::ErrorCode::InvalidHciCommandParameters)
256         }
257     }
258 
add_link(self: &Rc<Self>, peer: hci::Address) -> Result<(), LinkManagerError>259     pub fn add_link(self: &Rc<Self>, peer: hci::Address) -> Result<(), LinkManagerError> {
260         let index = self.links.iter().position(|link| link.peer.get().is_empty());
261 
262         if let Some(index) = index {
263             self.links[index].peer.set(peer);
264             let context = LinkContext { index: index as u8, manager: Rc::downgrade(self) };
265             self.procedures.borrow_mut()[index] = Some(Box::pin(procedure::run(context)));
266             Ok(())
267         } else {
268             Err(LinkManagerError::UnhandledHciPacket)
269         }
270     }
271 
remove_link(&self, peer: hci::Address) -> Result<(), LinkManagerError>272     pub fn remove_link(&self, peer: hci::Address) -> Result<(), LinkManagerError> {
273         let index = self.links.iter().position(|link| link.peer.get() == peer);
274 
275         if let Some(index) = index {
276             self.links[index].reset();
277             self.procedures.borrow_mut()[index] = None;
278             Ok(())
279         } else {
280             Err(LinkManagerError::UnknownPeer)
281         }
282     }
283 
tick(&self)284     pub fn tick(&self) {
285         let waker = noop_waker();
286 
287         for procedures in self.procedures.borrow_mut().iter_mut().filter_map(Option::as_mut) {
288             let _ = procedures.as_mut().poll(&mut Context::from_waker(&waker));
289         }
290     }
291 
link(&self, idx: u8) -> &Link292     fn link(&self, idx: u8) -> &Link {
293         &self.links[idx as usize]
294     }
295 }
296 
297 struct LinkContext {
298     index: u8,
299     manager: Weak<LinkManager>,
300 }
301 
302 impl procedure::Context for LinkContext {
poll_hci_command<C: TryFrom<hci::Command>>(&self) -> Poll<C>303     fn poll_hci_command<C: TryFrom<hci::Command>>(&self) -> Poll<C> {
304         if let Some(manager) = self.manager.upgrade() {
305             manager.link(self.index).poll_hci_command()
306         } else {
307             Poll::Pending
308         }
309     }
310 
poll_lmp_packet<P: TryFrom<lmp::LmpPacket>>(&self) -> Poll<P>311     fn poll_lmp_packet<P: TryFrom<lmp::LmpPacket>>(&self) -> Poll<P> {
312         if let Some(manager) = self.manager.upgrade() {
313             manager.link(self.index).poll_lmp_packet()
314         } else {
315             Poll::Pending
316         }
317     }
318 
send_hci_event<E: Into<hci::Event>>(&self, event: E)319     fn send_hci_event<E: Into<hci::Event>>(&self, event: E) {
320         if let Some(manager) = self.manager.upgrade() {
321             manager.ops.send_hci_event(&event.into().encode_to_vec().unwrap())
322         }
323     }
324 
send_lmp_packet<P: Into<lmp::LmpPacket>>(&self, packet: P)325     fn send_lmp_packet<P: Into<lmp::LmpPacket>>(&self, packet: P) {
326         if let Some(manager) = self.manager.upgrade() {
327             manager
328                 .ops
329                 .send_lmp_packet(self.peer_address(), &packet.into().encode_to_vec().unwrap())
330         }
331     }
332 
peer_address(&self) -> hci::Address333     fn peer_address(&self) -> hci::Address {
334         if let Some(manager) = self.manager.upgrade() {
335             manager.link(self.index).peer.get()
336         } else {
337             hci::EMPTY_ADDRESS
338         }
339     }
340 
peer_handle(&self) -> u16341     fn peer_handle(&self) -> u16 {
342         if let Some(manager) = self.manager.upgrade() {
343             manager.ops.get_handle(self.peer_address())
344         } else {
345             0
346         }
347     }
348 
extended_features(&self, features_page: u8) -> u64349     fn extended_features(&self, features_page: u8) -> u64 {
350         if let Some(manager) = self.manager.upgrade() {
351             manager.ops.get_extended_features(features_page)
352         } else {
353             0
354         }
355     }
356 }
357