drivers: ieee802154_nrf5: Add ACK handling

nRF5 driver did not utilize `ieee802154_radio_handle_ack` API, therefore
did not provide ACK frames to the upper layer. This commit fixes this
problem.

Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
This commit is contained in:
Robert Lubos 2019-04-11 13:29:25 +02:00 committed by Anas Nashif
commit 2624d65b60
2 changed files with 54 additions and 10 deletions

View file

@ -256,6 +256,49 @@ static int nrf5_set_txpower(struct device *dev, s16_t dbm)
return 0; return 0;
} }
static int handle_ack(struct nrf5_802154_data *nrf5_radio)
{
u8_t ack_len = nrf5_radio->ack_frame.psdu[0] - NRF5_FCS_LENGTH;
struct net_pkt *ack_pkt;
int err = 0;
ack_pkt = net_pkt_alloc_with_buffer(nrf5_radio->iface, ack_len,
AF_UNSPEC, 0, K_NO_WAIT);
if (!ack_pkt) {
LOG_ERR("No free packet available.");
err = -ENOMEM;
goto free_nrf_ack;
}
/* Upper layers expect the frame to start at the MAC header, skip the
* PHY header (1 byte).
*/
if (net_pkt_write(ack_pkt, nrf5_radio->ack_frame.psdu + 1,
ack_len) < 0) {
LOG_ERR("Failed to write to a packet.");
err = -ENOMEM;
goto free_net_ack;
}
net_pkt_set_ieee802154_lqi(ack_pkt, nrf5_radio->ack_frame.lqi);
net_pkt_set_ieee802154_rssi(ack_pkt, nrf5_radio->ack_frame.rssi);
net_pkt_cursor_init(ack_pkt);
if (ieee802154_radio_handle_ack(nrf5_radio->iface, ack_pkt) != NET_OK) {
LOG_INF("ACK packet not handled - releasing.");
}
free_net_ack:
net_pkt_unref(ack_pkt);
free_nrf_ack:
nrf_802154_buffer_free_raw(nrf5_radio->ack_frame.psdu);
nrf5_radio->ack_frame.psdu = NULL;
return err;
}
static int nrf5_tx(struct device *dev, static int nrf5_tx(struct device *dev,
struct net_pkt *pkt, struct net_pkt *pkt,
struct net_buf *frag) struct net_buf *frag)
@ -294,14 +337,13 @@ static int nrf5_tx(struct device *dev,
LOG_DBG("Result: %d", nrf5_data.tx_result); LOG_DBG("Result: %d", nrf5_data.tx_result);
if (nrf5_radio->tx_result == NRF_802154_TX_ERROR_NONE) { if (nrf5_radio->tx_result == NRF_802154_TX_ERROR_NONE) {
/* ACK frame not used currently. */ if (nrf5_radio->ack_frame.psdu == NULL) {
if (nrf5_radio->ack != NULL) { /* No ACK was requested. */
nrf_802154_buffer_free_raw(nrf5_radio->ack); return 0;
} }
nrf5_radio->ack = NULL; /* Handle ACK packet. */
return handle_ack(nrf5_radio);
return 0;
} }
return -EIO; return -EIO;
@ -466,7 +508,9 @@ void nrf_802154_transmitted_raw(const uint8_t *frame, uint8_t *ack,
ARG_UNUSED(lqi); ARG_UNUSED(lqi);
nrf5_data.tx_result = NRF_802154_TX_ERROR_NONE; nrf5_data.tx_result = NRF_802154_TX_ERROR_NONE;
nrf5_data.ack = ack; nrf5_data.ack_frame.psdu = ack;
nrf5_data.ack_frame.rssi = power;
nrf5_data.ack_frame.lqi = lqi;
k_sem_give(&nrf5_data.tx_wait); k_sem_give(&nrf5_data.tx_wait);
} }

View file

@ -61,10 +61,10 @@ struct nrf5_802154_data {
/* TX result, updated in radio transmit callbacks. */ /* TX result, updated in radio transmit callbacks. */
u8_t tx_result; u8_t tx_result;
/* A pointer to the received ACK frame. May be NULL if no ACK was /* A buffer for the received ACK frame. psdu pointer be NULL if no
* requested/received. * ACK was requested/received.
*/ */
u8_t *ack; struct nrf5_802154_rx_frame ack_frame;
}; };
#endif /* ZEPHYR_DRIVERS_IEEE802154_IEEE802154_NRF5_H_ */ #endif /* ZEPHYR_DRIVERS_IEEE802154_IEEE802154_NRF5_H_ */