From 517f4d37cc51bf88865f4d0e79ff08bfb2565d3e Mon Sep 17 00:00:00 2001
From: Koen Zandberg <koen@bergzand.net>
Date: Thu, 12 Jul 2018 15:54:31 +0200
Subject: [PATCH] mrf24j40: Fix netdev recv implementation

The mrf24j40 driver should return the frame length when both buf is NULL
and len is zero and drop the packet when len is nonzero and buf is NULL.
This commit fixes that behaviour
---
 drivers/mrf24j40/mrf24j40_netdev.c | 47 +++++++++++++++---------------
 1 file changed, 23 insertions(+), 24 deletions(-)

diff --git a/drivers/mrf24j40/mrf24j40_netdev.c b/drivers/mrf24j40/mrf24j40_netdev.c
index 10f534689b..41c35395ef 100644
--- a/drivers/mrf24j40/mrf24j40_netdev.c
+++ b/drivers/mrf24j40/mrf24j40_netdev.c
@@ -110,46 +110,45 @@ static int _recv(netdev_t *netdev, void *buf, size_t len, void *info)
     mrf24j40_t *dev = (mrf24j40_t *)netdev;
     uint8_t phr;
     size_t pkt_len;
+    int res = -ENOBUFS;
 
     /* Disable receiving while reading the RX fifo (datasheet sec. 3.11.4) */
     mrf24j40_reg_write_short(dev, MRF24J40_REG_BBREG1, MRF24J40_BBREG1_RXDECINV );
 
-    /* get the size of the received packet */
+    /* get the size of the received packet, this resets the receive FIFO to be
+     * ready for a new frame, so we have to disable RX first (see above) */
     phr = mrf24j40_reg_read_long(dev, MRF24J40_RX_FIFO);
 
     pkt_len = (phr & 0x7f) - 2;
 
     /* just return length when buf == NULL */
-    if (buf == NULL) {
+    if (buf == NULL && len == 0) {
         return pkt_len;
     }
+    /* Only fill buffer if it is supplied and is large enough */
+    if (buf && pkt_len <= len) {
+        /* copy payload */
+        mrf24j40_rx_fifo_read(dev, 1, (uint8_t *)buf, pkt_len);
+
+        if (info != NULL) {
+            netdev_ieee802154_rx_info_t *radio_info = info;
+            uint8_t rssi_scalar = 0;
+            /* Read LQI and RSSI values from the RX fifo */
+            mrf24j40_rx_fifo_read(dev, phr + 1, &(radio_info->lqi), 1);
+            mrf24j40_rx_fifo_read(dev, phr + 2, &(rssi_scalar), 1);
+            radio_info->rssi = mrf24j40_dbm_from_reg(rssi_scalar);
+        }
 #ifdef MODULE_NETSTATS_L2
-    netdev->stats.rx_count++;
-    netdev->stats.rx_bytes += pkt_len;
+        netdev->stats.rx_count++;
+        netdev->stats.rx_bytes += pkt_len;
 #endif
-    /* not enough space in buf */
-    if (pkt_len > len) {
-        DEBUG("[mrf24j40] No space in receive buffers\n");
-        mrf24j40_reg_write_short(dev, MRF24J40_REG_RXFLUSH, MRF24J40_RXFLUSH_RXFLUSH);
-        /* Turn on reception of packets off the air */
-        mrf24j40_reg_write_short(dev, MRF24J40_REG_BBREG1, 0x00);
-        return -ENOBUFS;
-    }
-    /* copy payload */
-    mrf24j40_rx_fifo_read(dev, 1, (uint8_t *)buf, pkt_len);
-
-    if (info != NULL) {
-        netdev_ieee802154_rx_info_t *radio_info = info;
-        uint8_t rssi_scalar = 0;
-        /* Read LQI and RSSI values from the RX fifo */
-        mrf24j40_rx_fifo_read(dev, phr + 1, &(radio_info->lqi), 1);
-        mrf24j40_rx_fifo_read(dev, phr + 2, &(rssi_scalar), 1);
-        radio_info->rssi = mrf24j40_dbm_from_reg(rssi_scalar);
+        res = pkt_len;
     }
-
     /* Turn on reception of packets off the air */
     mrf24j40_reg_write_short(dev, MRF24J40_REG_BBREG1, 0x00);
-    return pkt_len;
+    /* Return -ENOBUFS if a too small buffer is supplied. Return packet size
+     * otherwise */
+    return res;
 }
 
 static netopt_state_t _get_state(mrf24j40_t *dev)
-- 
GitLab