From dff0c528ff60ec8d61b017b5c6acb2ceb1e91835 Mon Sep 17 00:00:00 2001
From: Martine Lenders <mlenders@inf.fu-berlin.de>
Date: Mon, 25 Jan 2016 00:17:49 +0100
Subject: [PATCH] tests: modify driver_at86rf2xx for pure netdev2

---
 tests/driver_at86rf2xx/Makefile |   7 +-
 tests/driver_at86rf2xx/addr.c   |  31 ++++
 tests/driver_at86rf2xx/cmd.c    | 306 ++++++++++++++++++++++++++++++++
 tests/driver_at86rf2xx/common.h |  53 ++++++
 tests/driver_at86rf2xx/main.c   |  97 ++++++++--
 tests/driver_at86rf2xx/recv.c   | 117 ++++++++++++
 6 files changed, 593 insertions(+), 18 deletions(-)
 create mode 100644 tests/driver_at86rf2xx/addr.c
 create mode 100644 tests/driver_at86rf2xx/cmd.c
 create mode 100644 tests/driver_at86rf2xx/common.h
 create mode 100644 tests/driver_at86rf2xx/recv.c

diff --git a/tests/driver_at86rf2xx/Makefile b/tests/driver_at86rf2xx/Makefile
index 03f6c10e65..02dc1afe96 100644
--- a/tests/driver_at86rf2xx/Makefile
+++ b/tests/driver_at86rf2xx/Makefile
@@ -3,12 +3,9 @@ include ../Makefile.tests_common
 
 FEATURES_REQUIRED = periph_spi periph_gpio
 
-BOARD_INSUFFICIENT_MEMORY := nucleo-f334 stm32f0discovery weio
+DISABLE_MODULE += auto_init
 
-USEMODULE += auto_init_gnrc_netif
-USEMODULE += gnrc_netif
-USEMODULE += gnrc_nomac
-USEMODULE += gnrc_pktdump
+USEMODULE += od
 USEMODULE += shell
 USEMODULE += shell_commands
 USEMODULE += ps
diff --git a/tests/driver_at86rf2xx/addr.c b/tests/driver_at86rf2xx/addr.c
new file mode 100644
index 0000000000..af6b0c2261
--- /dev/null
+++ b/tests/driver_at86rf2xx/addr.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser
+ * General Public License v2.1. See the file LICENSE in the top level
+ * directory for more details.
+ */
+
+/**
+ * @{
+ *
+ * @file
+ * @author Martine Lenders <mlenders@inf.fu-berlin.de>
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+
+#include "common.h"
+
+void print_addr(uint8_t *addr, size_t addr_len)
+{
+    for (int i = 0; i < addr_len; i++) {
+        if (i != 0) {
+            printf(":");
+        }
+        printf("%02x", (unsigned)addr[i]);
+    }
+}
+
+/** @} */
diff --git a/tests/driver_at86rf2xx/cmd.c b/tests/driver_at86rf2xx/cmd.c
new file mode 100644
index 0000000000..10d44df3f9
--- /dev/null
+++ b/tests/driver_at86rf2xx/cmd.c
@@ -0,0 +1,306 @@
+/*
+ * Copyright (C) 2016 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser
+ * General Public License v2.1. See the file LICENSE in the top level
+ * directory for more details.
+ */
+
+/**
+ * @{
+ *
+ * @file
+ * @author  Martine Lenders <mlenders@inf.fu-berlin.de>
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "net/netdev2/ieee802154.h"
+#include "net/ieee802154.h"
+
+#include "common.h"
+
+#include "od.h"
+
+#define _MAX_ADDR_LEN   (8)
+
+static int _parse_addr(uint8_t *out, size_t out_len, const char *in);
+static int send(int iface, le_uint16_t dst_pan, uint8_t *dst_addr,
+                size_t dst_len, char *data);
+
+int ifconfig_list(int idx)
+{
+    int res;
+    uint8_t array_val[_MAX_ADDR_LEN];
+    netdev2_ieee802154_t *dev = (netdev2_ieee802154_t *)(&devs[idx]);
+
+    int (*get)(netdev2_t *, netopt_t, void *, size_t) = dev->netdev.driver->get;
+    netopt_enable_t enable_val;
+    uint16_t u16_val;
+
+    printf("Iface %3d  HWaddr: ", idx);
+    print_addr(dev->short_addr, IEEE802154_SHORT_ADDRESS_LEN);
+    printf(", Long HWaddr: ");
+    print_addr(dev->long_addr, IEEE802154_LONG_ADDRESS_LEN);
+    printf(", PAN: 0x%04x", dev->pan);
+
+    res = get((netdev2_t *)dev, NETOPT_ADDR_LEN, &u16_val, sizeof(u16_val));
+    if (res < 0) {
+        puts("(err)");
+        return 1;
+    }
+    printf("\n           Address length: %u", (unsigned)u16_val);
+
+    res = get((netdev2_t *)dev, NETOPT_SRC_LEN, &u16_val, sizeof(u16_val));
+    if (res < 0) {
+        puts("(err)");
+        return 1;
+    }
+    printf(", Source address length: %u", (unsigned)u16_val);
+
+    res = get((netdev2_t *)dev, NETOPT_MAX_PACKET_SIZE, &u16_val,
+              sizeof(u16_val));
+    if (res < 0) {
+        puts("(err)");
+        return 1;
+    }
+    printf(", Max.Payload: %u", (unsigned)u16_val);
+
+    res = get((netdev2_t *)dev, NETOPT_IPV6_IID, array_val, sizeof(array_val));
+    if (res > 0) {
+        printf("\n           IPv6 IID: ");
+        print_addr(array_val, res);
+    }
+
+    printf("\n           Channel: %u", dev->chan);
+
+    res = get((netdev2_t *)dev, NETOPT_CHANNEL_PAGE, &u16_val, sizeof(u16_val));
+    if (res < 0) {
+        puts("(err)");
+        return 1;
+    }
+    printf(", Ch.page: %u", (unsigned)u16_val);
+
+    res = get((netdev2_t *)dev, NETOPT_TX_POWER, &u16_val, sizeof(u16_val));
+    if (res < 0) {
+        puts("(err)");
+        return 1;
+    }
+    printf(", TXPower: %d dBm", (int)u16_val);
+    res = get((netdev2_t *)dev, NETOPT_IS_WIRED, &u16_val, sizeof(u16_val));
+    if (res < 0) {
+        puts(", wireless");
+    }
+    else {
+        puts(", wired");
+    }
+
+    printf("         ");
+    res = get((netdev2_t *)dev, NETOPT_PRELOADING, &enable_val,
+              sizeof(netopt_enable_t));
+    if ((res > 0) && (enable_val == NETOPT_ENABLE)) {
+        printf("  PRELOAD");
+    }
+    res = get((netdev2_t *)dev, NETOPT_AUTOACK, &enable_val,
+              sizeof(netopt_enable_t));
+    if ((res > 0) && (enable_val == NETOPT_ENABLE)) {
+        printf("  AUTOACK");
+    }
+    res = get((netdev2_t *)dev, NETOPT_RAWMODE, &enable_val,
+              sizeof(netopt_enable_t));
+    if ((res > 0) && (enable_val == NETOPT_ENABLE)) {
+        printf("  RAW");
+    }
+    res = get((netdev2_t *)dev, NETOPT_AUTOCCA, &enable_val,
+              sizeof(netopt_enable_t));
+    if ((res > 0) && (enable_val == NETOPT_ENABLE)) {
+        printf("  AUTOCCA");
+    }
+    res = get((netdev2_t *)dev, NETOPT_CSMA, &enable_val,
+              sizeof(netopt_enable_t));
+    if ((res > 0) && (enable_val == NETOPT_ENABLE)) {
+        printf("  CSMA");
+    }
+    puts("");
+
+    return 0;
+}
+
+int ifconfig(int argc, char **argv)
+{
+    (void)argc;
+    (void)argv;
+    for (int i = 0; i < AT86RF2XX_NUM; i++) {
+        ifconfig_list(i);
+    }
+    return 0;
+}
+
+static void txtsnd_usage(char *cmd_name)
+{
+    printf("usage: %s <iface> [<pan>] <addr> <text>\n", cmd_name);
+}
+
+int txtsnd(int argc, char **argv)
+{
+    char *text;
+    uint8_t addr[_MAX_ADDR_LEN];
+    int iface, idx = 2, res;
+    le_uint16_t pan = { 0 };
+
+    switch (argc) {
+        case 4:
+            break;
+        case 5:
+            res = _parse_addr((uint8_t *)&pan, sizeof(pan), argv[idx++]);
+            if ((res <= 0) || (res > sizeof(pan))) {
+                txtsnd_usage(argv[0]);
+                return 1;
+            }
+            pan.u16 = byteorder_swaps(pan.u16);
+            break;
+        default:
+            txtsnd_usage(argv[0]);
+            return 1;
+    }
+
+    iface = atoi(argv[1]);
+    res = _parse_addr(addr, sizeof(addr), argv[idx++]);
+    if (res <= 0) {
+        txtsnd_usage(argv[0]);
+        return 1;
+    }
+    text = argv[idx++];
+    return send(iface, pan, addr, (size_t)res, text);
+}
+
+static inline int _dehex(char c, int default_)
+{
+    if ('0' <= c && c <= '9') {
+        return c - '0';
+    }
+    else if ('A' <= c && c <= 'F') {
+        return c - 'A' + 10;
+    }
+    else if ('a' <= c && c <= 'f') {
+        return c - 'a' + 10;
+    }
+    else {
+        return default_;
+    }
+}
+
+static int _parse_addr(uint8_t *out, size_t out_len, const char *in)
+{
+    const char *end_str = in;
+    uint8_t *out_end = out;
+    size_t count = 0;
+    int assert_cell = 1;
+
+    if (!in || !*in) {
+        return 0;
+    }
+    while (end_str[1]) {
+        ++end_str;
+    }
+
+    while (end_str >= in) {
+        int a = 0, b = _dehex(*end_str--, -1);
+        if (b < 0) {
+            if (assert_cell) {
+                return 0;
+            }
+            else {
+                assert_cell = 1;
+                continue;
+            }
+        }
+        assert_cell = 0;
+
+        if (end_str >= in) {
+            a = _dehex(*end_str--, 0);
+        }
+
+        if (++count > out_len) {
+            return 0;
+        }
+        *out_end++ = (a << 4) | b;
+    }
+    if (assert_cell) {
+        return 0;
+    }
+    /* out is reversed */
+
+    while (out < --out_end) {
+        uint8_t tmp = *out_end;
+        *out_end = *out;
+        *out++ = tmp;
+    }
+
+    return count;
+}
+
+static int send(int iface, le_uint16_t dst_pan, uint8_t *dst, size_t dst_len,
+                char *data)
+{
+    int res;
+    netdev2_ieee802154_t *dev;
+    const size_t count = 2;         /* mhr + payload */
+    struct iovec vector[count];
+    uint8_t *src;
+    size_t src_len;
+    uint8_t mhr[IEEE802154_MAX_HDR_LEN];
+    uint8_t flags;
+    le_uint16_t src_pan;
+
+    if (((unsigned)iface) > (AT86RF2XX_NUM - 1)) {
+        printf("txtsnd: %d is not an interface\n", iface);
+        return 1;
+    }
+
+    dev = (netdev2_ieee802154_t *)&devs[iface];
+    flags = (uint8_t)(dev->flags & NETDEV2_IEEE802154_SEND_MASK);
+    flags |= IEEE802154_FCF_TYPE_DATA;
+    vector[1].iov_base = data;
+    vector[1].iov_len = strlen(data);
+    src_pan = byteorder_btols(byteorder_htons(dev->pan));
+    if (dst_pan.u16 == 0) {
+        dst_pan = src_pan;
+    }
+    if (dev->flags & NETDEV2_IEEE802154_SRC_MODE_LONG) {
+        src_len = 8;
+        src = dev->long_addr;
+    }
+    else {
+        src_len = 2;
+        src = dev->short_addr;
+    }
+    /* fill MAC header, seq should be set by device */
+    if ((res = ieee802154_set_frame_hdr(mhr, src, src_len,
+                                        dst, dst_len,
+                                        src_pan, dst_pan,
+                                        flags, dev->seq++)) < 0) {
+        puts("txtsnd: Error preperaring frame");
+        return 1;
+    }
+    vector[0].iov_base = mhr;
+    vector[0].iov_len = (size_t)res;
+    res = dev->netdev.driver->send((netdev2_t *)dev, vector, count);
+    if (res < 0) {
+        puts("txtsnd: Error on sending");
+        return 1;
+    }
+    else {
+        printf("txtsnd: send %u bytes to ", (unsigned)vector[1].iov_len);
+        print_addr(dst, dst_len);
+        printf(" (PAN: ");
+        print_addr((uint8_t *)&dst_pan, sizeof(dst_pan));
+        puts(")");
+    }
+    return 0;
+}
+
+/** @} */
diff --git a/tests/driver_at86rf2xx/common.h b/tests/driver_at86rf2xx/common.h
new file mode 100644
index 0000000000..8829b6e54d
--- /dev/null
+++ b/tests/driver_at86rf2xx/common.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2016 Martine Lenders <mlenders@inf.fu-berlin.de>
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser
+ * General Public License v2.1. See the file LICENSE in the top level
+ * directory for more details.
+ */
+
+/**
+ * @ingroup     tests
+ * @{
+ *
+ * @file
+ * @brief   Common header for at86rf2xx tests
+ *
+ * @author  Martine Lenders <mlenders@inf.fu-berlin.de>
+ */
+#ifndef COMMON_H_
+#define COMMON_H_
+
+#include <stdint.h>
+
+#include "at86rf2xx.h"
+#include "at86rf2xx_params.h"
+#include "net/netdev2.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief   Application-internal functions and variables for at86rf2xx tests
+ * @internal
+ * @{
+ */
+#define AT86RF2XX_NUM   (sizeof(at86rf2xx_params) / sizeof(at86rf2xx_params[0]))
+
+extern at86rf2xx_t devs[AT86RF2XX_NUM];
+
+void recv(netdev2_t *dev);
+int ifconfig(int argc, char **argv);
+int txtsnd(int argc, char **argv);
+void print_addr(uint8_t *addr, size_t addr_len);
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* COMMON_H_ */
+/** @} */
diff --git a/tests/driver_at86rf2xx/main.c b/tests/driver_at86rf2xx/main.c
index 1a5f12f9a7..1be7bfb5bb 100644
--- a/tests/driver_at86rf2xx/main.c
+++ b/tests/driver_at86rf2xx/main.c
@@ -20,31 +20,102 @@
 
 #include <stdio.h>
 
+#include "net/netdev2.h"
 #include "shell.h"
 #include "shell_commands.h"
-#include "net/gnrc/pktdump.h"
-#include "net/gnrc.h"
+#include "thread.h"
+#include "xtimer.h"
 
-/**
- * @brief   Maybe you are a golfer?!
- */
-int main(void)
+#include "common.h"
+
+#define _STACKSIZE      (THREAD_STACKSIZE_DEFAULT + THREAD_EXTRA_STACKSIZE_PRINTF)
+#define MSG_TYPE_ISR    (0x3456)
+
+static char stack[_STACKSIZE];
+static kernel_pid_t _recv_pid;
+
+at86rf2xx_t devs[AT86RF2XX_NUM];
+
+static const shell_command_t shell_commands[] = {
+    { "ifconfig", "Configure netdev2", ifconfig },
+    { "txtsnd", "Send IEEE 802.15.4 packet", txtsnd },
+    { NULL, NULL, NULL }
+};
+
+static void _event_cb(netdev2_t *dev, netdev2_event_t event, void *data)
 {
-    gnrc_netreg_entry_t dump;
+    (void) data;
+
+    if (event == NETDEV2_EVENT_ISR) {
+        msg_t msg;
+
+        msg.type = MSG_TYPE_ISR;
+        msg.content.ptr = (void *) dev;
+
+        if (msg_send(&msg, _recv_pid) <= 0) {
+            puts("gnrc_netdev2: possibly lost interrupt.");
+        }
+    }
+    else {
+        switch (event) {
+            case NETDEV2_EVENT_RX_COMPLETE:
+            {
+                recv(dev);
 
+                break;
+            }
+            default:
+                puts("Unexpected event received");
+                break;
+        }
+    }
+}
+
+void *_recv_thread(void *arg)
+{
+    while (1) {
+        msg_t msg;
+        msg_receive(&msg);
+        if (msg.type == MSG_TYPE_ISR) {
+            netdev2_t *dev = (netdev2_t *)msg.content.ptr;
+            dev->driver->isr(dev);
+        }
+        else {
+            puts("unexpected message type");
+        }
+    }
+}
+
+int main(void)
+{
     puts("AT86RF2xx device driver test");
+    xtimer_init();
+
+    for (unsigned i = 0; i < AT86RF2XX_NUM; i++) {
+        const at86rf2xx_params_t *p = &at86rf2xx_params[i];
+        netdev2_t *dev = (netdev2_t *)(&devs[i]);
+
+        printf("Initializing AT86RF2xx radio at SPI_%d\n", p->spi);
+        at86rf2xx_setup(&devs[i], p->spi, p->spi_speed, p->cs_pin,
+                        p->int_pin, p->sleep_pin, p->reset_pin);
+        dev->event_callback = _event_cb;
+        dev->driver->init(dev);
+    }
+
+    _recv_pid = thread_create(stack, sizeof(stack), THREAD_PRIORITY_MAIN - 1,
+                              THREAD_CREATE_STACKTEST, _recv_thread, NULL,
+                              "recv_thread");
 
-    /* register the pktdump thread */
-    puts("Register the packet dump thread for GNRC_NETTYPE_UNDEF packets");
-    dump.pid = gnrc_pktdump_pid;
-    dump.demux_ctx = GNRC_NETREG_DEMUX_CTX_ALL;
-    gnrc_netreg_register(GNRC_NETTYPE_UNDEF, &dump);
+    if (_recv_pid <= KERNEL_PID_UNDEF) {
+        puts("Creation of receiver thread failed");
+        return 1;
+    }
 
     /* start the shell */
     puts("Initialization successful - starting the shell now");
 
     char line_buf[SHELL_DEFAULT_BUFSIZE];
-    shell_run(NULL, line_buf, SHELL_DEFAULT_BUFSIZE);
+    shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE);
 
     return 0;
 }
diff --git a/tests/driver_at86rf2xx/recv.c b/tests/driver_at86rf2xx/recv.c
new file mode 100644
index 0000000000..d351eb2574
--- /dev/null
+++ b/tests/driver_at86rf2xx/recv.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser
+ * General Public License v2.1. See the file LICENSE in the top level
+ * directory for more details.
+ */
+
+/**
+ * @{
+ *
+ * @file
+ * @author Martine Lenders <mlenders@inf.fu-berlin.de>
+ */
+
+#include <stdio.h>
+
+#include "at86rf2xx.h"
+#include "od.h"
+#include "net/ieee802154.h"
+#include "net/netdev2.h"
+
+#include "common.h"
+
+#define MAX_LINE    (80)
+
+static uint8_t buffer[AT86RF2XX_MAX_PKT_LENGTH];
+
+void recv(netdev2_t *dev)
+{
+    uint8_t src[IEEE802154_LONG_ADDRESS_LEN], dst[IEEE802154_LONG_ADDRESS_LEN];
+    size_t mhr_len, data_len, src_len, dst_len;
+    netdev2_ieee802154_rx_info_t rx_info;
+    le_uint16_t src_pan, dst_pan;
+
+    putchar('\n');
+    data_len = dev->driver->recv(dev, (char *)buffer, sizeof(buffer), &rx_info);
+    mhr_len = ieee802154_get_frame_hdr_len(buffer);
+    if (mhr_len == 0) {
+        puts("Unexpected MHR for incoming packet");
+        return;
+    }
+    dst_len = ieee802154_get_dst(buffer, dst, &dst_pan);
+    src_len = ieee802154_get_src(buffer, src, &src_pan);
+    switch (buffer[0] & IEEE802154_FCF_TYPE_MASK) {
+        case IEEE802154_FCF_TYPE_BEACON:
+            puts("BEACON");
+            break;
+        case IEEE802154_FCF_TYPE_DATA:
+            puts("DATA");
+            break;
+        case IEEE802154_FCF_TYPE_ACK:
+            puts("ACK");
+            break;
+        case IEEE802154_FCF_TYPE_MACCMD:
+            puts("MACCMD");
+            break;
+        default:
+            puts("UNKNOWN");
+            break;
+    }
+    printf("Dest. PAN: 0x%04x, Dest. addr.: ",
+           byteorder_ntohs(byteorder_ltobs(dst_pan)));
+    print_addr(dst, dst_len);
+    printf("\nSrc. PAN: 0x%04x, Src. addr.: ",
+           byteorder_ntohs(byteorder_ltobs(src_pan)));
+    print_addr(src, src_len);
+    printf("\nSecurity: ");
+    if (buffer[0] & IEEE802154_FCF_SECURITY_EN) {
+        printf("1, ");
+    }
+    else {
+        printf("0, ");
+    }
+    printf("Frame pend.: ");
+    if (buffer[0] & IEEE802154_FCF_FRAME_PEND) {
+        printf("1, ");
+    }
+    else {
+        printf("0, ");
+    }
+    printf("ACK req.: ");
+    if (buffer[0] & IEEE802154_FCF_ACK_REQ) {
+        printf("1, ");
+    }
+    else {
+        printf("0, ");
+    }
+    printf("PAN comp.: ");
+    if (buffer[0] & IEEE802154_FCF_ACK_REQ) {
+        puts("1");
+    }
+    else {
+        puts("0");
+    }
+    printf("Version: ");
+    printf("%u, ", (unsigned)((buffer[1] & IEEE802154_FCF_VERS_MASK) >> 4));
+    printf("Seq.: %u\n", (unsigned)ieee802154_get_seq(buffer));
+    od_hex_dump(buffer + mhr_len, data_len - mhr_len, 0);
+    printf("txt: ");
+    for (int i = mhr_len; i < data_len; i++) {
+        if ((buffer[i] > 0x1F) && (buffer[i] < 0x80)) {
+            putchar((char)buffer[i]);
+        }
+        else {
+            putchar('?');
+        }
+        if (((((i - mhr_len) + 1) % (MAX_LINE - sizeof("txt: "))) == 1) &&
+            (i - mhr_len) != 0) {
+            printf("\n     ");
+        }
+    }
+    printf("\n");
+    printf("RSSI: %u, LQI: %u\n\n", rx_info.rssi, rx_info.lqi);
+}
+
+/** @} */
-- 
GitLab