
6 changed files with 593 additions and 18 deletions
@ -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]); |
||||
} |
||||
} |
||||
|
||||
/** @} */ |
@ -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; |
||||
} |
||||
|
||||
/** @} */ |
@ -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_ */ |
||||
/** @} */ |
@ -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); |
||||
} |
||||
|
||||
/** @} */ |
Loading…
Reference in new issue