From 9c3654602656316436fe0ddec1bbe2c3b4a27c07 Mon Sep 17 00:00:00 2001
From: daniel-k <github@daniel-krebs.net>
Date: Tue, 4 Aug 2015 17:46:50 +0200
Subject: [PATCH] netdev: add TX feedback events

---
 drivers/at86rf2xx/at86rf2xx_netdev.c | 33 ++++++++++++++++++++++++----
 sys/include/net/gnrc/netdev.h        |  2 ++
 2 files changed, 31 insertions(+), 4 deletions(-)

diff --git a/drivers/at86rf2xx/at86rf2xx_netdev.c b/drivers/at86rf2xx/at86rf2xx_netdev.c
index 1b591a5b09..4b3d0955c3 100644
--- a/drivers/at86rf2xx/at86rf2xx_netdev.c
+++ b/drivers/at86rf2xx/at86rf2xx_netdev.c
@@ -692,30 +692,55 @@ static void _isr_event(gnrc_netdev_t *device, uint32_t event_type)
     at86rf2xx_t *dev = (at86rf2xx_t *) device;
     uint8_t irq_mask;
     uint8_t state;
+    uint8_t trac_status;
 
     /* read (consume) device status */
     irq_mask = at86rf2xx_reg_read(dev, AT86RF2XX_REG__IRQ_STATUS);
 
     state = at86rf2xx_get_status(dev);
+    trac_status = at86rf2xx_reg_read(dev, AT86RF2XX_REG__TRX_STATE) &
+                    AT86RF2XX_TRX_STATE_MASK__TRAC;
 
     if (irq_mask & AT86RF2XX_IRQ_STATUS_MASK__RX_START) {
         dev->event_cb(NETDEV_EVENT_RX_STARTED, NULL);
         DEBUG("[at86rf2xx] EVT - RX_START\n");
     }
+
     if (irq_mask & AT86RF2XX_IRQ_STATUS_MASK__TRX_END) {
-        if (state == AT86RF2XX_STATE_RX_AACK_ON || state == AT86RF2XX_STATE_BUSY_RX_AACK) {
+        if(state == AT86RF2XX_STATE_RX_AACK_ON ||
+           state == AT86RF2XX_STATE_BUSY_RX_AACK) {
             DEBUG("[at86rf2xx] EVT - RX_END\n");
             if (!(dev->options & AT86RF2XX_OPT_TELL_RX_END)) {
                 return;
             }
             _receive_data(dev);
         }
-        else if (state == AT86RF2XX_STATE_TX_ARET_ON) {
+        else if (state == AT86RF2XX_STATE_TX_ARET_ON ||
+                 state == AT86RF2XX_STATE_BUSY_TX_ARET) {
             at86rf2xx_set_state(dev, dev->idle_state);
+            DEBUG("[at86rf2xx] EVT - TX_END\n");
+            DEBUG("[at86rf2xx] return to state 0x%x\n", dev->idle_state);
+
             if (dev->event_cb && (dev->options & AT86RF2XX_OPT_TELL_TX_END)) {
-                dev->event_cb(NETDEV_EVENT_TX_COMPLETE, NULL);
+                switch(trac_status) {
+                case AT86RF2XX_TRX_STATE__TRAC_SUCCESS:
+                case AT86RF2XX_TRX_STATE__TRAC_SUCCESS_DATA_PENDING:
+                    dev->event_cb(NETDEV_EVENT_TX_COMPLETE, NULL);
+                    DEBUG("[at86rf2xx] TX SUCCESS\n");
+                    break;
+                case AT86RF2XX_TRX_STATE__TRAC_NO_ACK:
+                    dev->event_cb(NETDEV_EVENT_TX_NOACK, NULL);
+                    DEBUG("[at86rf2xx] TX NO_ACK\n");
+                    break;
+                case AT86RF2XX_TRX_STATE__TRAC_CHANNEL_ACCESS_FAILURE:
+                    dev->event_cb(NETDEV_EVENT_TX_MEDIUM_BUSY, NULL);
+                    DEBUG("[at86rf2xx] TX_CHANNEL_ACCESS_FAILURE\n");
+                    break;
+                default:
+                    DEBUG("[at86rf2xx] Unhandled TRAC_STATUS: %d\n",
+                          trac_status >> 5);
+                }
             }
-            DEBUG("[at86rf2xx] EVT - TX_END\n");
         }
     }
 }
diff --git a/sys/include/net/gnrc/netdev.h b/sys/include/net/gnrc/netdev.h
index f1b5a5997b..135f7c271a 100644
--- a/sys/include/net/gnrc/netdev.h
+++ b/sys/include/net/gnrc/netdev.h
@@ -49,6 +49,8 @@ typedef enum {
     NETDEV_EVENT_RX_COMPLETE    = 0x0002,   /**< finished receiving a packet */
     NETDEV_EVENT_TX_STARTED     = 0x0004,   /**< started to transfer a packet */
     NETDEV_EVENT_TX_COMPLETE    = 0x0008,   /**< finished transferring packet */
+    NETDEV_EVENT_TX_NOACK       = 0x0010,   /**< ACK requested but not received */
+    NETDEV_EVENT_TX_MEDIUM_BUSY = 0x0020,   /**< couldn't transfer packet */
     /* expand this list if needed */
 } gnrc_netdev_event_t;
 
-- 
GitLab