1use core::future::Future;
4
5use embedded_io::ErrorType;
6
7use crate::controller::{ControllerCmdAsync, ControllerCmdSync};
8use crate::{param, FixedSizeValue, FromHciBytes, HostToControllerPacket, PacketKind, WriteHci};
9
10pub mod controller_baseband;
11pub mod info;
12pub mod le;
13pub mod link_control;
14pub mod status;
15
16#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
20#[cfg_attr(feature = "defmt", derive(defmt::Format))]
21pub struct OpcodeGroup(u8);
22
23impl OpcodeGroup {
24 pub const LINK_CONTROL: OpcodeGroup = OpcodeGroup(1);
26 pub const LINK_POLICY: OpcodeGroup = OpcodeGroup(2);
28 pub const CONTROL_BASEBAND: OpcodeGroup = OpcodeGroup(3);
30 pub const INFO_PARAMS: OpcodeGroup = OpcodeGroup(4);
32 pub const STATUS_PARAMS: OpcodeGroup = OpcodeGroup(5);
34 pub const TESTING: OpcodeGroup = OpcodeGroup(6);
36 pub const LE: OpcodeGroup = OpcodeGroup(8);
38 pub const VENDOR_SPECIFIC: OpcodeGroup = OpcodeGroup(0x3f);
40
41 pub const fn new(val: u8) -> Self {
43 Self(val)
44 }
45}
46
47param!(
48 struct Opcode(u16)
52);
53
54impl Opcode {
55 pub const fn new(ogf: OpcodeGroup, ocf: u16) -> Self {
57 Self(((ogf.0 as u16) << 10) | ocf)
58 }
59
60 pub const fn group(self) -> OpcodeGroup {
62 OpcodeGroup((self.0 >> 10) as u8)
63 }
64
65 pub const fn cmd(self) -> u16 {
67 self.0 & 0x03ff
68 }
69
70 pub const fn to_raw(self) -> u16 {
72 self.0
73 }
74}
75
76#[derive(Debug)]
78#[cfg_attr(feature = "defmt", derive(defmt::Format))]
79pub enum Error<E> {
80 Hci(param::Error),
82 Io(E),
84}
85
86impl<E> From<param::Error> for Error<E> {
87 fn from(e: param::Error) -> Self {
88 Self::Hci(e)
89 }
90}
91
92pub trait Cmd: WriteHci {
94 const OPCODE: Opcode;
96
97 type Params: WriteHci;
99
100 fn params(&self) -> &Self::Params;
102
103 fn header(&self) -> [u8; 3] {
105 let opcode_bytes = Self::OPCODE.0.to_le_bytes();
106 [opcode_bytes[0], opcode_bytes[1], self.params().size() as u8]
107 }
108}
109
110impl<T: Cmd> HostToControllerPacket for T {
111 const KIND: PacketKind = PacketKind::Cmd;
112}
113
114pub trait AsyncCmd: Cmd {
117 fn exec<C: ControllerCmdAsync<Self>>(
119 &self,
120 controller: &C,
121 ) -> impl Future<Output = Result<(), Error<<C as ErrorType>::Error>>> {
122 controller.exec(self)
123 }
124}
125
126pub trait CmdReturnBuf: Copy + AsRef<[u8]> + AsMut<[u8]> {
128 const LEN: usize;
130
131 fn new() -> Self;
133}
134
135impl<const N: usize> CmdReturnBuf for [u8; N] {
136 const LEN: usize = N;
137
138 #[inline(always)]
139 fn new() -> Self {
140 [0; N]
141 }
142}
143
144pub trait SyncCmd: Cmd {
147 type Return: for<'a> FromHciBytes<'a> + Copy;
149 type Handle: FixedSizeValue;
151 type ReturnBuf: CmdReturnBuf;
153
154 fn param_handle(&self) -> Self::Handle;
156
157 fn return_handle(_data: &[u8]) -> Result<Self::Handle, crate::FromHciBytesError>;
166
167 fn exec<C: ControllerCmdSync<Self>>(
169 &self,
170 controller: &C,
171 ) -> impl Future<Output = Result<Self::Return, Error<<C as ErrorType>::Error>>> {
172 controller.exec(self)
173 }
174}
175
176#[doc(hidden)]
177#[macro_export]
178macro_rules! cmd {
179 (
180 $(#[$attrs:meta])*
181 $name:ident($group:ident, $cmd:expr) {
182 $params:ident$(<$life:lifetime>)? {
183 $($param_name:ident: $param_ty:ty,)+
184 }
185 $ret:ident {
186 $($ret_name:ident: $ret_ty:ty,)+
187 }
188 $(Handle = $handle_name:ident: $handle:ty;)?
189 }
190 ) => {
191 $crate::cmd! {
192 $(#[$attrs])*
193 $name($group, $cmd) {
194 $params$(<$life>)? {
195 $($param_name: $param_ty,)+
196 }
197 Return = $ret;
198 $(Handle = $handle_name: $handle;)?
199 }
200 }
201
202 $crate::param! {
203 #[doc = "Return parameters for"]
204 $(#[$attrs])*
205 struct $ret {
206 $($handle_name: $handle,)?
207 $($ret_name: $ret_ty,)*
208 }
209 }
210 };
211 (
212 $(#[$attrs:meta])*
213 $name:ident($group:ident, $cmd:expr) {
214 Params = ();
215 $ret:ident {
216 $($ret_name:ident: $ret_ty:ty,)+
217 }
218 }
219 ) => {
220 $crate::cmd! {
221 $(#[$attrs])*
222 $name($group, $cmd) {
223 Params = ();
224 Return = $ret;
225 }
226 }
227
228 $crate::param! {
229 #[doc = "Return parameters for"]
230 $(#[$attrs])*
231 struct $ret {
232 $($ret_name: $ret_ty,)*
233 }
234 }
235 };
236 (
237 $(#[$attrs:meta])*
238 $name:ident($group:ident, $cmd:expr) {
239 Params$(<$life:lifetime>)? = $param:ty;
240 $ret:ident {
241 $($ret_name:ident: $ret_ty:ty,)+
242 }
243 $(Handle = $handle_name:ident: $handle:ty;)?
244 }
245 ) => {
246 $crate::cmd! {
247 $(#[$attrs])*
248 $name($group, $cmd) {
249 Params$(<$life>)? = $param;
250 Return = $ret;
251 $(Handle = $handle;)?
252 }
253 }
254
255 $crate::param! {
256 #[doc = "Return parameters for"]
257 $(#[$attrs])*
258 struct $ret {
259 $($handle_name: $handle,)?
260 $($ret_name: $ret_ty,)*
261 }
262 }
263 };
264 (
265 $(#[$attrs:meta])*
266 $name:ident($group:ident, $cmd:expr) {
267 $params:ident$(<$life:lifetime>)? {
268 $($param_name:ident: $param_ty:ty,)+
269 }
270 $(
271 Return = $ret:ty;
272 $(Handle = $handle_name:ident: $handle:ty;)?
273 )?
274 }
275 ) => {
276 $crate::cmd! {
277 BASE
278 $(#[$attrs])*
279 $name($group, $cmd) {
280 Params$(<$life>)? = $params$(<$life>)?;
281 $(
282 Return = $ret;
283 $(Handle = $handle;)?
284 )?
285 }
286 }
287
288 impl$(<$life>)? $name$(<$life>)? {
289 #[allow(clippy::too_many_arguments)]
290 pub fn new($($($handle_name: $handle,)?)? $($param_name: $param_ty),+) -> Self {
292 Self($params {
293 $($($handle_name,)?)?
294 $($param_name,)*
295 })
296 }
297
298 $(
299 $(
300 fn handle(&self) -> $handle {
301 self.0.$handle_name
302 }
303 )?
304 )?
305 }
306
307 $crate::param! {
308 #[doc = "Parameters for"]
309 $(#[$attrs])*
310 struct $params$(<$life>)? {
311 $($($handle_name: $handle,)?)?
312 $($param_name: $param_ty,)*
313 }
314 }
315 };
316 (
317 $(#[$attrs:meta])*
318 $name:ident($group:ident, $cmd:expr) {
319 Params = ();
320 $(Return = $ret:ty;)?
321 }
322 ) => {
323 $crate::cmd! {
324 BASE
325 $(#[$attrs])*
326 $name($group, $cmd) {
327 Params = ();
328 $(Return = $ret;)?
329 }
330 }
331
332 impl $name {
333 pub fn new() -> Self {
335 Self(())
336 }
337 }
338
339 impl Default for $name {
340 fn default() -> Self {
341 Self(())
342 }
343 }
344 };
345 (
346 $(#[$attrs:meta])*
347 $name:ident($group:ident, $cmd:expr) {
348 Params$(<$life:lifetime>)? = $params:ty;
349 $(
350 Return = $ret:ty;
351 $(Handle = $handle:ty;)?
352 )?
353 }
354 ) => {
355 $crate::cmd! {
356 BASE
357 $(#[$attrs])*
358 $name($group, $cmd) {
359 Params$(<$life>)? = $params;
360 $(
361 Return = $ret;
362 $(Handle = $handle;)?
363 )?
364 }
365 }
366
367 impl$(<$life>)? $name$(<$life>)? {
368 pub fn new(param: $params) -> Self {
370 Self(param)
371 }
372
373 $(
374 $(
375 fn handle(&self) -> $handle {
376 self.0
377 }
378 )?
379 )?
380 }
381 };
382 (
383 BASE
384 $(#[$attrs:meta])*
385 $name:ident($group:ident, $cmd:expr) {
386 Params$(<$life:lifetime>)? = $params:ty;
387 $(
388 Return = $ret:ty;
389 $(Handle = $handle:ty;)?
390 )?
391 }
392 ) => {
393 $(#[$attrs])*
394 #[repr(transparent)]
395 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
396 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
397 pub struct $name$(<$life>)?($params);
398
399 #[automatically_derived]
400 #[allow(unused_mut, unused_variables, unused_imports)]
401 impl$(<$life>)? $crate::cmd::Cmd for $name$(<$life>)? {
402 const OPCODE: $crate::cmd::Opcode = $crate::cmd::Opcode::new($crate::cmd::OpcodeGroup::$group, $cmd);
403 type Params = $params;
404
405 fn params(&self) -> &$params {
406 &self.0
407 }
408 }
409
410 #[automatically_derived]
411 impl$(<$life>)? From<$params> for $name$(<$life>)? {
412 fn from(params: $params) -> Self {
413 Self(params)
414 }
415 }
416
417 impl$(<$life>)? $crate::WriteHci for $name$(<$life>)? {
418 #[inline(always)]
419 fn size(&self) -> usize {
420 <$params as $crate::WriteHci>::size(&self.0) + 3
421 }
422
423 fn write_hci<W: embedded_io::Write>(&self, mut writer: W) -> Result<(), W::Error> {
424 writer.write_all(&<Self as $crate::cmd::Cmd>::header(self))?;
425 <$params as $crate::WriteHci>::write_hci(&self.0, writer)
426 }
427
428 async fn write_hci_async<W: embedded_io_async::Write>(&self, mut writer: W) -> Result<(), W::Error> {
429 writer.write_all(&<Self as $crate::cmd::Cmd>::header(self)).await?;
430 <$params as $crate::WriteHci>::write_hci_async(&self.0, writer).await
431 }
432 }
433
434 $crate::cmd! {
435 RETURN
436 $name$(<$life>)? {
437 $(
438 Return = $ret;
439 $(Handle = $handle;)?
440 )?
441 }
442 }
443 };
444 (
445 RETURN
446 $name:ident$(<$life:lifetime>)? {
447 Return = $ret:ty;
448 Handle = $handle:ty;
449 }
450 ) => {
451 impl$(<$life>)? $crate::cmd::SyncCmd for $name$(<$life>)? {
452 type Return = $ret;
453 type Handle = $handle;
454 type ReturnBuf = [u8; <$ret as $crate::ReadHci>::MAX_LEN];
455
456 fn param_handle(&self) -> Self::Handle {
457 self.handle()
458 }
459
460 fn return_handle(data: &[u8]) -> Result<Self::Handle, $crate::FromHciBytesError> {
461 <$handle as $crate::FromHciBytes>::from_hci_bytes(data).map(|(x, _)| x)
462 }
463 }
464 };
465 (
466 RETURN
467 $name:ident$(<$life:lifetime>)? {
468 Return = $ret:ty;
469 }
470 ) => {
471 impl$(<$life>)? $crate::cmd::SyncCmd for $name$(<$life>)? {
472 type Return = $ret;
473 type Handle = ();
474 type ReturnBuf = [u8; <$ret as $crate::ReadHci>::MAX_LEN];
475
476 fn param_handle(&self) {}
477
478 fn return_handle(_data: &[u8]) -> Result<Self::Handle, $crate::FromHciBytesError> {
479 Ok(())
480 }
481 }
482 };
483 (
484 RETURN
485 $name:ident$(<$life:lifetime>)? {
486 }
487 ) => {
488 impl$(<$life>)? $crate::cmd::AsyncCmd for $name$(<$life>)? {}
489 };
490}
491
492pub use cmd;