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