net: drivers: Add a fake ieee802154 radio driver for qemu
This driver is used for testing on Qemu where all "radio transmission" will go through a pipe between 2 Qemus. Change-Id: I5b4e75de82a98eb730ef9c70b460b4b60c0a60c3 Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
This commit is contained in:
parent
6b0732f632
commit
fc0e6497af
4 changed files with 366 additions and 0 deletions
|
@ -140,4 +140,36 @@ config TI_CC2520_AUTO_ACK
|
|||
filtering feature to work.
|
||||
|
||||
endif
|
||||
|
||||
config UPIPE_15_4
|
||||
bool "UART PIPE fake radio driver support for QEMU"
|
||||
depends on BOARD_QEMU_X86
|
||||
select NET_YAIP
|
||||
select UART_PIPE
|
||||
default n
|
||||
|
||||
config UPIPE_15_4_DRV_NAME
|
||||
string "UART PIPE Driver name"
|
||||
default "upipe_15_4"
|
||||
depends on UPIPE_15_4
|
||||
|
||||
config SYS_LOG_UPIPE_15_4_LEVEL
|
||||
int "UART PIPE driver log level"
|
||||
default 0
|
||||
depends on UPIPE_15_4
|
||||
help
|
||||
Sets log level for fake 802.15.4 UPIPE driver.
|
||||
|
||||
Levels are:
|
||||
|
||||
- 0 OFF, do not write
|
||||
|
||||
- 1 ERROR, only write SYS_LOG_ERR
|
||||
|
||||
- 2 WARNING, write SYS_LOG_WRN in adition to previous level
|
||||
|
||||
- 3 INFO, write SYS_LOG_INF in adition to previous levels
|
||||
|
||||
- 4 DEBUG, write SYS_LOG_DBG in adition to previous levels
|
||||
|
||||
endmenu
|
||||
|
|
|
@ -5,3 +5,4 @@ subdir-ccflags-y +=-I${srctree}/net/ip
|
|||
|
||||
obj-$(CONFIG_TI_CC2520_LEGACY) += ieee802154_cc2520_legacy.o
|
||||
obj-$(CONFIG_TI_CC2520) += ieee802154_cc2520.o
|
||||
obj-$(CONFIG_UPIPE_15_4) += ieee802154_uart_pipe.o
|
||||
|
|
297
drivers/ieee802154/ieee802154_uart_pipe.c
Normal file
297
drivers/ieee802154/ieee802154_uart_pipe.c
Normal file
|
@ -0,0 +1,297 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Intel Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define SYS_LOG_LEVEL CONFIG_SYS_LOG_UPIPE_15_4_LEVEL
|
||||
#define SYS_LOG_DOMAIN "net/ieee802154/upipe/"
|
||||
#include <misc/sys_log.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <nanokernel.h>
|
||||
#include <arch/cpu.h>
|
||||
|
||||
#include <board.h>
|
||||
#include <device.h>
|
||||
#include <init.h>
|
||||
#include <net/net_if.h>
|
||||
#include <net/nbuf.h>
|
||||
|
||||
#include <console/uart_pipe.h>
|
||||
#include <net/ieee802154_radio.h>
|
||||
|
||||
#include "ieee802154_uart_pipe.h"
|
||||
|
||||
/** Singleton device used in uart pipe callback */
|
||||
static struct device *upipe_dev;
|
||||
|
||||
static uint8_t *upipe_rx(uint8_t *buf, size_t *off)
|
||||
{
|
||||
struct upipe_context *upipe = upipe_dev->driver_data;
|
||||
struct net_buf *pkt_buf = NULL;
|
||||
struct net_buf *nbuf = NULL;
|
||||
|
||||
if (!upipe_dev) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!upipe->rx && *buf == UART_PIPE_RADIO_15_4_FRAME_TYPE) {
|
||||
upipe->rx = true;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!upipe->rx_len) {
|
||||
if (*buf > 127) {
|
||||
goto flush;
|
||||
}
|
||||
|
||||
upipe->rx_len = *buf;
|
||||
goto done;
|
||||
}
|
||||
|
||||
upipe->rx_buf[upipe->rx_off++] = *buf;
|
||||
|
||||
if (upipe->rx_len == upipe->rx_off) {
|
||||
nbuf = net_nbuf_get_reserve_rx(0);
|
||||
if (!nbuf) {
|
||||
SYS_LOG_DBG("No buf available");
|
||||
goto flush;
|
||||
}
|
||||
|
||||
pkt_buf = net_nbuf_get_reserve_data(0);
|
||||
if (!pkt_buf) {
|
||||
SYS_LOG_DBG("No fragment available");
|
||||
goto out;
|
||||
}
|
||||
|
||||
net_buf_frag_insert(nbuf, pkt_buf);
|
||||
|
||||
memcpy(pkt_buf->data, upipe->rx_buf, upipe->rx_len);
|
||||
net_buf_add(pkt_buf, upipe->rx_len);
|
||||
|
||||
if (ieee802154_radio_handle_ack(upipe->iface, nbuf) == NET_OK) {
|
||||
SYS_LOG_DBG("ACK packet handled");
|
||||
goto out;
|
||||
}
|
||||
|
||||
SYS_LOG_DBG("Caught a packet (%u)", upipe->rx_len - 2);
|
||||
if (net_recv_data(upipe->iface, nbuf) < 0) {
|
||||
SYS_LOG_DBG("Packet dropped by NET stack");
|
||||
goto out;
|
||||
}
|
||||
|
||||
goto flush;
|
||||
out:
|
||||
net_buf_unref(nbuf);
|
||||
flush:
|
||||
upipe->rx = false;
|
||||
upipe->rx_len = 0;
|
||||
upipe->rx_off = 0;
|
||||
}
|
||||
done:
|
||||
*off = 0;
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static int upipe_cca(struct device *dev)
|
||||
{
|
||||
struct upipe_context *upipe = dev->driver_data;
|
||||
|
||||
if (upipe->stopped) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int upipe_set_channel(struct device *dev, uint16_t channel)
|
||||
{
|
||||
struct upipe_context *upipe = dev->driver_data;
|
||||
|
||||
if (upipe->stopped) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int upipe_set_pan_id(struct device *dev, uint16_t pan_id)
|
||||
{
|
||||
struct upipe_context *upipe = dev->driver_data;
|
||||
|
||||
if (upipe->stopped) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int upipe_set_short_addr(struct device *dev, uint16_t short_addr)
|
||||
{
|
||||
struct upipe_context *upipe = dev->driver_data;
|
||||
|
||||
if (upipe->stopped) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int upipe_set_ieee_addr(struct device *dev, const uint8_t *ieee_addr)
|
||||
{
|
||||
struct upipe_context *upipe = dev->driver_data;
|
||||
|
||||
if (upipe->stopped) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int upipe_set_txpower(struct device *dev, int16_t dbm)
|
||||
{
|
||||
struct upipe_context *upipe = dev->driver_data;
|
||||
|
||||
if (upipe->stopped) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int upipe_tx(struct device *dev, struct net_buf *buf)
|
||||
{
|
||||
uint8_t len = net_nbuf_ll_reserve(buf) + net_buf_frags_len(buf);
|
||||
struct upipe_context *upipe = dev->driver_data;
|
||||
uint8_t *pkt_buf = net_nbuf_ll(buf);
|
||||
uint8_t i, data;
|
||||
|
||||
SYS_LOG_DBG("%p (%u)", buf, len);
|
||||
|
||||
if (upipe->stopped) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
data = UART_PIPE_RADIO_15_4_FRAME_TYPE;
|
||||
uart_pipe_send(&data, 1);
|
||||
|
||||
data = len + 2;
|
||||
uart_pipe_send(&data, 1);
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
uart_pipe_send(pkt_buf+i, 1);
|
||||
}
|
||||
|
||||
/* The 2 dummy bytes representing FCS */
|
||||
data = 0xFF;
|
||||
uart_pipe_send(&data, 1);
|
||||
uart_pipe_send(&data, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int upipe_start(struct device *dev)
|
||||
{
|
||||
struct upipe_context *upipe = dev->driver_data;
|
||||
|
||||
if (!upipe->stopped) {
|
||||
return -EALREADY;
|
||||
}
|
||||
|
||||
upipe->stopped = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int upipe_stop(struct device *dev)
|
||||
{
|
||||
struct upipe_context *upipe = dev->driver_data;
|
||||
|
||||
if (upipe->stopped) {
|
||||
return -EALREADY;
|
||||
}
|
||||
|
||||
upipe->stopped = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int upipe_init(struct device *dev)
|
||||
{
|
||||
struct upipe_context *upipe = dev->driver_data;
|
||||
|
||||
memset(upipe, 0, sizeof(struct upipe_context));
|
||||
|
||||
uart_pipe_register(upipe->uart_pipe_buf, 1, upipe_rx);
|
||||
|
||||
upipe_stop(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline uint8_t *get_mac(struct device *dev)
|
||||
{
|
||||
struct upipe_context *upipe = dev->driver_data;
|
||||
|
||||
upipe->mac_addr[0] = 0x00;
|
||||
upipe->mac_addr[1] = 0x10;
|
||||
upipe->mac_addr[2] = 0x20;
|
||||
upipe->mac_addr[3] = 0x30;
|
||||
|
||||
UNALIGNED_PUT(sys_cpu_to_be32(sys_rand32_get()),
|
||||
(uint32_t *) ((void *)upipe->mac_addr+4));
|
||||
|
||||
return upipe->mac_addr;
|
||||
}
|
||||
|
||||
static void upipe_iface_init(struct net_if *iface)
|
||||
{
|
||||
struct device *dev = net_if_get_device(iface);
|
||||
struct upipe_context *upipe = dev->driver_data;
|
||||
uint8_t *mac = get_mac(dev);
|
||||
|
||||
SYS_LOG_DBG("");
|
||||
|
||||
net_if_set_link_addr(iface, mac, 8);
|
||||
|
||||
upipe_dev = dev;
|
||||
upipe->iface = iface;
|
||||
|
||||
ieee802154_init(iface);
|
||||
}
|
||||
|
||||
static struct upipe_context upipe_context_data;
|
||||
|
||||
static struct ieee802154_radio_api upipe_radio_api = {
|
||||
.iface_api.init = upipe_iface_init,
|
||||
.iface_api.send = ieee802154_radio_send,
|
||||
|
||||
.cca = upipe_cca,
|
||||
.set_channel = upipe_set_channel,
|
||||
.set_pan_id = upipe_set_pan_id,
|
||||
.set_short_addr = upipe_set_short_addr,
|
||||
.set_ieee_addr = upipe_set_ieee_addr,
|
||||
.set_txpower = upipe_set_txpower,
|
||||
.tx = upipe_tx,
|
||||
.start = upipe_start,
|
||||
.stop = upipe_stop,
|
||||
};
|
||||
|
||||
NET_DEVICE_INIT(upipe_15_4, CONFIG_UPIPE_15_4_DRV_NAME,
|
||||
upipe_init, &upipe_context_data, NULL,
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
|
||||
&upipe_radio_api, IEEE802154_L2,
|
||||
NET_L2_GET_CTX_TYPE(IEEE802154_L2), 127);
|
36
drivers/ieee802154/ieee802154_uart_pipe.h
Normal file
36
drivers/ieee802154/ieee802154_uart_pipe.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
/* ieee802154_uart_pipe.h - Private header for UART PIPE fake radio driver */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2016 Intel Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __IEEE802154_UART_PIPE_H__
|
||||
#define __IEEE802154_UART_PIPE_H__
|
||||
|
||||
#define UART_PIPE_RADIO_15_4_FRAME_TYPE 0xF0
|
||||
|
||||
struct upipe_context {
|
||||
struct net_if *iface;
|
||||
uint8_t mac_addr[8];
|
||||
bool stopped;
|
||||
/** RX specific attributes */
|
||||
uint8_t uart_pipe_buf[1];
|
||||
bool rx;
|
||||
uint8_t rx_len;
|
||||
uint8_t rx_off;
|
||||
uint8_t rx_buf[127];
|
||||
};
|
||||
|
||||
#endif /* __IEEE802154_UART_PIPE_H__ */
|
Loading…
Add table
Add a link
Reference in a new issue