stm32wb_hci/types/
advertisement.rs

1//! Types for LE advertisements
2
3use byteorder::{ByteOrder, LittleEndian};
4
5use super::CommonDataType;
6
7/// LE Advertisement Type
8#[cfg_attr(feature = "defmt", derive(defmt::Format))]
9pub enum Advertisement<'a> {
10    /// Complete local name of the device.
11    CompleteLocalName(&'a str),
12    /// Service data with 16-bit UUID.
13    ///
14    /// The first parameter is the UUID, the second parameter is the payload.
15    ///
16    /// The payload may be up to 27 bytes for legacy advertising mode.
17    ServiceData16BitUuid(u16, &'a [u8]),
18    /// Service data with 32-bit UUID
19    ///
20    /// The first parameter is the UUID, the second parameter is the payload.
21    ///
22    /// The payload may be up to 25 bytes for legacy advertising mode.
23    ServiceData32BitUuid(u32, &'a [u8]),
24    /// Service data with 128-bit UUID
25    ///
26    /// The first parameter is the UUID, the second parameter is the payload.
27    ///
28    /// The payload may be up to 13 bytes for legacy advertising mode.
29    ServiceData128BitUuid(u128, &'a [u8]),
30    /// Manufacturer-specific data
31    ///
32    /// The first parameter is the manufacturer ID, the second parameter is the
33    /// payload.
34    ///
35    /// The payload may be up to 27 bytes for legacy advertising mode.
36    ManufacturerSpecificData(u16, &'a [u8]),
37}
38
39impl Advertisement<'_> {
40    /// Gets the length of the advertisement payload, in bytes.
41    ///
42    /// This includes the length byte itself.
43    #[allow(clippy::len_without_is_empty)]
44    pub fn len(&self) -> usize {
45        use Advertisement::*;
46        2 + match self {
47            CompleteLocalName(n) => n.len(),
48            ServiceData16BitUuid(_, b) | ManufacturerSpecificData(_, b) => 2 + b.len(),
49            ServiceData32BitUuid(_, b) => 4 + b.len(),
50            ServiceData128BitUuid(_, b) => 16 + b.len(),
51        }
52    }
53
54    /// Gets the [CommonDataType] for this advertisement.
55    const fn get_type(&self) -> CommonDataType {
56        use Advertisement::*;
57        match self {
58            CompleteLocalName(_) => CommonDataType::CompleteLocalName,
59            ServiceData16BitUuid(_, _) => CommonDataType::ServiceData16BitUuid,
60            ServiceData32BitUuid(_, _) => CommonDataType::ServiceData32BitUuid,
61            ServiceData128BitUuid(_, _) => CommonDataType::ServiceData128BitUuid,
62            ManufacturerSpecificData(_, _) => CommonDataType::ManufacturerSpecificData,
63        }
64    }
65
66    /// Serialize the advertisement into the given buffer, and return the number
67    /// of bytes written.
68    ///
69    /// The maximum length of advertisements in legacy mode is 31 bytes.
70    ///
71    /// `bytes` must be at least [Self::len()] bytes.
72    pub fn copy_into_slice(&self, bytes: &mut [u8]) -> usize {
73        use Advertisement::*;
74        let len = self.len();
75        // Don't count the length byte.
76        bytes[0] = (len - 1) as u8;
77        bytes[1] = self.get_type() as u8;
78        match self {
79            CompleteLocalName(n) => {
80                bytes[2..2 + n.len()].copy_from_slice(n.as_bytes());
81            }
82            ServiceData16BitUuid(u, b) | ManufacturerSpecificData(u, b) => {
83                LittleEndian::write_u16(&mut bytes[2..], *u);
84                bytes[4..4 + b.len()].copy_from_slice(b);
85            }
86            ServiceData32BitUuid(u, b) => {
87                LittleEndian::write_u32(&mut bytes[2..], *u);
88                bytes[6..6 + b.len()].copy_from_slice(b);
89            }
90            ServiceData128BitUuid(u, b) => {
91                LittleEndian::write_u128(&mut bytes[2..], *u);
92                bytes[18..18 + b.len()].copy_from_slice(b);
93            }
94        }
95        len
96    }
97}