1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/*
*
* Copyright (c) 2026 Project CHIP Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
//! FixedLabel cluster handler (Matter Application Cluster spec).
//!
//! Per-endpoint **read-only** list of `(label, value)` string pairs
//! that the manufacturer bakes into the device firmware — typical use
//! is exposing immutable tags such as `"serial"` → `"abc123"` or
//! `"hwrev"` → `"B"`. Compare with [`super::user_label`], the
//! writable counterpart used by commissioners.
//!
//! The list is **fixed** in the F-quality sense (Matter Core spec):
//! it never changes for the lifetime of the device firmware,
//! so we don't need a persistence layer, a mutex, or any per-entry
//! storage. [`FixedLabelHandler`] just borrows a static slice of
//! [`FixedLabelEntry`] from the application and iterates it on read.
//! Writes are rejected by the framework before they reach the handler
//! because the cluster metadata declares `LabelList` as read-only
//! (`Access::READ`), which the IM dispatch maps to `UnsupportedWrite`
//! — exactly the behaviour `TC_FLABEL_2_1` step 3 expects.
//!
//! Application wiring:
//!
//! ```ignore
//! const LABELS: &[FixedLabelEntry] = &[
//! FixedLabelEntry { label: "room", value: "kitchen" },
//! FixedLabelEntry { label: "hwrev", value: "B" },
//! ];
//!
//! let handler = FixedLabelHandler::new(Dataver::new_rand(rand), LABELS);
//! ```
use crate;
use crate;
use crateTLVBuilderParent;
use cratewith;
pub use crate*;
pub use crate;
/// Cluster metadata exposed by [`FixedLabelHandler`].
///
/// Exposed as a free constant so callers can spell out
/// `EpClMatcher::new(Some(ep), Some(fixed_label::CLUSTER.id))` without
/// reaching for the lifetime-parameterised handler type.
pub const CLUSTER: = FULL_CLUSTER.with_attrs;
/// One entry in a `LabelList`.
///
/// Per Matter Application Cluster spec (`LabelStruct`), each
/// field is at most 16 characters. We don't enforce this here — the
/// application is responsible for supplying spec-compliant data, and
/// `TC_FLABEL_2_1` step 2 sanity-checks the lengths on the read path.
/// The handler for the FixedLabel Matter cluster.
///
/// Per-endpoint instance: each endpoint that advertises FixedLabel
/// must own its own handler so the per-cluster-instance `Dataver`
/// stays granular (Matter Core spec). The entries slice is
/// borrowed — typically a `&'static [FixedLabelEntry<'static>]` —
/// because the list is part of the device's firmware identity and
/// doesn't change at runtime.