Line data Source code
1 1 : /*
2 : * Copyright (c) 2023 Florian Grandel, Zephyr Project.
3 : *
4 : * SPDX-License-Identifier: Apache-2.0
5 : */
6 :
7 : /**
8 : * @file
9 : * @brief IEEE 802.15.4 MAC information element (IE) related types and helpers
10 : *
11 : * This is not to be included by the application. This file contains only those
12 : * parts of the types required for IE support that need to be visible to IEEE
13 : * 802.15.4 drivers and L2 at the same time, i.e. everything related to header
14 : * IE representation, parsing and generation.
15 : *
16 : * All specification references in this file refer to IEEE 802.15.4-2020.
17 : *
18 : * @note All structs and attributes in this file that directly represent parts
19 : * of IEEE 802.15.4 frames are in LITTLE ENDIAN, see section 4, especially
20 : * section 4.3.
21 : */
22 :
23 : #ifndef ZEPHYR_INCLUDE_NET_IEEE802154_IE_H_
24 : #define ZEPHYR_INCLUDE_NET_IEEE802154_IE_H_
25 :
26 : #include <zephyr/net_buf.h>
27 : #include <zephyr/sys/byteorder.h>
28 :
29 : /**
30 : * @addtogroup ieee802154_driver
31 : * @{
32 : *
33 : * @name IEEE 802.15.4, section 7.4.2: MAC header information elements
34 : * @{
35 : */
36 :
37 : /**
38 : * @brief Information Element Types.
39 : *
40 : * @details See sections 7.4.2.1 and 7.4.3.1.
41 : */
42 1 : enum ieee802154_ie_type {
43 : IEEE802154_IE_TYPE_HEADER = 0x0, /**< Header type */
44 : IEEE802154_IE_TYPE_PAYLOAD, /**< Payload type */
45 : };
46 :
47 : /**
48 : * @brief Header Information Element IDs.
49 : *
50 : * @details See section 7.4.2.1, table 7-7, partial list, only IEs actually used
51 : * are implemented.
52 : */
53 1 : enum ieee802154_header_ie_element_id {
54 : IEEE802154_HEADER_IE_ELEMENT_ID_VENDOR_SPECIFIC_IE = 0x00, /**< Vendor specific IE */
55 : IEEE802154_HEADER_IE_ELEMENT_ID_CSL_IE = 0x1a, /**< CSL IE */
56 : IEEE802154_HEADER_IE_ELEMENT_ID_RIT_IE = 0x1b, /**< RIT IE */
57 : IEEE802154_HEADER_IE_ELEMENT_ID_RENDEZVOUS_TIME_IE = 0x1d, /**< Rendezvous time IE */
58 : IEEE802154_HEADER_IE_ELEMENT_ID_TIME_CORRECTION_IE = 0x1e, /**< Time correction IE */
59 : IEEE802154_HEADER_IE_ELEMENT_ID_HEADER_TERMINATION_1 = 0x7e, /**< Header termination 1 */
60 : IEEE802154_HEADER_IE_ELEMENT_ID_HEADER_TERMINATION_2 = 0x7f, /**< Header termination 2 */
61 : /* partial list, add additional ids as needed */
62 : };
63 :
64 : /** @cond INTERNAL_HIDDEN */
65 : #define IEEE802154_VENDOR_SPECIFIC_IE_OUI_LEN 3
66 : /** INTERNAL_HIDDEN @endcond */
67 :
68 : /** @brief Vendor Specific Header IE, see section 7.4.2.3. */
69 1 : struct ieee802154_header_ie_vendor_specific {
70 : /** Vendor OUI */
71 1 : uint8_t vendor_oui[IEEE802154_VENDOR_SPECIFIC_IE_OUI_LEN];
72 : /** Vendor specific information */
73 1 : uint8_t *vendor_specific_info;
74 : } __packed;
75 :
76 : /** @brief Full CSL IE, see section 7.4.2.3. */
77 1 : struct ieee802154_header_ie_csl_full {
78 1 : uint16_t csl_phase; /**< CSL phase */
79 1 : uint16_t csl_period; /**< CSL period */
80 1 : uint16_t csl_rendezvous_time; /**< Rendezvous time */
81 : } __packed;
82 :
83 : /** @brief Reduced CSL IE, see section 7.4.2.3. */
84 1 : struct ieee802154_header_ie_csl_reduced {
85 1 : uint16_t csl_phase; /**< CSL phase */
86 1 : uint16_t csl_period; /**< CSL period */
87 : } __packed;
88 :
89 : /** @brief Generic CSL IE, see section 7.4.2.3. */
90 1 : struct ieee802154_header_ie_csl {
91 : union {
92 : /** CSL full information */
93 1 : struct ieee802154_header_ie_csl_full full;
94 : /** CSL reduced information */
95 1 : struct ieee802154_header_ie_csl_reduced reduced;
96 0 : };
97 : } __packed;
98 :
99 : /** @brief RIT IE, see section 7.4.2.4. */
100 1 : struct ieee802154_header_ie_rit {
101 1 : uint8_t time_to_first_listen; /**< Time to First Listen */
102 1 : uint8_t number_of_repeat_listen; /**< Number of Repeat Listen */
103 1 : uint16_t repeat_listen_interval; /**< Repeat listen interval */
104 : } __packed;
105 :
106 : /**
107 : * @brief Full Rendezvous Time IE, see section 7.4.2.6
108 : * (macCslInterval is nonzero).
109 : */
110 1 : struct ieee802154_header_ie_rendezvous_time_full {
111 1 : uint16_t rendezvous_time; /**< Rendezvous time */
112 1 : uint16_t wakeup_interval; /**< Wakeup interval */
113 : } __packed;
114 :
115 : /**
116 : * @brief Reduced Rendezvous Time IE, see section 7.4.2.6
117 : * (macCslInterval is zero).
118 : */
119 1 : struct ieee802154_header_ie_rendezvous_time_reduced {
120 1 : uint16_t rendezvous_time; /**< Rendezvous time */
121 : } __packed;
122 :
123 : /** @brief Rendezvous Time IE, see section 7.4.2.6. */
124 1 : struct ieee802154_header_ie_rendezvous_time {
125 : union {
126 : /** Rendezvous time full information */
127 1 : struct ieee802154_header_ie_rendezvous_time_full full;
128 : /** Rendezvous time reduced information */
129 1 : struct ieee802154_header_ie_rendezvous_time_reduced reduced;
130 0 : };
131 : } __packed;
132 :
133 : /** @brief Time Correction IE, see section 7.4.2.7. */
134 1 : struct ieee802154_header_ie_time_correction {
135 1 : uint16_t time_sync_info; /**< Time synchronization information */
136 : } __packed;
137 :
138 : /** @cond INTERNAL_HIDDEN */
139 :
140 : /* @brief Generic Header IE, see section 7.4.2.1. */
141 : struct ieee802154_header_ie {
142 : #if CONFIG_LITTLE_ENDIAN
143 : uint16_t length : 7;
144 : uint16_t element_id_low : 1; /* see enum ieee802154_header_ie_element_id */
145 : uint16_t element_id_high : 7;
146 : uint16_t type : 1; /* always 0 */
147 : #else
148 : uint16_t element_id_low : 1; /* see enum ieee802154_header_ie_element_id */
149 : uint16_t length : 7;
150 : uint16_t type : 1; /* always 0 */
151 : uint16_t element_id_high : 7;
152 : #endif
153 : union {
154 : struct ieee802154_header_ie_vendor_specific vendor_specific;
155 : struct ieee802154_header_ie_csl csl;
156 : struct ieee802154_header_ie_rit rit;
157 : struct ieee802154_header_ie_rendezvous_time rendezvous_time;
158 : struct ieee802154_header_ie_time_correction time_correction;
159 : /* add additional supported header IEs here */
160 : } content;
161 : } __packed;
162 :
163 : /** INTERNAL_HIDDEN @endcond */
164 :
165 : /** @brief The header IE's header length (2 bytes). */
166 1 : #define IEEE802154_HEADER_IE_HEADER_LENGTH sizeof(uint16_t)
167 :
168 :
169 : /** @cond INTERNAL_HIDDEN */
170 : #define IEEE802154_DEFINE_HEADER_IE(_element_id, _length, _content, _content_type) \
171 : (struct ieee802154_header_ie) { \
172 : .length = (_length), \
173 : .element_id_high = (_element_id) >> 1U, .element_id_low = (_element_id) & 0x01, \
174 : .type = IEEE802154_IE_TYPE_HEADER, \
175 : .content._content_type = _content, \
176 : }
177 :
178 : #define IEEE802154_DEFINE_HEADER_IE_VENDOR_SPECIFIC_CONTENT_LEN(_vendor_specific_info_len) \
179 : (IEEE802154_VENDOR_SPECIFIC_IE_OUI_LEN + (_vendor_specific_info_len))
180 :
181 : #define IEEE802154_DEFINE_HEADER_IE_VENDOR_SPECIFIC_CONTENT(_vendor_oui, _vendor_specific_info) \
182 : (struct ieee802154_header_ie_vendor_specific) { \
183 : .vendor_oui = _vendor_oui, .vendor_specific_info = (_vendor_specific_info), \
184 : }
185 :
186 : #define IEEE802154_DEFINE_HEADER_IE_CSL_REDUCED_CONTENT(_csl_phase, _csl_period) \
187 : (struct ieee802154_header_ie_csl_reduced) { \
188 : .csl_phase = sys_cpu_to_le16(_csl_phase), \
189 : .csl_period = sys_cpu_to_le16(_csl_period), \
190 : }
191 :
192 : #define IEEE802154_DEFINE_HEADER_IE_CSL_FULL_CONTENT(_csl_phase, _csl_period, \
193 : _csl_rendezvous_time) \
194 : (struct ieee802154_header_ie_csl_full) { \
195 : .csl_phase = sys_cpu_to_le16(_csl_phase), \
196 : .csl_period = sys_cpu_to_le16(_csl_period), \
197 : .csl_rendezvous_time = sys_cpu_to_le16(_csl_rendezvous_time), \
198 : }
199 :
200 : #define IEEE802154_HEADER_IE_TIME_CORRECTION_NACK 0x8000
201 : #define IEEE802154_HEADER_IE_TIME_CORRECTION_MASK 0x0fff
202 : #define IEEE802154_HEADER_IE_TIME_CORRECTION_SIGN_BIT_MASK 0x0800
203 :
204 : #define IEEE802154_DEFINE_HEADER_IE_TIME_CORRECTION_CONTENT(_ack, _time_correction_us) \
205 : (struct ieee802154_header_ie_time_correction) { \
206 : .time_sync_info = sys_cpu_to_le16( \
207 : (!(_ack) * IEEE802154_HEADER_IE_TIME_CORRECTION_NACK) | \
208 : ((_time_correction_us) & IEEE802154_HEADER_IE_TIME_CORRECTION_MASK)), \
209 : }
210 : /** INTERNAL_HIDDEN @endcond */
211 :
212 : /**
213 : * @brief Define a vendor specific header IE, see section 7.4.2.3.
214 : *
215 : * @details Example usage (all parameters in little endian):
216 : *
217 : * @code{.c}
218 : * uint8_t vendor_specific_info[] = {...some vendor specific IE content...};
219 : * struct ieee802154_header_ie header_ie = IEEE802154_DEFINE_HEADER_IE_VENDOR_SPECIFIC(
220 : * {0x9b, 0xb8, 0xea}, vendor_specific_info, sizeof(vendor_specific_info));
221 : * @endcode
222 : *
223 : * @param _vendor_oui an initializer for a 3 byte vendor oui array in little
224 : * endian
225 : * @param _vendor_specific_info pointer to a variable length uint8_t array with
226 : * the vendor specific IE content
227 : * @param _vendor_specific_info_len the length of the vendor specific IE content
228 : * (in bytes)
229 : */
230 : #define IEEE802154_DEFINE_HEADER_IE_VENDOR_SPECIFIC(_vendor_oui, _vendor_specific_info, \
231 1 : _vendor_specific_info_len) \
232 : IEEE802154_DEFINE_HEADER_IE(IEEE802154_HEADER_IE_ELEMENT_ID_VENDOR_SPECIFIC_IE, \
233 : IEEE802154_DEFINE_HEADER_IE_VENDOR_SPECIFIC_CONTENT_LEN( \
234 : _vendor_specific_info_len), \
235 : IEEE802154_DEFINE_HEADER_IE_VENDOR_SPECIFIC_CONTENT( \
236 : _vendor_oui, _vendor_specific_info), \
237 : vendor_specific)
238 :
239 : /**
240 : * @brief Define a reduced CSL IE, see section 7.4.2.3.
241 : *
242 : * @details Example usage (all parameters in CPU byte order):
243 : *
244 : * @code{.c}
245 : * uint16_t csl_phase = ...;
246 : * uint16_t csl_period = ...;
247 : * struct ieee802154_header_ie header_ie =
248 : * IEEE802154_DEFINE_HEADER_IE_CSL_REDUCED(csl_phase, csl_period);
249 : * @endcode
250 : *
251 : * @param _csl_phase CSL phase in CPU byte order
252 : * @param _csl_period CSL period in CPU byte order
253 : */
254 1 : #define IEEE802154_DEFINE_HEADER_IE_CSL_REDUCED(_csl_phase, _csl_period) \
255 : IEEE802154_DEFINE_HEADER_IE( \
256 : IEEE802154_HEADER_IE_ELEMENT_ID_CSL_IE, \
257 : sizeof(struct ieee802154_header_ie_csl_reduced), \
258 : IEEE802154_DEFINE_HEADER_IE_CSL_REDUCED_CONTENT(_csl_phase, _csl_period), \
259 : csl.reduced)
260 :
261 : /**
262 : * @brief Define a full CSL IE, see section 7.4.2.3.
263 : *
264 : * @details Example usage (all parameters in CPU byte order):
265 : *
266 : * @code{.c}
267 : * uint16_t csl_phase = ...;
268 : * uint16_t csl_period = ...;
269 : * uint16_t csl_rendezvous_time = ...;
270 : * struct ieee802154_header_ie header_ie =
271 : * IEEE802154_DEFINE_HEADER_IE_CSL_REDUCED(csl_phase, csl_period, csl_rendezvous_time);
272 : * @endcode
273 : *
274 : * @param _csl_phase CSL phase in CPU byte order
275 : * @param _csl_period CSL period in CPU byte order
276 : * @param _csl_rendezvous_time CSL rendezvous time in CPU byte order
277 : */
278 1 : #define IEEE802154_DEFINE_HEADER_IE_CSL_FULL(_csl_phase, _csl_period, _csl_rendezvous_time) \
279 : IEEE802154_DEFINE_HEADER_IE(IEEE802154_HEADER_IE_ELEMENT_ID_CSL_IE, \
280 : sizeof(struct ieee802154_header_ie_csl_full), \
281 : IEEE802154_DEFINE_HEADER_IE_CSL_FULL_CONTENT( \
282 : _csl_phase, _csl_period, _csl_rendezvous_time), \
283 : csl.full)
284 :
285 : /**
286 : * @brief Define a Time Correction IE, see section 7.4.2.7.
287 : *
288 : * @details Example usage (parameter in CPU byte order):
289 : *
290 : * @code{.c}
291 : * uint16_t time_sync_info = ...;
292 : * struct ieee802154_header_ie header_ie =
293 : * IEEE802154_DEFINE_HEADER_IE_TIME_CORRECTION(true, time_sync_info);
294 : * @endcode
295 : *
296 : * @param _ack whether or not the enhanced ACK frame that receives this IE is an
297 : * ACK (true) or NACK (false)
298 : * @param _time_correction_us the positive or negative deviation from expected
299 : * RX time in microseconds
300 : */
301 1 : #define IEEE802154_DEFINE_HEADER_IE_TIME_CORRECTION(_ack, _time_correction_us) \
302 : IEEE802154_DEFINE_HEADER_IE( \
303 : IEEE802154_HEADER_IE_ELEMENT_ID_TIME_CORRECTION_IE, \
304 : sizeof(struct ieee802154_header_ie_time_correction), \
305 : IEEE802154_DEFINE_HEADER_IE_TIME_CORRECTION_CONTENT(_ack, _time_correction_us), \
306 : time_correction)
307 :
308 : /**
309 : * @brief Retrieve the time correction value in microseconds from a Time Correction IE,
310 : * see section 7.4.2.7.
311 : *
312 : * @param[in] ie pointer to the Time Correction IE structure
313 : *
314 : * @return The time correction value in microseconds.
315 : */
316 : static inline int16_t
317 1 : ieee802154_header_ie_get_time_correction_us(struct ieee802154_header_ie_time_correction *ie)
318 : {
319 : if (ie->time_sync_info & IEEE802154_HEADER_IE_TIME_CORRECTION_SIGN_BIT_MASK) {
320 : /* Negative integer */
321 : return (int16_t)ie->time_sync_info | ~IEEE802154_HEADER_IE_TIME_CORRECTION_MASK;
322 : }
323 :
324 : /* Positive integer */
325 : return (int16_t)ie->time_sync_info & IEEE802154_HEADER_IE_TIME_CORRECTION_MASK;
326 : }
327 :
328 : /**
329 : * @brief Set the element ID of a header IE.
330 : *
331 : * @param[in] ie pointer to a header IE
332 : * @param[in] element_id IE element id in CPU byte order
333 : */
334 1 : static inline void ieee802154_header_ie_set_element_id(struct ieee802154_header_ie *ie,
335 : uint8_t element_id)
336 : {
337 : ie->element_id_high = element_id >> 1U;
338 : ie->element_id_low = element_id & 0x01;
339 : }
340 :
341 : /**
342 : * @brief Get the element ID of a header IE.
343 : *
344 : * @param[in] ie pointer to a header IE
345 : *
346 : * @return header IE element id in CPU byte order
347 : */
348 1 : static inline uint8_t ieee802154_header_ie_get_element_id(struct ieee802154_header_ie *ie)
349 : {
350 : return (ie->element_id_high << 1U) | ie->element_id_low;
351 : }
352 :
353 : /** @brief The length in bytes of a "Time Correction" header IE. */
354 1 : #define IEEE802154_TIME_CORRECTION_HEADER_IE_LEN \
355 : (IEEE802154_HEADER_IE_HEADER_LENGTH + sizeof(struct ieee802154_header_ie_time_correction))
356 :
357 : /** @brief The length in bytes of a "Header Termination 1" header IE. */
358 1 : #define IEEE802154_HEADER_TERMINATION_1_HEADER_IE_LEN IEEE802154_HEADER_IE_HEADER_LENGTH
359 :
360 : /**
361 : * @}
362 : *
363 : * @}
364 : */
365 :
366 : #endif /* ZEPHYR_INCLUDE_NET_IEEE802154_IE_H_ */
|