Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/apps/src/ble_bas_peripheral.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ async fn advertise<'values, 'server, C: Controller>(
let len = AdStructure::encode_slice(
&[
AdStructure::Flags(LE_GENERAL_DISCOVERABLE | BR_EDR_NOT_SUPPORTED),
AdStructure::ServiceUuids16(&[[0x0f, 0x18]]),
AdStructure::IncompleteServiceUuids16(&[[0x0f, 0x18]]),
AdStructure::CompleteLocalName(name.as_bytes()),
],
&mut advertiser_data[..],
Expand Down
2 changes: 1 addition & 1 deletion examples/apps/src/ble_bas_peripheral_auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ async fn advertise<'values, 'server, C: Controller>(
let len = AdStructure::encode_slice(
&[
AdStructure::Flags(LE_GENERAL_DISCOVERABLE | BR_EDR_NOT_SUPPORTED),
AdStructure::ServiceUuids16(&[[0x0f, 0x18]]),
AdStructure::IncompleteServiceUuids16(&[[0x0f, 0x18]]),
AdStructure::CompleteLocalName(name.as_bytes()),
],
&mut advertiser_data[..],
Expand Down
2 changes: 1 addition & 1 deletion examples/apps/src/ble_bas_peripheral_bonding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ async fn advertise<'values, 'server, C: Controller>(
let len = AdStructure::encode_slice(
&[
AdStructure::Flags(LE_GENERAL_DISCOVERABLE | BR_EDR_NOT_SUPPORTED),
AdStructure::ServiceUuids16(&[
AdStructure::IncompleteServiceUuids16(&[
service::BATTERY.to_le_bytes(),
service::HUMAN_INTERFACE_DEVICE.to_le_bytes(),
]),
Expand Down
2 changes: 1 addition & 1 deletion examples/apps/src/ble_bas_peripheral_pass_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ async fn advertise<'values, 'server, C: Controller>(
let len = AdStructure::encode_slice(
&[
AdStructure::Flags(LE_GENERAL_DISCOVERABLE | BR_EDR_NOT_SUPPORTED),
AdStructure::ServiceUuids16(&[[0x0f, 0x18]]),
AdStructure::IncompleteServiceUuids16(&[[0x0f, 0x18]]),
AdStructure::CompleteLocalName(name.as_bytes()),
],
&mut advertiser_data[..],
Expand Down
2 changes: 1 addition & 1 deletion examples/apps/src/ble_bas_peripheral_sec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ async fn advertise<'values, 'server, C: Controller>(
let len = AdStructure::encode_slice(
&[
AdStructure::Flags(LE_GENERAL_DISCOVERABLE | BR_EDR_NOT_SUPPORTED),
AdStructure::ServiceUuids16(&[[0x0f, 0x18]]),
AdStructure::IncompleteServiceUuids16(&[[0x0f, 0x18]]),
AdStructure::CompleteLocalName(name.as_bytes()),
],
&mut advertiser_data[..],
Expand Down
99 changes: 85 additions & 14 deletions host/src/advertise.rs
Original file line number Diff line number Diff line change
Expand Up @@ -360,13 +360,32 @@ pub enum AdStructure<'a> {
/// Must not be used in scan response data.
Flags(u8),

/// List of 16-bit service UUIDs.
/// Incomplete List of 16-bit service UUIDs.
/// The UUID data matches the ble network's endian order (should be little endian).
ServiceUuids16(&'a [[u8; 2]]),
IncompleteServiceUuids16(&'a [[u8; 2]]),

/// List of 128-bit service UUIDs.
/// Complete List of 16-bit service UUIDs.
/// The UUID data matches the ble network's endian order (should be little endian).
ServiceUuids128(&'a [[u8; 16]]),
CompleteServiceUuids16(&'a [[u8; 2]]),

/// Incomplete List of 32-bit service UUIDs.
/// The UUID data matches the ble network's endian order (should be little endian).
IncompleteServiceUuids32(&'a [[u8; 4]]),

/// Complete List of 32-bit service UUIDs.
/// The UUID data matches the ble network's endian order (should be little endian).
CompleteServiceUuids32(&'a [[u8; 4]]),

/// Incomplete List of 128-bit service UUIDs.
/// The UUID data matches the ble network's endian order (should be little endian).
IncompleteServiceUuids128(&'a [[u8; 16]]),

/// Complete List of 128-bit service UUIDs.
/// The UUID data matches the ble network's endian order (should be little endian).
CompleteServiceUuids128(&'a [[u8; 16]]),

/// Sets the Tx Power Level in dBm.
TxPowerLevel(i8),

/// Service data with 16-bit service UUID.
/// The UUID data matches the ble network's endian order (should be little endian).
Expand Down Expand Up @@ -417,13 +436,37 @@ impl AdStructure<'_> {
AdStructure::Flags(flags) => {
w.append(&[0x02, 0x01, *flags])?;
}
AdStructure::ServiceUuids16(uuids) => {
AdStructure::IncompleteServiceUuids16(uuids) => {
w.append(&[(uuids.len() * 2 + 1) as u8, 0x02])?;
for uuid in uuids.iter() {
w.write_ref(&Uuid::Uuid16(*uuid))?;
}
}
AdStructure::ServiceUuids128(uuids) => {
AdStructure::CompleteServiceUuids16(uuids) => {
w.append(&[(uuids.len() * 2 + 1) as u8, 0x03])?;
for uuid in uuids.iter() {
w.write_ref(&Uuid::Uuid16(*uuid))?;
}
}
AdStructure::IncompleteServiceUuids32(uuids) => {
w.append(&[(uuids.len() * 4 + 1) as u8, 0x04])?;
for uuid in uuids.iter() {
w.write_ref(&Uuid::Uuid32(*uuid))?;
}
}
AdStructure::CompleteServiceUuids32(uuids) => {
w.append(&[(uuids.len() * 4 + 1) as u8, 0x05])?;
for uuid in uuids.iter() {
w.write_ref(&Uuid::Uuid32(*uuid))?;
}
}
AdStructure::IncompleteServiceUuids128(uuids) => {
w.append(&[(uuids.len() * 16 + 1) as u8, 0x06])?;
for uuid in uuids.iter() {
w.write_ref(&Uuid::Uuid128(*uuid))?;
}
}
AdStructure::CompleteServiceUuids128(uuids) => {
w.append(&[(uuids.len() * 16 + 1) as u8, 0x07])?;
for uuid in uuids.iter() {
w.write_ref(&Uuid::Uuid128(*uuid))?;
Expand All @@ -437,6 +480,9 @@ impl AdStructure<'_> {
w.append(&[(name.len() + 1) as u8, 0x09])?;
w.append(name)?;
}
AdStructure::TxPowerLevel(power) => {
w.append(&[0x02, 0x0a, *power as u8])?;
}
AdStructure::ServiceData16 { uuid, data } => {
w.append(&[(data.len() + 3) as u8, 0x16])?;
w.write(Uuid::Uuid16(*uuid))?;
Expand Down Expand Up @@ -485,24 +531,48 @@ impl<'d> AdStructureIter<'d> {
// Flags
0x01 => Ok(AdStructure::Flags(data[0])),
// Incomplete List of 16-bit Service or Service Class UUIDs
// 0x02 =>
0x02 => match zerocopy::FromBytes::ref_from_bytes(data) {
Ok(x) => Ok(AdStructure::IncompleteServiceUuids16(x)),
Err(e) => {
let _ = zerocopy::SizeError::from(e);
Err(codec::Error::InvalidValue)
}
},
// Complete List of 16-bit Service or Service Class UUIDs
0x03 => match zerocopy::FromBytes::ref_from_bytes(data) {
Ok(x) => Ok(AdStructure::ServiceUuids16(x)),
Ok(x) => Ok(AdStructure::CompleteServiceUuids16(x)),
Err(e) => {
let _ = zerocopy::SizeError::from(e);
Err(codec::Error::InvalidValue)
}
},
// Incomplete List of 32-bit Service or Service Class UUIDs
// 0x04 =>
0x04 => match zerocopy::FromBytes::ref_from_bytes(data) {
Ok(x) => Ok(AdStructure::IncompleteServiceUuids32(x)),
Err(e) => {
let _ = zerocopy::SizeError::from(e);
Err(codec::Error::InvalidValue)
}
},
// Complete List of 32-bit Service or Service Class UUIDs
// 0x05
0x05 => match zerocopy::FromBytes::ref_from_bytes(data) {
Ok(x) => Ok(AdStructure::CompleteServiceUuids32(x)),
Err(e) => {
let _ = zerocopy::SizeError::from(e);
Err(codec::Error::InvalidValue)
}
},
// Incomplete List of 128-bit Service or Service Class UUIDs
// 0x06
0x06 => match zerocopy::FromBytes::ref_from_bytes(data) {
Ok(x) => Ok(AdStructure::IncompleteServiceUuids128(x)),
Err(e) => {
let _ = zerocopy::SizeError::from(e);
Err(codec::Error::InvalidValue)
}
},
// Complete List of 128-bit Service or Service Class UUIDs
0x07 => match zerocopy::FromBytes::ref_from_bytes(data) {
Ok(x) => Ok(AdStructure::ServiceUuids128(x)),
Ok(x) => Ok(AdStructure::CompleteServiceUuids128(x)),
Err(e) => {
let _ = zerocopy::SizeError::from(e);
Err(codec::Error::InvalidValue)
Expand All @@ -512,8 +582,9 @@ impl<'d> AdStructureIter<'d> {
0x08 => Ok(AdStructure::ShortenedLocalName(data)),
// Complete Local Name
0x09 => Ok(AdStructure::CompleteLocalName(data)),
// Tx Power Level
0x0a => Ok(AdStructure::TxPowerLevel(data[0] as i8)),
/*
0x0A Tx Power Level
0x0D Class of Device
0x0E Simple Pairing Hash C-192
0x0F Simple Pairing Randomizer R-192
Expand Down Expand Up @@ -594,7 +665,7 @@ mod tests {
assert!(AdStructure::encode_slice(
&[
AdStructure::Flags(LE_GENERAL_DISCOVERABLE | BR_EDR_NOT_SUPPORTED),
AdStructure::ServiceUuids16(&[[0x0f, 0x18]]),
AdStructure::IncompleteServiceUuids16(&[[0x0f, 0x18]]),
AdStructure::CompleteLocalName(b"12345678901234567890123"),
],
&mut adv_data[..],
Expand Down
29 changes: 27 additions & 2 deletions host/src/types/uuid.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! UUID types.

use bt_hci::uuid::{BluetoothUuid128, BluetoothUuid16};
use bt_hci::uuid::{BluetoothUuid128, BluetoothUuid16, BluetoothUuid32};

use crate::codec::{Decode, Encode, Error, Type};

Expand All @@ -10,6 +10,8 @@ use crate::codec::{Decode, Encode, Error, Type};
pub enum Uuid {
/// 16-bit UUID
Uuid16([u8; 2]),
/// 32-bit UUID
Uuid32([u8; 4]),
/// 128-bit UUID
Uuid128([u8; 16]),
}
Expand All @@ -20,6 +22,12 @@ impl From<BluetoothUuid16> for Uuid {
}
}

impl From<BluetoothUuid32> for Uuid {
fn from(data: bt_hci::uuid::BluetoothUuid32) -> Self {
Uuid::Uuid32(data.into())
}
}

impl From<BluetoothUuid128> for Uuid {
fn from(data: bt_hci::uuid::BluetoothUuid128) -> Self {
Uuid::Uuid128(data.into())
Expand All @@ -38,6 +46,18 @@ impl From<[u8; 16]> for Uuid {
}
}

impl From<[u8; 4]> for Uuid {
fn from(data: [u8; 4]) -> Self {
Uuid::Uuid32(data)
}
}

impl From<u32> for Uuid {
fn from(data: u32) -> Self {
Uuid::Uuid32(data.to_le_bytes())
}
}

impl From<[u8; 2]> for Uuid {
fn from(data: [u8; 2]) -> Self {
Uuid::Uuid16(data)
Expand Down Expand Up @@ -65,6 +85,7 @@ impl Uuid {
pub fn bytes(&self, data: &mut [u8]) {
match self {
Uuid::Uuid16(uuid) => data.copy_from_slice(uuid),
Uuid::Uuid32(uuid) => data.copy_from_slice(uuid),
Uuid::Uuid128(uuid) => data.copy_from_slice(uuid),
}
}
Expand All @@ -73,13 +94,15 @@ impl Uuid {
pub fn get_type(&self) -> u8 {
match self {
Uuid::Uuid16(_) => 0x01,
Uuid::Uuid128(_) => 0x02,
Uuid::Uuid32(_) => 0x02,
Uuid::Uuid128(_) => 0x03,
}
}

pub(crate) fn size(&self) -> usize {
match self {
Uuid::Uuid16(_) => 6,
Uuid::Uuid32(_) => 8,
Uuid::Uuid128(_) => 20,
}
}
Expand All @@ -96,6 +119,7 @@ impl Uuid {
pub fn as_raw(&self) -> &[u8] {
match self {
Uuid::Uuid16(uuid) => uuid,
Uuid::Uuid32(uuid) => uuid,
Uuid::Uuid128(uuid) => uuid,
}
}
Expand All @@ -108,6 +132,7 @@ impl TryFrom<&[u8]> for Uuid {
match value.len() {
// Slice length has already been verified, so unwrap can be used
2 => Ok(Uuid::Uuid16(value.try_into().unwrap())),
4 => Ok(Uuid::Uuid32(value.try_into().unwrap())),
16 => {
let mut bytes = [0; 16];
bytes.copy_from_slice(value);
Expand Down
Loading