Implement the filter function to update short address, pan id and ieee
address on change. Allowing for hardware address filtering needed for
auto ACK. Switch state machine to use auto ACK states for rx.

This will handle CSMA/CA for us as well as re-sending frames when no ack comes
in timely.

The register names have been wrong since the beginning but it only showed up now
as they are actualy used for the upcoming auto ACK support.

Signed-off-by: Stefan Schmidt <ste...@datenfreihafen.org>
---
 drivers/ieee802154/at86rf230.c |  108 ++++++++++++++++++++++++++++++++++++++-
 1 files changed, 105 insertions(+), 3 deletions(-)

diff --git a/drivers/ieee802154/at86rf230.c b/drivers/ieee802154/at86rf230.c
index 4d32ac4..761343b 100644
--- a/drivers/ieee802154/at86rf230.c
+++ b/drivers/ieee802154/at86rf230.c
@@ -38,6 +38,9 @@
 long unsigned int bytes_tx;
 long unsigned int bytes_rx;
 
+#define ENABLE_AACK
+#define ENABLE_ARET
+
 struct at86rf230_local {
        struct spi_device *spi;
        int rstn, slp_tr, dig2;
@@ -236,8 +239,8 @@ struct at86rf230_local {
 #define STATE_SLEEP            0x0F
 #define STATE_BUSY_RX_AACK     0x11
 #define STATE_BUSY_TX_ARET     0x12
-#define STATE_BUSY_RX_AACK_ON  0x16
-#define STATE_BUSY_TX_ARET_ON  0x19
+#define STATE_RX_AACK_ON       0x16
+#define STATE_TX_ARET_ON       0x19
 #define STATE_RX_ON_NOCLK      0x1C
 #define STATE_RX_AACK_ON_NOCLK 0x1D
 #define STATE_BUSY_RX_AACK_NOCLK 0x1E
@@ -462,7 +465,11 @@ at86rf230_state(struct ieee802154_dev *dev, int state)
        might_sleep();
 
        if (state == STATE_FORCE_TX_ON)
+#ifdef ENABLE_ARET
+               desired_status = STATE_TX_ARET_ON;
+#else
                desired_status = STATE_TX_ON;
+#endif
        else if (state == STATE_FORCE_TRX_OFF)
                desired_status = STATE_TRX_OFF;
        else
@@ -488,10 +495,43 @@ at86rf230_state(struct ieee802154_dev *dev, int state)
                        goto err;
        } while (val == STATE_TRANSITION_IN_PROGRESS);
 
+#ifdef ENABLE_ARET
+       /* Make sure we go to TX_ON before we go to STATE_TX_ARET_ON  */
+       if (desired_status == STATE_TX_ARET_ON) {
+               rc = at86rf230_write_subreg(lp, SR_TRX_CMD, STATE_TX_ON);
+               if (rc)
+                       goto err;
+
+               do {
+                       rc = at86rf230_read_subreg(lp, SR_TRX_STATUS, &val);
+                       if (rc)
+                               goto err;
+                       pr_debug("%s val3 = %x\n", __func__, val);
+               } while (val == STATE_TRANSITION_IN_PROGRESS);
+
+               rc = at86rf230_write_subreg(lp, SR_TRX_CMD, desired_status);
+               if (rc)
+                       goto err;
+
+               do {
+                       rc = at86rf230_read_subreg(lp, SR_TRX_STATUS, &val);
+                       if (rc)
+                               goto err;
+                       pr_debug("%s val4 = %x\n", __func__, val);
+               } while (val == STATE_TRANSITION_IN_PROGRESS);
+       }
+#endif
 
        if (val == desired_status)
                return 0;
 
+#ifdef ENABLE_AACK
+       if (state == STATE_RX_AACK_ON && val == STATE_BUSY_RX_AACK)
+#else
+       if (state == STATE_RX_ON && val == STATE_BUSY_RX)
+#endif
+               return 0;
+
        pr_err("unexpected state change: %d, asked for %d\n", val, state);
        return -EBUSY;
 
@@ -510,7 +550,11 @@ at86rf230_start(struct ieee802154_dev *dev)
        if (rc)
                return rc;
 
+#ifdef ENABLE_AACK
+       return at86rf230_state(dev, STATE_RX_AACK_ON);
+#else
        return at86rf230_state(dev, STATE_RX_ON);
+#endif
 }
 
 static void
@@ -625,6 +669,54 @@ err:
        return -EINVAL;
 }
 
+#ifdef ENABLE_AACK
+static int
+at86rf230_set_hw_addr_filt(struct ieee802154_dev *dev,
+                                               struct ieee802154_hw_addr_filt 
*filt,
+                                               unsigned long changed)
+{
+       struct at86rf230_local *lp = dev->priv;
+
+       might_sleep();
+
+       at86rf230_stop(dev);
+
+       msleep(10);
+
+       if (changed & IEEE802515_AFILT_SADDR_CHANGED) {
+               __at86rf230_write(lp, RG_SHORT_ADDR_0, filt->short_addr & 
0xff); /* LSB */
+               __at86rf230_write(lp, RG_SHORT_ADDR_1, (filt->short_addr >> 8) 
& 0xff); /* MSB */
+       }
+
+       if (changed & IEEE802515_AFILT_PANID_CHANGED) {
+               __at86rf230_write(lp, RG_PAN_ID_0, filt->pan_id & 0xff); /* LSB 
*/
+               __at86rf230_write(lp, RG_PAN_ID_1, (filt->pan_id >> 8) & 0xff); 
/* MSB */
+       }
+
+       if (changed & IEEE802515_AFILT_IEEEADDR_CHANGED) {
+               // Make sure order MSB to LSB is correct
+               at86rf230_write_subreg(lp, SR_IEEE_ADDR_0, filt->ieee_addr[7]);
+               at86rf230_write_subreg(lp, SR_IEEE_ADDR_1, filt->ieee_addr[6]);
+               at86rf230_write_subreg(lp, SR_IEEE_ADDR_2, filt->ieee_addr[5]);
+               at86rf230_write_subreg(lp, SR_IEEE_ADDR_3, filt->ieee_addr[4]);
+               at86rf230_write_subreg(lp, SR_IEEE_ADDR_4, filt->ieee_addr[3]);
+               at86rf230_write_subreg(lp, SR_IEEE_ADDR_5, filt->ieee_addr[2]);
+               at86rf230_write_subreg(lp, SR_IEEE_ADDR_6, filt->ieee_addr[1]);
+               at86rf230_write_subreg(lp, SR_IEEE_ADDR_7, filt->ieee_addr[0]);
+       }
+
+       if (changed & IEEE802515_AFILT_PANC_CHANGED) {
+               if (filt->pan_coord)
+                       at86rf230_write_subreg(lp, SR_AACK_I_AM_COORD, 1);
+               else
+                       at86rf230_write_subreg(lp, SR_AACK_I_AM_COORD, 0);
+       }
+
+       at86rf230_start(dev);
+
+       return 0;
+}
+#endif
 static struct ieee802154_ops at86rf230_ops = {
        .owner = THIS_MODULE,
        .xmit = at86rf230_xmit,
@@ -632,6 +724,9 @@ static struct ieee802154_ops at86rf230_ops = {
        .set_channel = at86rf230_channel,
        .start = at86rf230_start,
        .stop = at86rf230_stop,
+#ifdef ENABLE_AACK
+       .set_hw_addr_filt = at86rf230_set_hw_addr_filt,
+#endif
 };
 
 static void at86rf230_irqwork(struct work_struct *work)
@@ -680,7 +775,6 @@ static irqreturn_t at86rf230_isr(int irq, void *data)
        return IRQ_HANDLED;
 }
 
-
 static int at86rf230_hw_init(struct at86rf230_local *lp)
 {
        u8 status;
@@ -718,7 +812,11 @@ static int at86rf230_hw_init(struct at86rf230_local *lp)
        /* Wait the next SLEEP cycle */
        msleep(100);
 
+#ifdef ENABLE_ARET
+       rc = at86rf230_write_subreg(lp, SR_TRX_CMD, STATE_TX_ARET_ON);
+#else
        rc = at86rf230_write_subreg(lp, SR_TRX_CMD, STATE_TX_ON);
+#endif
        if (rc)
                return rc;
        msleep(1);
@@ -802,7 +900,11 @@ static int __devinit at86rf230_probe(struct spi_device 
*spi)
        dev->extra_tx_headroom = 0;
        /* We do support only 2.4 Ghz */
        dev->phy->channels_supported[0] = 0x7FFF800;
+#ifdef ENABLE_AACK
+       dev->flags = IEEE802154_HW_OMIT_CKSUM | IEEE802154_HW_AACK;
+#else
        dev->flags = IEEE802154_HW_OMIT_CKSUM;
+#endif
 
        mutex_init(&lp->bmux);
        INIT_WORK(&lp->irqwork, at86rf230_irqwork);
-- 
1.7.5.4


------------------------------------------------------------------------------
Everyone hates slow websites. So do we.
Make your web apps faster with AppDynamics
Download AppDynamics Lite for free today:
http://p.sf.net/sfu/appdyn_d2d_mar
_______________________________________________
Linux-zigbee-devel mailing list
Linux-zigbee-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-zigbee-devel

Reply via email to