diff options
-rw-r--r-- | Cargo.lock | 7 | ||||
-rw-r--r-- | examples/src/bin/ble_bas_peripheral.rs | 4 | ||||
-rw-r--r-- | nrf-softdevice-macro/Cargo.toml | 1 | ||||
-rw-r--r-- | nrf-softdevice-macro/src/lib.rs | 21 | ||||
-rw-r--r-- | nrf-softdevice-macro/src/uuid.rs | 43 |
5 files changed, 65 insertions, 11 deletions
@@ -538,6 +538,7 @@ dependencies = [ "proc-macro2", "quote", "syn", + "uuid", ] [[package]] @@ -884,6 +885,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" [[package]] +name = "uuid" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fde2f6a4bea1d6e007c4ad38c6839fa71cbb63b6dbf5b595aa38dc9b1093c11" + +[[package]] name = "vcell" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/examples/src/bin/ble_bas_peripheral.rs b/examples/src/bin/ble_bas_peripheral.rs index b2d294b..f81cc53 100644 --- a/examples/src/bin/ble_bas_peripheral.rs +++ b/examples/src/bin/ble_bas_peripheral.rs @@ -23,9 +23,6 @@ async fn softdevice_task(sd: &'static Softdevice) { sd.run().await; } -const GATT_BAS_SVC_UUID: Uuid = Uuid::new_16(0x180F); -const GATT_BAS_BATTERY_LEVEL_CHAR_UUID: Uuid = Uuid::new_16(0x2A19); - #[nrf_softdevice::gatt_server(uuid = "180f")] struct BatteryService { #[characteristic(uuid = "2a19", read, write, notify)] @@ -35,7 +32,6 @@ struct BatteryService { #[task] async fn bluetooth_task(sd: &'static Softdevice) { let server: BatteryService = gatt_server::register(sd).dewrap(); - #[rustfmt::skip] let adv_data = &[ 0x02, 0x01, raw::BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE as u8, diff --git a/nrf-softdevice-macro/Cargo.toml b/nrf-softdevice-macro/Cargo.toml index 81ddcb8..81bbba8 100644 --- a/nrf-softdevice-macro/Cargo.toml +++ b/nrf-softdevice-macro/Cargo.toml @@ -10,6 +10,7 @@ quote = "1.0.7" darling = "0.10.2" proc-macro2 = "1.0.18" Inflector = "0.11.4" +uuid = "0.8.1" [lib] proc-macro = true diff --git a/nrf-softdevice-macro/src/lib.rs b/nrf-softdevice-macro/src/lib.rs index 158679b..4e6a0fd 100644 --- a/nrf-softdevice-macro/src/lib.rs +++ b/nrf-softdevice-macro/src/lib.rs @@ -2,20 +2,25 @@ extern crate proc_macro; +use core::str::FromStr; use darling::FromMeta; -use proc_macro::{TokenStream}; -use proc_macro2::{TokenStream as TokenStream2}; +use proc_macro::TokenStream; +use proc_macro2::TokenStream as TokenStream2; use quote::{format_ident, quote}; use std::iter::FromIterator; use syn::spanned::Spanned; +mod uuid; + +use crate::uuid::Uuid; + #[derive(Debug, FromMeta)] struct ServerArgs { - uuid: String, + uuid: Uuid, } #[derive(Debug, FromMeta)] struct CharacteristicArgs { - uuid: String, + uuid: Uuid, #[darling(default)] read: bool, #[darling(default)] @@ -38,7 +43,7 @@ pub fn gatt_server(args: TokenStream, item: TokenStream) -> TokenStream { let args = syn::parse_macro_input!(args as syn::AttributeArgs); let mut struc = syn::parse_macro_input!(item as syn::ItemStruct); - let _args = match ServerArgs::from_list(&args) { + let args = match ServerArgs::from_list(&args) { Ok(v) => v, Err(e) => { return e.write_errors().into(); @@ -115,6 +120,7 @@ pub fn gatt_server(args: TokenStream, item: TokenStream) -> TokenStream { let set_fn = format_ident!("{}_set", ch.name); let notify_fn = format_ident!("{}_notify", ch.name); + let uuid = ch.args.uuid; let read = ch.args.read; let write = ch.args.write; let notify = ch.args.notify; @@ -132,7 +138,7 @@ pub fn gatt_server(args: TokenStream, item: TokenStream) -> TokenStream { code_register_chars.extend(quote!( let #char_name = register_char( Characteristic { - uuid: GATT_BAS_BATTERY_LEVEL_CHAR_UUID, + uuid: #uuid, can_read: #read, can_write: #write, can_notify: #notify, @@ -220,6 +226,7 @@ pub fn gatt_server(args: TokenStream, item: TokenStream) -> TokenStream { //panic!(); } + let uuid = args.uuid; struct_fields.named = syn::punctuated::Punctuated::from_iter(fields); let result = quote! { @@ -233,7 +240,7 @@ pub fn gatt_server(args: TokenStream, item: TokenStream) -> TokenStream { type Event = #event_enum_name; fn uuid() -> Uuid { - GATT_BAS_SVC_UUID + #uuid } fn register<F>(service_handle: u16, mut register_char: F) -> Result<Self, RegisterError> diff --git a/nrf-softdevice-macro/src/uuid.rs b/nrf-softdevice-macro/src/uuid.rs new file mode 100644 index 0000000..950c3fd --- /dev/null +++ b/nrf-softdevice-macro/src/uuid.rs @@ -0,0 +1,43 @@ +use core::str::FromStr; +use darling::FromMeta; +use proc_macro2::TokenStream as TokenStream2; +use quote::quote; + +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +pub enum Uuid { + Uuid16(u16), + Uuid128([u8; 16]), +} + +impl FromMeta for Uuid { + fn from_string(value: &str) -> darling::Result<Self> { + if let Ok(u) = uuid::Uuid::from_str(value) { + return Ok(Uuid::Uuid128(*u.as_bytes())); + } + + if value.len() == 4 { + if let Ok(u) = u16::from_str_radix(value, 16) { + return Ok(Uuid::Uuid16(u)); + } + } + + Err(darling::Error::custom( + "Invalid UUID (must be a 16-bit or 128-bit UUID)", + )) + } +} + +impl quote::ToTokens for Uuid { + fn to_tokens(&self, tokens: &mut TokenStream2) { + match self { + Uuid::Uuid16(u) => tokens.extend(quote!(::nrf_softdevice::ble::Uuid::new_16(#u))), + Uuid::Uuid128(u) => { + let mut s = TokenStream2::new(); + for b in u { + s.extend(quote!(#b,)) + } + tokens.extend(quote!(::nrf_softdevice::ble::Uuid::new_128(&[#s]))); + } + } + } +} |