• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! Host Controller Interface (HCI)
2 
3 /// HCI controller info
4 pub mod controller;
5 /// Controller facade service
6 pub mod controller_facade;
7 /// HCI errors
8 pub mod error;
9 /// HCI layer facade service
10 pub mod facade;
11 
12 pub use bt_hci_custom_types::*;
13 pub use controller::ControllerExports;
14 
15 use bt_common::time::Alarm;
16 use bt_hal::ControlHal;
17 use bt_packets::hci::EventChild::{
18     CommandComplete, CommandStatus, LeMetaEvent, MaxSlotsChange, PageScanRepetitionModeChange,
19     VendorSpecificEvent,
20 };
21 use bt_packets::hci::{
22     CommandExpectations, CommandPacket, ErrorCode, EventCode, EventPacket, LeMetaEventPacket,
23     ResetBuilder, SubeventCode,
24 };
25 use error::Result;
26 use gddi::{module, part_out, provides, Stoppable};
27 use log::error;
28 use std::collections::HashMap;
29 use std::sync::Arc;
30 use std::time::Duration;
31 use tokio::runtime::Runtime;
32 use tokio::select;
33 use tokio::sync::mpsc::{channel, Receiver, Sender};
34 use tokio::sync::{oneshot, Mutex};
35 
36 module! {
37     hci_module,
38     submodules {
39         facade::facade_module,
40         controller_facade::controller_facade_module,
41         controller::controller_module,
42     },
43     providers {
44         parts Hci => provide_hci,
45     },
46 }
47 
48 #[part_out]
49 #[derive(Clone, Stoppable)]
50 struct Hci {
51     raw_commands: RawCommandSender,
52     commands: CommandSender,
53     events: EventRegistry,
54 }
55 
56 #[provides]
provide_hci(control: ControlHal, rt: Arc<Runtime>) -> Hci57 async fn provide_hci(control: ControlHal, rt: Arc<Runtime>) -> Hci {
58     let (cmd_tx, cmd_rx) = channel::<QueuedCommand>(10);
59     let evt_handlers = Arc::new(Mutex::new(HashMap::new()));
60     let le_evt_handlers = Arc::new(Mutex::new(HashMap::new()));
61 
62     rt.spawn(dispatch(
63         evt_handlers.clone(),
64         le_evt_handlers.clone(),
65         control.rx,
66         control.tx,
67         cmd_rx,
68     ));
69 
70     let raw_commands = RawCommandSender { cmd_tx };
71     let mut commands = CommandSender { raw: raw_commands.clone() };
72 
73     assert!(
74         commands.send(ResetBuilder {}).await.get_status() == ErrorCode::Success,
75         "reset did not complete successfully"
76     );
77 
78     Hci { raw_commands, commands, events: EventRegistry { evt_handlers, le_evt_handlers } }
79 }
80 
81 #[derive(Debug)]
82 struct QueuedCommand {
83     cmd: CommandPacket,
84     fut: oneshot::Sender<EventPacket>,
85 }
86 
87 /// Sends raw commands. Only useful for facades & shims, or wrapped as a CommandSender.
88 #[derive(Clone, Stoppable)]
89 pub struct RawCommandSender {
90     cmd_tx: Sender<QueuedCommand>,
91 }
92 
93 impl RawCommandSender {
94     /// Send a command, but does not automagically associate the expected returning event type.
95     ///
96     /// Only really useful for facades & shims.
send(&mut self, cmd: CommandPacket) -> Result<EventPacket>97     pub async fn send(&mut self, cmd: CommandPacket) -> Result<EventPacket> {
98         let (tx, rx) = oneshot::channel::<EventPacket>();
99         self.cmd_tx.send(QueuedCommand { cmd, fut: tx }).await?;
100         let event = rx.await?;
101         Ok(event)
102     }
103 }
104 
105 /// Sends commands to the controller
106 #[derive(Clone, Stoppable)]
107 pub struct CommandSender {
108     raw: RawCommandSender,
109 }
110 
111 impl CommandSender {
112     /// Send a command to the controller, getting an expected response back
send<T: Into<CommandPacket> + CommandExpectations>( &mut self, cmd: T, ) -> T::ResponseType113     pub async fn send<T: Into<CommandPacket> + CommandExpectations>(
114         &mut self,
115         cmd: T,
116     ) -> T::ResponseType {
117         T::_to_response_type(self.raw.send(cmd.into()).await.unwrap())
118     }
119 }
120 
121 /// Provides ability to register and unregister for HCI events
122 #[derive(Clone, Stoppable)]
123 pub struct EventRegistry {
124     evt_handlers: Arc<Mutex<HashMap<EventCode, Sender<EventPacket>>>>,
125     le_evt_handlers: Arc<Mutex<HashMap<SubeventCode, Sender<LeMetaEventPacket>>>>,
126 }
127 
128 impl EventRegistry {
129     /// Indicate interest in specific HCI events
register(&mut self, code: EventCode, sender: Sender<EventPacket>)130     pub async fn register(&mut self, code: EventCode, sender: Sender<EventPacket>) {
131         match code {
132             EventCode::CommandStatus
133             | EventCode::CommandComplete
134             | EventCode::LeMetaEvent
135             | EventCode::PageScanRepetitionModeChange
136             | EventCode::MaxSlotsChange
137             | EventCode::VendorSpecific => panic!("{:?} is a protected event", code),
138             _ => {
139                 assert!(
140                     self.evt_handlers.lock().await.insert(code, sender).is_none(),
141                     "A handler for {:?} is already registered",
142                     code
143                 );
144             }
145         }
146     }
147 
148     /// Remove interest in specific HCI events
unregister(&mut self, code: EventCode)149     pub async fn unregister(&mut self, code: EventCode) {
150         self.evt_handlers.lock().await.remove(&code);
151     }
152 
153     /// Indicate interest in specific LE events
register_le(&mut self, code: SubeventCode, sender: Sender<LeMetaEventPacket>)154     pub async fn register_le(&mut self, code: SubeventCode, sender: Sender<LeMetaEventPacket>) {
155         assert!(
156             self.le_evt_handlers.lock().await.insert(code, sender).is_none(),
157             "A handler for {:?} is already registered",
158             code
159         );
160     }
161 
162     /// Remove interest in specific LE events
unregister_le(&mut self, code: SubeventCode)163     pub async fn unregister_le(&mut self, code: SubeventCode) {
164         self.le_evt_handlers.lock().await.remove(&code);
165     }
166 }
167 
dispatch( evt_handlers: Arc<Mutex<HashMap<EventCode, Sender<EventPacket>>>>, le_evt_handlers: Arc<Mutex<HashMap<SubeventCode, Sender<LeMetaEventPacket>>>>, evt_rx: Arc<Mutex<Receiver<EventPacket>>>, cmd_tx: Sender<CommandPacket>, mut cmd_rx: Receiver<QueuedCommand>, )168 async fn dispatch(
169     evt_handlers: Arc<Mutex<HashMap<EventCode, Sender<EventPacket>>>>,
170     le_evt_handlers: Arc<Mutex<HashMap<SubeventCode, Sender<LeMetaEventPacket>>>>,
171     evt_rx: Arc<Mutex<Receiver<EventPacket>>>,
172     cmd_tx: Sender<CommandPacket>,
173     mut cmd_rx: Receiver<QueuedCommand>,
174 ) {
175     let mut pending: Option<QueuedCommand> = None;
176     let mut hci_timeout = Alarm::new();
177     loop {
178         select! {
179             Some(evt) = consume(&evt_rx) => {
180                 match evt.specialize() {
181                     CommandStatus(evt) => {
182                         hci_timeout.cancel();
183                         let this_opcode = evt.get_command_op_code();
184                         match pending.take() {
185                             Some(QueuedCommand{cmd, fut}) if cmd.get_op_code() == this_opcode => {
186                                 if let Err(e) = fut.send(evt.into()) {
187                                     error!("failure dispatching command status {:?}", e);
188                                 }
189                             },
190                             Some(QueuedCommand{cmd, ..}) => panic!("Waiting for {:?}, got {:?}", cmd.get_op_code(), this_opcode),
191                             None => panic!("Unexpected status event with opcode {:?}", this_opcode),
192                         }
193                     },
194                     CommandComplete(evt) => {
195                         hci_timeout.cancel();
196                         let this_opcode = evt.get_command_op_code();
197                         match pending.take() {
198                             Some(QueuedCommand{cmd, fut}) if cmd.get_op_code() == this_opcode => {
199                                 if let Err(e) = fut.send(evt.into()) {
200                                     error!("failure dispatching command complete {:?}", e);
201                                 }
202                             },
203                             Some(QueuedCommand{cmd, ..}) => panic!("Waiting for {:?}, got {:?}", cmd.get_op_code(), this_opcode),
204                             None => panic!("Unexpected complete event with opcode {:?}", this_opcode),
205                         }
206                     },
207                     LeMetaEvent(evt) => {
208                         let code = evt.get_subevent_code();
209                         match le_evt_handlers.lock().await.get(&code) {
210                             Some(sender) => {
211                                 if let Err(e) = sender.send(evt).await {
212                                     error!("le meta event channel closed {:?}", e);
213                                 }
214                             },
215                             None => panic!("Unhandled le subevent {:?}", code),
216                         }
217                     },
218                     PageScanRepetitionModeChange(_) => {},
219                     MaxSlotsChange(_) => {},
220                     VendorSpecificEvent(_) => {},
221                     _ => {
222                         let code = evt.get_event_code();
223                         match evt_handlers.lock().await.get(&code) {
224                             Some(sender) => {
225                                 if let Err(e) = sender.send(evt).await {
226                                     error!("hci event channel closed {:?}", e);
227                                 }
228                             },
229                             None if code == EventCode::NumberOfCompletedPackets =>{},
230                             None => panic!("Unhandled event {:?}", code),
231                         }
232                     },
233                 }
234             },
235             Some(queued) = cmd_rx.recv(), if pending.is_none() => {
236                 if let Err(e) = cmd_tx.send(queued.cmd.clone()).await {
237                     error!("command queue closed: {:?}", e);
238                 }
239                 hci_timeout.reset(Duration::from_secs(2));
240                 pending = Some(queued);
241             },
242             _ = hci_timeout.expired() => panic!("Timed out waiting for {:?}", pending.unwrap().cmd.get_op_code()),
243             else => break,
244         }
245     }
246 }
247 
consume(evt_rx: &Arc<Mutex<Receiver<EventPacket>>>) -> Option<EventPacket>248 async fn consume(evt_rx: &Arc<Mutex<Receiver<EventPacket>>>) -> Option<EventPacket> {
249     evt_rx.lock().await.recv().await
250 }
251