Skip to main content

esp_idf_svc/ble/
mbuf.rs

1//! Safe interaction with the NimBLE os_mbuf buffer system
2
3#[cfg(esp_idf_bt_nimble_gatt_server)]
4use core::ffi::c_int;
5use core::ffi::c_void;
6use core::marker::PhantomData;
7
8use crate::sys::*;
9
10use super::BleError;
11
12// On chips whose BLE controller lives in ROM (`SOC_ESP_NIMBLE_CONTROLLER`), the NimBLE headers
13// alias `os_mbuf_append` to the ROM symbol `r_os_mbuf_append`, so that is the only name bindgen
14// emits there; on the other chips it is an ordinary function pulled in by the glob import above.
15#[cfg(all(esp_idf_soc_esp_nimble_controller, esp_idf_bt_controller_enabled))]
16use crate::sys::r_os_mbuf_append as os_mbuf_append;
17
18/// View of an os_mbuf, the data buffers used by NimBLE
19pub struct Mbuf<'a> {
20    om: *mut os_mbuf,
21    _p: PhantomData<&'a mut os_mbuf>,
22}
23
24impl Mbuf<'_> {
25    pub(crate) fn from_raw(om: *mut os_mbuf) -> Self {
26        Self {
27            om,
28            _p: PhantomData,
29        }
30    }
31
32    /// Copy this Mbuf into `buf`, returning the number of bytes copied or error if buf is too small
33    pub fn read(&self, buf: &mut [u8]) -> Result<usize, BleError> {
34        // A completion callback delivered with an error status may carry a null mbuf.
35        if self.om.is_null() {
36            return Ok(0);
37        }
38
39        let mut copied: u16 = 0;
40
41        BleError::from_raw(unsafe {
42            ble_hs_mbuf_to_flat(
43                self.om,
44                buf.as_mut_ptr() as *mut c_void,
45                buf.len() as u16,
46                &mut copied,
47            )
48        })?;
49
50        Ok(copied as usize)
51    }
52
53    /// Append `buf` to the mbuf.
54    pub fn append(&mut self, buf: &[u8]) -> Result<(), BleError> {
55        BleError::from_raw(unsafe {
56            os_mbuf_append(self.om, buf.as_ptr() as *const c_void, buf.len() as u16)
57        })
58    }
59}
60
61/// Allocate an `os_mbuf` and copy `buf` into it. Errors with `BLE_HS_ENOMEM` if
62/// allocation fails.
63#[cfg(esp_idf_bt_nimble_gatt_server)]
64pub(crate) fn mbuf_from_slice(buf: &[u8]) -> Result<*mut os_mbuf, BleError> {
65    let om = unsafe { ble_hs_mbuf_from_flat(buf.as_ptr() as *const c_void, buf.len() as u16) };
66
67    if om.is_null() {
68        Err(BleError::new(BLE_HS_ENOMEM as c_int))
69    } else {
70        Ok(om)
71    }
72}