1use core::cell::RefCell;
4use core::future::{poll_fn, Future};
5use core::mem::MaybeUninit;
6use core::task::Poll;
7
8use cmd::controller_baseband::Reset;
9use embassy_sync::blocking_mutex::raw::NoopRawMutex;
10use embassy_sync::signal::Signal;
11use embassy_sync::waitqueue::AtomicWaker;
12use embedded_io::ErrorType;
13use futures_intrusive::sync::LocalSemaphore;
14
15use crate::cmd::{Cmd, CmdReturnBuf};
16use crate::event::{CommandComplete, CommandCompleteWithStatus, CommandStatus, EventKind};
17use crate::param::{RemainingBytes, Status};
18use crate::transport::Transport;
19use crate::{cmd, data, ControllerToHostPacket, FixedSizeValue, FromHciBytes, FromHciBytesError};
20
21pub mod blocking;
22
23pub trait Controller: ErrorType {
25 fn write_acl_data(&self, packet: &data::AclPacket) -> impl Future<Output = Result<(), Self::Error>>;
27 fn write_sync_data(&self, packet: &data::SyncPacket) -> impl Future<Output = Result<(), Self::Error>>;
29 fn write_iso_data(&self, packet: &data::IsoPacket) -> impl Future<Output = Result<(), Self::Error>>;
31
32 fn read<'a>(&self, buf: &'a mut [u8]) -> impl Future<Output = Result<ControllerToHostPacket<'a>, Self::Error>>;
34}
35
36pub trait ControllerCmdSync<C: cmd::SyncCmd + ?Sized>: Controller {
38 fn exec(&self, cmd: &C) -> impl Future<Output = Result<C::Return, cmd::Error<Self::Error>>>;
40}
41
42pub trait ControllerCmdAsync<C: cmd::AsyncCmd + ?Sized>: Controller {
44 fn exec(&self, cmd: &C) -> impl Future<Output = Result<(), cmd::Error<Self::Error>>>;
46}
47
48pub struct ExternalController<T, const SLOTS: usize> {
56 transport: T,
57 slots: ControllerState<SLOTS>,
58}
59
60impl<T, const SLOTS: usize> ExternalController<T, SLOTS> {
61 pub fn new(transport: T) -> Self {
63 Self {
64 slots: ControllerState::new(),
65 transport,
66 }
67 }
68}
69
70impl<T, const SLOTS: usize> ErrorType for ExternalController<T, SLOTS>
71where
72 T: ErrorType,
73{
74 type Error = T::Error;
75}
76
77impl<T, const SLOTS: usize> Controller for ExternalController<T, SLOTS>
78where
79 T: Transport,
80 T::Error: From<FromHciBytesError>,
81{
82 async fn write_acl_data(&self, packet: &data::AclPacket<'_>) -> Result<(), Self::Error> {
83 self.transport.write(packet).await?;
84 Ok(())
85 }
86
87 async fn write_sync_data(&self, packet: &data::SyncPacket<'_>) -> Result<(), Self::Error> {
88 self.transport.write(packet).await?;
89 Ok(())
90 }
91
92 async fn write_iso_data(&self, packet: &data::IsoPacket<'_>) -> Result<(), Self::Error> {
93 self.transport.write(packet).await?;
94 Ok(())
95 }
96
97 async fn read<'a>(&self, buf: &'a mut [u8]) -> Result<ControllerToHostPacket<'a>, Self::Error> {
98 loop {
99 {
100 let buf = unsafe { core::slice::from_raw_parts_mut(buf.as_mut_ptr(), buf.len()) };
102 let value = self.transport.read(&mut buf[..]).await?;
103 match value {
104 ControllerToHostPacket::Event(ref event) => match event.kind {
105 EventKind::CommandComplete => {
106 let e = CommandComplete::from_hci_bytes_complete(event.data)?;
107 if !e.has_status() {
108 return Ok(value);
109 }
110 let e: CommandCompleteWithStatus = e.try_into()?;
111 self.slots.complete(
112 e.cmd_opcode,
113 e.status,
114 e.num_hci_cmd_pkts as usize,
115 e.return_param_bytes.as_ref(),
116 );
117 continue;
118 }
119 EventKind::CommandStatus => {
120 let e = CommandStatus::from_hci_bytes_complete(event.data)?;
121 self.slots
122 .complete(e.cmd_opcode, e.status, e.num_hci_cmd_pkts as usize, &[]);
123 continue;
124 }
125 _ => return Ok(value),
126 },
127 _ => return Ok(value),
128 }
129 }
130 }
131 }
132}
133
134impl<T, const SLOTS: usize> blocking::Controller for ExternalController<T, SLOTS>
135where
136 T: crate::transport::blocking::Transport,
137 T::Error: From<FromHciBytesError>,
138{
139 fn write_acl_data(&self, packet: &data::AclPacket<'_>) -> Result<(), Self::Error> {
140 loop {
141 match self.try_write_acl_data(packet) {
142 Err(blocking::TryError::Busy) => {}
143 Err(blocking::TryError::Error(e)) => return Err(e),
144 Ok(r) => return Ok(r),
145 }
146 }
147 }
148
149 fn write_sync_data(&self, packet: &data::SyncPacket<'_>) -> Result<(), Self::Error> {
150 loop {
151 match self.try_write_sync_data(packet) {
152 Err(blocking::TryError::Busy) => {}
153 Err(blocking::TryError::Error(e)) => return Err(e),
154 Ok(r) => return Ok(r),
155 }
156 }
157 }
158
159 fn write_iso_data(&self, packet: &data::IsoPacket<'_>) -> Result<(), Self::Error> {
160 loop {
161 match self.try_write_iso_data(packet) {
162 Err(blocking::TryError::Busy) => {}
163 Err(blocking::TryError::Error(e)) => return Err(e),
164 Ok(r) => return Ok(r),
165 }
166 }
167 }
168
169 fn read<'a>(&self, buf: &'a mut [u8]) -> Result<ControllerToHostPacket<'a>, Self::Error> {
170 loop {
171 let buf = unsafe { core::slice::from_raw_parts_mut(buf.as_mut_ptr(), buf.len()) };
173 match self.try_read(buf) {
174 Err(blocking::TryError::Busy) => {}
175 Err(blocking::TryError::Error(e)) => return Err(e),
176 Ok(r) => return Ok(r),
177 }
178 }
179 }
180
181 fn try_write_acl_data(&self, packet: &data::AclPacket<'_>) -> Result<(), blocking::TryError<Self::Error>> {
182 self.transport.write(packet)?;
183 Ok(())
184 }
185
186 fn try_write_sync_data(&self, packet: &data::SyncPacket<'_>) -> Result<(), blocking::TryError<Self::Error>> {
187 self.transport.write(packet)?;
188 Ok(())
189 }
190
191 fn try_write_iso_data(&self, packet: &data::IsoPacket<'_>) -> Result<(), blocking::TryError<Self::Error>> {
192 self.transport.write(packet)?;
193 Ok(())
194 }
195
196 fn try_read<'a>(&self, buf: &'a mut [u8]) -> Result<ControllerToHostPacket<'a>, blocking::TryError<Self::Error>> {
197 loop {
198 {
199 let buf = unsafe { core::slice::from_raw_parts_mut(buf.as_mut_ptr(), buf.len()) };
201 let value = self.transport.read(&mut buf[..])?;
202 match value {
203 ControllerToHostPacket::Event(ref event) => match event.kind {
204 EventKind::CommandComplete => {
205 let e = CommandComplete::from_hci_bytes_complete(event.data)?;
206 if !e.has_status() {
207 return Ok(value);
208 }
209 let e: CommandCompleteWithStatus = e.try_into()?;
210 self.slots.complete(
211 e.cmd_opcode,
212 e.status,
213 e.num_hci_cmd_pkts as usize,
214 e.return_param_bytes.as_ref(),
215 );
216 continue;
217 }
218 EventKind::CommandStatus => {
219 let e = CommandStatus::from_hci_bytes_complete(event.data)?;
220 self.slots
221 .complete(e.cmd_opcode, e.status, e.num_hci_cmd_pkts as usize, &[]);
222 continue;
223 }
224 _ => return Ok(value),
225 },
226 _ => return Ok(value),
227 }
228 }
229 }
230 }
231}
232
233impl<T, C, const SLOTS: usize> ControllerCmdSync<C> for ExternalController<T, SLOTS>
234where
235 T: Transport,
236 C: cmd::SyncCmd,
237 C::Return: FixedSizeValue,
238 T::Error: From<FromHciBytesError>,
239{
240 async fn exec(&self, cmd: &C) -> Result<C::Return, cmd::Error<Self::Error>> {
241 let mut retval: C::ReturnBuf = C::ReturnBuf::new();
242
243 let (slot, idx) = self.slots.acquire(C::OPCODE, retval.as_mut()).await;
245 let _d = OnDrop::new(|| {
246 self.slots.release_slot(idx);
247 });
248
249 self.transport.write(cmd).await.map_err(cmd::Error::Io)?;
250
251 let result = slot.wait().await;
252 let return_param_bytes = RemainingBytes::from_hci_bytes_complete(&retval.as_ref()[..result.len]).unwrap();
253 let e = CommandCompleteWithStatus {
254 num_hci_cmd_pkts: 0,
255 status: result.status,
256 cmd_opcode: C::OPCODE,
257 return_param_bytes,
258 };
259 let r = e.to_result::<C>().map_err(cmd::Error::Hci)?;
260 Ok(r)
262 }
263}
264
265impl<T, C, const SLOTS: usize> ControllerCmdAsync<C> for ExternalController<T, SLOTS>
266where
267 T: Transport,
268 C: cmd::AsyncCmd,
269 T::Error: From<FromHciBytesError>,
270{
271 async fn exec(&self, cmd: &C) -> Result<(), cmd::Error<Self::Error>> {
272 let (slot, idx) = self.slots.acquire(C::OPCODE, &mut []).await;
273 let _d = OnDrop::new(|| {
274 self.slots.release_slot(idx);
275 });
276
277 self.transport.write(cmd).await.map_err(cmd::Error::Io)?;
278
279 let result = slot.wait().await;
280 result.status.to_result()?;
281 Ok(())
282 }
283}
284
285struct ControllerState<const SLOTS: usize> {
286 permits: LocalSemaphore,
287 slots: RefCell<[CommandSlot; SLOTS]>,
288 signals: [Signal<NoopRawMutex, CommandResponse>; SLOTS],
289 waker: AtomicWaker,
290}
291
292struct CommandResponse {
293 status: Status,
294 len: usize,
295}
296
297enum CommandSlot {
298 Empty,
299 Pending { opcode: u16, event: *mut [u8] },
300}
301
302impl<const SLOTS: usize> Default for ControllerState<SLOTS> {
303 fn default() -> Self {
304 Self::new()
305 }
306}
307
308impl<const SLOTS: usize> ControllerState<SLOTS> {
309 const EMPTY_SLOT: CommandSlot = CommandSlot::Empty;
310 #[allow(clippy::declare_interior_mutable_const)]
311 const EMPTY_SIGNAL: Signal<NoopRawMutex, CommandResponse> = Signal::new();
312
313 fn new() -> Self {
314 Self {
315 permits: LocalSemaphore::new(true, 1),
316 slots: RefCell::new([Self::EMPTY_SLOT; SLOTS]),
317 signals: [Self::EMPTY_SIGNAL; SLOTS],
318 waker: AtomicWaker::new(),
319 }
320 }
321
322 fn complete(&self, op: cmd::Opcode, status: Status, num_hci_command_packets: usize, data: &[u8]) {
323 let mut slots = self.slots.borrow_mut();
324 for (idx, slot) in slots.iter_mut().enumerate() {
325 match slot {
326 CommandSlot::Pending { opcode, event } if *opcode == op.to_raw() => {
327 if !data.is_empty() {
328 assert!(!event.is_null());
329 unsafe { (&mut (**event))[..data.len()].copy_from_slice(data) };
331 }
332 self.signals[idx].signal(CommandResponse {
333 status,
334 len: data.len(),
335 });
336 if op != Reset::OPCODE {
337 break;
338 }
339 }
340 CommandSlot::Pending { opcode: _, event: _ } if op == Reset::OPCODE => {
341 self.signals[idx].signal(CommandResponse {
343 status: Status::CONTROLLER_BUSY,
344 len: 0,
345 });
346 }
347 _ => {}
348 }
349 }
350
351 self.permits
353 .release(num_hci_command_packets.saturating_sub(self.permits.permits()));
354 }
355
356 fn release_slot(&self, idx: usize) {
357 let mut slots = self.slots.borrow_mut();
358 slots[idx] = CommandSlot::Empty;
359 }
360
361 async fn acquire(&self, op: cmd::Opcode, event: *mut [u8]) -> (&Signal<NoopRawMutex, CommandResponse>, usize) {
362 let to_acquire = if op == Reset::OPCODE { self.permits.permits() } else { 1 };
363 let mut permit = self.permits.acquire(to_acquire).await;
364 permit.disarm();
365 poll_fn(|cx| match self.acquire_slot(op, event) {
366 Some(ret) => Poll::Ready(ret),
367 None => {
368 self.waker.register(cx.waker());
369 Poll::Pending
370 }
371 })
372 .await
373 }
374
375 fn acquire_slot(
376 &self,
377 op: cmd::Opcode,
378 event: *mut [u8],
379 ) -> Option<(&Signal<NoopRawMutex, CommandResponse>, usize)> {
380 let mut slots = self.slots.borrow_mut();
381 for slot in slots.iter() {
383 match slot {
384 CommandSlot::Pending { opcode, event: _ } if *opcode == op.to_raw() => {
385 return None;
386 }
387 _ => {}
388 }
389 }
390 for (idx, slot) in slots.iter_mut().enumerate() {
392 if matches!(slot, CommandSlot::Empty) {
393 *slot = CommandSlot::Pending {
394 opcode: op.to_raw(),
395 event,
396 };
397 self.signals[idx].reset();
398 return Some((&self.signals[idx], idx));
399 }
400 }
401 None
402 }
403}
404
405#[must_use = "to delay the drop handler invocation to the end of the scope"]
407struct OnDrop<F: FnOnce()> {
408 f: MaybeUninit<F>,
409}
410
411impl<F: FnOnce()> OnDrop<F> {
412 pub(crate) fn new(f: F) -> Self {
414 Self { f: MaybeUninit::new(f) }
415 }
416}
417
418impl<F: FnOnce()> Drop for OnDrop<F> {
419 fn drop(&mut self) {
420 unsafe { self.f.as_ptr().read()() }
421 }
422}
423
424#[cfg(test)]
425mod tests {
426 use super::*;
427
428 pub struct TestTransport<'d> {
429 pub rx: &'d [u8],
430 }
431
432 #[derive(Clone, Copy, Debug, PartialEq)]
433 pub struct Error;
434
435 impl From<FromHciBytesError> for Error {
436 fn from(_: FromHciBytesError) -> Self {
437 Self
438 }
439 }
440
441 impl ErrorType for TestTransport<'_> {
442 type Error = Error;
443 }
444 impl embedded_io::Error for Error {
445 fn kind(&self) -> embedded_io::ErrorKind {
446 embedded_io::ErrorKind::Other
447 }
448 }
449 impl Transport for TestTransport<'_> {
450 fn read<'a>(&self, rx: &'a mut [u8]) -> impl Future<Output = Result<ControllerToHostPacket<'a>, Self::Error>> {
451 async {
452 let to_read = rx.len().min(self.rx.len());
453
454 rx[..to_read].copy_from_slice(&self.rx[..to_read]);
455 let pkt = ControllerToHostPacket::from_hci_bytes_complete(&rx[..to_read])?;
456 Ok(pkt)
457 }
458 }
459
460 fn write<T: crate::HostToControllerPacket>(&self, _val: &T) -> impl Future<Output = Result<(), Self::Error>> {
461 async { todo!() }
462 }
463 }
464
465 #[futures_test::test]
466 pub async fn test_can_handle_unsolicited_command_complete() {
467 let t = TestTransport {
468 rx: &[
469 4, 0x0e, 3, 1, 0, 0, ],
472 };
473 let c: ExternalController<_, 10> = ExternalController::new(t);
474
475 let mut rx = [0; 255];
476 let pkt = c.read(&mut rx).await;
477 assert!(pkt.is_ok());
478 }
479}