blob: 8fc8dc081434f87b9756265f4a6cb3bf056196a5 [file] [log] [blame]
/*
* Copyright (c) 2016 Intel Corporation.
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __IEEE802154_RADIO_UTILS_H__
#define __IEEE802154_RADIO_UTILS_H__
#include "ieee802154_utils.h"
typedef int (ieee802154_radio_tx_frag_t)(struct net_if *iface,
struct net_pkt *pkt,
struct net_buf *frag);
static inline bool prepare_for_ack(struct ieee802154_context *ctx,
struct net_pkt *pkt,
struct net_buf *frag)
{
if (ieee802154_is_ar_flag_set(pkt)) {
struct ieee802154_fcf_seq *fs;
fs = (struct ieee802154_fcf_seq *)(frag->data -
net_pkt_ll_reserve(pkt));
ctx->ack_seq = fs->sequence;
ctx->ack_received = false;
k_sem_init(&ctx->ack_lock, 0, UINT_MAX);
return true;
}
return false;
}
static inline int wait_for_ack(struct net_if *iface,
bool ack_required)
{
struct ieee802154_context *ctx = net_if_l2_data(iface);
if (!ack_required ||
(ieee802154_get_hw_capabilities(iface) & IEEE802154_HW_TX_RX_ACK)) {
return 0;
}
if (k_sem_take(&ctx->ack_lock, 10) == 0) {
/*
* We reinit the semaphore in case handle_ack
* got called multiple times.
*/
k_sem_init(&ctx->ack_lock, 0, UINT_MAX);
}
ctx->ack_seq = 0;
return ctx->ack_received ? 0 : -EIO;
}
static inline int handle_ack(struct ieee802154_context *ctx,
struct net_pkt *pkt)
{
if (pkt->frags->len == IEEE802154_ACK_PKT_LENGTH) {
struct ieee802154_fcf_seq *fs;
fs = ieee802154_validate_fc_seq(net_pkt_ll(pkt), NULL);
if (!fs || fs->sequence != ctx->ack_seq) {
return NET_CONTINUE;
}
ctx->ack_received = true;
k_sem_give(&ctx->ack_lock);
return NET_OK;
}
return NET_CONTINUE;
}
static inline int tx_packet_fragments(struct net_if *iface,
struct net_pkt *pkt,
ieee802154_radio_tx_frag_t *tx_func)
{
int ret = 0;
struct net_buf *frag;
frag = pkt->frags;
while (frag) {
if (IS_ENABLED(CONFIG_NET_L2_IEEE802154_RADIO_CSMA_CA) &&
ieee802154_get_hw_capabilities(iface) &
IEEE802154_HW_CSMA) {
ret = ieee802154_tx(iface, pkt, frag);
} else {
ret = tx_func(iface, pkt, frag);
}
if (ret) {
break;
}
frag = frag->frags;
}
if (!ret) {
net_pkt_unref(pkt);
}
return ret;
}
#endif /* __IEEE802154_RADIO_UTILS_H__ */