Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
taks committed Sep 29, 2024
1 parent 29fc8a5 commit 1af3825
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 132 deletions.
13 changes: 5 additions & 8 deletions examples/ble_l2cap_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,11 @@ fn main() {
.unwrap();
ble_advertising.lock().start().unwrap();

L2capServer::create(0x1001, 512, |data| {
::log::info!("Data received(0x1001): {:X?}", data.sdu_rx());
})
.unwrap();
L2capServer::create(0x1002, 512, |data| {
::log::info!("Data received(0x1002): {:X?}", data.sdu_rx());
})
.unwrap();
let l2cap1 = L2capServer::create(0x1001, 512).unwrap();
let l2cap2 = L2capServer::create(0x1002, 512).unwrap();

block_on(async {
});

loop {
esp_idf_hal::delay::FreeRtos::delay_ms(1000);
Expand Down
54 changes: 8 additions & 46 deletions src/l2cap/l2cap_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,17 @@ use alloc::boxed::Box;
use core::borrow::BorrowMut;
use esp_idf_hal::task::block_on;

#[cfg(not(esp_idf_soc_esp_nimble_controller))]
use esp_idf_sys::os_mbuf_free;
#[cfg(esp_idf_soc_esp_nimble_controller)]
use esp_idf_sys::r_os_mbuf_free as os_mbuf_free;

use super::{L2cap, ReceivedData};
use crate::{
ble,
utilities::{os_mbuf_append, voidp_to_ref},
BLEClient, BLEError, Signal,
ble, utilities::voidp_to_ref, BLEClient, BLEError, Channel, Signal
};

#[allow(clippy::type_complexity)]
pub struct L2capClient {
l2cap: L2cap,
coc_chan: *mut esp_idf_sys::ble_l2cap_chan,
signal: Signal<u32>,
on_data_received: Option<Box<dyn FnMut(ReceivedData) + Send + Sync>>,
channel: Channel<ReceivedData, 1>,
}

impl L2capClient {
Expand All @@ -28,7 +21,7 @@ impl L2capClient {
l2cap: Default::default(),
coc_chan: core::ptr::null_mut(),
signal: Signal::new(),
on_data_received: None,
channel: Channel::new(),
});

ret.l2cap.init(mtu, 3)?;
Expand Down Expand Up @@ -60,39 +53,12 @@ impl L2capClient {
Ok(())
}

pub fn send(&mut self, data: &[u8]) -> Result<(), BLEError> {
let mtu = L2cap::get_chan_info(self.coc_chan).peer_l2cap_mtu as usize;
let mut data = data;

while !data.is_empty() {
let sdu_rx = self.l2cap.sdu_rx();
let (data0, data1) = data.split_at(if data.len() < mtu { data.len() } else { mtu });

let rc = os_mbuf_append(sdu_rx, data0);
assert_eq!(rc, 0);

loop {
let rc = unsafe { esp_idf_sys::ble_l2cap_send(self.coc_chan, sdu_rx) };
match rc as _ {
0 | esp_idf_sys::BLE_HS_ESTALLED => break,
esp_idf_sys::BLE_HS_EBUSY => {}
rc => return BLEError::convert(rc),
}
unsafe { esp_idf_sys::vPortYield() };
}

data = data1;
}

Ok(())
pub fn tx(&mut self, data: &[u8]) -> Result<(), BLEError> {
self.l2cap.tx(self.coc_chan, data)
}

pub fn on_data_received(
&mut self,
callback: impl FnMut(ReceivedData) + Send + Sync + 'static,
) -> &mut Self {
self.on_data_received = Some(Box::new(callback));
self
pub async fn rx(&mut self) -> ReceivedData {
self.channel.receive().await
}

pub(crate) extern "C" fn blecent_l2cap_coc_event_cb(
Expand Down Expand Up @@ -126,11 +92,7 @@ impl L2capClient {
esp_idf_sys::BLE_L2CAP_EVENT_COC_DATA_RECEIVED => {
let receive = unsafe { event.__bindgen_anon_1.receive };
if !receive.sdu_rx.is_null() {
if let Some(callback) = &mut client.on_data_received {
callback(ReceivedData::from_raw(receive));
} else {
unsafe { os_mbuf_free(receive.sdu_rx) };
}
let _ = client.channel.try_send(ReceivedData::from_raw(receive));
}
client.l2cap.ble_l2cap_recv_ready(receive.chan);
0
Expand Down
93 changes: 93 additions & 0 deletions src/l2cap/l2cap_core.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
use crate::{ble, utilities::os_mbuf_append, BLEError};
use alloc::vec::Vec;

#[derive(Default)]
pub struct L2cap {
mempool: esp_idf_sys::os_mempool,
mbuf_pool: esp_idf_sys::os_mbuf_pool,
coc_memory: Vec<esp_idf_sys::os_membuf_t>,
}

impl L2cap {
pub fn init(&mut self, mtu: u16, coc_buf_count: u16) -> Result<(), BLEError> {
self
.coc_memory
.reserve_exact(os_mempool_size(coc_buf_count as _, mtu as _));

unsafe {
ble!(super::os_mempool_init(
&mut self.mempool,
coc_buf_count,
mtu as _,
self.coc_memory.as_mut_ptr() as _,
c"coc_sdu_pool".as_ptr()
))?;

ble!(super::os_mbuf_pool_init(
&mut self.mbuf_pool as _,
&mut self.mempool as _,
mtu,
coc_buf_count
))?;
}

Ok(())
}

pub fn tx(&mut self, chan: *mut esp_idf_sys::ble_l2cap_chan, data: &[u8]) -> Result<(), BLEError> {
let mtu = L2cap::get_chan_info(chan).peer_l2cap_mtu as usize;
let mut data = data;

while !data.is_empty() {
let sdu_rx = self.sdu_rx();
let (data0, data1) = data.split_at(if data.len() < mtu { data.len() } else { mtu });

let rc = os_mbuf_append(sdu_rx, data0);
assert_eq!(rc, 0);

loop {
let rc = unsafe { esp_idf_sys::ble_l2cap_send(chan, sdu_rx) };
match rc as _ {
0 | esp_idf_sys::BLE_HS_ESTALLED => break,
esp_idf_sys::BLE_HS_EBUSY => {}
rc => return BLEError::convert(rc),
}
unsafe { esp_idf_sys::vPortYield() };
}

data = data1;
}

Ok(())
}

pub fn sdu_rx(&mut self) -> *mut esp_idf_sys::os_mbuf {
loop {
let ret = unsafe { super::os_mbuf_get_pkthdr(&mut self.mbuf_pool, 0) };
if !ret.is_null() {
return ret;
}
esp_idf_hal::delay::FreeRtos::delay_ms(10);
}
}

pub(crate) fn ble_l2cap_recv_ready(&mut self, chan: *mut esp_idf_sys::ble_l2cap_chan) -> i32 {
let sdu_rx = self.sdu_rx();
unsafe { esp_idf_sys::ble_l2cap_recv_ready(chan, sdu_rx) }
}

pub(crate) fn get_chan_info(
chan: *mut esp_idf_sys::ble_l2cap_chan,
) -> esp_idf_sys::ble_l2cap_chan_info {
let mut chan_info = esp_idf_sys::ble_l2cap_chan_info::default();
let rc = unsafe { esp_idf_sys::ble_l2cap_get_chan_info(chan, &mut chan_info as _) };
assert_eq!(rc, 0);
chan_info
}
}

#[inline]
const fn os_mempool_size(n: usize, blksize: usize) -> usize {
let size = core::mem::size_of::<esp_idf_sys::os_membuf_t>();
blksize.div_ceil(size) * n
}
17 changes: 15 additions & 2 deletions src/l2cap/l2cap_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ static SERVER_LIST: Mutex<heapless::Vec<L2capServer, N>> = Mutex::new(heapless::
#[allow(clippy::type_complexity)]
pub struct L2capServer {
l2cap: L2cap,
coc_chan: *mut esp_idf_sys::ble_l2cap_chan,
peer_sdu_size: u16,
channel: Channel<ReceivedData, 1>,
}
Expand All @@ -20,11 +21,12 @@ impl L2capServer {
pub fn create(
psm: u16,
mtu: u16,
) -> Result<(), BLEError> {
) -> Result<&'_ mut L2capServer, BLEError> {
let mut list = SERVER_LIST.lock();
list
.push(L2capServer {
l2cap: Default::default(),
coc_chan: core::ptr::null_mut(),
peer_sdu_size: 0,
channel: Channel::new(),
})
Expand All @@ -41,7 +43,11 @@ impl L2capServer {
server as *mut Self as _,
))?;
}
Ok(())
Ok(list.last_mut().unwrap())
}

pub fn tx(&mut self, data: &[u8]) -> Result<(), BLEError> {
self.l2cap.tx(self.coc_chan, data)
}

pub async fn rx(&mut self) -> ReceivedData {
Expand All @@ -63,6 +69,13 @@ impl L2capServer {
return 0;
}

server.coc_chan = connect.chan;
0
}
esp_idf_sys::BLE_L2CAP_EVENT_COC_DISCONNECTED => {
let disconnect = unsafe { event.__bindgen_anon_1.disconnect };
::log::debug!("LE CoC disconnected: {:?}", disconnect.chan);
server.coc_chan = core::ptr::null_mut();
0
}
esp_idf_sys::BLE_L2CAP_EVENT_COC_ACCEPT => {
Expand Down
13 changes: 12 additions & 1 deletion src/l2cap/mod.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,20 @@

#[cfg(not(esp_idf_soc_esp_nimble_controller))]
use esp_idf_sys::{os_mbuf_free, os_mbuf_get_pkthdr, os_mbuf_pool_init, os_mempool_init};
#[cfg(esp_idf_soc_esp_nimble_controller)]
use esp_idf_sys::{
r_os_mbuf_free as os_mbuf_free, r_os_mbuf_get_pkthdr as os_mbuf_get_pkthdr,
r_os_mbuf_pool_init as os_mbuf_pool_init, r_os_mempool_init as os_mempool_init,
};

mod l2cap_client;
pub use l2cap_client::L2capClient;

mod l2cap_server;
pub use l2cap_server::L2capServer;

mod l2cap_core;
use l2cap_core::L2cap;

mod utilities;
pub(crate) use utilities::L2cap;
pub use utilities::ReceivedData;
77 changes: 2 additions & 75 deletions src/l2cap/utilities.rs
Original file line number Diff line number Diff line change
@@ -1,77 +1,4 @@
use crate::{ble, utilities::os_mbuf_into_slice, BLEError};
use alloc::vec::Vec;

#[cfg(not(esp_idf_soc_esp_nimble_controller))]
use esp_idf_sys::{os_mbuf_free, os_mbuf_get_pkthdr, os_mbuf_pool_init, os_mempool_init};
#[cfg(esp_idf_soc_esp_nimble_controller)]
use esp_idf_sys::{
r_os_mbuf_free as os_mbuf_free, r_os_mbuf_get_pkthdr as os_mbuf_get_pkthdr,
r_os_mbuf_pool_init as os_mbuf_pool_init, r_os_mempool_init as os_mempool_init,
};

#[derive(Default)]
pub struct L2cap {
mempool: esp_idf_sys::os_mempool,
mbuf_pool: esp_idf_sys::os_mbuf_pool,
coc_memory: Vec<esp_idf_sys::os_membuf_t>,
}

impl L2cap {
pub fn init(&mut self, mtu: u16, coc_buf_count: u16) -> Result<(), BLEError> {
self
.coc_memory
.reserve_exact(os_mempool_size(coc_buf_count as _, mtu as _));

unsafe {
ble!(os_mempool_init(
&mut self.mempool,
coc_buf_count,
mtu as _,
self.coc_memory.as_mut_ptr() as _,
c"coc_sdu_pool".as_ptr()
))?;

ble!(os_mbuf_pool_init(
&mut self.mbuf_pool as _,
&mut self.mempool as _,
mtu,
coc_buf_count
))?;
}

Ok(())
}

pub fn sdu_rx(&mut self) -> *mut esp_idf_sys::os_mbuf {
loop {
let ret = unsafe { os_mbuf_get_pkthdr(&mut self.mbuf_pool, 0) };
if !ret.is_null() {
return ret;
}
esp_idf_hal::delay::FreeRtos::delay_ms(10);
}
}

pub(crate) fn ble_l2cap_recv_ready(&mut self, chan: *mut esp_idf_sys::ble_l2cap_chan) -> i32 {
let sdu_rx = self.sdu_rx();
unsafe { esp_idf_sys::ble_l2cap_recv_ready(chan, sdu_rx) }
}

pub(crate) fn get_chan_info(
chan: *mut esp_idf_sys::ble_l2cap_chan,
) -> esp_idf_sys::ble_l2cap_chan_info {
let mut chan_info = esp_idf_sys::ble_l2cap_chan_info::default();
let rc = unsafe { esp_idf_sys::ble_l2cap_get_chan_info(chan, &mut chan_info as _) };
assert_eq!(rc, 0);
chan_info
}
}

#[inline]
const fn os_mempool_size(n: usize, blksize: usize) -> usize {
let size = core::mem::size_of::<esp_idf_sys::os_membuf_t>();
blksize.div_ceil(size) * n
}
use crate::utilities::os_mbuf_into_slice;

pub struct ReceivedData(esp_idf_sys::ble_l2cap_event__bindgen_ty_1__bindgen_ty_4);

Expand All @@ -94,6 +21,6 @@ impl ReceivedData {

impl Drop for ReceivedData {
fn drop(&mut self) {
unsafe { os_mbuf_free(self.0.sdu_rx) };
unsafe { super::os_mbuf_free(self.0.sdu_rx) };
}
}

0 comments on commit 1af3825

Please sign in to comment.