1use core::cell::RefCell;
2use core::ffi::CStr;
3use core::future::poll_fn;
4use core::marker::PhantomData;
5use core::mem::MaybeUninit;
6use core::sync::atomic::{AtomicBool, AtomicPtr, Ordering};
7use core::task::{Poll, Waker};
8
9use bt_hci::cmd::le::LeSetPeriodicAdvResponseData;
10use bt_hci::cmd::Cmd;
11use bt_hci::controller::blocking::TryError;
12use bt_hci::controller::{blocking, Controller};
13use bt_hci::event::EventParams;
14use bt_hci::{AsHciBytes, FixedSizeValue, FromHciBytes, WriteHci};
15use embassy_nrf::{peripherals, Peri};
16use embassy_sync::blocking_mutex::raw::NoopRawMutex;
17use embassy_sync::signal::Signal;
18use embassy_sync::waitqueue::AtomicWaker;
19use embedded_io::ErrorType;
20use nrf_mpsl::MultiprotocolServiceLayer;
21use rand_core::CryptoRng;
22use raw::{
23 sdc_cfg_adv_buffer_cfg_t, sdc_cfg_buffer_cfg_t, sdc_cfg_buffer_count_t, sdc_cfg_role_count_t, sdc_cfg_t,
24 SDC_CFG_TYPE_NONE, SDC_DEFAULT_RESOURCE_CFG_TAG,
25};
26
27use crate::{raw, Error, RetVal};
28
29static WAKER: AtomicWaker = AtomicWaker::new();
30static SDC_RNG: AtomicPtr<()> = AtomicPtr::new(core::ptr::null_mut());
31
32#[cfg(feature = "nrf52")]
46pub struct Peripherals<'d> {
47 pub ppi_ch17: Peri<'d, peripherals::PPI_CH17>,
49 pub ppi_ch18: Peri<'d, peripherals::PPI_CH18>,
51 pub ppi_ch20: Peri<'d, peripherals::PPI_CH20>,
53 pub ppi_ch21: Peri<'d, peripherals::PPI_CH21>,
55 pub ppi_ch22: Peri<'d, peripherals::PPI_CH22>,
57 pub ppi_ch23: Peri<'d, peripherals::PPI_CH23>,
59 pub ppi_ch24: Peri<'d, peripherals::PPI_CH24>,
61 pub ppi_ch25: Peri<'d, peripherals::PPI_CH25>,
63 pub ppi_ch26: Peri<'d, peripherals::PPI_CH26>,
65 pub ppi_ch27: Peri<'d, peripherals::PPI_CH27>,
67 pub ppi_ch28: Peri<'d, peripherals::PPI_CH28>,
69 pub ppi_ch29: Peri<'d, peripherals::PPI_CH29>,
71}
72#[cfg(feature = "nrf53")]
73pub struct Peripherals<'d> {
84 pub ppi_ch3: Peri<'d, peripherals::PPI_CH3>,
86 pub ppi_ch4: Peri<'d, peripherals::PPI_CH4>,
88 pub ppi_ch5: Peri<'d, peripherals::PPI_CH5>,
90 pub ppi_ch6: Peri<'d, peripherals::PPI_CH6>,
92 pub ppi_ch7: Peri<'d, peripherals::PPI_CH7>,
94 pub ppi_ch8: Peri<'d, peripherals::PPI_CH8>,
96 pub ppi_ch9: Peri<'d, peripherals::PPI_CH9>,
98 pub ppi_ch10: Peri<'d, peripherals::PPI_CH10>,
100 pub ppi_ch11: Peri<'d, peripherals::PPI_CH11>,
102 pub ppi_ch12: Peri<'d, peripherals::PPI_CH12>,
104}
105
106impl<'d> Peripherals<'d> {
107 #[allow(clippy::too_many_arguments)]
109 #[cfg(feature = "nrf52")]
110 pub fn new(
111 ppi_ch17: Peri<'d, peripherals::PPI_CH17>,
112 ppi_ch18: Peri<'d, peripherals::PPI_CH18>,
113 ppi_ch20: Peri<'d, peripherals::PPI_CH20>,
114 ppi_ch21: Peri<'d, peripherals::PPI_CH21>,
115 ppi_ch22: Peri<'d, peripherals::PPI_CH22>,
116 ppi_ch23: Peri<'d, peripherals::PPI_CH23>,
117 ppi_ch24: Peri<'d, peripherals::PPI_CH24>,
118 ppi_ch25: Peri<'d, peripherals::PPI_CH25>,
119 ppi_ch26: Peri<'d, peripherals::PPI_CH26>,
120 ppi_ch27: Peri<'d, peripherals::PPI_CH27>,
121 ppi_ch28: Peri<'d, peripherals::PPI_CH28>,
122 ppi_ch29: Peri<'d, peripherals::PPI_CH29>,
123 ) -> Self {
124 Peripherals {
125 ppi_ch17,
126 ppi_ch18,
127 ppi_ch20,
128 ppi_ch21,
129 ppi_ch22,
130 ppi_ch23,
131 ppi_ch24,
132 ppi_ch25,
133 ppi_ch26,
134 ppi_ch27,
135 ppi_ch28,
136 ppi_ch29,
137 }
138 }
139
140 #[allow(clippy::too_many_arguments)]
142 #[cfg(feature = "nrf53")]
143 pub fn new(
144 ppi_ch3: Peri<'d, peripherals::PPI_CH3>,
145 ppi_ch4: Peri<'d, peripherals::PPI_CH4>,
146 ppi_ch5: Peri<'d, peripherals::PPI_CH5>,
147 ppi_ch6: Peri<'d, peripherals::PPI_CH6>,
148 ppi_ch7: Peri<'d, peripherals::PPI_CH7>,
149 ppi_ch8: Peri<'d, peripherals::PPI_CH8>,
150 ppi_ch9: Peri<'d, peripherals::PPI_CH9>,
151 ppi_ch10: Peri<'d, peripherals::PPI_CH10>,
152 ppi_ch11: Peri<'d, peripherals::PPI_CH11>,
153 ppi_ch12: Peri<'d, peripherals::PPI_CH12>,
154 ) -> Self {
155 Peripherals {
156 ppi_ch3,
157 ppi_ch4,
158 ppi_ch5,
159 ppi_ch6,
160 ppi_ch7,
161 ppi_ch8,
162 ppi_ch9,
163 ppi_ch10,
164 ppi_ch11,
165 ppi_ch12,
166 }
167 }
168}
169
170unsafe extern "C" fn fault_handler(file: *const core::ffi::c_char, line: u32) {
171 panic!(
172 "SoftdeviceController: {}:{}",
173 unsafe { core::str::from_utf8_unchecked(CStr::from_ptr(file).to_bytes()) },
175 line
176 )
177}
178
179extern "C" fn sdc_callback() {
180 WAKER.wake()
181}
182
183unsafe extern "C" fn rand_blocking<R: CryptoRng + Send>(p_buff: *mut u8, length: u8) {
190 let rng = SDC_RNG.load(Ordering::Acquire) as *mut R;
191 if rng.is_null() {
192 panic!("rand_blocking called from Softdevice Controller when no rng is set");
193 }
194 let buf = core::slice::from_raw_parts_mut(p_buff, usize::from(length));
195 (*rng).fill_bytes(buf);
196}
197
198#[repr(align(8))]
202pub struct Mem<const N: usize>(MaybeUninit<[u8; N]>);
203
204impl<const N: usize> Mem<N> {
205 pub fn new() -> Self {
207 Self(MaybeUninit::uninit())
208 }
209}
210
211impl<const N: usize> Default for Mem<N> {
212 fn default() -> Self {
213 Self::new()
214 }
215}
216
217pub struct Builder {
219 _private: PhantomData<*mut ()>,
221}
222
223impl Builder {
224 pub fn new() -> Result<Self, Error> {
226 let ret = unsafe { raw::sdc_init(Some(fault_handler)) };
227 RetVal::from(ret).to_result().and(Ok(Builder { _private: PhantomData }))
228 }
229
230 pub fn central_count(self, count: u8) -> Result<Self, Error> {
232 self.cfg_set(
233 raw::SDC_CFG_TYPE_CENTRAL_COUNT,
234 sdc_cfg_t {
235 central_count: sdc_cfg_role_count_t { count },
236 },
237 )
238 }
239
240 pub fn peripheral_count(self, count: u8) -> Result<Self, Error> {
242 self.cfg_set(
243 raw::SDC_CFG_TYPE_PERIPHERAL_COUNT,
244 sdc_cfg_t {
245 peripheral_count: sdc_cfg_role_count_t { count },
246 },
247 )
248 }
249
250 pub fn buffer_cfg(
252 self,
253 tx_packet_size: u16,
254 rx_packet_size: u16,
255 tx_packet_count: u8,
256 rx_packet_count: u8,
257 ) -> Result<Self, Error> {
258 self.cfg_set(
259 raw::SDC_CFG_TYPE_BUFFER_CFG,
260 sdc_cfg_t {
261 buffer_cfg: sdc_cfg_buffer_cfg_t {
262 tx_packet_size,
263 rx_packet_size,
264 tx_packet_count,
265 rx_packet_count,
266 },
267 },
268 )
269 }
270
271 pub fn adv_count(self, count: u8) -> Result<Self, Error> {
273 self.cfg_set(
274 raw::SDC_CFG_TYPE_ADV_COUNT,
275 sdc_cfg_t {
276 adv_count: sdc_cfg_role_count_t { count },
277 },
278 )
279 }
280
281 pub fn scan_buffer_cfg(self, count: u8) -> Result<Self, Error> {
283 self.cfg_set(
284 raw::SDC_CFG_TYPE_SCAN_BUFFER_CFG,
285 sdc_cfg_t {
286 scan_buffer_cfg: sdc_cfg_buffer_count_t { count },
287 },
288 )
289 }
290
291 pub fn adv_buffer_cfg(self, max_adv_data: u16) -> Result<Self, Error> {
293 self.cfg_set(
294 raw::SDC_CFG_TYPE_ADV_BUFFER_CFG,
295 sdc_cfg_t {
296 adv_buffer_cfg: sdc_cfg_adv_buffer_cfg_t { max_adv_data },
297 },
298 )
299 }
300
301 pub fn periodic_adv_count(self, count: u8) -> Result<Self, Error> {
303 self.cfg_set(
304 raw::SDC_CFG_TYPE_PERIODIC_ADV_COUNT,
305 sdc_cfg_t {
306 periodic_adv_count: sdc_cfg_role_count_t { count },
307 },
308 )
309 }
310
311 pub fn periodic_sync_count(self, count: u8) -> Result<Self, Error> {
313 self.cfg_set(
314 raw::SDC_CFG_TYPE_PERIODIC_SYNC_COUNT,
315 sdc_cfg_t {
316 periodic_sync_count: sdc_cfg_role_count_t { count },
317 },
318 )
319 }
320
321 pub fn periodic_sync_buffer_cfg(self, count: u8) -> Result<Self, Error> {
323 self.cfg_set(
324 raw::SDC_CFG_TYPE_PERIODIC_SYNC_BUFFER_CFG,
325 sdc_cfg_t {
326 periodic_sync_buffer_cfg: sdc_cfg_buffer_count_t { count },
327 },
328 )
329 }
330
331 pub fn periodic_adv_list_len(self, len: u8) -> Result<Self, Error> {
333 self.cfg_set(
334 raw::SDC_CFG_TYPE_PERIODIC_ADV_LIST_SIZE,
335 sdc_cfg_t {
336 periodic_adv_list_size: len,
337 },
338 )
339 }
340
341 pub fn support_adv(self) -> Result<Self, Error> {
343 self.support(raw::sdc_support_adv)
344 }
345
346 pub fn support_ext_adv(self) -> Result<Self, Error> {
348 self.support(raw::sdc_support_ext_adv)
349 }
350
351 pub fn support_peripheral(self) -> Result<Self, Error> {
353 self.support(raw::sdc_support_peripheral)
354 }
355
356 pub fn support_scan(self) -> Result<Self, Error> {
358 self.support(raw::sdc_support_scan)
359 }
360
361 pub fn support_ext_scan(self) -> Result<Self, Error> {
363 self.support(raw::sdc_support_ext_scan)
364 }
365
366 pub fn support_central(self) -> Result<Self, Error> {
368 self.support(raw::sdc_support_central)
369 }
370
371 pub fn support_ext_central(self) -> Result<Self, Error> {
373 self.support(raw::sdc_support_ext_central)
374 }
375
376 pub fn support_dle_central(self) -> Result<Self, Error> {
378 self.support(raw::sdc_support_dle_central)
379 }
380
381 pub fn support_dle_peripheral(self) -> Result<Self, Error> {
383 self.support(raw::sdc_support_dle_peripheral)
384 }
385
386 pub fn support_le_2m_phy(self) -> Result<Self, Error> {
388 self.support(raw::sdc_support_le_2m_phy)
389 }
390
391 pub fn support_le_coded_phy(self) -> Result<Self, Error> {
393 self.support(raw::sdc_support_le_coded_phy)
394 }
395
396 pub fn support_phy_update_central(self) -> Result<Self, Error> {
398 self.support(raw::sdc_support_phy_update_central)
399 }
400
401 pub fn support_phy_update_peripheral(self) -> Result<Self, Error> {
403 self.support(raw::sdc_support_phy_update_peripheral)
404 }
405
406 pub fn support_le_periodic_adv(self) -> Result<Self, Error> {
408 self.support(raw::sdc_support_le_periodic_adv)
409 }
410
411 pub fn support_le_periodic_sync(self) -> Result<Self, Error> {
413 self.support(raw::sdc_support_le_periodic_sync)
414 }
415
416 pub fn support_le_power_control_central(self) -> Result<Self, Error> {
418 self.support(raw::sdc_support_le_power_control_central)
419 }
420
421 pub fn support_le_power_control_peripheral(self) -> Result<Self, Error> {
423 self.support(raw::sdc_support_le_power_control_peripheral)
424 }
425
426 pub fn support_sca_central(self) -> Result<Self, Error> {
428 self.support(raw::sdc_support_sca_central)
429 }
430
431 pub fn support_sca_peripheral(self) -> Result<Self, Error> {
433 self.support(raw::sdc_support_sca_peripheral)
434 }
435
436 pub fn support_le_conn_cte_rsp_central(self) -> Result<Self, Error> {
438 self.support(raw::sdc_support_le_conn_cte_rsp_central)
439 }
440
441 pub fn support_le_conn_cte_rsp_peripheral(self) -> Result<Self, Error> {
443 self.support(raw::sdc_support_le_conn_cte_rsp_peripheral)
444 }
445
446 pub fn support_periodic_adv_sync_transfer_sender_central(self) -> Result<Self, Error> {
448 self.support(raw::sdc_support_periodic_adv_sync_transfer_sender_central)
449 }
450
451 pub fn support_periodic_adv_sync_transfer_sender_peripheral(self) -> Result<Self, Error> {
453 self.support(raw::sdc_support_periodic_adv_sync_transfer_sender_peripheral)
454 }
455
456 pub fn support_periodic_adv_sync_transfer_receiver_central(self) -> Result<Self, Error> {
458 self.support(raw::sdc_support_periodic_adv_sync_transfer_receiver_central)
459 }
460
461 pub fn support_periodic_adv_sync_transfer_receiver_peripheral(self) -> Result<Self, Error> {
463 self.support(raw::sdc_support_periodic_adv_sync_transfer_receiver_peripheral)
464 }
465
466 pub fn support_qos_channel_survey(self) -> Result<Self, Error> {
468 self.support(raw::sdc_support_qos_channel_survey)
469 }
470
471 pub fn default_tx_power(self, dbm: i8) -> Result<Self, Error> {
473 RetVal::from(unsafe { raw::sdc_default_tx_power_set(dbm) })
474 .to_result()
475 .and(Ok(self))
476 }
477
478 pub fn required_memory(&self) -> Result<usize, Error> {
480 let ret = unsafe {
481 raw::sdc_cfg_set(
482 SDC_DEFAULT_RESOURCE_CFG_TAG as u8,
483 SDC_CFG_TYPE_NONE as u8,
484 core::ptr::null(),
485 )
486 };
487 RetVal::from(ret).to_result().map(|x| x as usize)
488 }
489
490 pub fn build<'d, R: CryptoRng + Send, const N: usize>(
496 self,
497 p: Peripherals<'d>,
498 rng: &'d mut R,
499 mpsl: &'d MultiprotocolServiceLayer,
500 mem: &'d mut Mem<N>,
501 ) -> Result<SoftdeviceController<'d>, Error> {
502 let _ = (p, mpsl);
504
505 let required = self.required_memory()?;
506 match N.cmp(&required) {
507 core::cmp::Ordering::Less => {
508 error!("Memory buffer too small. {} bytes needed.", required);
509 return Err(Error::EINVAL);
510 }
511 core::cmp::Ordering::Equal => (),
512 core::cmp::Ordering::Greater => {
513 warn!("Memory buffer too big. {} bytes needed", required);
514 }
515 }
516
517 unwrap!(
518 SDC_RNG.compare_exchange(
519 core::ptr::null_mut(),
520 rng as *mut _ as _,
521 Ordering::Release,
522 Ordering::Relaxed
523 ),
524 "SoftdeviceController already initialized!"
525 );
526 let rand_source = raw::sdc_rand_source_t {
527 rand_poll: Some(rand_blocking::<R>),
528 };
529 let ret = unsafe { raw::sdc_rand_source_register(&rand_source) };
530 RetVal::from(ret).to_result()?;
531
532 let ret = unsafe { raw::sdc_enable(Some(sdc_callback), mem.0.as_mut_ptr() as *mut _) };
533 RetVal::from(ret).to_result().and(Ok(SoftdeviceController {
534 using_ext_adv_cmds: Default::default(),
535 periodic_adv_response_data_in_progress: AtomicBool::new(false),
536 periodic_adv_response_data_complete: Signal::new(),
537 _private: PhantomData,
538 }))
539 }
540
541 #[inline]
542 fn support(self, f: unsafe extern "C" fn() -> i32) -> Result<Self, Error> {
543 RetVal::from(unsafe { f() }).to_result().and(Ok(self))
544 }
545
546 fn cfg_set(self, config_type: u32, value: sdc_cfg_t) -> Result<Self, Error> {
547 let ret = unsafe { raw::sdc_cfg_set(SDC_DEFAULT_RESOURCE_CFG_TAG as u8, config_type as u8, &value) };
548 RetVal::from(ret).to_result().and(Ok(self))
549 }
550}
551
552pub struct SoftdeviceController<'d> {
556 using_ext_adv_cmds: RefCell<Option<bool>>,
557 periodic_adv_response_data_in_progress: AtomicBool,
558 periodic_adv_response_data_complete: Signal<NoopRawMutex, (bt_hci::param::Status, bt_hci::param::SyncHandle)>,
559 _private: PhantomData<&'d *mut ()>,
561}
562
563impl Drop for SoftdeviceController<'_> {
564 fn drop(&mut self) {
565 unsafe { raw::sdc_disable() };
566 SDC_RNG.store(core::ptr::null_mut(), Ordering::Release);
567 }
568}
569
570#[inline(always)]
571unsafe fn bytes_of<T: Copy>(t: &T) -> &[u8] {
572 let len = core::mem::size_of::<T>();
573 core::slice::from_raw_parts(t as *const _ as *const u8, len)
574}
575
576impl<'d> SoftdeviceController<'d> {
577 pub fn build_revision() -> Result<[u8; raw::SDC_BUILD_REVISION_SIZE as usize], Error> {
579 let mut rev = [0; raw::SDC_BUILD_REVISION_SIZE as usize];
580 let ret = unsafe { raw::sdc_build_revision_get(rev.as_mut_ptr()) };
581 RetVal::from(ret).to_result().and(Ok(rev))
582 }
583
584 pub fn hci_data_put(&self, buf: &[u8]) -> Result<(), Error> {
586 assert!(buf.len() >= 4 && buf.len() >= 4 + usize::from(u16::from_le_bytes([buf[2], buf[3]])));
587 RetVal::from(unsafe { raw::sdc_hci_data_put(buf.as_ptr()) })
588 .to_result()
589 .and(Ok(()))
590 }
591
592 pub fn hci_iso_data_put(&self, buf: &[u8]) -> Result<(), Error> {
594 assert!(buf.len() >= 4 && buf.len() >= 4 + usize::from(u16::from_le_bytes([buf[2], buf[3]])));
595 RetVal::from(unsafe { raw::sdc_hci_iso_data_put(buf.as_ptr()) })
596 .to_result()
597 .and(Ok(()))
598 }
599
600 pub fn try_hci_get(&self, buf: &mut [u8]) -> Result<bt_hci::PacketKind, Error> {
602 assert!(buf.len() >= raw::HCI_MSG_BUFFER_MAX_SIZE as usize);
603 let mut msg_type: raw::sdc_hci_msg_type_t = 0;
604
605 let ret = unsafe { raw::sdc_hci_get(buf.as_mut_ptr(), (&mut msg_type) as *mut _ as *mut u8) };
606 RetVal::from(ret).to_result()?;
607 let kind = match msg_type {
608 raw::SDC_HCI_MSG_TYPE_DATA => bt_hci::PacketKind::AclData,
609 raw::SDC_HCI_MSG_TYPE_EVT => bt_hci::PacketKind::Event,
610 _ => unreachable!(),
611 };
612
613 if let bt_hci::PacketKind::Event = kind {
615 if let Ok((header, data)) = bt_hci::event::EventPacketHeader::from_hci_bytes(buf) {
616 if header.code == bt_hci::event::CommandComplete::EVENT_CODE {
617 if let Ok(event) =
618 bt_hci::event::CommandComplete::from_hci_bytes_complete(&data[..usize::from(header.params_len)])
619 {
620 if event.cmd_opcode == LeSetPeriodicAdvResponseData::OPCODE {
621 if let Ok(return_params) = event.return_params::<LeSetPeriodicAdvResponseData>() {
622 self.periodic_adv_response_data_complete
623 .signal((event.status, return_params));
624 return Err(Error::EAGAIN);
625 }
626 }
627 }
628 }
629 }
630 }
631
632 Ok(kind)
633 }
634
635 pub async fn hci_get(&self, buf: &mut [u8]) -> Result<bt_hci::PacketKind, Error> {
637 poll_fn(|ctx| match self.try_hci_get(buf) {
638 Err(Error::EAGAIN) => {
639 WAKER.register(ctx.waker());
640 Poll::Pending
641 }
642 res => Poll::Ready(res),
643 })
644 .await
645 }
646
647 pub fn register_waker(&self, waker: &Waker) {
649 WAKER.register(waker);
650 }
651
652 #[inline(always)]
653 unsafe fn raw_cmd(&self, f: unsafe extern "C" fn() -> u8) -> Result<(), bt_hci::param::Error> {
654 bt_hci::param::Status::from(f()).to_result()
655 }
656
657 #[inline(always)]
658 unsafe fn raw_cmd_params<P1: FixedSizeValue, P2: Copy>(
659 &self,
660 f: unsafe extern "C" fn(*const P2) -> u8,
661 params: &P1,
662 ) -> Result<(), bt_hci::param::Error> {
663 debug_assert_eq!(core::mem::size_of::<P1>(), core::mem::size_of::<P2>());
664 bt_hci::param::Status::from(f(params.as_hci_bytes().as_ptr() as *const _)).to_result()
665 }
666
667 #[inline(always)]
668 unsafe fn raw_cmd_return<R1: FixedSizeValue, R2: Copy>(
669 &self,
670 f: unsafe extern "C" fn(*mut R2) -> u8,
671 ) -> Result<R1, bt_hci::param::Error> {
672 debug_assert_eq!(core::mem::size_of::<R1>(), core::mem::size_of::<R2>());
673 let mut out = core::mem::zeroed();
674 bt_hci::param::Status::from(f(&mut out)).to_result()?;
675 Ok(unwrap!(R1::from_hci_bytes_complete(bytes_of(&out))))
676 }
677
678 #[inline(always)]
679 unsafe fn raw_cmd_params_return<P1: FixedSizeValue, R1: FixedSizeValue, P2: Copy, R2: Copy>(
680 &self,
681 f: unsafe extern "C" fn(*const P2, *mut R2) -> u8,
682 params: &P1,
683 ) -> Result<R1, bt_hci::param::Error> {
684 debug_assert_eq!(core::mem::size_of::<P1>(), core::mem::size_of::<P2>());
685 debug_assert_eq!(core::mem::size_of::<R1>(), core::mem::size_of::<R2>());
686
687 let mut out = core::mem::zeroed();
688 bt_hci::param::Status::from(f(params.as_hci_bytes().as_ptr() as *const _, &mut out)).to_result()?;
689 Ok(unwrap!(R1::from_hci_bytes_complete(bytes_of(&out))))
690 }
691
692 fn check_adv_cmd(&self, ext_adv: bool) -> Result<(), bt_hci::param::Error> {
693 let mut using_ext_adv = self.using_ext_adv_cmds.borrow_mut();
694 match *using_ext_adv {
695 None => {
696 *using_ext_adv = Some(ext_adv);
697 Ok(())
698 }
699 Some(x) if x == ext_adv => Ok(()),
700 _ => Err(bt_hci::param::Error::CMD_DISALLOWED),
701 }
702 }
703}
704
705impl ErrorType for SoftdeviceController<'_> {
706 type Error = Error;
707}
708
709impl<'a> Controller for SoftdeviceController<'a> {
710 async fn write_acl_data(&self, packet: &bt_hci::data::AclPacket<'_>) -> Result<(), Self::Error> {
711 let mut buf = [0u8; raw::HCI_DATA_PACKET_MAX_SIZE as usize];
712 packet.write_hci(buf.as_mut_slice()).map_err(|err| match err {
713 embedded_io::SliceWriteError::Full => Error::ENOMEM,
714 _ => unreachable!(),
715 })?;
716 self.hci_data_put(buf.as_slice())
717 }
718
719 async fn write_sync_data(&self, _packet: &bt_hci::data::SyncPacket<'_>) -> Result<(), Self::Error> {
720 unimplemented!()
721 }
722
723 async fn write_iso_data(&self, packet: &bt_hci::data::IsoPacket<'_>) -> Result<(), Self::Error> {
724 let mut buf = [0u8; raw::HCI_DATA_PACKET_MAX_SIZE as usize];
725 packet.write_hci(buf.as_mut_slice()).map_err(|err| match err {
726 embedded_io::SliceWriteError::Full => Error::ENOMEM,
727 _ => unreachable!(),
728 })?;
729 self.hci_iso_data_put(buf.as_slice())
730 }
731
732 async fn read<'b>(&self, buf: &'b mut [u8]) -> Result<bt_hci::ControllerToHostPacket<'b>, Self::Error> {
733 let kind = self.hci_get(buf).await?;
734 bt_hci::ControllerToHostPacket::from_hci_bytes_with_kind(kind, buf)
735 .map(|(x, _)| x)
736 .map_err(|err| match err {
737 bt_hci::FromHciBytesError::InvalidSize => Error::ENOMEM,
738 bt_hci::FromHciBytesError::InvalidValue => Error::EINVAL,
739 })
740 }
741}
742
743impl blocking::Controller for SoftdeviceController<'_> {
744 fn try_write_acl_data(&self, packet: &bt_hci::data::AclPacket<'_>) -> Result<(), blocking::TryError<Self::Error>> {
745 let mut buf = [0u8; raw::HCI_DATA_PACKET_MAX_SIZE as usize];
746 packet
747 .write_hci(buf.as_mut_slice())
748 .map_err(|err| match err {
749 embedded_io::SliceWriteError::Full => Error::ENOMEM,
750 _ => unreachable!(),
751 })
752 .map_err(into_try_err)?;
753 self.hci_data_put(buf.as_slice()).map_err(into_try_err)
754 }
755
756 fn try_write_sync_data(
757 &self,
758 _packet: &bt_hci::data::SyncPacket<'_>,
759 ) -> Result<(), blocking::TryError<Self::Error>> {
760 unimplemented!()
761 }
762
763 fn try_write_iso_data(&self, packet: &bt_hci::data::IsoPacket<'_>) -> Result<(), blocking::TryError<Self::Error>> {
764 let mut buf = [0u8; raw::HCI_DATA_PACKET_MAX_SIZE as usize];
765 packet
766 .write_hci(buf.as_mut_slice())
767 .map_err(|err| match err {
768 embedded_io::SliceWriteError::Full => Error::ENOMEM,
769 _ => unreachable!(),
770 })
771 .map_err(into_try_err)?;
772 self.hci_iso_data_put(buf.as_slice()).map_err(into_try_err)
773 }
774
775 fn try_read<'b>(
776 &self,
777 buf: &'b mut [u8],
778 ) -> Result<bt_hci::ControllerToHostPacket<'b>, blocking::TryError<Self::Error>> {
779 let kind = self.try_hci_get(buf).map_err(into_try_err)?;
780 bt_hci::ControllerToHostPacket::from_hci_bytes_with_kind(kind, buf)
781 .map(|(x, _)| x)
782 .map_err(|err| match err {
783 bt_hci::FromHciBytesError::InvalidSize => Error::ENOMEM,
784 bt_hci::FromHciBytesError::InvalidValue => Error::EINVAL,
785 })
786 .map_err(into_try_err)
787 }
788
789 fn write_acl_data(&self, packet: &bt_hci::data::AclPacket) -> Result<(), Self::Error> {
790 loop {
791 match self.try_write_acl_data(packet) {
792 Ok(v) => return Ok(v),
793 Err(TryError::Error(e)) => return Err(e),
794 Err(TryError::Busy) => {}
795 }
796 }
797 }
798
799 fn write_sync_data(&self, packet: &bt_hci::data::SyncPacket) -> Result<(), Self::Error> {
800 loop {
801 match self.try_write_sync_data(packet) {
802 Ok(v) => return Ok(v),
803 Err(TryError::Error(e)) => return Err(e),
804 Err(TryError::Busy) => {}
805 }
806 }
807 }
808
809 fn write_iso_data(&self, packet: &bt_hci::data::IsoPacket) -> Result<(), Self::Error> {
810 loop {
811 match self.try_write_iso_data(packet) {
812 Ok(v) => return Ok(v),
813 Err(TryError::Error(e)) => return Err(e),
814 Err(TryError::Busy) => {}
815 }
816 }
817 }
818
819 fn read<'b>(&self, buf: &'b mut [u8]) -> Result<bt_hci::ControllerToHostPacket<'b>, Self::Error> {
820 loop {
821 let buf = unsafe { core::slice::from_raw_parts_mut(buf.as_mut_ptr(), buf.len()) };
823 match self.try_read(buf) {
824 Ok(v) => return Ok(v),
825 Err(TryError::Error(e)) => return Err(e),
826 Err(TryError::Busy) => {}
827 }
828 }
829 }
830}
831
832fn into_try_err(e: Error) -> blocking::TryError<Error> {
833 match e {
834 Error::EAGAIN => blocking::TryError::Busy,
835 other => blocking::TryError::Error(other),
836 }
837}
838
839macro_rules! sdc_cmd {
840 (async $cmd:ty => $raw:ident()) => {
841 sdc_cmd!(async $cmd => raw_cmd($raw));
842 };
843
844 (async $cmd:ty => $raw:ident(x)) => {
845 sdc_cmd!(async $cmd => raw_cmd_params($raw, $cmd));
846 };
847
848 (async $cmd:ty => $method:ident($raw:ident$(, $params:ty)?) $($ext_adv:literal)?) => {
849 #[automatically_derived]
850 #[allow(unused_variables)]
851 impl<'d> bt_hci::controller::ControllerCmdAsync<$cmd> for $crate::sdc::SoftdeviceController<'d> {
852 async fn exec(&self, cmd: &$cmd) -> Result<(), bt_hci::cmd::Error<Self::Error>> {
853 $(self.check_adv_cmd($ext_adv)?;)?
854 unsafe { self.$method(raw::$raw$(, <$params as bt_hci::cmd::Cmd>::params(cmd))?) }.map_err(bt_hci::cmd::Error::Hci)
855 }
856 }
857 };
858
859 ($cmd:ty => $raw:ident()) => {
860 sdc_cmd!($cmd => raw_cmd($raw));
861 };
862
863 ($cmd:ty => $raw:ident(x)) => {
864 sdc_cmd!($cmd => raw_cmd_params($raw, $cmd));
865 };
866
867 ($cmd:ty => $raw:ident() -> y) => {
868 sdc_cmd!($cmd => raw_cmd_return($raw));
869 };
870
871 ($cmd:ty => $raw:ident(x) -> y) => {
872 sdc_cmd!($cmd => raw_cmd_params_return($raw, $cmd));
873 };
874
875 ($cmd:ty => $method:ident($raw:ident$(, $params:ty)*) $($ext_adv:literal)?) => {
876 #[automatically_derived]
877 #[allow(unused_variables)]
878 impl<'d> bt_hci::controller::ControllerCmdSync<$cmd> for $crate::sdc::SoftdeviceController<'d> {
879 async fn exec(&self, cmd: &$cmd) -> Result<<$cmd as bt_hci::cmd::SyncCmd>::Return, bt_hci::cmd::Error<Self::Error>> {
880 $(self.check_adv_cmd($ext_adv)?;)?
881 let ret = unsafe { self.$method(raw::$raw$(, <$params as bt_hci::cmd::Cmd>::params(cmd))?) }?;
882 Ok(ret)
883 }
884 }
885 };
886}
887
888mod link_control {
890 use bt_hci::cmd::link_control::*;
891
892 use crate::raw;
893
894 sdc_cmd!(Disconnect => sdc_hci_cmd_lc_disconnect(x));
895 sdc_cmd!(async ReadRemoteVersionInformation => sdc_hci_cmd_lc_read_remote_version_information(x));
896}
897
898mod controller_baseband {
900 use bt_hci::cmd::controller_baseband::*;
901 use bt_hci::cmd::{Cmd, Error as CmdError};
902 use bt_hci::controller::ControllerCmdSync;
903 use bt_hci::param::ConnHandleCompletedPackets;
904 use bt_hci::WriteHci;
905
906 use crate::raw;
907
908 impl<'d> ControllerCmdSync<Reset> for super::SoftdeviceController<'d> {
909 async fn exec(&self, _cmd: &Reset) -> Result<<Reset as bt_hci::cmd::SyncCmd>::Return, CmdError<Self::Error>> {
910 *self.using_ext_adv_cmds.borrow_mut() = None;
911 unsafe { self.raw_cmd(raw::sdc_hci_cmd_cb_reset) }.map_err(bt_hci::cmd::Error::Hci)
912 }
913 }
914
915 sdc_cmd!(SetEventMask => sdc_hci_cmd_cb_set_event_mask(x));
916 sdc_cmd!(ReadTransmitPowerLevel => sdc_hci_cmd_cb_read_transmit_power_level(x) -> y);
917 sdc_cmd!(SetControllerToHostFlowControl => sdc_hci_cmd_cb_set_controller_to_host_flow_control(x));
918 sdc_cmd!(HostBufferSize => sdc_hci_cmd_cb_host_buffer_size(x));
919 sdc_cmd!(SetEventMaskPage2 => sdc_hci_cmd_cb_set_event_mask_page_2(x));
920 sdc_cmd!(ReadAuthenticatedPayloadTimeout => sdc_hci_cmd_cb_read_authenticated_payload_timeout(x) -> y);
921 sdc_cmd!(WriteAuthenticatedPayloadTimeout => sdc_hci_cmd_cb_write_authenticated_payload_timeout(x) -> y);
922
923 impl<'a, 'd> ControllerCmdSync<HostNumberOfCompletedPackets<'a>> for super::SoftdeviceController<'d> {
924 async fn exec(
925 &self,
926 cmd: &HostNumberOfCompletedPackets<'a>,
927 ) -> Result<<HostNumberOfCompletedPackets<'a> as bt_hci::cmd::SyncCmd>::Return, CmdError<Self::Error>> {
928 const MAX_CONN_HANDLES: usize = 63;
929 const N: usize = 1 + MAX_CONN_HANDLES + core::mem::size_of::<ConnHandleCompletedPackets>();
930 let mut buf = [0; N];
931 unwrap!(cmd.params().write_hci(buf.as_mut_slice()));
932 let ret = unsafe { raw::sdc_hci_cmd_cb_host_number_of_completed_packets(buf.as_ptr() as *const _) };
933 bt_hci::param::Status::from(ret).to_result().map_err(CmdError::Hci)
934 }
935 }
936}
937
938mod info {
940 use bt_hci::cmd::info::*;
941
942 use crate::raw;
943
944 sdc_cmd!(ReadLocalVersionInformation => sdc_hci_cmd_ip_read_local_version_information() -> y);
945 sdc_cmd!(ReadLocalSupportedCmds => sdc_hci_cmd_ip_read_local_supported_commands() -> y);
946 sdc_cmd!(ReadLocalSupportedFeatures => sdc_hci_cmd_ip_read_local_supported_features() -> y);
947 sdc_cmd!(ReadBdAddr => sdc_hci_cmd_ip_read_bd_addr() -> y);
948}
949
950mod status {
952 use bt_hci::cmd::status::*;
953
954 use crate::raw;
955
956 sdc_cmd!(ReadRssi => sdc_hci_cmd_sp_read_rssi(x) -> y);
957}
958
959mod le {
961 use core::sync::atomic::Ordering;
962
963 use bt_hci::cmd::le::*;
964 use bt_hci::cmd::{Cmd, Error as CmdError};
965 use bt_hci::controller::{ControllerCmdAsync, ControllerCmdSync};
966 use bt_hci::param::{AdvHandle, AdvSet, ConnHandle, InitiatingPhy, ScanningPhy, SyncHandle};
967 use bt_hci::{FromHciBytes, WriteHci};
968
969 use crate::raw;
970
971 const MAX_PHY_COUNT: usize = 3;
972 const MAX_ADV_SET: usize = 63;
973 const MAX_ANTENNA_IDS: usize = 75;
974 const MAX_SUBEVENTS: usize = 128;
975
976 sdc_cmd!(LeSetAdvParams => raw_cmd_params(sdc_hci_cmd_le_set_adv_params, LeSetAdvParams) false);
978 sdc_cmd!(LeReadAdvPhysicalChannelTxPower => raw_cmd_return(sdc_hci_cmd_le_read_adv_physical_channel_tx_power) false);
979 sdc_cmd!(LeSetAdvData => raw_cmd_params(sdc_hci_cmd_le_set_adv_data, LeSetAdvData) false);
980 sdc_cmd!(LeSetScanResponseData => raw_cmd_params(sdc_hci_cmd_le_set_scan_response_data, LeSetScanResponseData) false);
981 sdc_cmd!(LeSetAdvEnable => raw_cmd_params(sdc_hci_cmd_le_set_adv_enable, LeSetAdvEnable) false);
982 sdc_cmd!(LeSetScanParams => raw_cmd_params(sdc_hci_cmd_le_set_scan_params, LeSetScanParams) false);
983 sdc_cmd!(LeSetScanEnable => raw_cmd_params(sdc_hci_cmd_le_set_scan_enable, LeSetScanEnable) false);
984 sdc_cmd!(async LeCreateConn => raw_cmd_params(sdc_hci_cmd_le_create_conn, LeCreateConn) false);
985
986 sdc_cmd!(LeSetExtAdvParams => raw_cmd_params_return(sdc_hci_cmd_le_set_ext_adv_params, LeSetExtAdvParams) true);
988 sdc_cmd!(LeSetExtAdvParamsV2 => raw_cmd_params_return(sdc_hci_cmd_le_set_ext_adv_params_v2, LeSetExtAdvParamsV2) true);
989 sdc_cmd!(LeReadMaxAdvDataLength => raw_cmd_return(sdc_hci_cmd_le_read_max_adv_data_length) true);
990 sdc_cmd!(LeReadNumberOfSupportedAdvSets => raw_cmd_return(sdc_hci_cmd_le_read_number_of_supported_adv_sets) true);
991 sdc_cmd!(LeRemoveAdvSet => raw_cmd_params(sdc_hci_cmd_le_remove_adv_set, LeRemoveAdvSet) true);
992 sdc_cmd!(LeClearAdvSets => raw_cmd(sdc_hci_cmd_le_clear_adv_sets) true);
993 sdc_cmd!(LeSetPeriodicAdvParams => raw_cmd_params(sdc_hci_cmd_le_set_periodic_adv_params, LeSetPeriodicAdvParams) true);
994 sdc_cmd!(LeSetPeriodicAdvParamsV2 => raw_cmd_params_return(sdc_hci_cmd_le_set_periodic_adv_params_v2, LeSetPeriodicAdvParamsV2) true);
995 sdc_cmd!(LeSetPeriodicAdvEnable => raw_cmd_params(sdc_hci_cmd_le_set_periodic_adv_enable, LeSetPeriodicAdvEnable) true);
996 sdc_cmd!(LeSetExtScanEnable => raw_cmd_params(sdc_hci_cmd_le_set_ext_scan_enable, LeSetExtScanEnable) true);
997 sdc_cmd!(async LePeriodicAdvCreateSync => raw_cmd_params(sdc_hci_cmd_le_periodic_adv_create_sync, LePeriodicAdvCreateSync) true);
998 sdc_cmd!(LePeriodicAdvCreateSyncCancel => raw_cmd(sdc_hci_cmd_le_periodic_adv_create_sync_cancel) true);
999 sdc_cmd!(LePeriodicAdvTerminateSync => raw_cmd_params(sdc_hci_cmd_le_periodic_adv_terminate_sync, LePeriodicAdvTerminateSync) true);
1000 sdc_cmd!(LeAddDeviceToPeriodicAdvList => raw_cmd_params(sdc_hci_cmd_le_add_device_to_periodic_adv_list, LeAddDeviceToPeriodicAdvList) true);
1001 sdc_cmd!(LeRemoveDeviceFromPeriodicAdvList => raw_cmd_params(sdc_hci_cmd_le_remove_device_from_periodic_adv_list, LeRemoveDeviceFromPeriodicAdvList) true);
1002 sdc_cmd!(LeClearPeriodicAdvList => raw_cmd(sdc_hci_cmd_le_clear_periodic_adv_list) true);
1003 sdc_cmd!(LeReadPeriodicAdvListSize => raw_cmd_return(sdc_hci_cmd_le_read_periodic_adv_list_size) true);
1004 sdc_cmd!(LeSetPeriodicAdvSyncTransferParams => raw_cmd_params_return(sdc_hci_cmd_le_set_periodic_adv_sync_transfer_params, LeSetPeriodicAdvSyncTransferParams) true);
1005 sdc_cmd!(LeSetDefaultPeriodicAdvSyncTransferParams => raw_cmd_params(sdc_hci_cmd_le_set_default_periodic_adv_sync_transfer_params, LeSetDefaultPeriodicAdvSyncTransferParams) true);
1006
1007 sdc_cmd!(LeSetEventMask => sdc_hci_cmd_le_set_event_mask(x));
1008 sdc_cmd!(LeReadBufferSize => sdc_hci_cmd_le_read_buffer_size() -> y);
1009 sdc_cmd!(LeReadLocalSupportedFeatures => sdc_hci_cmd_le_read_local_supported_features() -> y);
1010 sdc_cmd!(LeSetRandomAddr => sdc_hci_cmd_le_set_random_address(x));
1011 sdc_cmd!(LeCreateConnCancel => sdc_hci_cmd_le_create_conn_cancel());
1012 sdc_cmd!(LeReadFilterAcceptListSize => sdc_hci_cmd_le_read_filter_accept_list_size() -> y);
1013 sdc_cmd!(LeClearFilterAcceptList => sdc_hci_cmd_le_clear_filter_accept_list());
1014 sdc_cmd!(LeAddDeviceToFilterAcceptList => sdc_hci_cmd_le_add_device_to_filter_accept_list(x));
1015 sdc_cmd!(LeRemoveDeviceFromFilterAcceptList => sdc_hci_cmd_le_remove_device_from_filter_accept_list(x));
1016 sdc_cmd!(async LeConnUpdate => sdc_hci_cmd_le_conn_update(x));
1017 sdc_cmd!(LeSetHostChannelClassification => sdc_hci_cmd_le_set_host_channel_classification(x));
1018 sdc_cmd!(LeReadChannelMap => sdc_hci_cmd_le_read_channel_map(x) -> y);
1019 sdc_cmd!(async LeReadRemoteFeatures => sdc_hci_cmd_le_read_remote_features(x));
1020 sdc_cmd!(LeEncrypt => sdc_hci_cmd_le_encrypt(x) -> y);
1021 sdc_cmd!(LeRand => sdc_hci_cmd_le_rand() -> y);
1022 sdc_cmd!(async LeEnableEncryption => sdc_hci_cmd_le_enable_encryption(x));
1023 sdc_cmd!(LeLongTermKeyRequestReply => sdc_hci_cmd_le_long_term_key_request_reply(x) -> y);
1024 sdc_cmd!(LeLongTermKeyRequestNegativeReply => sdc_hci_cmd_le_long_term_key_request_negative_reply(x) -> y);
1025 sdc_cmd!(LeReadSupportedStates => sdc_hci_cmd_le_read_supported_states() -> y);
1026 sdc_cmd!(LeTestEnd => sdc_hci_cmd_le_test_end() -> y);
1027 sdc_cmd!(LeSetDataLength => sdc_hci_cmd_le_set_data_length(x) -> y);
1028 sdc_cmd!(LeReadSuggestedDefaultDataLength => sdc_hci_cmd_le_read_suggested_default_data_length() -> y);
1029 sdc_cmd!(LeWriteSuggestedDefaultDataLength => sdc_hci_cmd_le_write_suggested_default_data_length(x));
1030 sdc_cmd!(LeAddDeviceToResolvingList => sdc_hci_cmd_le_add_device_to_resolving_list(x));
1031 sdc_cmd!(LeRemoveDeviceFromResolvingList => sdc_hci_cmd_le_remove_device_from_resolving_list(x));
1032 sdc_cmd!(LeClearResolvingList => sdc_hci_cmd_le_clear_resolving_list());
1033 sdc_cmd!(LeReadResolvingListSize => sdc_hci_cmd_le_read_resolving_list_size() -> y);
1034 sdc_cmd!(LeSetAddrResolutionEnable => sdc_hci_cmd_le_set_address_resolution_enable(x));
1035 sdc_cmd!(LeSetResolvablePrivateAddrTimeout => sdc_hci_cmd_le_set_resolvable_private_address_timeout(x));
1036 sdc_cmd!(LeReadMaxDataLength => sdc_hci_cmd_le_read_max_data_length() -> y);
1037 sdc_cmd!(LeReadPhy => sdc_hci_cmd_le_read_phy(x) -> y);
1038 sdc_cmd!(LeSetDefaultPhy => sdc_hci_cmd_le_set_default_phy(x));
1039 sdc_cmd!(async LeSetPhy => sdc_hci_cmd_le_set_phy(x));
1040 sdc_cmd!(LeSetAdvSetRandomAddr => sdc_hci_cmd_le_set_adv_set_random_address(x));
1041 sdc_cmd!(LeReadTransmitPower => sdc_hci_cmd_le_read_transmit_power() -> y);
1042 sdc_cmd!(LeReadRfPathCompensation => sdc_hci_cmd_le_read_rf_path_compensation() -> y);
1043 sdc_cmd!(LeWriteRfPathCompensation => sdc_hci_cmd_le_write_rf_path_compensation(x));
1044 sdc_cmd!(LeSetPrivacyMode => sdc_hci_cmd_le_set_privacy_mode(x));
1045 sdc_cmd!(LeSetConnectionlessCteTransmitEnable => sdc_hci_cmd_le_set_connless_cte_transmit_enable(x));
1046 sdc_cmd!(LeConnCteResponseEnable => sdc_hci_cmd_le_conn_cte_response_enable(x) -> y);
1047 sdc_cmd!(LeReadAntennaInformation => sdc_hci_cmd_le_read_antenna_information() -> y);
1048 sdc_cmd!(LeSetPeriodicAdvReceiveEnable => sdc_hci_cmd_le_set_periodic_adv_receive_enable(x));
1049 sdc_cmd!(LePeriodicAdvSyncTransfer => sdc_hci_cmd_le_periodic_adv_sync_transfer(x) -> y);
1050 sdc_cmd!(LePeriodicAdvSetInfoTransfer => sdc_hci_cmd_le_periodic_adv_set_info_transfer(x) -> y);
1051 sdc_cmd!(async LeRequestPeerSca => sdc_hci_cmd_le_request_peer_sca(x));
1052 sdc_cmd!(LeEnhancedReadTransmitPowerLevel => sdc_hci_cmd_le_enhanced_read_transmit_power_level(x) -> y);
1053 sdc_cmd!(async LeReadRemoteTransmitPowerLevel => sdc_hci_cmd_le_read_remote_transmit_power_level(x));
1054 sdc_cmd!(LeSetPathLossReportingParams => sdc_hci_cmd_le_set_path_loss_reporting_params(x) -> y);
1055 sdc_cmd!(LeSetPathLossReportingEnable => sdc_hci_cmd_le_set_path_loss_reporting_enable(x) -> y);
1056 sdc_cmd!(LeSetTransmitPowerReportingEnable => sdc_hci_cmd_le_set_transmit_power_reporting_enable(x) -> y);
1057 sdc_cmd!(LeSetDataRelatedAddrChanges => sdc_hci_cmd_le_set_data_related_address_changes(x));
1058 sdc_cmd!(LeSetHostFeature => sdc_hci_cmd_le_set_host_feature(x));
1059 sdc_cmd!(LeSetHostFeatureV2 => sdc_hci_cmd_le_set_host_feature_v2(x));
1060
1061 impl<'a, 'd> ControllerCmdSync<LeSetExtAdvData<'a>> for super::SoftdeviceController<'d> {
1062 async fn exec(&self, cmd: &LeSetExtAdvData<'a>) -> Result<(), CmdError<nrf_mpsl::Error>> {
1063 self.check_adv_cmd(true)?;
1064 const N: usize = 4 + 251;
1065 let mut buf = [0; N];
1066 unwrap!(cmd.params().write_hci(buf.as_mut_slice()));
1067 let ret = unsafe { raw::sdc_hci_cmd_le_set_ext_adv_data(buf.as_ptr() as *const _) };
1068 bt_hci::param::Status::from(ret).to_result().map_err(CmdError::Hci)
1069 }
1070 }
1071
1072 impl<'a, 'd> ControllerCmdSync<LeSetExtScanResponseData<'a>> for super::SoftdeviceController<'d> {
1073 async fn exec(&self, cmd: &LeSetExtScanResponseData<'a>) -> Result<(), CmdError<nrf_mpsl::Error>> {
1074 self.check_adv_cmd(true)?;
1075 const N: usize = 4 + 251;
1076 let mut buf = [0; N];
1077 unwrap!(cmd.params().write_hci(buf.as_mut_slice()));
1078 let ret = unsafe { raw::sdc_hci_cmd_le_set_ext_scan_response_data(buf.as_ptr() as *const _) };
1079 bt_hci::param::Status::from(ret).to_result().map_err(CmdError::Hci)
1080 }
1081 }
1082
1083 impl<'a, 'd> ControllerCmdSync<LeSetExtAdvEnable<'a>> for super::SoftdeviceController<'d> {
1084 async fn exec(&self, cmd: &LeSetExtAdvEnable<'a>) -> Result<(), CmdError<nrf_mpsl::Error>> {
1085 self.check_adv_cmd(true)?;
1086 const N: usize = 2 + MAX_ADV_SET * core::mem::size_of::<AdvSet>();
1087 let mut buf = [0; N];
1088 unwrap!(cmd.params().write_hci(buf.as_mut_slice()));
1089 let ret = unsafe { raw::sdc_hci_cmd_le_set_ext_adv_enable(buf.as_ptr() as *const _) };
1090 bt_hci::param::Status::from(ret).to_result().map_err(CmdError::Hci)
1091 }
1092 }
1093
1094 impl<'a, 'd> ControllerCmdSync<LeSetPeriodicAdvData<'a>> for super::SoftdeviceController<'d> {
1095 async fn exec(&self, cmd: &LeSetPeriodicAdvData<'a>) -> Result<(), CmdError<nrf_mpsl::Error>> {
1096 self.check_adv_cmd(true)?;
1097 const N: usize = 3 + 252;
1098 let mut buf = [0; N];
1099 unwrap!(cmd.params().write_hci(buf.as_mut_slice()));
1100 let ret = unsafe { raw::sdc_hci_cmd_le_set_periodic_adv_data(buf.as_ptr() as *const _) };
1101 bt_hci::param::Status::from(ret).to_result().map_err(CmdError::Hci)
1102 }
1103 }
1104
1105 impl<'d> ControllerCmdSync<LeSetExtScanParams> for super::SoftdeviceController<'d> {
1106 async fn exec(&self, cmd: &LeSetExtScanParams) -> Result<(), CmdError<nrf_mpsl::Error>> {
1107 self.check_adv_cmd(true)?;
1108 const N: usize = 3 + MAX_PHY_COUNT * core::mem::size_of::<ScanningPhy>();
1109 let mut buf = [0; N];
1110 unwrap!(cmd.params().write_hci(buf.as_mut_slice()));
1111 let ret = unsafe { raw::sdc_hci_cmd_le_set_ext_scan_params(buf.as_ptr() as *const _) };
1112 bt_hci::param::Status::from(ret).to_result().map_err(CmdError::Hci)
1113 }
1114 }
1115
1116 impl<'d> ControllerCmdAsync<LeExtCreateConn> for super::SoftdeviceController<'d> {
1117 async fn exec(&self, cmd: &LeExtCreateConn) -> Result<(), CmdError<nrf_mpsl::Error>> {
1118 self.check_adv_cmd(true)?;
1119 const N: usize = 10 + MAX_PHY_COUNT * core::mem::size_of::<InitiatingPhy>();
1120 let mut buf = [0; N];
1121 unwrap!(cmd.params().write_hci(buf.as_mut_slice()));
1122 let ret = unsafe { raw::sdc_hci_cmd_le_ext_create_conn(buf.as_ptr() as *const _) };
1123 bt_hci::param::Status::from(ret).to_result().map_err(CmdError::Hci)
1124 }
1125 }
1126
1127 impl<'a, 'd> ControllerCmdSync<LeSetConnectionlessCteTransmitParams<'a>> for super::SoftdeviceController<'d> {
1128 async fn exec(&self, cmd: &LeSetConnectionlessCteTransmitParams<'a>) -> Result<(), CmdError<nrf_mpsl::Error>> {
1129 const N: usize = 5 + MAX_ANTENNA_IDS;
1130 let mut buf = [0; N];
1131 unwrap!(cmd.params().write_hci(buf.as_mut_slice()));
1132 let ret = unsafe { raw::sdc_hci_cmd_le_set_connless_cte_transmit_params(buf.as_ptr() as *const _) };
1133 bt_hci::param::Status::from(ret).to_result().map_err(CmdError::Hci)
1134 }
1135 }
1136
1137 impl<'a, 'd> ControllerCmdSync<LeSetConnCteTransmitParams<'a>> for super::SoftdeviceController<'d> {
1138 async fn exec(&self, cmd: &LeSetConnCteTransmitParams<'a>) -> Result<ConnHandle, CmdError<nrf_mpsl::Error>> {
1139 const N: usize = 5 + MAX_ANTENNA_IDS;
1140 let mut buf = [0; N];
1141 unwrap!(cmd.params().write_hci(buf.as_mut_slice()));
1142
1143 let mut out = unsafe { core::mem::zeroed() };
1144 let ret = unsafe { raw::sdc_hci_cmd_le_set_conn_cte_transmit_params(buf.as_ptr() as *const _, &mut out) };
1145
1146 bt_hci::param::Status::from(ret).to_result()?;
1147 Ok(unwrap!(ConnHandle::from_hci_bytes_complete(unsafe {
1148 super::bytes_of(&out)
1149 })))
1150 }
1151 }
1152
1153 impl<'d> ControllerCmdAsync<LeExtCreateConnV2> for super::SoftdeviceController<'d> {
1154 async fn exec(&self, cmd: &LeExtCreateConnV2) -> Result<(), CmdError<nrf_mpsl::Error>> {
1155 self.check_adv_cmd(true)?;
1156 const N: usize = 12 + MAX_PHY_COUNT * 16;
1157 let mut buf = [0; N];
1158 unwrap!(cmd.params().write_hci(buf.as_mut_slice()));
1159
1160 let ret = unsafe { raw::sdc_hci_cmd_le_ext_create_conn_v2(buf.as_ptr() as *const _) };
1161 bt_hci::param::Status::from(ret).to_result().map_err(CmdError::Hci)
1162 }
1163 }
1164
1165 impl<'a, 'd> ControllerCmdSync<LeSetPeriodicAdvSubeventData<'a>> for super::SoftdeviceController<'d> {
1166 async fn exec(&self, cmd: &LeSetPeriodicAdvSubeventData<'a>) -> Result<AdvHandle, CmdError<nrf_mpsl::Error>> {
1167 self.check_adv_cmd(true)?;
1168 const N: usize = raw::HCI_CMD_MAX_SIZE as usize;
1169 let mut buf = [0; N];
1170 unwrap!(cmd.params().write_hci(buf.as_mut_slice()));
1171
1172 let mut out = unsafe { core::mem::zeroed() };
1173 let ret = unsafe { raw::sdc_hci_cmd_le_set_periodic_adv_subevent_data(buf.as_ptr() as *const _, &mut out) };
1174
1175 bt_hci::param::Status::from(ret).to_result()?;
1176 Ok(unwrap!(AdvHandle::from_hci_bytes_complete(unsafe {
1177 super::bytes_of(&out)
1178 })))
1179 }
1180 }
1181
1182 impl<'a, 'd> ControllerCmdSync<LeSetPeriodicAdvResponseData<'a>> for super::SoftdeviceController<'d> {
1183 async fn exec(&self, cmd: &LeSetPeriodicAdvResponseData<'a>) -> Result<SyncHandle, CmdError<nrf_mpsl::Error>> {
1184 if self
1185 .periodic_adv_response_data_in_progress
1186 .swap(true, Ordering::Relaxed)
1187 {
1188 return Err(CmdError::Hci(bt_hci::param::Error::CONTROLLER_BUSY));
1189 }
1190
1191 self.check_adv_cmd(true)?;
1192 const N: usize = raw::HCI_CMD_MAX_SIZE as usize;
1193 let mut buf = [0; N];
1194 unwrap!(cmd.params().write_hci(buf.as_mut_slice()));
1195
1196 let mut out = unsafe { core::mem::zeroed() };
1197 let ret = unsafe { raw::sdc_hci_cmd_le_set_periodic_adv_response_data(buf.as_ptr() as *const _, &mut out) };
1198 bt_hci::param::Status::from(ret).to_result()?;
1199
1200 let (status, handle) = self.periodic_adv_response_data_complete.wait().await;
1202 self.periodic_adv_response_data_in_progress
1203 .store(false, Ordering::Relaxed);
1204
1205 status.to_result().map(|_| handle).map_err(CmdError::Hci)
1206 }
1207 }
1208
1209 impl<'a, 'd> ControllerCmdSync<LeSetPeriodicSyncSubevent<'a>> for super::SoftdeviceController<'d> {
1210 async fn exec(&self, cmd: &LeSetPeriodicSyncSubevent<'a>) -> Result<SyncHandle, CmdError<nrf_mpsl::Error>> {
1211 self.check_adv_cmd(true)?;
1212 const N: usize = 5 + MAX_SUBEVENTS;
1213 let mut buf = [0; N];
1214 unwrap!(cmd.params().write_hci(buf.as_mut_slice()));
1215
1216 let mut out = unsafe { core::mem::zeroed() };
1217 let ret = unsafe { raw::sdc_hci_cmd_le_set_periodic_sync_subevent(buf.as_ptr() as *const _, &mut out) };
1218
1219 bt_hci::param::Status::from(ret).to_result()?;
1220 Ok(unwrap!(SyncHandle::from_hci_bytes_complete(unsafe {
1221 super::bytes_of(&out)
1222 })))
1223 }
1224 }
1225}
1226
1227pub mod vendor {
1229 #![allow(missing_docs)]
1230 use bt_hci::cmd::Error as CmdError;
1231 use bt_hci::controller::ControllerCmdSync;
1232 use bt_hci::param::{BdAddr, ChannelMap, ConnHandle, Duration};
1233 use bt_hci::{cmd, param, FromHciBytes};
1234
1235 use crate::raw;
1236
1237 param!(
1238 struct ZephyrStaticAddr {
1239 addr: BdAddr,
1240 identity_root: [u8; 16],
1241 }
1242 );
1243
1244 param!(
1245 struct ZephyrTxPower {
1246 handle_type: u8,
1247 handle: u16,
1248 selected_tx_power: i8,
1249 }
1250 );
1251
1252 cmd! {
1253 ZephyrReadVersionInfo(VENDOR_SPECIFIC, 0x0001) {
1255 Params = ();
1256 ZephyrReadVersionInfoReturn {
1257 hw_platform: u16,
1258 hw_variant: u16,
1259 fw_variant: u8,
1260 fw_version: u8,
1261 fw_revision: u16,
1262 fw_build: u32,
1263 }
1264 }
1265 }
1266
1267 cmd! {
1268 ZephyrReadSupportedCommands(VENDOR_SPECIFIC, 0x0002) {
1270 Params = ();
1271 Return = [u8; 64];
1272 }
1273 }
1274
1275 cmd! {
1276 ZephyrWriteBdAddr(VENDOR_SPECIFIC, 0x0006) {
1278 Params = BdAddr;
1279 Return = ();
1280 }
1281 }
1282
1283 cmd! {
1284 ZephyrReadStaticAddrs(VENDOR_SPECIFIC, 0x0009) {
1286 Params = ();
1287 ZephyrReadStaticAddrsReturn {
1288 num_addresses: u8,
1289 addr: ZephyrStaticAddr, }
1291 }
1292 }
1293
1294 cmd! {
1295 ZephyrReadKeyHierarchyRoots(VENDOR_SPECIFIC, 0x000a) {
1297 Params = ();
1298 ZephyrReadKeyHierarchyRootsReturn {
1299 ir: [u8; 16usize],
1300 er: [u8; 16usize],
1301 }
1302 }
1303 }
1304
1305 cmd! {
1306 ZephyrReadChipTemp(VENDOR_SPECIFIC, 0x000b) {
1308 Params = ();
1309 Return = i8;
1310 }
1311 }
1312
1313 cmd! {
1314 ZephyrWriteTxPower(VENDOR_SPECIFIC, 0x000e) {
1316 Params = ZephyrWriteTxPowerParams;
1317 Return = ZephyrTxPower;
1318 }
1319 }
1320
1321 param! {
1322 struct ZephyrWriteTxPowerParams {
1323 handle_type: u8,
1324 handle: u16,
1325 tx_power_level: i8,
1326 }
1327 }
1328
1329 cmd! {
1330 ZephyrReadTxPower(VENDOR_SPECIFIC, 0x000f) {
1332 Params = ZephyrReadTxPowerParams;
1333 Return = ZephyrTxPower;
1334 }
1335 }
1336
1337 param! {
1338 struct ZephyrReadTxPowerParams {
1339 handle_type: u8,
1340 handle: u16,
1341 }
1342 }
1343
1344 cmd! {
1345 NordicLlpmModeSet(VENDOR_SPECIFIC, 0x0101) {
1346 Params = bool;
1347 Return = ();
1348 }
1349 }
1350
1351 cmd! {
1352 NordicConnUpdate(VENDOR_SPECIFIC, 0x0102) {
1353 Params = NordicConnUpdateParams;
1354 Return = ();
1355 }
1356 }
1357
1358 param! {
1359 struct NordicConnUpdateParams {
1360 handle: ConnHandle,
1361 interval_us: u32,
1362 latency: u16,
1363 supervision_timeout: Duration<10_000>,
1364 }
1365 }
1366
1367 cmd! {
1368 NordicConnEventExtend(VENDOR_SPECIFIC, 0x0103) {
1369 Params = bool;
1370 Return = ();
1371 }
1372 }
1373
1374 cmd! {
1375 NordicQosConnEventReportEnable(VENDOR_SPECIFIC, 0x0104) {
1376 Params = bool;
1377 Return = ();
1378 }
1379 }
1380
1381 cmd! {
1382 NordicEventLengthSet(VENDOR_SPECIFIC, 0x0105) {
1383 Params = u32;
1384 Return = ();
1385 }
1386 }
1387
1388 cmd! {
1389 NordicPeriodicAdvEventLengthSet(VENDOR_SPECIFIC, 0x0106) {
1390 Params = u32;
1391 Return = ();
1392 }
1393 }
1394
1395 cmd! {
1396 NordicPeripheralLatencyModeSet(VENDOR_SPECIFIC, 0x0109) {
1397 Params = NordicPeripheralLatencyModeSetParams;
1398 Return = ();
1399 }
1400 }
1401
1402 param! {
1403 struct NordicPeripheralLatencyModeSetParams{
1404 handle: ConnHandle,
1405 mode: u8,
1406 }
1407 }
1408
1409 cmd! {
1410 NordicWriteRemoteTxPower(VENDOR_SPECIFIC, 0x010a) {
1411 Params = NordicWriteRemoteTxPowerParams;
1412 Return = ();
1413 }
1414 }
1415
1416 param! {
1417 struct NordicWriteRemoteTxPowerParams {
1418 handle: ConnHandle,
1419 phy: u8,
1420 delta: i8,
1421 }
1422 }
1423
1424 cmd! {
1425 NordicSetAdvRandomness(VENDOR_SPECIFIC, 0x010c) {
1426 Params = NordicSetAdvRandomnessParams;
1427 Return = ();
1428 }
1429 }
1430
1431 param! {
1432 struct NordicSetAdvRandomnessParams {
1433 adv_handle: u8,
1434 rand_us: u16,
1435 }
1436 }
1437
1438 cmd! {
1439 NordicCompatModeWindowOffsetSet(VENDOR_SPECIFIC, 0x010d) {
1440 Params = bool;
1441 Return = ();
1442 }
1443 }
1444
1445 cmd! {
1446 NordicQosChannelSurveyEnable(VENDOR_SPECIFIC, 0x010e) {
1447 NordicQosChannelSurveyEnableParams {
1448 enable: bool,
1449 interval_us: u32,
1450 }
1451 Return = ();
1452 }
1453 }
1454
1455 cmd! {
1456 NordicSetPowerControlRequestParams(VENDOR_SPECIFIC, 0x0110) {
1457 NordicSetPowerControlRequestParamsParams {
1458 auto_enable: bool,
1459 apr_enable: bool,
1460 beta: u16,
1461 lower_limit: i8,
1462 upper_limit: i8,
1463 lower_target_rssi: i8,
1464 upper_target_rssi: i8,
1465 wait_period_ms: Duration<1_000>,
1466 apr_margin: u8,
1467 }
1468 Return = ();
1469 }
1470 }
1471
1472 cmd! {
1473 NordicReadAverageRssi(VENDOR_SPECIFIC, 0x111) {
1474 Params = ConnHandle;
1475 NordicReadAverageRssiReturn {
1476 avg_rssi: i8,
1477 }
1478 Handle = handle: ConnHandle;
1479 }
1480 }
1481
1482 cmd! {
1483 NordicCentralAclEventSpacingSet(VENDOR_SPECIFIC, 0x112) {
1484 Params = u32;
1485 Return = ();
1486 }
1487 }
1488
1489 cmd! {
1490 NordicGetNextConnEventCounter(VENDOR_SPECIFIC, 0x114) {
1491 Params = ConnHandle;
1492 NordicGetNextConnEventCounterReturn {
1493 next_conn_event_counter: u16,
1494 }
1495 Handle = handle: ConnHandle;
1496 }
1497 }
1498
1499 cmd! {
1500 NordicAllowParallelConnectionEstablishments(VENDOR_SPECIFIC, 0x115) {
1501 Params = bool;
1502 Return = ();
1503 }
1504 }
1505
1506 cmd! {
1507 NordicMinValOfMaxAclTxPayloadSet(VENDOR_SPECIFIC, 0x116) {
1508 Params = u8;
1509 Return = ();
1510 }
1511 }
1512
1513 cmd! {
1514 NordicIsoReadTxTimestamp(VENDOR_SPECIFIC, 0x117) {
1515 Params = ConnHandle;
1516 NordicIsoReadTxTimestampReturn {
1517 packet_sequence_number: u16,
1518 tx_time_stamp: u32,
1519 }
1520 Handle = handle: ConnHandle;
1521 }
1522 }
1523
1524 cmd! {
1525 NordicBigReservedTimeSet(VENDOR_SPECIFIC, 0x118) {
1526 Params = u32;
1527 Return = ();
1528 }
1529 }
1530
1531 cmd! {
1532 NordicCigReservedTimeSet(VENDOR_SPECIFIC, 0x119) {
1533 Params = u32;
1534 Return = ();
1535 }
1536 }
1537
1538 cmd! {
1539 NordicCisSubeventLengthSet(VENDOR_SPECIFIC, 0x11a) {
1540 Params = u32;
1541 Return = ();
1542 }
1543 }
1544
1545 cmd! {
1546 NordicScanChannelMapSet(VENDOR_SPECIFIC, 0x11b) {
1547 Params = ChannelMap;
1548 Return = ();
1549 }
1550 }
1551
1552 cmd! {
1553 NordicScanAcceptExtAdvPacketsSet(VENDOR_SPECIFIC, 0x11c) {
1554 Params = bool;
1555 Return = ();
1556 }
1557 }
1558
1559 cmd! {
1560 NordicSetRolePriority(VENDOR_SPECIFIC, 0x11d) {
1561 NordicSetRolePriorityParams {
1562 handle_type: u8,
1563 handle: u16,
1564 priority: u8,
1565 }
1566 Return = ();
1567 }
1568 }
1569
1570 cmd! {
1571 NordicSetEventStartTask(VENDOR_SPECIFIC, 0x11e) {
1572 NordicSetEventStartTaskParams {
1573 handle_type: u8,
1574 handle: u16,
1575 task_address: u32,
1576 }
1577 Return = ();
1578 }
1579 }
1580
1581 cmd! {
1582 NordicConnAnchorPointUpdateEventReportEnable(VENDOR_SPECIFIC, 0x11f) {
1583 Params = bool;
1584 Return = ();
1585 }
1586 }
1587
1588 sdc_cmd!(ZephyrReadVersionInfo => sdc_hci_cmd_vs_zephyr_read_version_info() -> y);
1589 sdc_cmd!(ZephyrReadSupportedCommands => sdc_hci_cmd_vs_zephyr_read_supported_commands() -> y);
1590 sdc_cmd!(ZephyrWriteBdAddr => sdc_hci_cmd_vs_zephyr_write_bd_addr(x));
1591 sdc_cmd!(ZephyrReadKeyHierarchyRoots => sdc_hci_cmd_vs_zephyr_read_key_hierarchy_roots() -> y);
1592 sdc_cmd!(ZephyrReadChipTemp => sdc_hci_cmd_vs_zephyr_read_chip_temp() -> y);
1593 sdc_cmd!(ZephyrWriteTxPower => sdc_hci_cmd_vs_zephyr_write_tx_power(x) -> y);
1594 sdc_cmd!(ZephyrReadTxPower => sdc_hci_cmd_vs_zephyr_read_tx_power(x) -> y);
1595 sdc_cmd!(NordicLlpmModeSet => sdc_hci_cmd_vs_llpm_mode_set(x));
1596 sdc_cmd!(NordicConnUpdate => sdc_hci_cmd_vs_conn_update(x));
1597 sdc_cmd!(NordicConnEventExtend => sdc_hci_cmd_vs_conn_event_extend(x));
1598 sdc_cmd!(NordicQosConnEventReportEnable => sdc_hci_cmd_vs_qos_conn_event_report_enable(x));
1599 sdc_cmd!(NordicEventLengthSet => sdc_hci_cmd_vs_event_length_set(x));
1600 sdc_cmd!(NordicPeriodicAdvEventLengthSet => sdc_hci_cmd_vs_periodic_adv_event_length_set(x));
1601 sdc_cmd!(NordicPeripheralLatencyModeSet => sdc_hci_cmd_vs_peripheral_latency_mode_set(x));
1602 sdc_cmd!(NordicWriteRemoteTxPower => sdc_hci_cmd_vs_write_remote_tx_power(x));
1603 sdc_cmd!(NordicSetAdvRandomness => sdc_hci_cmd_vs_set_adv_randomness(x));
1604 sdc_cmd!(NordicCompatModeWindowOffsetSet => sdc_hci_cmd_vs_compat_mode_window_offset_set(x));
1605 sdc_cmd!(NordicQosChannelSurveyEnable => sdc_hci_cmd_vs_qos_channel_survey_enable(x));
1606 sdc_cmd!(NordicSetPowerControlRequestParams => sdc_hci_cmd_vs_set_power_control_request_params(x));
1607 sdc_cmd!(NordicReadAverageRssi => sdc_hci_cmd_vs_read_average_rssi(x) -> y);
1608 sdc_cmd!(NordicCentralAclEventSpacingSet => sdc_hci_cmd_vs_central_acl_event_spacing_set(x));
1609 sdc_cmd!(NordicGetNextConnEventCounter => sdc_hci_cmd_vs_get_next_conn_event_counter(x) -> y);
1610 sdc_cmd!(NordicAllowParallelConnectionEstablishments => sdc_hci_cmd_vs_allow_parallel_connection_establishments(x));
1611 sdc_cmd!(NordicMinValOfMaxAclTxPayloadSet => sdc_hci_cmd_vs_min_val_of_max_acl_tx_payload_set(x));
1612 sdc_cmd!(NordicIsoReadTxTimestamp => sdc_hci_cmd_vs_iso_read_tx_timestamp(x) -> y);
1613 sdc_cmd!(NordicBigReservedTimeSet => sdc_hci_cmd_vs_big_reserved_time_set(x));
1614 sdc_cmd!(NordicCigReservedTimeSet => sdc_hci_cmd_vs_cig_reserved_time_set(x));
1615 sdc_cmd!(NordicCisSubeventLengthSet => sdc_hci_cmd_vs_cis_subevent_length_set(x));
1616 sdc_cmd!(NordicScanChannelMapSet => sdc_hci_cmd_vs_scan_channel_map_set(x));
1617 sdc_cmd!(NordicScanAcceptExtAdvPacketsSet => sdc_hci_cmd_vs_scan_accept_ext_adv_packets_set(x));
1618 sdc_cmd!(NordicSetRolePriority => sdc_hci_cmd_vs_set_role_priority(x));
1619 sdc_cmd!(NordicSetEventStartTask => sdc_hci_cmd_vs_set_event_start_task(x));
1620 sdc_cmd!(NordicConnAnchorPointUpdateEventReportEnable => sdc_hci_cmd_vs_conn_anchor_point_update_event_report_enable(x));
1621
1622 impl<'d> ControllerCmdSync<ZephyrReadStaticAddrs> for super::SoftdeviceController<'d> {
1623 async fn exec(
1624 &self,
1625 _cmd: &ZephyrReadStaticAddrs,
1626 ) -> Result<<ZephyrReadStaticAddrs as bt_hci::cmd::SyncCmd>::Return, CmdError<Self::Error>> {
1627 const N: usize = core::mem::size_of::<ZephyrReadStaticAddrsReturn>();
1628 let mut out = [0; N];
1629 let ret = unsafe { raw::sdc_hci_cmd_vs_zephyr_read_static_addresses(out.as_mut_ptr() as *mut _) };
1630 bt_hci::param::Status::from(ret).to_result()?;
1631 Ok(unwrap!(ZephyrReadStaticAddrsReturn::from_hci_bytes_complete(&out)))
1632 }
1633 }
1634}