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::packets::{hci, lmp}; 14 use crate::procedure; 15 16 use hci::Packet as _; 17 use lmp::Packet as _; 18 19 /// Number of hci command packets used 20 /// in Command Complete and Command Status 21 #[allow(non_upper_case_globals)] 22 pub const num_hci_command_packets: u8 = 1; 23 24 struct Link { 25 peer: Cell<hci::Address>, 26 // Only store one HCI packet as our Num_HCI_Command_Packets 27 // is always 1 28 hci: Cell<Option<hci::CommandPacket>>, 29 lmp: RefCell<VecDeque<lmp::PacketPacket>>, 30 } 31 32 impl Default for Link { default() -> Self33 fn default() -> Self { 34 Link { 35 peer: Cell::new(hci::EMPTY_ADDRESS), 36 hci: Default::default(), 37 lmp: Default::default(), 38 } 39 } 40 } 41 42 impl Link { ingest_lmp(&self, packet: lmp::PacketPacket)43 fn ingest_lmp(&self, packet: lmp::PacketPacket) { 44 self.lmp.borrow_mut().push_back(packet); 45 } 46 ingest_hci(&self, command: hci::CommandPacket)47 fn ingest_hci(&self, command: hci::CommandPacket) { 48 assert!(self.hci.replace(Some(command)).is_none(), "HCI flow control violation"); 49 } 50 poll_hci_command<C: TryFrom<hci::CommandPacket>>(&self) -> Poll<C>51 fn poll_hci_command<C: TryFrom<hci::CommandPacket>>(&self) -> Poll<C> { 52 let command = self.hci.take(); 53 54 if let Some(command) = command.clone().and_then(|c| c.try_into().ok()) { 55 Poll::Ready(command) 56 } else { 57 self.hci.set(command); 58 Poll::Pending 59 } 60 } 61 poll_lmp_packet<P: TryFrom<lmp::PacketPacket>>(&self) -> Poll<P>62 fn poll_lmp_packet<P: TryFrom<lmp::PacketPacket>>(&self) -> Poll<P> { 63 let mut queue = self.lmp.borrow_mut(); 64 let packet = queue.front().and_then(|packet| packet.clone().try_into().ok()); 65 66 if let Some(packet) = packet { 67 queue.pop_front(); 68 Poll::Ready(packet) 69 } else { 70 Poll::Pending 71 } 72 } 73 reset(&self)74 fn reset(&self) { 75 self.peer.set(hci::EMPTY_ADDRESS); 76 self.hci.set(None); 77 self.lmp.borrow_mut().clear(); 78 } 79 } 80 81 #[derive(Error, Debug)] 82 pub enum LinkManagerError { 83 #[error("Unknown peer")] 84 UnknownPeer, 85 #[error("Unhandled HCI packet")] 86 UnhandledHciPacket, 87 #[error("Maximum number of links reached")] 88 MaxNumberOfLink, 89 } 90 91 /// Max number of Bluetooth Peers 92 pub const MAX_PEER_NUMBER: usize = 7; 93 94 pub struct LinkManager { 95 ops: LinkManagerOps, 96 links: [Link; MAX_PEER_NUMBER], 97 procedures: RefCell<[Option<Pin<Box<dyn Future<Output = ()>>>>; MAX_PEER_NUMBER]>, 98 } 99 100 impl LinkManager { new(ops: LinkManagerOps) -> Self101 pub fn new(ops: LinkManagerOps) -> Self { 102 Self { ops, links: Default::default(), procedures: Default::default() } 103 } 104 get_link(&self, peer: hci::Address) -> Option<&Link>105 fn get_link(&self, peer: hci::Address) -> Option<&Link> { 106 self.links.iter().find(|link| link.peer.get() == peer) 107 } 108 ingest_lmp( &self, from: hci::Address, packet: lmp::PacketPacket, ) -> Result<(), LinkManagerError>109 pub fn ingest_lmp( 110 &self, 111 from: hci::Address, 112 packet: lmp::PacketPacket, 113 ) -> Result<(), LinkManagerError> { 114 if let Some(link) = self.get_link(from) { 115 link.ingest_lmp(packet); 116 }; 117 Ok(()) 118 } 119 ingest_hci(&self, command: hci::CommandPacket) -> Result<(), LinkManagerError>120 pub fn ingest_hci(&self, command: hci::CommandPacket) -> Result<(), LinkManagerError> { 121 // Try to find the peer address from the command arguments 122 let peer = hci::command_connection_handle(&command) 123 .map(|handle| self.ops.get_address(handle)) 124 .or_else(|| hci::command_remote_device_address(&command)); 125 126 if let Some(peer) = peer { 127 if let Some(link) = self.get_link(peer) { 128 link.ingest_hci(command); 129 }; 130 Ok(()) 131 } else { 132 Err(LinkManagerError::UnhandledHciPacket) 133 } 134 } 135 add_link(self: &Rc<Self>, peer: hci::Address) -> Result<(), LinkManagerError>136 pub fn add_link(self: &Rc<Self>, peer: hci::Address) -> Result<(), LinkManagerError> { 137 let index = self.links.iter().position(|link| link.peer.get().is_empty()); 138 139 if let Some(index) = index { 140 self.links[index].peer.set(peer); 141 let context = LinkContext { index: index as u8, manager: Rc::downgrade(self) }; 142 self.procedures.borrow_mut()[index] = Some(Box::pin(procedure::run(context))); 143 Ok(()) 144 } else { 145 Err(LinkManagerError::UnhandledHciPacket) 146 } 147 } 148 remove_link(&self, peer: hci::Address) -> Result<(), LinkManagerError>149 pub fn remove_link(&self, peer: hci::Address) -> Result<(), LinkManagerError> { 150 let index = self.links.iter().position(|link| link.peer.get() == peer); 151 152 if let Some(index) = index { 153 self.links[index].reset(); 154 self.procedures.borrow_mut()[index] = None; 155 Ok(()) 156 } else { 157 Err(LinkManagerError::UnknownPeer) 158 } 159 } 160 tick(&self)161 pub fn tick(&self) { 162 let waker = noop_waker(); 163 164 for procedures in self.procedures.borrow_mut().iter_mut().filter_map(Option::as_mut) { 165 let _ = procedures.as_mut().poll(&mut Context::from_waker(&waker)); 166 } 167 } 168 link(&self, idx: u8) -> &Link169 fn link(&self, idx: u8) -> &Link { 170 &self.links[idx as usize] 171 } 172 } 173 174 struct LinkContext { 175 index: u8, 176 manager: Weak<LinkManager>, 177 } 178 179 impl procedure::Context for LinkContext { poll_hci_command<C: TryFrom<hci::CommandPacket>>(&self) -> Poll<C>180 fn poll_hci_command<C: TryFrom<hci::CommandPacket>>(&self) -> Poll<C> { 181 if let Some(manager) = self.manager.upgrade() { 182 manager.link(self.index).poll_hci_command() 183 } else { 184 Poll::Pending 185 } 186 } 187 poll_lmp_packet<P: TryFrom<lmp::PacketPacket>>(&self) -> Poll<P>188 fn poll_lmp_packet<P: TryFrom<lmp::PacketPacket>>(&self) -> Poll<P> { 189 if let Some(manager) = self.manager.upgrade() { 190 manager.link(self.index).poll_lmp_packet() 191 } else { 192 Poll::Pending 193 } 194 } 195 send_hci_event<E: Into<hci::EventPacket>>(&self, event: E)196 fn send_hci_event<E: Into<hci::EventPacket>>(&self, event: E) { 197 if let Some(manager) = self.manager.upgrade() { 198 manager.ops.send_hci_event(&event.into().to_vec()) 199 } 200 } 201 send_lmp_packet<P: Into<lmp::PacketPacket>>(&self, packet: P)202 fn send_lmp_packet<P: Into<lmp::PacketPacket>>(&self, packet: P) { 203 if let Some(manager) = self.manager.upgrade() { 204 manager.ops.send_lmp_packet(self.peer_address(), &packet.into().to_vec()) 205 } 206 } 207 peer_address(&self) -> hci::Address208 fn peer_address(&self) -> hci::Address { 209 if let Some(manager) = self.manager.upgrade() { 210 manager.link(self.index).peer.get() 211 } else { 212 hci::EMPTY_ADDRESS 213 } 214 } 215 peer_handle(&self) -> u16216 fn peer_handle(&self) -> u16 { 217 if let Some(manager) = self.manager.upgrade() { 218 manager.ops.get_handle(self.peer_address()) 219 } else { 220 0 221 } 222 } 223 extended_features(&self, features_page: u8) -> u64224 fn extended_features(&self, features_page: u8) -> u64 { 225 if let Some(manager) = self.manager.upgrade() { 226 manager.ops.extended_features(features_page) 227 } else { 228 0 229 } 230 } 231 } 232