mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
drivers/xbee: adapted to netdev2
This commit is contained in:
parent
11a0422b83
commit
83d206e2b0
@ -73,3 +73,6 @@ endif
|
||||
ifneq (,$(filter w5100,$(USEMODULE)))
|
||||
USEMODULE_INCLUDES += $(RIOTBASE)/drivers/w5100/include
|
||||
endif
|
||||
ifneq (,$(filter xbee,$(USEMODULE)))
|
||||
USEMODULE_INCLUDES += $(RIOTBASE)/drivers/xbee/include
|
||||
endif
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2014 INRIA
|
||||
* Copyright (C) 2015 Freie Universität Berlin
|
||||
* Copyright (C) 2015-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
|
||||
@ -29,8 +29,9 @@
|
||||
#include "xtimer.h"
|
||||
#include "periph/uart.h"
|
||||
#include "periph/gpio.h"
|
||||
#include "net/gnrc.h"
|
||||
#include "net/netdev2.h"
|
||||
#include "net/ieee802154.h"
|
||||
#include "net/gnrc/nettype.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -55,6 +56,11 @@ extern "C" {
|
||||
*/
|
||||
#define XBEE_MAX_RESP_LENGTH (16U)
|
||||
|
||||
/**
|
||||
* @brief Maximal possible size of a TX header
|
||||
*/
|
||||
#define XBEE_MAX_TXHDR_LENGTH (14U)
|
||||
|
||||
/**
|
||||
* @brief Default protocol for data that is coming in
|
||||
*/
|
||||
@ -95,31 +101,43 @@ extern "C" {
|
||||
* frame specific data as the frame size, frame type, and checksums.
|
||||
*/
|
||||
typedef enum {
|
||||
XBEE_INT_STATE_IDLE, /**< waiting for the beginning of a new frame */
|
||||
XBEE_INT_STATE_SIZE1, /**< waiting for the first byte (MSB) of the
|
||||
* frame size field */
|
||||
XBEE_INT_STATE_SIZE2, /**< waiting for the second byte (LSB) of the
|
||||
* frame size field */
|
||||
XBEE_INT_STATE_TYPE, /**< waiting for the frame type field */
|
||||
XBEE_INT_STATE_RESP, /**< handling incoming data for AT command
|
||||
* responses */
|
||||
XBEE_INT_STATE_RX, /**< handling incoming data when receiving radio
|
||||
* packets */
|
||||
XBEE_INT_STATE_IDLE, /**< waiting for the beginning of a new frame */
|
||||
XBEE_INT_STATE_SIZE1, /**< waiting for the first byte (MSB) of the
|
||||
* frame size field */
|
||||
XBEE_INT_STATE_SIZE2, /**< waiting for the second byte (LSB) of the
|
||||
* frame size field */
|
||||
XBEE_INT_STATE_TYPE, /**< waiting for the frame type field */
|
||||
XBEE_INT_STATE_RESP, /**< handling incoming data for AT command
|
||||
* responses */
|
||||
XBEE_INT_STATE_RX, /**< handling incoming data when receiving radio
|
||||
* packets */
|
||||
} xbee_rx_state_t;
|
||||
|
||||
/**
|
||||
* @brief Configuration parameters for XBee devices
|
||||
*/
|
||||
typedef struct {
|
||||
uart_t uart; /**< UART interfaced the device is connected to */
|
||||
uint32_t br; /**< baudrate to use */
|
||||
gpio_t pin_sleep; /**< GPIO pin that is connected to the SLEEP pin
|
||||
set to GPIO_UNDEF if not used */
|
||||
gpio_t pin_reset; /**< GPIO pin that is connected to the STATUS pin
|
||||
set to GPIO_UNDEF if not used */
|
||||
} xbee_params_t;
|
||||
|
||||
/**
|
||||
* @brief XBee device descriptor
|
||||
*/
|
||||
typedef struct {
|
||||
/* netdev fields */
|
||||
gnrc_netdev_driver_t const *driver; /**< pointer to the devices interface */
|
||||
gnrc_netdev_event_cb_t event_cb; /**< netdev event callback */
|
||||
kernel_pid_t mac_pid; /**< the driver's thread's PID */
|
||||
const struct netdev2_driver *driver; /**< ptr to that driver's interface. */
|
||||
netdev2_event_cb_t event_callback; /**< callback for device events */
|
||||
void* context; /**< ptr to network stack context */
|
||||
#ifdef MODULE_NETSTATS_L2
|
||||
netstats_t stats; /**< transceiver's statistics */
|
||||
#endif
|
||||
/* device driver specific fields */
|
||||
uart_t uart; /**< UART interfaced used */
|
||||
gpio_t reset_pin; /**< GPIO pin connected to RESET */
|
||||
gpio_t sleep_pin; /**< GPIO pin connected to SLEEP */
|
||||
gnrc_nettype_t proto; /**< protocol the interface speaks */
|
||||
xbee_params_t p; /**< configuration parameters */
|
||||
uint8_t options; /**< options field */
|
||||
uint8_t addr_flags; /**< address flags as defined above */
|
||||
uint8_t addr_short[2]; /**< onw 802.15.4 short address */
|
||||
@ -131,7 +149,8 @@ typedef struct {
|
||||
/* values for the UART TX state machine */
|
||||
mutex_t tx_lock; /**< mutex to allow only one
|
||||
* transmission at a time */
|
||||
uint8_t tx_buf[XBEE_MAX_PKT_LENGTH];/**< transmit data buffer */
|
||||
uint8_t cmd_buf[XBEE_MAX_RESP_LENGTH];/**< command data buffer */
|
||||
uint8_t tx_fid; /**< TX frame ID */
|
||||
/* buffer and synchronization for command responses */
|
||||
mutex_t resp_lock; /**< mutex for waiting for AT command
|
||||
* response frames */
|
||||
@ -145,24 +164,23 @@ typedef struct {
|
||||
} xbee_t;
|
||||
|
||||
/**
|
||||
* @brief auto_init struct holding Xbee device initalization params
|
||||
* @brief Data structure for extraction L2 information of received packets
|
||||
*/
|
||||
typedef struct xbee_params {
|
||||
uart_t uart; /**< UART interfaced the device is connected to */
|
||||
uint32_t baudrate; /**< baudrate to use */
|
||||
gpio_t sleep_pin; /**< GPIO pin that is connected to the SLEEP pin
|
||||
set to GPIO_UNDEF if not used */
|
||||
gpio_t reset_pin; /**< GPIO pin that is connected to the STATUS pin
|
||||
set to GPIO_UNDEF if not used */
|
||||
} xbee_params_t;
|
||||
typedef struct {
|
||||
uint8_t addr_len; /**< L2 address length (SRC and DST) */
|
||||
uint8_t bcast; /**< 0 := unicast, 1:=broadcast */
|
||||
uint8_t rssi; /**< RSSI value */
|
||||
uint8_t src_addr[8]; /**< L2 source address */
|
||||
uint8_t dst_addr[8]; /**< L2 dst address */
|
||||
} xbee_l2hdr_t;
|
||||
|
||||
/**
|
||||
* @brief Reference to the XBee driver interface
|
||||
*/
|
||||
extern const gnrc_netdev_driver_t xbee_driver;
|
||||
extern const netdev2_driver_t xbee_driver;
|
||||
|
||||
/**
|
||||
* @brief Initialize the given Xbee device
|
||||
* @brief Prepare the given Xbee device
|
||||
*
|
||||
* @param[out] dev Xbee device to initialize
|
||||
* @param[in] params parameters for device initialization
|
||||
@ -171,7 +189,34 @@ extern const gnrc_netdev_driver_t xbee_driver;
|
||||
* @return -ENODEV on invalid device descriptor
|
||||
* @return -ENXIO on invalid UART or GPIO pins
|
||||
*/
|
||||
int xbee_init(xbee_t *dev, const xbee_params_t *params);
|
||||
void xbee_setup(xbee_t *dev, const xbee_params_t *params);
|
||||
|
||||
/**
|
||||
* @brief Put together the internal proprietary XBee header
|
||||
*
|
||||
* @param[out] xhdr buffer to write the header into, MUST be at least of
|
||||
* length XBEE_MAX_TXHDR_LENGTH
|
||||
* @param[in] payload_len actual payload length (without the XBee header)
|
||||
* @param[in] dst_addr link layer (L2) destination address
|
||||
* @param[in] addr_len length of @p dst_addr in byte (MUST be 2 or 8)
|
||||
*
|
||||
* @return the length of the created header in byte
|
||||
* @return -EOVERFLOW if @p payload_len is greater than XBEE_MAX_PAYLOAD_LENGTH
|
||||
* @return -ENOMSG if the given destination address has an invalid length
|
||||
*/
|
||||
int xbee_build_hdr(xbee_t *dev, uint8_t *xhdr, size_t payload_len,
|
||||
void *dst_addr, size_t addr_len);
|
||||
|
||||
/**
|
||||
* @brief Extract IEEE802.15.4 L2 header information from the XBee header
|
||||
*
|
||||
* @param[in] xhdr XBee header, starting with the API identifier
|
||||
* @param[out] l2hdr the L2 header information is written here
|
||||
*
|
||||
* @return the length of the XBee header
|
||||
* @return -ENOMST if the given XBee header is invalid
|
||||
*/
|
||||
int xbee_parse_hdr(xbee_t *dev, const uint8_t *xhdr, xbee_l2hdr_t *l2hdr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
66
drivers/xbee/include/xbee_params.h
Normal file
66
drivers/xbee/include/xbee_params.h
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Kaspar Schleiser <kaspar@schleiser.de>
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup drivers_xbee
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Default configuration for XBee devices
|
||||
*
|
||||
* @author Kaspar Schleiser <kaspar@schleiser.de>
|
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
*/
|
||||
|
||||
#ifndef XBEE_PARAMS_H
|
||||
#define XBEE_PARAMS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Set default configuration parameters for the XBee driver
|
||||
* @{
|
||||
*/
|
||||
#ifndef XBEE_PARAM_UART
|
||||
#define XBEE_PARAM_UART (UART_DEV(1))
|
||||
#endif
|
||||
#ifndef XBEE_PARAM_BR
|
||||
#define XBEE_PARAM_BR (9600U)
|
||||
#endif
|
||||
#ifndef XBEE_PARAM_PIN_SLEEP
|
||||
#define XBEE_PARAM_PIN_SLEEP (GPIO_UNDEF)
|
||||
#endif
|
||||
#ifndef XBEE_PARAM_PIN_RESET
|
||||
#define XBEE_PARAM_PIN_RESET (GPIO_UNDEF)
|
||||
#endif
|
||||
|
||||
#ifndef XBEE_PARAMS
|
||||
#define XBEE_PARAMS { .uart = XBEE_PARAM_UART, \
|
||||
.br = XBEE_PARAM_BR, \
|
||||
.pin_sleep = XBEE_PARAM_PIN_SLEEP, \
|
||||
.pin_reset = XBEE_PARAM_PIN_RESET }
|
||||
#endif
|
||||
/**@}*/
|
||||
|
||||
/**
|
||||
* @brief XBee configuration
|
||||
*/
|
||||
static const xbee_params_t xbee_params[] =
|
||||
{
|
||||
XBEE_PARAMS
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* XBEE_PARAMS_H */
|
||||
/** @} */
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2014 INRIA
|
||||
* Copyright (C) 2015 Freie Universität Berlin
|
||||
* Copyright (C) 2015-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
|
||||
@ -21,13 +21,14 @@
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "xbee.h"
|
||||
#include "assert.h"
|
||||
#include "xtimer.h"
|
||||
#include "msg.h"
|
||||
#include "net/eui64.h"
|
||||
#include "net/netdev2.h"
|
||||
#include "net/ieee802154.h"
|
||||
#include "periph/cpuid.h"
|
||||
|
||||
#define ENABLE_DEBUG (0)
|
||||
#include "debug.h"
|
||||
@ -76,6 +77,8 @@
|
||||
* @{
|
||||
*/
|
||||
#define OPT_DIS_AUTO_ACK (0x01) /**< disable sending of auto ACKs */
|
||||
#define OPT_BCAST_ADDR (0x02) /**< address broadcast */
|
||||
#define OPT_BCAST_PAN (0x04) /**< PAN broadcast */
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
@ -91,10 +94,10 @@ typedef struct {
|
||||
/*
|
||||
* Driver's internal utility functions
|
||||
*/
|
||||
static uint8_t _cksum(uint8_t *buf, size_t size)
|
||||
static uint8_t _cksum(size_t offset, uint8_t *buf, size_t size)
|
||||
{
|
||||
uint8_t res = 0xff;
|
||||
for (size_t i = 3; i < size; i++) {
|
||||
for (size_t i = offset; i < size; i++) {
|
||||
res -= buf[i];
|
||||
}
|
||||
return res;
|
||||
@ -102,9 +105,9 @@ static uint8_t _cksum(uint8_t *buf, size_t size)
|
||||
|
||||
static void _at_cmd(xbee_t *dev, const char *cmd)
|
||||
{
|
||||
DEBUG("xbee: AT_CMD: %s\n", cmd);
|
||||
DEBUG("[xbee] AT_CMD: %s\n", cmd);
|
||||
|
||||
uart_write(dev->uart, (uint8_t *)cmd, strlen(cmd));
|
||||
uart_write(dev->p.uart, (uint8_t *)cmd, strlen(cmd));
|
||||
}
|
||||
|
||||
static void isr_resp_timeout(void *arg)
|
||||
@ -120,23 +123,23 @@ static void isr_resp_timeout(void *arg)
|
||||
|
||||
static void _api_at_cmd(xbee_t *dev, uint8_t *cmd, uint8_t size, resp_t *resp)
|
||||
{
|
||||
DEBUG("xbee: AT_CMD: %s\n", cmd);
|
||||
DEBUG("[xbee] AT_CMD: %s\n", cmd);
|
||||
|
||||
/* acquire TX lock */
|
||||
mutex_lock(&(dev->tx_lock));
|
||||
/* construct API frame */
|
||||
dev->tx_buf[0] = API_START_DELIMITER;
|
||||
dev->tx_buf[1] = (size + 2) >> 8;
|
||||
dev->tx_buf[2] = (size + 2) & 0xff;
|
||||
dev->tx_buf[3] = API_ID_AT;
|
||||
dev->tx_buf[4] = 1; /* use fixed frame id */
|
||||
memcpy(dev->tx_buf + 5, cmd, size);
|
||||
dev->tx_buf[size + 5] = _cksum(dev->tx_buf, size + 5);
|
||||
dev->cmd_buf[0] = API_START_DELIMITER;
|
||||
dev->cmd_buf[1] = (size + 2) >> 8;
|
||||
dev->cmd_buf[2] = (size + 2) & 0xff;
|
||||
dev->cmd_buf[3] = API_ID_AT;
|
||||
dev->cmd_buf[4] = 1; /* use fixed frame id */
|
||||
memcpy(dev->cmd_buf + 5, cmd, size);
|
||||
dev->cmd_buf[size + 5] = _cksum(3, dev->cmd_buf, size + 5);
|
||||
|
||||
/* reset the response data counter */
|
||||
dev->resp_count = 0;
|
||||
/* start send data */
|
||||
uart_write(dev->uart, dev->tx_buf, size + 6);
|
||||
uart_write(dev->p.uart, dev->cmd_buf, size + 6);
|
||||
|
||||
xtimer_ticks64_t sent_time = xtimer_now64();
|
||||
|
||||
@ -158,7 +161,7 @@ static void _api_at_cmd(xbee_t *dev, uint8_t *cmd, uint8_t size, resp_t *resp)
|
||||
xtimer_remove(&resp_timer);
|
||||
|
||||
if (dev->resp_limit != dev->resp_count) {
|
||||
DEBUG("xbee: response timeout\n");
|
||||
DEBUG("[xbee] api_at_cmd: response timeout\n");
|
||||
resp->status = 255;
|
||||
mutex_unlock(&(dev->tx_lock));
|
||||
|
||||
@ -180,7 +183,6 @@ static void _api_at_cmd(xbee_t *dev, uint8_t *cmd, uint8_t size, resp_t *resp)
|
||||
static void _rx_cb(void *arg, uint8_t c)
|
||||
{
|
||||
xbee_t *dev = (xbee_t *)arg;
|
||||
msg_t msg;
|
||||
|
||||
switch (dev->int_state) {
|
||||
case XBEE_INT_STATE_IDLE:
|
||||
@ -228,9 +230,9 @@ static void _rx_cb(void *arg, uint8_t c)
|
||||
dev->rx_buf[dev->rx_count++] = c;
|
||||
if (dev->rx_count == dev->rx_limit) {
|
||||
/* packet is complete */
|
||||
msg.type = GNRC_NETDEV_MSG_TYPE_EVENT;
|
||||
msg.content.value = ISR_EVENT_RX_DONE;
|
||||
msg_send_int(&msg, dev->mac_pid);
|
||||
if (dev->event_callback) {
|
||||
dev->event_callback((netdev2_t *)dev, NETDEV2_EVENT_ISR);
|
||||
}
|
||||
dev->int_state = XBEE_INT_STATE_IDLE;
|
||||
}
|
||||
break;
|
||||
@ -243,26 +245,6 @@ static void _rx_cb(void *arg, uint8_t c)
|
||||
/*
|
||||
* Getter and setter functions
|
||||
*/
|
||||
|
||||
static int _get_addr_short(xbee_t *dev, uint8_t *val, size_t len)
|
||||
{
|
||||
uint8_t cmd[2];
|
||||
resp_t resp;
|
||||
|
||||
if (len < 2) {
|
||||
return -EOVERFLOW;
|
||||
}
|
||||
|
||||
cmd[0] = 'M';
|
||||
cmd[1] = 'Y';
|
||||
_api_at_cmd(dev, cmd, 2, &resp);
|
||||
if (resp.status == 0) {
|
||||
memcpy(val, resp.data, IEEE802154_SHORT_ADDRESS_LEN);
|
||||
return IEEE802154_SHORT_ADDRESS_LEN;
|
||||
}
|
||||
return -ECANCELED;
|
||||
}
|
||||
|
||||
static int _get_addr_long(xbee_t *dev, uint8_t *val, size_t len)
|
||||
{
|
||||
uint8_t cmd[2];
|
||||
@ -325,7 +307,7 @@ static int _set_addr(xbee_t *dev, uint8_t *val, size_t len)
|
||||
#endif
|
||||
|
||||
if (dev->addr_flags & XBEE_ADDR_FLAGS_LONG ||
|
||||
_set_short_addr(dev, addr) == 0) {
|
||||
_set_short_addr(dev, addr) == 0) {
|
||||
|
||||
memcpy(dev->addr_short, addr, 2);
|
||||
|
||||
@ -440,24 +422,6 @@ static int _set_panid(xbee_t *dev, uint8_t *val, size_t len)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int _get_proto(xbee_t *dev, uint8_t *val, size_t max)
|
||||
{
|
||||
if (max < sizeof(gnrc_nettype_t)) {
|
||||
return -EOVERFLOW;
|
||||
}
|
||||
memcpy(val, &(dev->proto), sizeof(gnrc_nettype_t));
|
||||
return sizeof(gnrc_nettype_t);
|
||||
}
|
||||
|
||||
static int _set_proto(xbee_t *dev, uint8_t *val, size_t len)
|
||||
{
|
||||
if (len != sizeof(gnrc_nettype_t)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
memcpy(&(dev->proto), val, sizeof(gnrc_nettype_t));
|
||||
return sizeof(gnrc_nettype_t);
|
||||
}
|
||||
|
||||
#ifdef MODULE_XBEE_ENCRYPTION
|
||||
static int _set_encryption(xbee_t *dev, uint8_t *val)
|
||||
{
|
||||
@ -505,245 +469,271 @@ static int _set_encryption_key(xbee_t *dev, uint8_t *val, size_t len)
|
||||
/*
|
||||
* Driver's "public" functions
|
||||
*/
|
||||
int xbee_init(xbee_t *dev, const xbee_params_t *params)
|
||||
{
|
||||
uint8_t tmp[2];
|
||||
|
||||
/* check device and bus parameters */
|
||||
if (dev == NULL) {
|
||||
return -ENODEV;
|
||||
}
|
||||
if (params->uart >= UART_NUMOF) {
|
||||
return -ENXIO;
|
||||
}
|
||||
void xbee_setup(xbee_t *dev, const xbee_params_t *params)
|
||||
{
|
||||
assert(dev && (params->uart < UART_NUMOF));
|
||||
|
||||
/* set device driver */
|
||||
dev->driver = &xbee_driver;
|
||||
dev->event_callback = NULL;
|
||||
dev->context = dev;
|
||||
|
||||
/* set peripherals to use */
|
||||
dev->uart = params->uart;
|
||||
dev->reset_pin = params->reset_pin;
|
||||
dev->sleep_pin = params->sleep_pin;
|
||||
memcpy(&dev->p, params, sizeof(xbee_params_t));
|
||||
|
||||
/* initialize pins */
|
||||
if (dev->p.pin_reset != GPIO_UNDEF) {
|
||||
gpio_init(dev->p.pin_reset, GPIO_OUT);
|
||||
gpio_set(dev->p.pin_reset);
|
||||
}
|
||||
if (dev->p.pin_sleep != GPIO_UNDEF) {
|
||||
gpio_init(dev->p.pin_sleep, GPIO_OUT);
|
||||
gpio_clear(dev->p.pin_sleep);
|
||||
}
|
||||
/* we initialize the UART later, since we can not handle interrupts, yet */
|
||||
}
|
||||
|
||||
int xbee_build_hdr(xbee_t *dev, uint8_t *xhdr, size_t payload_len,
|
||||
void *dst_addr, size_t addr_len)
|
||||
{
|
||||
/* make sure payload fits into a packet */
|
||||
if (payload_len > XBEE_MAX_PAYLOAD_LENGTH) {
|
||||
return -EOVERFLOW;
|
||||
}
|
||||
|
||||
/* set start delimiter, configure address and set options. Also make sure,
|
||||
* that the link layer address is of known length */
|
||||
xhdr[0] = API_START_DELIMITER;
|
||||
xhdr[4] = dev->tx_fid++;
|
||||
if (addr_len == IEEE802154_SHORT_ADDRESS_LEN) {
|
||||
xhdr[3] = API_ID_TX_SHORT_ADDR;
|
||||
xhdr[7] = dev->options;
|
||||
}
|
||||
else if (addr_len == IEEE802154_LONG_ADDRESS_LEN) {
|
||||
xhdr[3] = API_ID_TX_LONG_ADDR;
|
||||
xhdr[13] = dev->options;
|
||||
}
|
||||
else {
|
||||
return -ENOMSG;
|
||||
}
|
||||
|
||||
/* finally configure the packet size and copy the actual dst address */
|
||||
uint16_t size = (uint16_t)(payload_len + addr_len + 3);
|
||||
xhdr[1] = (uint8_t)(size >> 8);
|
||||
xhdr[2] = (uint8_t)(size & 0xff);
|
||||
memcpy(&xhdr[5], dst_addr, addr_len);
|
||||
|
||||
return (int)(addr_len + 6);
|
||||
}
|
||||
|
||||
int xbee_parse_hdr(xbee_t *dev, const uint8_t *xhdr, xbee_l2hdr_t *l2hdr)
|
||||
{
|
||||
uint8_t alen;
|
||||
|
||||
assert(xhdr && l2hdr);
|
||||
|
||||
/* get the address length */
|
||||
if (xhdr[0] == API_ID_RX_SHORT_ADDR) {
|
||||
alen = IEEE802154_SHORT_ADDRESS_LEN;
|
||||
}
|
||||
else if (xhdr[0] == API_ID_RX_LONG_ADDR) {
|
||||
alen = IEEE802154_LONG_ADDRESS_LEN;
|
||||
}
|
||||
else {
|
||||
return -ENOMSG;
|
||||
}
|
||||
|
||||
/* copy the actual SRC address and the RSSI value */
|
||||
memcpy(l2hdr->src_addr, &xhdr[1], alen);
|
||||
l2hdr->rssi = xhdr[1 + alen];
|
||||
|
||||
/* copy the destination address */
|
||||
l2hdr->bcast = (xhdr[2 + alen] & OPT_BCAST_ADDR) ? 1 : 0;
|
||||
if (l2hdr->bcast) {
|
||||
memset(l2hdr->dst_addr, 0xff, alen);
|
||||
}
|
||||
else {
|
||||
if (alen == IEEE802154_SHORT_ADDRESS_LEN) {
|
||||
memcpy(l2hdr->dst_addr, dev->addr_short, alen);
|
||||
}
|
||||
else {
|
||||
memcpy(l2hdr->dst_addr, dev->addr_long.uint8, alen);
|
||||
}
|
||||
}
|
||||
l2hdr->addr_len = alen;
|
||||
|
||||
return (int)(alen + 3);
|
||||
}
|
||||
|
||||
int xbee_init(netdev2_t *dev)
|
||||
{
|
||||
uint8_t tmp[2];
|
||||
xbee_t *xbee = (xbee_t *)dev;
|
||||
|
||||
/* set default options */
|
||||
dev->addr_flags = 0;
|
||||
dev->proto = XBEE_DEFAULT_PROTOCOL;
|
||||
dev->options = 0;
|
||||
xbee->addr_flags = XBEE_ADDR_FLAGS_LONG;
|
||||
xbee->options = 0;
|
||||
/* initialize buffers and locks*/
|
||||
mutex_init(&(dev->tx_lock));
|
||||
mutex_init(&(dev->resp_lock));
|
||||
dev->resp_limit = 1; /* needs to be greater then 0 initially */
|
||||
dev->rx_count = 0;
|
||||
mutex_init(&(xbee->tx_lock));
|
||||
mutex_init(&(xbee->resp_lock));
|
||||
xbee->resp_limit = 1; /* needs to be greater then 0 initially */
|
||||
xbee->rx_count = 0;
|
||||
/* initialize UART and GPIO pins */
|
||||
if (uart_init(params->uart, params->baudrate, _rx_cb, dev) != UART_OK) {
|
||||
DEBUG("xbee: Error initializing UART\n");
|
||||
if (uart_init(xbee->p.uart, xbee->p.br, _rx_cb, xbee) != UART_OK) {
|
||||
DEBUG("[xbee] init: error initializing UART\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
if (params->reset_pin != GPIO_UNDEF) {
|
||||
if (gpio_init(params->reset_pin, GPIO_OUT) < 0) {
|
||||
DEBUG("xbee: Error initializing RESET pin\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
gpio_set(params->reset_pin);
|
||||
}
|
||||
if (params->sleep_pin != GPIO_UNDEF) {
|
||||
if (gpio_init(params->sleep_pin, GPIO_OUT) < 0) {
|
||||
DEBUG("xbee: Error initializing SLEEP pin\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
gpio_clear(params->sleep_pin);
|
||||
}
|
||||
/* if reset pin is connected, do a hardware reset */
|
||||
if (params->reset_pin != GPIO_UNDEF) {
|
||||
gpio_clear(params->reset_pin);
|
||||
if (xbee->p.pin_reset != GPIO_UNDEF) {
|
||||
gpio_clear(xbee->p.pin_reset);
|
||||
xtimer_usleep(RESET_DELAY);
|
||||
gpio_set(params->reset_pin);
|
||||
gpio_set(xbee->p.pin_reset);
|
||||
}
|
||||
/* put the XBee device into command mode */
|
||||
xtimer_usleep(ENTER_CMD_MODE_DELAY);
|
||||
_at_cmd(dev, "+++");
|
||||
_at_cmd(xbee, "+++");
|
||||
xtimer_usleep(ENTER_CMD_MODE_DELAY);
|
||||
/* disable non IEEE802.15.4 extensions */
|
||||
_at_cmd(dev, "ATMM2\r");
|
||||
_at_cmd(xbee, "ATMM2\r");
|
||||
/* put XBee module in "API mode without escaped characters" */
|
||||
_at_cmd(dev, "ATAP1\r");
|
||||
_at_cmd(xbee, "ATAP1\r");
|
||||
/* apply AT commands */
|
||||
_at_cmd(dev, "ATAC\r");
|
||||
_at_cmd(xbee, "ATAC\r");
|
||||
/* exit command mode */
|
||||
_at_cmd(dev, "ATCN\r");
|
||||
_at_cmd(xbee, "ATCN\r");
|
||||
|
||||
/* load long address (we can not set it, its read only for Xbee devices) */
|
||||
if (_get_addr_long(dev, dev->addr_long.uint8, IEEE802154_LONG_ADDRESS_LEN) < 0) {
|
||||
DEBUG("xbee: Error getting address\n");
|
||||
if (_get_addr_long(xbee, xbee->addr_long.uint8, IEEE802154_LONG_ADDRESS_LEN) < 0) {
|
||||
DEBUG("[xbee] init: error getting address\n");
|
||||
return -EIO;
|
||||
}
|
||||
if (_set_addr(dev, &((dev->addr_long).uint8[6]), IEEE802154_SHORT_ADDRESS_LEN) < 0) {
|
||||
DEBUG("xbee: Error setting short address\n");
|
||||
if (_set_addr(xbee, &((xbee->addr_long).uint8[6]), IEEE802154_SHORT_ADDRESS_LEN) < 0) {
|
||||
DEBUG("[xbee] init: error setting short address\n");
|
||||
return -EIO;
|
||||
}
|
||||
/* set default channel */
|
||||
tmp[1] = 0;
|
||||
tmp[0] = XBEE_DEFAULT_CHANNEL;
|
||||
if (_set_channel(dev, tmp, 2) < 0) {
|
||||
DEBUG("xbee: Error setting channel\n");
|
||||
if (_set_channel(xbee, tmp, 2) < 0) {
|
||||
DEBUG("[xbee] init: error setting channel\n");
|
||||
return -EIO;
|
||||
}
|
||||
/* set default PAN ID */
|
||||
tmp[1] = (uint8_t)(XBEE_DEFAULT_PANID >> 8);
|
||||
tmp[0] = (uint8_t)(XBEE_DEFAULT_PANID & 0xff);
|
||||
if (_set_panid(dev, tmp, 2) < 0) {
|
||||
DEBUG("xbee: Error setting PAN ID\n");
|
||||
if (_set_panid(xbee, tmp, 2) < 0) {
|
||||
DEBUG("[xbee] init: error setting PAN ID\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
DEBUG("xbee: Initialization successful\n");
|
||||
DEBUG("[xbee] init: Initialization successful\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline bool _is_broadcast(gnrc_netif_hdr_t *hdr)
|
||||
static int xbee_send(netdev2_t *dev, const struct iovec *vector, unsigned count)
|
||||
{
|
||||
/* IEEE 802.15.4 does not support multicast so we need to check both flags */
|
||||
return (bool)(hdr->flags & (GNRC_NETIF_HDR_FLAGS_BROADCAST |
|
||||
GNRC_NETIF_HDR_FLAGS_MULTICAST));
|
||||
}
|
||||
|
||||
static int _send(gnrc_netdev_t *netdev, gnrc_pktsnip_t *pkt)
|
||||
{
|
||||
xbee_t *dev = (xbee_t *)netdev;
|
||||
xbee_t *xbee = (xbee_t *)dev;
|
||||
size_t size;
|
||||
size_t pos;
|
||||
gnrc_netif_hdr_t *hdr;
|
||||
gnrc_pktsnip_t *payload;
|
||||
uint8_t csum;
|
||||
|
||||
/* check device descriptor and packet */
|
||||
if (pkt == NULL) {
|
||||
return -ENOMSG;
|
||||
}
|
||||
if (dev == NULL) {
|
||||
gnrc_pktbuf_release(pkt);
|
||||
return -ENODEV;
|
||||
}
|
||||
assert(xbee && vector && (count > 0));
|
||||
|
||||
/* figure out the size of the payload to send */
|
||||
size = gnrc_pkt_len(pkt->next);
|
||||
if (size > XBEE_MAX_PAYLOAD_LENGTH) {
|
||||
DEBUG("xbee: Error sending data, payload length exceeds limit\n");
|
||||
gnrc_pktbuf_release(pkt);
|
||||
return -EOVERFLOW;
|
||||
}
|
||||
/* get netif header check address length and flags */
|
||||
hdr = (gnrc_netif_hdr_t *)pkt->data;
|
||||
if (!((hdr->dst_l2addr_len == IEEE802154_SHORT_ADDRESS_LEN) ||
|
||||
(hdr->dst_l2addr_len == IEEE802154_LONG_ADDRESS_LEN) ||
|
||||
_is_broadcast(hdr))) {
|
||||
gnrc_pktbuf_release(pkt);
|
||||
return -ENOMSG;
|
||||
}
|
||||
|
||||
/* acquire TX lock */
|
||||
mutex_lock(&(dev->tx_lock));
|
||||
/* put together the API frame */
|
||||
dev->tx_buf[0] = API_START_DELIMITER;
|
||||
dev->tx_buf[4] = 0; /* set to zero to disable response frame */
|
||||
/* set size, API id and address field depending on dst address length */
|
||||
if (_is_broadcast(hdr)) {
|
||||
DEBUG("xbee: sending broadcast");
|
||||
dev->tx_buf[1] = (uint8_t)((size + 5) >> 8);
|
||||
dev->tx_buf[2] = (uint8_t)(size + 5);
|
||||
dev->tx_buf[3] = API_ID_TX_SHORT_ADDR;
|
||||
dev->tx_buf[5] = 0xff;
|
||||
dev->tx_buf[6] = 0xff;
|
||||
pos = 7;
|
||||
}
|
||||
else if (hdr->dst_l2addr_len == IEEE802154_SHORT_ADDRESS_LEN) {
|
||||
uint8_t *destination = gnrc_netif_hdr_get_dst_addr(hdr);
|
||||
|
||||
DEBUG("xbee: sending unicast to %02x:%02x",
|
||||
(uint8_t) destination[0], (uint8_t) destination[1]);
|
||||
|
||||
dev->tx_buf[1] = (uint8_t)((size + 5) >> 8);
|
||||
dev->tx_buf[2] = (uint8_t)(size + 5);
|
||||
dev->tx_buf[3] = API_ID_TX_SHORT_ADDR;
|
||||
memcpy(dev->tx_buf + 5, destination, IEEE802154_SHORT_ADDRESS_LEN);
|
||||
pos = 7;
|
||||
}
|
||||
else {
|
||||
uint8_t *destination = gnrc_netif_hdr_get_dst_addr(hdr);
|
||||
|
||||
DEBUG("xbee: sending unicast to %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
(uint8_t) destination[0], (uint8_t) destination[1],
|
||||
(uint8_t) destination[2], (uint8_t) destination[3],
|
||||
(uint8_t) destination[4], (uint8_t) destination[5],
|
||||
(uint8_t) destination[6], (uint8_t) destination[7]);
|
||||
|
||||
dev->tx_buf[1] = (uint8_t)((size + 11) >> 8);
|
||||
dev->tx_buf[2] = (uint8_t)(size + 11);
|
||||
dev->tx_buf[3] = API_ID_TX_LONG_ADDR;
|
||||
memcpy(dev->tx_buf + 5, destination, IEEE802154_LONG_ADDRESS_LEN);
|
||||
pos = 13;
|
||||
}
|
||||
/* set options */
|
||||
DEBUG(", option: %02x", dev->options);
|
||||
dev->tx_buf[pos++] = dev->options;
|
||||
/* copy payload */
|
||||
DEBUG(", payload:");
|
||||
payload = pkt->next;
|
||||
while (payload) {
|
||||
#if ENABLE_DEBUG
|
||||
for (size_t i = 0; i < payload->size; i++) {
|
||||
DEBUG(" %02x", ((uint8_t *) payload->data)[i]);
|
||||
/* calculate the checksum and the packet size */
|
||||
size = vector[0].iov_len;
|
||||
csum = _cksum(3, (uint8_t *)vector[0].iov_base, size);
|
||||
for (unsigned i = 1; i < count; i++) {
|
||||
size += vector[i].iov_len;
|
||||
for (size_t p = 0; p < vector[i].iov_len; p++) {
|
||||
csum -= ((uint8_t *)vector[i].iov_base)[p];
|
||||
}
|
||||
#endif
|
||||
memcpy(&(dev->tx_buf[pos]), payload->data, payload->size);
|
||||
pos += payload->size;
|
||||
payload = payload->next;
|
||||
}
|
||||
/* set checksum */
|
||||
dev->tx_buf[pos] = _cksum(dev->tx_buf, pos);
|
||||
/* start transmission */
|
||||
uart_write(dev->uart, dev->tx_buf, pos + 1);
|
||||
/* release data */
|
||||
gnrc_pktbuf_release(pkt);
|
||||
/* release TX lock */
|
||||
mutex_unlock(&(dev->tx_lock));
|
||||
|
||||
/* make sure the data fits into a packet */
|
||||
if (size >= XBEE_MAX_PKT_LENGTH) {
|
||||
DEBUG("[xbee] send: data to send is too large for TX buffer\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* send the actual data packet */
|
||||
DEBUG("[xbee] send: now sending out %i byte\n", (int)size);
|
||||
mutex_lock(&(xbee->tx_lock));
|
||||
for (unsigned i = 0; i < count; i++) {
|
||||
uart_write(xbee->p.uart, vector[i].iov_base, vector[i].iov_len);
|
||||
}
|
||||
uart_write(xbee->p.uart, &csum, 1);
|
||||
mutex_unlock(&(xbee->tx_lock));
|
||||
|
||||
/* return number of payload byte */
|
||||
DEBUG("\n");
|
||||
return (int)size;
|
||||
}
|
||||
|
||||
static int _add_cb(gnrc_netdev_t *dev, gnrc_netdev_event_cb_t cb)
|
||||
static int xbee_recv(netdev2_t *dev, void *buf, size_t len, void *info)
|
||||
{
|
||||
if (dev == NULL) {
|
||||
return -ENODEV;
|
||||
(void)info;
|
||||
size_t size;
|
||||
xbee_t *xbee = (xbee_t *)dev;
|
||||
|
||||
assert(xbee);
|
||||
|
||||
/* make sure we have new data waiting */
|
||||
if (xbee->rx_count != xbee->rx_limit) {
|
||||
DEBUG("[xbee] recv: no data available for reading\n");
|
||||
return 0;
|
||||
}
|
||||
if (dev->event_cb != NULL) {
|
||||
return -ENOBUFS;
|
||||
|
||||
/* data available, so we read it (or it's size) */
|
||||
size = (size_t)(xbee->rx_limit - 1);
|
||||
if (buf == NULL) {
|
||||
if (len > 0) {
|
||||
DEBUG("[xbee] recv: reading size and dropping: %i\n", size);
|
||||
xbee->rx_count = 0;
|
||||
}
|
||||
else {
|
||||
DEBUG("[xbee] recv: reading size without dropping: %i\n", size);
|
||||
}
|
||||
}
|
||||
dev->event_cb = cb;
|
||||
return 0;
|
||||
else {
|
||||
size = (size > len) ? len : size;
|
||||
DEBUG("[xbee] recv: consuming packet: reading %i byte\n", size);
|
||||
memcpy(buf, xbee->rx_buf, size);
|
||||
xbee->rx_count = 0;
|
||||
}
|
||||
|
||||
return (int)size;
|
||||
}
|
||||
|
||||
static int _rem_cb(gnrc_netdev_t *dev, gnrc_netdev_event_cb_t cb)
|
||||
{
|
||||
if (dev == NULL) {
|
||||
return -ENODEV;
|
||||
}
|
||||
if (dev->event_cb != cb) {
|
||||
return -ENOENT;
|
||||
}
|
||||
dev->event_cb = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _get(gnrc_netdev_t *netdev, netopt_t opt, void *value, size_t max_len)
|
||||
static void xbee_isr(netdev2_t *netdev)
|
||||
{
|
||||
xbee_t *dev = (xbee_t *)netdev;
|
||||
if (dev == NULL) {
|
||||
return -ENODEV;
|
||||
|
||||
if (dev->rx_count == dev->rx_limit) {
|
||||
/* make sure the checksum checks out */
|
||||
if (_cksum(0, dev->rx_buf, dev->rx_limit) != 0) {
|
||||
DEBUG("[xbee] isr: invalid RX checksum\n");
|
||||
dev->rx_count = 0;
|
||||
}
|
||||
else {
|
||||
DEBUG("[xbee] isr: data available, waiting for read\n");
|
||||
dev->event_callback(netdev, NETDEV2_EVENT_RX_COMPLETE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int xbee_get(netdev2_t *ndev, netopt_t opt, void *value, size_t max_len)
|
||||
{
|
||||
xbee_t *dev = (xbee_t *)ndev;
|
||||
assert(dev);
|
||||
|
||||
switch (opt) {
|
||||
case NETOPT_ADDRESS:
|
||||
return _get_addr_short(dev, (uint8_t *)value, max_len);
|
||||
assert(max_len >= IEEE802154_SHORT_ADDRESS_LEN);
|
||||
memcpy(value, dev->addr_short, IEEE802154_SHORT_ADDRESS_LEN);
|
||||
return IEEE802154_SHORT_ADDRESS_LEN;
|
||||
case NETOPT_ADDRESS_LONG:
|
||||
return _get_addr_long(dev, (uint8_t *)value, max_len);
|
||||
assert(max_len >= IEEE802154_LONG_ADDRESS_LEN);
|
||||
memcpy(value, dev->addr_long.uint8, IEEE802154_LONG_ADDRESS_LEN);
|
||||
return IEEE802154_LONG_ADDRESS_LEN;
|
||||
case NETOPT_ADDR_LEN:
|
||||
case NETOPT_SRC_LEN:
|
||||
if (max_len < sizeof(uint16_t)) {
|
||||
@ -761,12 +751,13 @@ static int _get(gnrc_netdev_t *netdev, netopt_t opt, void *value, size_t max_len
|
||||
return -EOVERFLOW;
|
||||
}
|
||||
if (dev->addr_flags & XBEE_ADDR_FLAGS_LONG) {
|
||||
ieee802154_get_iid(value, (uint8_t *)&dev->addr_long, IEEE802154_LONG_ADDRESS_LEN);
|
||||
ieee802154_get_iid(value, dev->addr_long.uint8,
|
||||
IEEE802154_LONG_ADDRESS_LEN);
|
||||
}
|
||||
else {
|
||||
ieee802154_get_iid(value, (uint8_t *)&dev->addr_short, IEEE802154_SHORT_ADDRESS_LEN);
|
||||
ieee802154_get_iid(value, dev->addr_short,
|
||||
IEEE802154_SHORT_ADDRESS_LEN);
|
||||
}
|
||||
|
||||
return sizeof(eui64_t);
|
||||
case NETOPT_CHANNEL:
|
||||
return _get_channel(dev, (uint8_t *)value, max_len);
|
||||
@ -778,161 +769,45 @@ static int _get(gnrc_netdev_t *netdev, netopt_t opt, void *value, size_t max_len
|
||||
return sizeof(uint16_t);
|
||||
case NETOPT_NID:
|
||||
return _get_panid(dev, (uint8_t *)value, max_len);
|
||||
case NETOPT_PROTO:
|
||||
return _get_proto(dev, (uint8_t *)value, max_len);
|
||||
default:
|
||||
return -ENOTSUP;
|
||||
}
|
||||
}
|
||||
|
||||
static int _set(gnrc_netdev_t *netdev, netopt_t opt, void *value, size_t value_len)
|
||||
static int xbee_set(netdev2_t *ndev, netopt_t opt, void *value, size_t len)
|
||||
{
|
||||
xbee_t *dev = (xbee_t *)netdev;
|
||||
if (dev == NULL) {
|
||||
return -ENODEV;
|
||||
}
|
||||
xbee_t *dev = (xbee_t *)ndev;
|
||||
assert(dev);
|
||||
|
||||
switch (opt) {
|
||||
case NETOPT_ADDRESS:
|
||||
return _set_addr(dev, (uint8_t *)value, value_len);
|
||||
return _set_addr(dev, (uint8_t *)value, len);
|
||||
case NETOPT_ADDR_LEN:
|
||||
case NETOPT_SRC_LEN:
|
||||
return _set_addr_len(dev, value, value_len);
|
||||
return _set_addr_len(dev, value, len);
|
||||
case NETOPT_CHANNEL:
|
||||
return _set_channel(dev, (uint8_t *)value, value_len);
|
||||
return _set_channel(dev, (uint8_t *)value, len);
|
||||
case NETOPT_NID:
|
||||
return _set_panid(dev, (uint8_t *)value, value_len);
|
||||
case NETOPT_PROTO:
|
||||
return _set_proto(dev, (uint8_t *)value, value_len);
|
||||
return _set_panid(dev, (uint8_t *)value, len);
|
||||
#ifdef MODULE_XBEE_ENCRYPTION
|
||||
case NETOPT_ENCRYPTION:
|
||||
return _set_encryption(dev, (uint8_t *)value);
|
||||
case NETOPT_ENCRYPTION_KEY:
|
||||
return _set_encryption_key(dev, (uint8_t *)value, value_len);
|
||||
return _set_encryption_key(dev, (uint8_t *)value, len);
|
||||
#endif
|
||||
default:
|
||||
return -ENOTSUP;
|
||||
}
|
||||
}
|
||||
|
||||
static void _isr_event(gnrc_netdev_t *netdev, uint32_t event_type)
|
||||
{
|
||||
xbee_t *dev = (xbee_t *)netdev;
|
||||
gnrc_pktsnip_t *pkt_head;
|
||||
gnrc_pktsnip_t *pkt;
|
||||
gnrc_netif_hdr_t *hdr;
|
||||
size_t pos;
|
||||
size_t addr_len;
|
||||
uint8_t cksum = 0;
|
||||
|
||||
/* check device */
|
||||
if (dev == NULL) {
|
||||
return;
|
||||
}
|
||||
/* check rx callback and event type */
|
||||
if (event_type != ISR_EVENT_RX_DONE || dev->event_cb == NULL) {
|
||||
dev->rx_count = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* read address length */
|
||||
if (dev->rx_buf[0] == API_ID_RX_SHORT_ADDR) {
|
||||
addr_len = IEEE802154_SHORT_ADDRESS_LEN;
|
||||
}
|
||||
else {
|
||||
addr_len = IEEE802154_LONG_ADDRESS_LEN;
|
||||
}
|
||||
|
||||
#ifdef XBEE_DENIED_ADDRESSES
|
||||
if (addr_len == 8) {
|
||||
uint8_t denied_addresses[] = XBEE_DENIED_ADDRESSES;
|
||||
for (size_t i = 0; i < sizeof(denied_addresses) / 8; i++) {
|
||||
if (memcmp(&(dev->rx_buf[1]),
|
||||
&denied_addresses[i * 8],
|
||||
addr_len) == 0) {
|
||||
dev->rx_count = 0;
|
||||
|
||||
DEBUG("xbee: dropping denied packet\n");
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* check checksum for correctness */
|
||||
for (int i = 0; i < dev->rx_limit; i++) {
|
||||
cksum += dev->rx_buf[i];
|
||||
}
|
||||
if (cksum != 0xff) {
|
||||
DEBUG("xbee: Received packet with incorrect checksum, dropping it\n");
|
||||
dev->rx_count = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* allocate and fill interface header */
|
||||
pkt_head = gnrc_pktbuf_add(NULL, NULL,
|
||||
sizeof(gnrc_netif_hdr_t) + (2 * addr_len),
|
||||
GNRC_NETTYPE_NETIF);
|
||||
if (pkt_head == NULL) {
|
||||
DEBUG("xbee: Error allocating netif header in packet buffer on RX\n");
|
||||
dev->rx_count = 0;
|
||||
return;
|
||||
}
|
||||
hdr = (gnrc_netif_hdr_t *)pkt_head->data;
|
||||
hdr->src_l2addr_len = (uint8_t)addr_len;
|
||||
hdr->dst_l2addr_len = (uint8_t)addr_len;
|
||||
hdr->if_pid = dev->mac_pid;
|
||||
hdr->rssi = dev->rx_buf[1 + addr_len]; /* API ID + source address */
|
||||
hdr->lqi = 0;
|
||||
gnrc_netif_hdr_set_src_addr(hdr, &(dev->rx_buf[1]), addr_len);
|
||||
if (addr_len == 2) {
|
||||
gnrc_netif_hdr_set_dst_addr(hdr, dev->addr_short, IEEE802154_SHORT_ADDRESS_LEN);
|
||||
}
|
||||
else {
|
||||
gnrc_netif_hdr_set_dst_addr(hdr, dev->addr_long.uint8, IEEE802154_LONG_ADDRESS_LEN);
|
||||
}
|
||||
pos = 3 + addr_len;
|
||||
/* allocate and copy payload */
|
||||
pkt = gnrc_pktbuf_add(pkt_head, &(dev->rx_buf[pos]), dev->rx_limit - pos - 1,
|
||||
dev->proto);
|
||||
if (pkt == NULL) {
|
||||
DEBUG("xbee: Error allocating payload in packet buffer on RX\n");
|
||||
gnrc_pktbuf_release(pkt_head);
|
||||
dev->rx_count = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
#if ENABLE_DEBUG
|
||||
DEBUG("xbee: received packet from");
|
||||
for (size_t i = 0; i < addr_len; i++) {
|
||||
DEBUG(" %02x", (uint8_t) gnrc_netif_hdr_get_src_addr(hdr)[i]);
|
||||
}
|
||||
|
||||
DEBUG(", RSSI: -%d dBm", hdr->rssi);
|
||||
DEBUG(", options: %02x", (uint8_t) dev->rx_buf[1 + addr_len + 1]); /* API ID + source address + RSSI */
|
||||
DEBUG(", payload:");
|
||||
|
||||
for (size_t i = 0; i < pkt->size; i++) {
|
||||
DEBUG(" %02x", ((uint8_t *) pkt->data)[i]);
|
||||
}
|
||||
DEBUG("\n");
|
||||
#endif
|
||||
|
||||
/* pass on the received packet */
|
||||
dev->event_cb(NETDEV_EVENT_RX_COMPLETE, pkt);
|
||||
/* reset RX byte counter to enable receiving of the next packet */
|
||||
dev->rx_count = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The drivers netdev interface
|
||||
*/
|
||||
const gnrc_netdev_driver_t xbee_driver = {
|
||||
.send_data = _send,
|
||||
.add_event_callback = _add_cb,
|
||||
.rem_event_callback = _rem_cb,
|
||||
.get = _get,
|
||||
.set = _set,
|
||||
.isr_event = _isr_event,
|
||||
const netdev2_driver_t xbee_driver = {
|
||||
.send = xbee_send,
|
||||
.recv = xbee_recv,
|
||||
.init = xbee_init,
|
||||
.isr = xbee_isr,
|
||||
.get = xbee_get,
|
||||
.set = xbee_set,
|
||||
};
|
||||
|
@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Kaspar Schleiser <kaspar@schleiser.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 xbee driver parameters example, used by auto_init_gnrc_netif
|
||||
*
|
||||
* @author Kaspar Schleiser <kaspar@schleiser.de>
|
||||
*/
|
||||
|
||||
#ifndef XBEE_PARAMS_H
|
||||
#define XBEE_PARAMS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static xbee_params_t xbee_params[] = {
|
||||
{ .uart = XBEE_UART,
|
||||
.baudrate = 9600U,
|
||||
.sleep_pin = GPIO_UNDEF,
|
||||
.reset_pin = GPIO_UNDEF
|
||||
},
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* XBEE_PARAMS_H */
|
||||
/** @} */
|
@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Kaspar Schleiser <kaspar@schleiser.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 xbee driver parameters example, used by auto_init_gnrc_netif
|
||||
*
|
||||
* @author Kaspar Schleiser <kaspar@schleiser.de>
|
||||
*/
|
||||
|
||||
#ifndef XBEE_PARAMS_H
|
||||
#define XBEE_PARAMS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static xbee_params_t xbee_params[] = {
|
||||
{ .uart = XBEE_UART,
|
||||
.baudrate = 9600U,
|
||||
.sleep_pin = GPIO_UNDEF,
|
||||
.reset_pin = GPIO_UNDEF
|
||||
},
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* XBEE_PARAMS_H */
|
||||
/** @} */
|
Loading…
Reference in New Issue
Block a user