rktk_drivers_nrf/softdevice/split/
peripheral.rs1use core::marker::PhantomData;
2
3use embassy_futures::join::join;
4use embassy_sync::pipe::Pipe;
5use nrf_softdevice::{
6 ble::{
7 advertisement_builder::{
8 Flag, LegacyAdvertisementBuilder, LegacyAdvertisementPayload, ServiceList,
9 },
10 l2cap, peripheral,
11 },
12 Softdevice,
13};
14use rktk::drivers::interface::split::SplitDriver;
15use rktk::utils::RawMutex;
16use rktk_log::error;
17
18use super::packet::Packet;
19use super::PSM;
20
21static TX_PIPE: Pipe<RawMutex, 128> = Pipe::new();
22static RX_PIPE: Pipe<RawMutex, 128> = Pipe::new();
23
24#[embassy_executor::task]
25async fn ble_split_peripheral_task(sd: &'static Softdevice) {
26 embassy_time::Timer::after_secs(3).await;
27 error!("ble split start");
28
29 static ADV_DATA: LegacyAdvertisementPayload = LegacyAdvertisementBuilder::new()
30 .flags(&[Flag::GeneralDiscovery, Flag::LE_Only])
31 .services_128(ServiceList::Complete, &[super::RKTK_SPLIT_SERVICE_ID])
32 .short_name("H")
33 .build();
34
35 static SCAN_DATA: [u8; 0] = [];
36
37 let l = l2cap::L2cap::<Packet>::init(sd);
38
39 let config = peripheral::Config::default();
40 let adv = peripheral::ConnectableAdvertisement::ScannableUndirected {
41 adv_data: &ADV_DATA,
42 scan_data: &SCAN_DATA,
43 };
44 let conn = loop {
45 match peripheral::advertise_connectable(sd, adv, &config).await {
46 Ok(conn) => break conn,
47 Err(e) => {
48 rktk::print!("{:?}", e);
49 continue;
50 }
51 };
52 };
53
54 rktk::print!("advertising done!");
55
56 let config = l2cap::Config { credits: 8 };
57 let ch = l.listen(&conn, &config, PSM).await.unwrap();
58 rktk::print!("l2cap connected");
59
60 let ch2 = ch.clone();
61 join(
62 async move {
63 loop {
64 let Ok(p) = ch.rx().await else {
65 continue;
66 };
67 rktk::print!("Received: {:?}", p);
68 RX_PIPE.write_all(p.as_bytes()).await;
69 }
70 },
71 async move {
72 loop {
73 let mut buf = [0; 128];
74 let size = TX_PIPE.read(&mut buf).await;
75 let packet = Packet::new(&buf[0..size]);
76 rktk::print!("Sending: {:?}", packet);
77 let _ = ch2.tx(packet).await;
78 }
79 },
80 )
81 .await;
82}
83
84pub struct SoftdeviceBlePeripheralSplitDriver {
86 _phantom: PhantomData<()>,
87}
88
89impl SoftdeviceBlePeripheralSplitDriver {
90 pub async fn new(sd: &'static Softdevice) -> Self {
91 embassy_executor::Spawner::for_current_executor()
92 .await
93 .spawn(ble_split_peripheral_task(sd))
94 .unwrap();
95
96 Self {
97 _phantom: PhantomData,
98 }
99 }
100}
101
102impl SplitDriver for SoftdeviceBlePeripheralSplitDriver {
103 type Error = core::convert::Infallible;
104
105 async fn recv(&mut self, buf: &mut [u8], _is_master: bool) -> Result<usize, Self::Error> {
106 let size = RX_PIPE.read(buf).await;
107 Ok(size)
108 }
109
110 async fn send_all(&mut self, buf: &[u8], _is_master: bool) -> Result<(), Self::Error> {
111 TX_PIPE.write_all(buf).await;
112 Ok(())
113 }
114}