LCOV - code coverage report
Current view: top level - zephyr/net - ieee802154_ie.h Hit Total Coverage
Test: new.info Lines: 40 42 95.2 %
Date: 2024-12-21 18:13:37

          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_ */

Generated by: LCOV version 1.14