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