mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
netdev/ieee802154_submac: add compatibility layer
This commit is contained in:
parent
e100a67099
commit
4bb77b0b2f
@ -108,6 +108,11 @@ ifneq (,$(filter netdev_ieee802154,$(USEMODULE)))
|
||||
USEMODULE += random
|
||||
endif
|
||||
|
||||
ifneq (,$(filter netdev_ieee802154_submac,$(USEMODULE)))
|
||||
USEMODULE += ieee802154_radio_hal
|
||||
USEMODULE += ieee802154_submac
|
||||
endif
|
||||
|
||||
ifneq (,$(filter gnrc_dhcpv6_%, $(USEMODULE)))
|
||||
USEMODULE += gnrc_dhcpv6
|
||||
endif
|
||||
@ -191,6 +196,9 @@ ifneq (,$(filter gnrc_netif,$(USEMODULE)))
|
||||
USEMODULE += netif
|
||||
USEMODULE += l2util
|
||||
USEMODULE += fmt
|
||||
ifneq (,$(filter netdev_ieee802154_submac,$(USEMODULE)))
|
||||
USEMODULE += gnrc_netif_pktq
|
||||
endif
|
||||
ifneq (,$(filter netdev_ieee802154,$(USEMODULE)))
|
||||
USEMODULE += gnrc_netif_ieee802154
|
||||
endif
|
||||
|
70
drivers/include/net/netdev/ieee802154_submac.h
Normal file
70
drivers/include/net/netdev/ieee802154_submac.h
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (C) 2020 HAW Hamburg
|
||||
*
|
||||
* 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_netdev_ieee802154_submac IEEE802.15.4 SubMAC netdev layer
|
||||
* @ingroup drivers_netdev_api
|
||||
* @experimental This API is experimental and in an early state - expect
|
||||
* changes!
|
||||
|
||||
* @brief This module defines implements the netdev API on top of the
|
||||
* IEEE 802.15.4 radio HAL
|
||||
*
|
||||
* @{
|
||||
*
|
||||
* @author José I. Alamos <jose.alamos@haw-hamburg.de>
|
||||
*/
|
||||
#ifndef NET_NETDEV_IEEE802154_SUBMAC_H
|
||||
#define NET_NETDEV_IEEE802154_SUBMAC_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "net/netdev.h"
|
||||
#include "net/netdev/ieee802154.h"
|
||||
#include "net/ieee802154/submac.h"
|
||||
#include "net/ieee802154/radio.h"
|
||||
#include "xtimer.h"
|
||||
|
||||
#include "od.h"
|
||||
#include "event/thread.h"
|
||||
#include "event/callback.h"
|
||||
#include "xtimer.h"
|
||||
|
||||
#define NETDEV_SUBMAC_FLAGS_ACK_TIMEOUT (1 << 0) /**< Flag for ACK Timeout event */
|
||||
#define NETDEV_SUBMAC_FLAGS_TX_DONE (1 << 1) /**< Flag for TX Done event */
|
||||
#define NETDEV_SUBMAC_FLAGS_RX_DONE (1 << 2) /**< Flag for RX Done event */
|
||||
|
||||
/**
|
||||
* @brief IEEE 802.15.4 SubMAC netdev descriptor
|
||||
*/
|
||||
typedef struct {
|
||||
netdev_ieee802154_t dev; /**< IEEE 802.15.4 netdev descriptor */
|
||||
ieee802154_submac_t submac; /**< IEEE 802.15.4 SubMAC descriptor */
|
||||
xtimer_t ack_timer; /**< xtimer descriptor for the ACK timeout timer */
|
||||
int isr_flags; /**< netdev submac @ref NETDEV_EVENT_ISR flags */
|
||||
} netdev_ieee802154_submac_t;
|
||||
|
||||
/**
|
||||
* @brief Init the IEEE 802.15.4 SubMAC netdev adoption.
|
||||
*
|
||||
* @param[in] netdev_submac pointer to the netdev submac descriptor.
|
||||
* @param[in] dev pointer to the device associated to @p netdev_submac.
|
||||
*
|
||||
* @return 0 on success.
|
||||
* @return negative errno on failure.
|
||||
*/
|
||||
int netdev_ieee802154_submac_init(netdev_ieee802154_submac_t *netdev_submac,
|
||||
ieee802154_dev_t *dev);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* NET_NETDEV_IEEE802154_SUBMAC_H */
|
||||
/** @} */
|
1
drivers/netdev_ieee802154_submac/Makefile
Normal file
1
drivers/netdev_ieee802154_submac/Makefile
Normal file
@ -0,0 +1 @@
|
||||
include $(RIOTBASE)/Makefile.base
|
326
drivers/netdev_ieee802154_submac/netdev_ieee802154_submac.c
Normal file
326
drivers/netdev_ieee802154_submac/netdev_ieee802154_submac.c
Normal file
@ -0,0 +1,326 @@
|
||||
/*
|
||||
* Copyright (C) 2020 HAW Hamburg
|
||||
*
|
||||
* 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 José I. Alamos <jose.alamos@haw-hamburg.de>
|
||||
*/
|
||||
|
||||
#include "net/netdev/ieee802154_submac.h"
|
||||
#include "event/thread.h"
|
||||
|
||||
static const ieee802154_submac_cb_t _cb;
|
||||
|
||||
static const netdev_driver_t netdev_submac_driver;
|
||||
|
||||
static void _ack_timeout(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
netdev_ieee802154_submac_t *netdev_submac = arg;
|
||||
netdev_t *netdev = arg;
|
||||
|
||||
netdev_submac->isr_flags |= NETDEV_SUBMAC_FLAGS_ACK_TIMEOUT;
|
||||
|
||||
netdev->event_callback(netdev, NETDEV_EVENT_ISR);
|
||||
}
|
||||
|
||||
static netopt_state_t _get_submac_state(ieee802154_submac_t *submac)
|
||||
{
|
||||
ieee802154_submac_state_t state = ieee802154_get_state(submac);
|
||||
|
||||
netopt_state_t netopt_state;
|
||||
switch (state) {
|
||||
case IEEE802154_STATE_OFF:
|
||||
netopt_state = NETOPT_STATE_SLEEP;
|
||||
break;
|
||||
case IEEE802154_STATE_IDLE:
|
||||
netopt_state = NETOPT_STATE_STANDBY;
|
||||
break;
|
||||
case IEEE802154_STATE_LISTEN:
|
||||
default:
|
||||
netopt_state = NETOPT_STATE_IDLE;
|
||||
break;
|
||||
}
|
||||
|
||||
return netopt_state;
|
||||
}
|
||||
|
||||
static int _get(netdev_t *netdev, netopt_t opt, void *value, size_t max_len)
|
||||
{
|
||||
netdev_ieee802154_submac_t *netdev_submac = (netdev_ieee802154_submac_t *)netdev;
|
||||
ieee802154_submac_t *submac = &netdev_submac->submac;
|
||||
|
||||
switch (opt) {
|
||||
case NETOPT_STATE:
|
||||
*((netopt_state_t*) value) = _get_submac_state(submac);
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return netdev_ieee802154_get((netdev_ieee802154_t *)netdev, opt,
|
||||
value, max_len);
|
||||
}
|
||||
|
||||
static int _set_submac_state(ieee802154_submac_t *submac, netopt_state_t state)
|
||||
{
|
||||
switch (state) {
|
||||
case NETOPT_STATE_STANDBY:
|
||||
return ieee802154_set_state(submac, IEEE802154_STATE_IDLE);
|
||||
case NETOPT_STATE_SLEEP:
|
||||
return ieee802154_set_state(submac, IEEE802154_STATE_OFF);
|
||||
case NETOPT_STATE_IDLE:
|
||||
return ieee802154_set_state(submac, IEEE802154_STATE_LISTEN);
|
||||
default:
|
||||
return -ENOTSUP;
|
||||
}
|
||||
}
|
||||
|
||||
static int _set(netdev_t *netdev, netopt_t opt, const void *value,
|
||||
size_t value_len)
|
||||
{
|
||||
netdev_ieee802154_submac_t *netdev_submac =
|
||||
(netdev_ieee802154_submac_t *)netdev;
|
||||
ieee802154_submac_t *submac = &netdev_submac->submac;
|
||||
|
||||
int res;
|
||||
int16_t tx_power;
|
||||
|
||||
switch (opt) {
|
||||
case NETOPT_ADDRESS:
|
||||
ieee802154_set_short_addr(submac, value);
|
||||
break;
|
||||
case NETOPT_ADDRESS_LONG:
|
||||
ieee802154_set_ext_addr(submac, value);
|
||||
break;
|
||||
case NETOPT_NID:
|
||||
ieee802154_set_panid(submac, value);
|
||||
break;
|
||||
case NETOPT_CHANNEL:
|
||||
ieee802154_set_channel_number(submac, *((uint16_t *)value));
|
||||
break;
|
||||
case NETOPT_TX_POWER:
|
||||
tx_power = *((int16_t *)value);
|
||||
res = ieee802154_set_tx_power(submac, tx_power);
|
||||
if (res >= 0) {
|
||||
netdev_submac->dev.txpower = tx_power;
|
||||
}
|
||||
return res;
|
||||
case NETOPT_STATE:
|
||||
return _set_submac_state(submac, *((netopt_state_t*) value));
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return netdev_ieee802154_set((netdev_ieee802154_t *)netdev, opt,
|
||||
value, value_len);
|
||||
}
|
||||
|
||||
void ieee802154_submac_ack_timer_set(ieee802154_submac_t *submac, uint16_t us)
|
||||
{
|
||||
netdev_ieee802154_submac_t *netdev_submac = container_of(submac,
|
||||
netdev_ieee802154_submac_t,
|
||||
submac);
|
||||
|
||||
xtimer_set(&netdev_submac->ack_timer, us);
|
||||
}
|
||||
|
||||
void ieee802154_submac_ack_timer_cancel(ieee802154_submac_t *submac)
|
||||
{
|
||||
netdev_ieee802154_submac_t *netdev_submac = container_of(submac,
|
||||
netdev_ieee802154_submac_t,
|
||||
submac);
|
||||
|
||||
xtimer_remove(&netdev_submac->ack_timer);
|
||||
}
|
||||
|
||||
static int _send(netdev_t *netdev, const iolist_t *pkt)
|
||||
{
|
||||
netdev_ieee802154_submac_t *netdev_submac =
|
||||
(netdev_ieee802154_submac_t *)netdev;
|
||||
|
||||
return ieee802154_send(&netdev_submac->submac, pkt);
|
||||
}
|
||||
|
||||
static void _isr(netdev_t *netdev)
|
||||
{
|
||||
netdev_ieee802154_submac_t *netdev_submac =
|
||||
(netdev_ieee802154_submac_t *)netdev;
|
||||
ieee802154_submac_t *submac = &netdev_submac->submac;
|
||||
|
||||
do {
|
||||
irq_disable();
|
||||
int flags = netdev_submac->isr_flags;
|
||||
netdev_submac->isr_flags = 0;
|
||||
irq_enable();
|
||||
|
||||
if (flags & NETDEV_SUBMAC_FLAGS_ACK_TIMEOUT) {
|
||||
ieee802154_submac_ack_timeout_fired(&netdev_submac->submac);
|
||||
}
|
||||
|
||||
if (flags & NETDEV_SUBMAC_FLAGS_TX_DONE) {
|
||||
ieee802154_submac_tx_done_cb(&netdev_submac->submac);
|
||||
}
|
||||
|
||||
if (flags & NETDEV_SUBMAC_FLAGS_RX_DONE) {
|
||||
ieee802154_submac_rx_done_cb(submac);
|
||||
}
|
||||
} while (netdev_submac->isr_flags != 0);
|
||||
}
|
||||
|
||||
static int _recv(netdev_t *netdev, void *buf, size_t len, void *info)
|
||||
{
|
||||
netdev_ieee802154_submac_t *netdev_submac =
|
||||
(netdev_ieee802154_submac_t *)netdev;
|
||||
ieee802154_submac_t *submac = &netdev_submac->submac;
|
||||
ieee802154_rx_info_t rx_info;
|
||||
|
||||
if (buf == NULL && len == 0) {
|
||||
return ieee802154_get_frame_length(submac);
|
||||
}
|
||||
|
||||
int res = ieee802154_read_frame(submac, buf, len, &rx_info);
|
||||
|
||||
if (info) {
|
||||
netdev_ieee802154_rx_info_t *netdev_rx_info = info;
|
||||
netdev_rx_info->rssi = rx_info.rssi;
|
||||
netdev_rx_info->lqi = rx_info.lqi;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static void submac_tx_done(ieee802154_submac_t *submac, int status,
|
||||
ieee802154_tx_info_t *info)
|
||||
{
|
||||
(void)status;
|
||||
(void)info;
|
||||
netdev_ieee802154_submac_t *netdev_submac = container_of(submac,
|
||||
netdev_ieee802154_submac_t,
|
||||
submac);
|
||||
netdev_t *netdev = (netdev_t *)netdev_submac;
|
||||
|
||||
switch (status) {
|
||||
case TX_STATUS_SUCCESS:
|
||||
netdev->event_callback(netdev, NETDEV_EVENT_TX_COMPLETE);
|
||||
break;
|
||||
case TX_STATUS_FRAME_PENDING:
|
||||
netdev->event_callback(netdev, NETDEV_EVENT_TX_COMPLETE_DATA_PENDING);
|
||||
break;
|
||||
case TX_STATUS_MEDIUM_BUSY:
|
||||
netdev->event_callback(netdev, NETDEV_EVENT_TX_MEDIUM_BUSY);
|
||||
break;
|
||||
case TX_STATUS_NO_ACK:
|
||||
netdev->event_callback(netdev, NETDEV_EVENT_TX_NOACK);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void submac_rx_done(ieee802154_submac_t *submac)
|
||||
{
|
||||
netdev_ieee802154_submac_t *netdev_submac = container_of(submac,
|
||||
netdev_ieee802154_submac_t,
|
||||
submac);
|
||||
netdev_t *netdev = (netdev_t *)netdev_submac;
|
||||
|
||||
netdev->event_callback(netdev, NETDEV_EVENT_RX_COMPLETE);
|
||||
}
|
||||
|
||||
static const ieee802154_submac_cb_t _cb = {
|
||||
.rx_done = submac_rx_done,
|
||||
.tx_done = submac_tx_done,
|
||||
};
|
||||
|
||||
/* Event Notification callback */
|
||||
static void _hal_radio_cb(ieee802154_dev_t *dev, ieee802154_trx_ev_t status)
|
||||
{
|
||||
ieee802154_submac_t *submac = dev->ctx;
|
||||
netdev_ieee802154_submac_t *netdev_submac = container_of(submac,
|
||||
netdev_ieee802154_submac_t,
|
||||
submac);
|
||||
netdev_t *netdev = (netdev_t *)netdev_submac;
|
||||
|
||||
switch (status) {
|
||||
case IEEE802154_RADIO_CONFIRM_TX_DONE:
|
||||
netdev_submac->isr_flags |= NETDEV_SUBMAC_FLAGS_TX_DONE;
|
||||
break;
|
||||
case IEEE802154_RADIO_INDICATION_RX_DONE:
|
||||
netdev_submac->isr_flags |= NETDEV_SUBMAC_FLAGS_RX_DONE;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
netdev->event_callback(netdev, NETDEV_EVENT_ISR);
|
||||
}
|
||||
|
||||
static int _init(netdev_t *netdev)
|
||||
{
|
||||
netdev_ieee802154_submac_t *netdev_submac =
|
||||
(netdev_ieee802154_submac_t *)netdev;
|
||||
/* Call the init function of the device (this will be handled by
|
||||
* `auto_init`) */
|
||||
|
||||
ieee802154_submac_t *submac = &netdev_submac->submac;
|
||||
|
||||
ieee802154_submac_init(submac);
|
||||
|
||||
netdev_ieee802154_t *netdev_ieee802154 = (netdev_ieee802154_t *)netdev;
|
||||
|
||||
/* This function already sets the PAN ID to the default one */
|
||||
netdev_ieee802154_reset(netdev_ieee802154);
|
||||
|
||||
uint16_t chan = CONFIG_IEEE802154_DEFAULT_CHANNEL;
|
||||
int16_t tx_power = CONFIG_IEEE802154_DEFAULT_TXPOWER;
|
||||
|
||||
/* Initialise netdev_ieee802154_t struct */
|
||||
netdev_ieee802154_set(netdev_ieee802154, NETOPT_CHANNEL,
|
||||
&chan, sizeof(chan));
|
||||
netdev_ieee802154_set(netdev_ieee802154, NETOPT_ADDRESS,
|
||||
&submac->short_addr, sizeof(submac->short_addr));
|
||||
netdev_ieee802154_set(netdev_ieee802154, NETOPT_ADDRESS_LONG,
|
||||
&submac->ext_addr, sizeof(submac->ext_addr));
|
||||
|
||||
netdev_submac->dev.txpower = tx_power;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int netdev_ieee802154_submac_init(netdev_ieee802154_submac_t *netdev_submac,
|
||||
ieee802154_dev_t *dev)
|
||||
{
|
||||
netdev_t *netdev = (netdev_t *)netdev_submac;
|
||||
|
||||
netdev->driver = &netdev_submac_driver;
|
||||
ieee802154_submac_t *submac = &netdev_submac->submac;
|
||||
|
||||
submac->dev = dev;
|
||||
submac->cb = &_cb;
|
||||
submac->dev->ctx = submac;
|
||||
|
||||
/* Set the Event Notification */
|
||||
submac->dev->cb = _hal_radio_cb;
|
||||
|
||||
netdev_submac->ack_timer.callback = _ack_timeout;
|
||||
netdev_submac->ack_timer.arg = netdev_submac;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const netdev_driver_t netdev_submac_driver = {
|
||||
.get = _get,
|
||||
.set = _set,
|
||||
.send = _send,
|
||||
.recv = _recv,
|
||||
.isr = _isr,
|
||||
.init = _init,
|
||||
};
|
||||
|
||||
/** @} */
|
@ -128,6 +128,7 @@ PSEUDOMODULES += ztimer%
|
||||
|
||||
# ztimer's main module is called "ztimer_core"
|
||||
NO_PSEUDOMODULES += ztimer_core
|
||||
NO_PSEUDOMODULES += netdev_ieee802154_submac
|
||||
|
||||
# print ascii representation in function od_hex_dump()
|
||||
PSEUDOMODULES += od_string
|
||||
|
Loading…
Reference in New Issue
Block a user