rktk_drivers_nrf/softdevice/split/
central.rs1use core::marker::PhantomData;
2use core::slice;
3
4use embassy_futures::join::join;
5use embassy_sync::pipe::Pipe;
6use nrf_softdevice::Softdevice;
7use nrf_softdevice::ble::{Address, TxPower, central, l2cap};
8use rktk::drivers::interface::split::SplitDriver;
9use rktk::utils::RawMutex;
10use rktk_log::{error, info};
11
12use super::packet::Packet;
13use super::{PSM, RKTK_SPLIT_SERVICE_ID};
14
15static TX_PIPE: Pipe<RawMutex, 128> = Pipe::new();
16static RX_PIPE: Pipe<RawMutex, 128> = Pipe::new();
17
18#[embassy_executor::task]
19async fn ble_split_central_task(sd: &'static Softdevice) {
20 embassy_time::Timer::after_secs(3).await;
21 error!("Scanning for peer...");
22
23 let config =
24 central::ScanConfig { whitelist: None, tx_power: TxPower::ZerodBm, ..Default::default() };
25 let res = central::scan(sd, &config, |params| {
26 let mut data =
27 unsafe { slice::from_raw_parts(params.data.p_data, params.data.len as usize) };
28 while !data.is_empty() {
29 let len = data[0] as usize;
30 if data.len() < len + 1 {
31 break;
32 }
33 if len < 1 {
34 break;
35 }
36 let key = data[1];
37 let value = &data[2..len + 1];
38
39 if key == 0x07 && value == RKTK_SPLIT_SERVICE_ID {
40 return Some(Address::from_raw(params.peer_addr));
42 }
43 data = &data[len + 1..];
44 }
45 None
46 })
47 .await;
48
49 let address = res.unwrap();
50 rktk::print!("Found slave address {:?}", address);
51
52 let addrs = &[&address];
53
54 let mut config = central::ConnectConfig::default();
55 config.scan_config.whitelist = Some(addrs);
56 let conn = match central::connect(sd, &config).await {
57 Ok(conn) => conn,
58 Err(e) => {
59 error!("connect failed: {:?}", e);
60 return;
61 }
62 };
63
64 let l = l2cap::L2cap::<super::packet::Packet>::init(sd);
65 let config = l2cap::Config { credits: 8 };
66 let ch = match l.setup(&conn, &config, PSM).await {
67 Ok(ch) => ch,
68 Err(e) => {
69 error!("l2cap connect failed: {:?}", e);
70 return;
71 }
72 };
73
74 info!("Starting split handler");
75
76 let ch2 = ch.clone();
77 join(
78 async move {
79 loop {
80 let Ok(p) = ch.rx().await else {
81 embassy_time::Timer::after_millis(100).await;
82 continue;
83 };
84 RX_PIPE.write_all(p.as_bytes()).await;
85 }
86 },
87 async move {
88 loop {
89 let mut buf = [0; 128];
90 let size = TX_PIPE.read(&mut buf).await;
91 let packet = Packet::new(&buf[0..size]);
92 let _ = ch2.tx(packet).await;
93 }
94 },
95 )
96 .await;
97}
98
99pub struct SoftdeviceBleCentralSplitDriver {
101 _phantom: PhantomData<()>,
102}
103
104impl SoftdeviceBleCentralSplitDriver {
105 pub async fn new(spawner: embassy_executor::Spawner, sd: &'static Softdevice) -> Self {
106 spawner.spawn(ble_split_central_task(sd).unwrap());
107
108 Self { _phantom: PhantomData }
109 }
110}
111
112impl SplitDriver for SoftdeviceBleCentralSplitDriver {
113 type Error = core::convert::Infallible;
114
115 async fn recv(&mut self, buf: &mut [u8], _is_master: bool) -> Result<usize, Self::Error> {
116 let size = RX_PIPE.read(buf).await;
117 Ok(size)
118 }
119
120 async fn send_all(&mut self, buf: &[u8], _is_master: bool) -> Result<(), Self::Error> {
121 TX_PIPE.write_all(buf).await;
122 Ok(())
123 }
124}