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