mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
net/gnrc/netif: Added CC1xxx adaption layer
This adaption layer is intended to be used by a rewrite of the CC110x driver and a new CC1200 driver that is currently being developed for RIOT.
This commit is contained in:
parent
3ce4b7454f
commit
ae7024b9a3
1
drivers/cc1xxx_common/Makefile
Normal file
1
drivers/cc1xxx_common/Makefile
Normal file
@ -0,0 +1 @@
|
||||
include $(RIOTBASE)/Makefile.base
|
171
drivers/cc1xxx_common/gnrc_netif_cc1xxx.c
Normal file
171
drivers/cc1xxx_common/gnrc_netif_cc1xxx.c
Normal file
@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Copyright (C) 2016-17 Freie Universität Berlin
|
||||
* 2018 Otto-von-Guericke-Universität Magdeburg
|
||||
*
|
||||
* 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 net_gnrc_netif
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
*
|
||||
* @author Martine Lenders <m.lenders@fu-berlin.de>
|
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
* @author Marian Buschsieweke <marian.buschsieweke@ovgu.de>
|
||||
*
|
||||
* Adapted from @ref gnrc_xbee.c with only minor modifications. So all credit
|
||||
* goes to Martine Lenders <m.lenders@fu-berlin.de> and to
|
||||
* Hauke Petersen <hauke.petersen@fu-berlin.de>.
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include "assert.h"
|
||||
#include "net/gnrc.h"
|
||||
#include "cc1xxx_common.h"
|
||||
|
||||
#define ENABLE_DEBUG (0)
|
||||
#include "debug.h"
|
||||
|
||||
#define BCAST (GNRC_NETIF_HDR_FLAGS_BROADCAST | GNRC_NETIF_HDR_FLAGS_MULTICAST)
|
||||
|
||||
static gnrc_pktsnip_t *cc1xxx_adpt_recv(gnrc_netif_t *netif)
|
||||
{
|
||||
netdev_t *dev = netif->dev;
|
||||
cc1xxx_rx_info_t rx_info;
|
||||
int pktlen;
|
||||
gnrc_pktsnip_t *payload;
|
||||
gnrc_pktsnip_t *hdr;
|
||||
gnrc_netif_hdr_t *netif_hdr;
|
||||
cc1xxx_l2hdr_t l2hdr;
|
||||
|
||||
assert(dev);
|
||||
|
||||
/* see how much data there is to process */
|
||||
pktlen = dev->driver->recv(dev, NULL, 0, &rx_info);
|
||||
if (pktlen <= 0) {
|
||||
DEBUG("[cc1xxx-gnrc] recv: no data available to process\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* allocate space for the packet in the pktbuf */
|
||||
payload = gnrc_pktbuf_add(NULL, NULL, pktlen, CC1XXX_DEFAULT_PROTOCOL);
|
||||
if (payload == NULL) {
|
||||
DEBUG("[cc1xxx-gnrc] recv: unable to allocate space in the pktbuf\n");
|
||||
/* tell the driver to drop the packet */
|
||||
dev->driver->recv(dev, NULL, pktlen, NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* copy the complete including the CC1XXX header into the packet buffer */
|
||||
dev->driver->recv(dev, payload->data, pktlen, NULL);
|
||||
|
||||
/* The first two bytes are the layer 2 header */
|
||||
l2hdr.dest_addr = ((uint8_t *)payload->data)[0];
|
||||
l2hdr.src_addr = ((uint8_t *)payload->data)[1];
|
||||
|
||||
/* crop the layer 2 header from the payload */
|
||||
hdr = gnrc_pktbuf_mark(payload, sizeof(cc1xxx_l2hdr_t), GNRC_NETTYPE_UNDEF);
|
||||
if (hdr == NULL) {
|
||||
DEBUG("[cc1xxx-gnrc] recv: unable to mark cc1xxx header snip\n");
|
||||
gnrc_pktbuf_release(payload);
|
||||
return NULL;
|
||||
}
|
||||
gnrc_pktbuf_remove_snip(payload, hdr);
|
||||
|
||||
/* create a netif hdr from the obtained data */
|
||||
hdr = gnrc_netif_hdr_build(&l2hdr.src_addr, CC1XXX_ADDR_SIZE,
|
||||
&l2hdr.dest_addr, CC1XXX_ADDR_SIZE);
|
||||
if (hdr == NULL) {
|
||||
DEBUG("[cc1xxx-gnrc] recv: unable to allocate netif header\n");
|
||||
gnrc_pktbuf_release(payload);
|
||||
return NULL;
|
||||
}
|
||||
netif_hdr = (gnrc_netif_hdr_t *)hdr->data;
|
||||
netif_hdr->if_pid = netif->pid;
|
||||
netif_hdr->rssi = rx_info.rssi;
|
||||
netif_hdr->lqi = rx_info.lqi;
|
||||
if (l2hdr.dest_addr == CC1XXX_BCAST_ADDR) {
|
||||
netif_hdr->flags = GNRC_NETIF_HDR_FLAGS_BROADCAST;
|
||||
}
|
||||
|
||||
DEBUG("[cc1xxx-gnrc] recv: successfully parsed packet\n");
|
||||
|
||||
/* and append the netif header */
|
||||
LL_APPEND(payload, hdr);
|
||||
|
||||
return payload;
|
||||
}
|
||||
|
||||
static int cc1xxx_adpt_send(gnrc_netif_t *netif, gnrc_pktsnip_t *pkt)
|
||||
{
|
||||
int res;
|
||||
size_t size;
|
||||
cc1xxx_t *cc1xxx_dev = (cc1xxx_t *)netif->dev;
|
||||
gnrc_netif_hdr_t *netif_hdr;
|
||||
cc1xxx_l2hdr_t l2hdr;
|
||||
|
||||
/* check device descriptor and packet */
|
||||
assert(netif && pkt);
|
||||
|
||||
/* get the payload size and the dst address details */
|
||||
size = gnrc_pkt_len(pkt->next);
|
||||
DEBUG("[cc1xxx-gnrc] send: payload of packet is %i\n", (int)size);
|
||||
netif_hdr = (gnrc_netif_hdr_t *)pkt->data;
|
||||
|
||||
|
||||
l2hdr.src_addr = cc1xxx_dev->addr;
|
||||
if (netif_hdr->flags & BCAST) {
|
||||
l2hdr.dest_addr = CC1XXX_BCAST_ADDR;
|
||||
DEBUG("[cc1xxx-gnrc] send: preparing to send broadcast\n");
|
||||
}
|
||||
else {
|
||||
/* check that destination address is valid */
|
||||
assert(netif_hdr->dst_l2addr_len > 0);
|
||||
uint8_t *addr = gnrc_netif_hdr_get_dst_addr(netif_hdr);
|
||||
l2hdr.dest_addr = addr[0];
|
||||
DEBUG("[cc1xxx-gnrc] send: preparing to send unicast %02x --> %02x\n",
|
||||
(int)l2hdr.src_addr, (int)l2hdr.dest_addr);
|
||||
}
|
||||
|
||||
/* now let's send out the stuff */
|
||||
iolist_t iolist = {
|
||||
.iol_next = (iolist_t *)pkt->next,
|
||||
.iol_base = &l2hdr,
|
||||
.iol_len = sizeof(l2hdr),
|
||||
};
|
||||
|
||||
#ifdef MODULE_NETSTATS_L2
|
||||
if (netif_hdr->flags & BCAST) {
|
||||
netif->dev->stats.tx_mcast_count++;
|
||||
}
|
||||
else {
|
||||
netif->dev->stats.tx_unicast_count++;
|
||||
}
|
||||
#endif
|
||||
DEBUG("[cc1xxx-gnrc] send: triggering the drivers send function\n");
|
||||
res = netif->dev->driver->send(netif->dev, &iolist);
|
||||
|
||||
gnrc_pktbuf_release(pkt);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static const gnrc_netif_ops_t cc1xxx_netif_ops = {
|
||||
.send = cc1xxx_adpt_send,
|
||||
.recv = cc1xxx_adpt_recv,
|
||||
.get = gnrc_netif_get_from_netdev,
|
||||
.set = gnrc_netif_set_from_netdev,
|
||||
};
|
||||
|
||||
gnrc_netif_t *gnrc_netif_cc1xxx_create(char *stack, int stacksize,
|
||||
char priority, char *name,
|
||||
netdev_t *dev)
|
||||
{
|
||||
return gnrc_netif_create(stack, stacksize, priority, name,
|
||||
dev, &cc1xxx_netif_ops);
|
||||
}
|
137
drivers/include/cc1xxx_common.h
Normal file
137
drivers/include/cc1xxx_common.h
Normal file
@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Freie Universität Berlin
|
||||
* 2018 Otto-von-Guericke-Universität Magdeburg
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup drivers_cc1xxx CC1100/CC1100e/CC1101/CC1200 common code
|
||||
* @ingroup drivers_netdev
|
||||
* @ingroup net_gnrc_netif
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief CC110x/CC1200 adaption for @ref net_gnrc_netif
|
||||
*
|
||||
* @author Martine Lenders <m.lenders@fu-berlin.de>
|
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
* @author Marian Buschsieweke <marian.buschsieweke@ovgu.de>
|
||||
*
|
||||
* Supported Transceivers
|
||||
* ======================
|
||||
*
|
||||
* This adaption layer is written to be used by CC110x and CC1200 transceivers,
|
||||
* but any transceiver using layer 2 addresses which are 1 byte in size would
|
||||
* likely be able to use it. Keep in mind that both CC110x and CC1200 are able
|
||||
* to transmit frames of up to 255 bytes (thus 253 bytes of payload, as the
|
||||
* layer 2 header is 2 bytes in size). Other transceivers only supporting
|
||||
* smaller frames may not be able to use all the upper layer protocols supported
|
||||
* by the CC110x and CC1200 transceivers.
|
||||
*
|
||||
* Frame Format
|
||||
* ============
|
||||
*
|
||||
* 0 1 2 3
|
||||
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Destination | Source | Payload...
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
*
|
||||
* | Field | Description |
|
||||
* |-------------|---------------------------------|
|
||||
* | Destination | The layer 2 destination address |
|
||||
* | Source | The layer 2 source address |
|
||||
* | Payload | The payload (variable size) |
|
||||
*
|
||||
* Layer 2 Broadcast
|
||||
* =================
|
||||
*
|
||||
* This adaption layer assumes that the layer 2 address `0x00` (see
|
||||
* @ref CC1XXX_BCAST_ADDR) is reserved for layer 2 broadcast, which is true for
|
||||
* CC110x and CC1200 transceivers (provided they are configured accordingly). If
|
||||
* more users of this adaption layer are added, this behaviour might needs to be
|
||||
* more generalized.
|
||||
*/
|
||||
#ifndef CC1XXX_COMMON_H
|
||||
#define CC1XXX_COMMON_H
|
||||
|
||||
#include "net/gnrc/netif.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Default protocol for data that is coming in
|
||||
*/
|
||||
#ifdef MODULE_GNRC_SIXLOWPAN
|
||||
#define CC1XXX_DEFAULT_PROTOCOL (GNRC_NETTYPE_SIXLOWPAN)
|
||||
#else
|
||||
#define CC1XXX_DEFAULT_PROTOCOL (GNRC_NETTYPE_UNDEF)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Size of a layer 2 address on CC110x/CC1200 transceivers
|
||||
*/
|
||||
#define CC1XXX_ADDR_SIZE (1)
|
||||
|
||||
/**
|
||||
* @brief Special layer 2 address reserved for broadcast frames
|
||||
*/
|
||||
#define CC1XXX_BCAST_ADDR (0x00)
|
||||
|
||||
/**
|
||||
* @brief Layer 2 header used in CC1xxx frames
|
||||
*
|
||||
* This structure has the same memory layout as the data send in the frames.
|
||||
*/
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t dest_addr; /**< Destination layer 2 address */
|
||||
uint8_t src_addr; /**< Source layer 2 address */
|
||||
} cc1xxx_l2hdr_t;
|
||||
|
||||
/**
|
||||
* @brief Users of the CC110x/CC1200 adaption layer have to overlap their
|
||||
* device handle with this structure.
|
||||
*
|
||||
* The first two fields of the device structure of any transceiver driver using
|
||||
* this adaption layer have to be equal to the `cc1xxx_t` structure. This allows
|
||||
* efficient access to the current layer 2 address of the device from the
|
||||
* adaption layer.
|
||||
*/
|
||||
typedef struct {
|
||||
netdev_t netdev; /**< RIOT's interface to this driver */
|
||||
uint8_t addr; /**< Layer 2 address of this device */
|
||||
} cc1xxx_t;
|
||||
|
||||
/**
|
||||
* @brief Statistics for one received frame
|
||||
*/
|
||||
typedef struct netdev_radio_rx_info cc1xxx_rx_info_t;
|
||||
|
||||
/**
|
||||
* @brief Creates a CC110x/CC1200 network interface
|
||||
*
|
||||
* @param[in] stack The stack for the network interface's thread.
|
||||
* @param[in] stacksize Size of @p stack.
|
||||
* @param[in] priority Priority for the network interface's thread.
|
||||
* @param[in] name Name for the network interface. May be NULL.
|
||||
* @param[in] dev Device for the interface.
|
||||
*
|
||||
* @see @ref gnrc_netif_create()
|
||||
*
|
||||
* @return The network interface on success.
|
||||
*/
|
||||
gnrc_netif_t *gnrc_netif_cc1xxx_create(char *stack, int stacksize,
|
||||
char priority, char *name,
|
||||
netdev_t *dev);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CC1XXX_COMMON_H */
|
||||
/** @} */
|
Loading…
Reference in New Issue
Block a user