1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/sys/include/net/ieee802154/submac.h
2021-06-17 10:07:43 +02:00

414 lines
12 KiB
C

/*
* Copyright (C) 2020 HAW Hamburg
*
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License v2.1. See the file LICENSE in the top level directory for more
* details.
*/
/**
* @defgroup net_ieee802154_submac IEEE802.15.4 SubMAC layer
* @ingroup net_ieee802154
* @experimental This API is experimental and in an early state - expect
* changes!
* @brief This module defines a common layer for handling the lower
* part of the IEEE 802.15.4 MAC layer.
*
* This layer is responsible for:
* - Handling CSMA-CA and retransmissions.
* - Maintaining part of the MAC Information Base, e.g IEEE 802.15.4 addresses,
* channel settings, CSMA-CA params, etc.
*
* @{
*
* @author José I. Alamos <jose.alamos@haw-hamburg.de>
*/
#ifndef NET_IEEE802154_SUBMAC_H
#define NET_IEEE802154_SUBMAC_H
#ifdef __cplusplus
extern "C" {
#endif
#include <string.h>
#include "net/ieee802154.h"
#include "net/ieee802154/radio.h"
#define IEEE802154_SUBMAC_MAX_RETRANSMISSIONS (4U) /**< maximum number of frame retransmissions */
/**
* @brief IEEE 802.15.4 SubMAC forward declaration
*/
typedef struct ieee802154_submac ieee802154_submac_t;
/**
* @brief SubMAC states
*/
typedef enum {
/**
* @brief SubMAC and network devices are off.
*
* The corresponding network device is put in a state with the
* lowest energy consumption.
*/
IEEE802154_STATE_OFF,
/**
* @brief SubMAC is ready to be used.
*/
IEEE802154_STATE_IDLE,
/**
* @brief SubMAC is ready to be used and listening to incoming frames.
*/
IEEE802154_STATE_LISTEN,
} ieee802154_submac_state_t;
/**
* @brief IEEE 802.15.4 SubMAC callbacks.
*/
typedef struct {
/**
* @brief RX done event
*
* This function is called from the SubMAC to indicate a IEEE 802.15.4
* frame is ready to be fetched from the device.
*
* @post If @ref ieee802154_submac_t::state is @ref IEEE802154_STATE_LISTEN, the
* SubMAC is ready to receive frames
*
* @note ACK frames are automatically handled and discarded by the SubMAC.
* @param[in] submac pointer to the SubMAC descriptor
*/
void (*rx_done)(ieee802154_submac_t *submac);
/**
* @brief TX done event
*
* This function is called from the SubMAC to indicate that the TX
* procedure finished.
*
* @pre If @ref ieee802154_submac_t::state is @ref IEEE802154_STATE_LISTEN, the
* SubMAC is ready to receive frames.
*
* @param[in] submac pointer to the SubMAC descriptor
* @param[out] info TX information associated to the transmission (status,
* number of retransmissions, pending bit, etc).
*/
void (*tx_done)(ieee802154_submac_t *submac, int status,
ieee802154_tx_info_t *info);
} ieee802154_submac_cb_t;
/**
* @brief IEEE 802.15.4 SubMAC descriptor
*/
struct ieee802154_submac {
eui64_t ext_addr; /**< IEEE 802.15.4 extended address */
network_uint16_t short_addr; /**< IEEE 802.15.4 short address */
ieee802154_dev_t *dev; /**< pointer to the 802.15.4 HAL descriptor */
const ieee802154_submac_cb_t *cb; /**< pointer to the SubMAC callbacks */
ieee802154_csma_be_t be; /**< CSMA-CA backoff exponent params */
bool wait_for_ack; /**< SubMAC is waiting for an ACK frame */
bool tx; /**< SubMAC is currently transmitting a frame */
uint16_t panid; /**< IEEE 802.15.4 PAN ID */
uint16_t channel_num; /**< IEEE 802.15.4 channel number */
uint8_t channel_page; /**< IEEE 802.15.4 channel page */
uint8_t retrans; /**< current number of retransmissions */
uint8_t csma_retries_nb; /**< current number of CSMA-CA retries */
uint8_t backoff_mask; /**< internal value used for random backoff calculation */
uint8_t csma_retries; /**< maximum number of CSMA-CA retries */
int8_t tx_pow; /**< Transmission power (in dBm) */
ieee802154_submac_state_t state; /**< State of the SubMAC */
ieee802154_phy_mode_t phy_mode; /**< IEEE 802.15.4 PHY mode */
};
/**
* @brief Get the internal state of the SubMAC
*
* @param[in] submac pointer to the SubMAC descriptor
*
* @return the SubMAC state
*/
static inline ieee802154_submac_state_t ieee802154_get_state(ieee802154_submac_t *submac)
{
return submac->state;
}
/**
* @brief Set the internal state of the SubMAC
*
* @param[in] submac pointer to the SubMAC descriptor
* @param[in] state the desired state
*
* @return 0 on success
* @return negative errno on error.
*/
int ieee802154_set_state(ieee802154_submac_t *submac, ieee802154_submac_state_t state);
/**
* @brief Transmit an IEEE 802.15.4 PSDU
*
* This function performs an IEEE 802.15.4 transmission, including CSMA-CA and
* retransmissions (if ACK Request bit is set). When the transmission finishes
* an @ref ieee802154_submac_cb_t::tx_done event is issued.
*
* @param[in] submac pointer to the SubMAC descriptor
* @param[in] iolist pointer to the PSDU frame (without FCS)
*
* @return 0 on success
* @return negative errno on error
*/
int ieee802154_send(ieee802154_submac_t *submac, const iolist_t *iolist);
/**
* @brief Set the IEEE 802.15.4 short address
*
* @param[in] submac pointer to the SubMAC descriptor
* @param[in] short_addr IEEE 802.15.4 short address
*
* @return 0 on success
* @return negative errno on error
*/
static inline int ieee802154_set_short_addr(ieee802154_submac_t *submac,
const network_uint16_t *short_addr)
{
int res = ieee802154_radio_config_addr_filter(submac->dev, IEEE802154_AF_SHORT_ADDR, short_addr);
if (res >= 0) {
memcpy(&submac->short_addr, short_addr, IEEE802154_SHORT_ADDRESS_LEN);
}
return res;
}
/**
* @brief Set the IEEE 802.15.4 extended address
*
* @param[in] submac pointer to the SubMAC descriptor
* @param[in] ext_addr IEEE 802.15.4 extended address
*
* @return 0 on success
* @return negative errno on error
*/
static inline int ieee802154_set_ext_addr(ieee802154_submac_t *submac,
const eui64_t *ext_addr)
{
int res = ieee802154_radio_config_addr_filter(submac->dev, IEEE802154_AF_EXT_ADDR, ext_addr);
if (res >= 0) {
memcpy(&submac->ext_addr, ext_addr, IEEE802154_LONG_ADDRESS_LEN);
}
return res;
}
/**
* @brief Set the IEEE 802.15.4 PAN ID
*
* @param[in] submac pointer to the SubMAC descriptor
* @param[in] panid IEEE 802.15.4 PAN ID
*
* @return 0 on success
* @return negative errno on error
*/
static inline int ieee802154_set_panid(ieee802154_submac_t *submac,
const uint16_t *panid)
{
int res = ieee802154_radio_config_addr_filter(submac->dev, IEEE802154_AF_PANID, panid);
if (res >= 0) {
submac->panid = *panid;
}
return res;
}
/**
* @brief Get IEEE 802.15.4 PHY mode
*
* @param[in] submac pointer to the SubMAC descriptor
*
* @return PHY mode.
*/
static inline ieee802154_phy_mode_t ieee802154_get_phy_mode(
ieee802154_submac_t *submac)
{
return submac->phy_mode;
}
/**
* @brief Set IEEE 802.15.4 PHY configuration (channel, TX power)
*
* @param[in] submac pointer to the SubMAC descriptor
* @param[in] channel_num channel number
* @param[in] channel_page channel page
* @param[in] tx_pow transmission power (in dBm)
*
* @return 0 on success
* @return -ENOTSUP if the PHY settings are not supported
* @return negative errno on error
*/
int ieee802154_set_phy_conf(ieee802154_submac_t *submac, uint16_t channel_num,
uint8_t channel_page, int8_t tx_pow);
/**
* @brief Set IEEE 802.15.4 channel number
*
* This is a shortcut to @ref ieee802154_set_phy_conf
*
* @param[in] submac pointer the SubMAC descriptor
* @param[in] channel_num channel number
*
* @return 0 on success
* @return -ENOTSUP if the channel number is not supported
* @return negative errno on error
*/
static inline int ieee802154_set_channel_number(ieee802154_submac_t *submac,
uint16_t channel_num)
{
return ieee802154_set_phy_conf(submac, channel_num, submac->channel_page,
submac->tx_pow);
}
/**
* @brief Set IEEE 802.15.4 channel page
*
* This is a shortcut to @ref ieee802154_set_phy_conf
*
* @param[in] submac pointer the SubMAC descriptor
* @param[in] channel_page channel page
*
* @return 0 on success
* @return -ENOTSUP if the channel page is not supported
* @return negative errno on error
*/
static inline int ieee802154_set_channel_page(ieee802154_submac_t *submac,
uint16_t channel_page)
{
return ieee802154_set_phy_conf(submac, submac->channel_num, channel_page,
submac->tx_pow);
}
/**
* @brief Set IEEE 802.15.4 transmission power
*
* This is a shortcut to @ref ieee802154_set_phy_conf
*
* @param[in] submac pointer the SubMAC descriptor
* @param[in] tx_pow transmission power (in dBm)
*
* @return 0 on success
* @return -ENOTSUP if the transmission power is not supported
* @return negative errno on error
*/
static inline int ieee802154_set_tx_power(ieee802154_submac_t *submac,
int8_t tx_pow)
{
return ieee802154_set_phy_conf(submac, submac->channel_num,
submac->channel_page, tx_pow);
}
/**
* @brief Get the received frame length
*
* @param[in] submac pointer to the SubMAC
*
* @return length of the PSDU (excluding FCS length)
*/
static inline int ieee802154_get_frame_length(ieee802154_submac_t *submac)
{
return ieee802154_radio_len(submac->dev);
}
/**
* @brief Read the received frame
*
* This functions reads the received PSDU from the device (excluding FCS)
*
* @param[in] submac pointer to the SubMAC descriptor
* @param[out] buf buffer to write into. If NULL, the packet is discarded
* @param[in] len length of the buffer
* @param[out] info RX information of the packet. If NULL, the information is not fetched.
*
* @return the number of bytes written to @p buf
* @return negative errno on error
*/
static inline int ieee802154_read_frame(ieee802154_submac_t *submac, void *buf,
size_t len, ieee802154_rx_info_t *info)
{
return ieee802154_radio_read(submac->dev, buf, len, info);
}
/**
* @brief Init the IEEE 802.15.4 SubMAC
*
* @param[in] submac pointer to the SubMAC descriptor
* @param[in] short_addr pointer to the IEEE 802.15.4 short address
* @param[in] ext_addr pointer to the IEEE 802.15.4 extended address
*
* @return 0 on success
* @return negative errno on error
*/
int ieee802154_submac_init(ieee802154_submac_t *submac, const network_uint16_t *short_addr,
const eui64_t *ext_addr);
/**
* @brief Set the ACK timeout timer
*
* @note This function should be implemented by the user of the SubMAC.
*
* @param[in] submac pointer to the SubMAC descriptor
* @param[in] us microseconds until the ACK timeout timer is fired
*/
extern void ieee802154_submac_ack_timer_set(ieee802154_submac_t *submac,
uint16_t us);
/**
* @brief Cancel the ACK timeout timer
*
* @note This function should be implemented by the user of the SubMAC.
*
* @param[in] submac pointer to the SubMAC descriptor
*/
extern void ieee802154_submac_ack_timer_cancel(ieee802154_submac_t *submac);
/**
* @brief Indicate the SubMAC that the ACK timeout fired.
*
* This function must be called when the ACK timeout timer fires.
*
* @note this function should not be called inside ISR context.
*
* @param[in] submac pointer to the SubMAC descriptor
*/
void ieee802154_submac_ack_timeout_fired(ieee802154_submac_t *submac);
/**
* @brief Indicate the SubMAC that the device received a frame.
*
* @param[in] submac pointer to the SubMAC descriptor
*/
void ieee802154_submac_rx_done_cb(ieee802154_submac_t *submac);
/**
* @brief Indicate the SubMAC that a frame with invalid CRC was received.
*
* @param[in] submac pointer to the SubMAC descriptor
*/
void ieee802154_submac_crc_error_cb(ieee802154_submac_t *submac);
/**
* @brief Indicate the SubMAC that the device finished the transmission procedure.
*
* @param[in] submac pointer to the SubMAC descriptor
*/
void ieee802154_submac_tx_done_cb(ieee802154_submac_t *submac);
#ifdef __cplusplus
}
#endif
#endif /* NET_IEEE802154_SUBMAC_H */
/** @} */