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 Softdevice,
7 ble::{
8 advertisement_builder::{
9 Flag, LegacyAdvertisementBuilder, LegacyAdvertisementPayload, ServiceList,
10 },
11 l2cap, peripheral,
12 },
13};
14use rktk::drivers::interface::split::SplitDriver;
15use rktk::utils::RawMutex;
16use rktk_log::error;
17
18use super::PSM;
19use super::packet::Packet;
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(spawner: embassy_executor::Spawner, sd: &'static Softdevice) -> Self {
91 spawner.spawn(ble_split_peripheral_task(sd)).unwrap();
92
93 Self {
94 _phantom: PhantomData,
95 }
96 }
97}
98
99impl SplitDriver for SoftdeviceBlePeripheralSplitDriver {
100 type Error = core::convert::Infallible;
101
102 async fn recv(&mut self, buf: &mut [u8], _is_master: bool) -> Result<usize, Self::Error> {
103 let size = RX_PIPE.read(buf).await;
104 Ok(size)
105 }
106
107 async fn send_all(&mut self, buf: &[u8], _is_master: bool) -> Result<(), Self::Error> {
108 TX_PIPE.write_all(buf).await;
109 Ok(())
110 }
111}