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