diff --git a/matter/src/data_model/sdm/noc.rs b/matter/src/data_model/sdm/noc.rs index 63f3d0f..929809c 100644 --- a/matter/src/data_model/sdm/noc.rs +++ b/matter/src/data_model/sdm/noc.rs @@ -124,6 +124,7 @@ impl NocCluster { base: Cluster::new(ID)?, }); c.base.add_attribute(attr_currfabindex_new()?)?; + c.base.add_attribute(attr_fabrics_new()?)?; Ok(c) } @@ -364,6 +365,15 @@ fn attr_currfabindex_new() -> Result { ) } +fn attr_fabrics_new() -> Result { + Attribute::new( + Attributes::Fabrics as u16, + AttrValue::Custom, + Access::RV | Access::FAB_SCOPED, + Quality::NONE, + ) +} + impl ClusterType for NocCluster { fn base(&self) -> &Cluster { &self.base @@ -395,6 +405,17 @@ impl ClusterType for NocCluster { Some(Attributes::CurrentFabricIndex) => { encoder.encode(EncodeValue::Value(&attr.fab_idx)) } + Some(Attributes::Fabrics) => encoder.encode(EncodeValue::Closure(&|tag, tw| { + let _ = tw.start_array(tag); + let _ = self.fabric_mgr.for_each(|entry, fab_idx| { + if !attr.fab_filter || attr.fab_idx == fab_idx { + let _ = entry + .get_fabric_desc(fab_idx) + .to_tlv(tw, TagType::Anonymous); + } + }); + let _ = tw.end_container(); + })), _ => { error!("Attribute not supported: this shouldn't happen"); } diff --git a/matter/src/fabric.rs b/matter/src/fabric.rs index 86919b3..c9ae240 100644 --- a/matter/src/fabric.rs +++ b/matter/src/fabric.rs @@ -28,6 +28,7 @@ use crate::{ group_keys::KeySet, mdns::{self, Mdns}, sys::{Psm, SysMdnsService}, + tlv::{OctetStr, TLVWriter, TagType, ToTLV, UtfStr}, }; const MAX_CERT_TLV_LEN: usize = 300; @@ -61,6 +62,19 @@ pub struct Fabric { mdns_service: Option, } +#[derive(ToTLV)] +#[tlvargs(lifetime = "'a", start = 1)] +pub struct FabricDescriptor<'a> { + root_public_key: OctetStr<'a>, + vendor_id: u16, + fabric_id: u64, + node_id: u64, + label: UtfStr<'a>, + // TODO: Instead of the direct value, we should consider GlobalElements::FabricIndex + #[tagval(0xFE)] + pub fab_idx: Option, +} + impl Fabric { pub fn new( key_pair: KeyPair, @@ -166,6 +180,17 @@ impl Fabric { self.fabric_id } + pub fn get_fabric_desc(&self, fab_idx: u8) -> FabricDescriptor { + FabricDescriptor { + root_public_key: OctetStr::new(self.root_ca.get_pubkey()), + vendor_id: self.vendor_id, + fabric_id: self.fabric_id, + node_id: self.node_id, + label: UtfStr::new(b""), + fab_idx: Some(fab_idx), + } + } + fn store(&self, index: usize, psm: &MutexGuard) -> Result<(), Error> { let mut key = [0u8; MAX_CERT_TLV_LEN]; let len = self.root_ca.as_tlv(&mut key)?; @@ -312,4 +337,18 @@ impl FabricMgr { } true } + + // Parameters to T are the Fabric and its Fabric Index + pub fn for_each(&self, mut f: T) -> Result<(), Error> + where + T: FnMut(&Fabric, u8), + { + let mgr = self.inner.read().unwrap(); + for i in 1..MAX_SUPPORTED_FABRICS { + if let Some(fabric) = &mgr.fabrics[i] { + f(fabric, i as u8) + } + } + Ok(()) + } }