zephyr/subsys/net/l2/ieee802154/ieee802154_utils.h
Jukka Rissanen 9a6bbbfb69 net: Check device driver API pointer
It is possible that the device driver API pointer is null.
For example if the device driver returns an error, the device
code will make the API pointer NULL so that the API would not
be used. This can cause errors in networking code where we
typically do not check the NULL value.

Fixes #15003

Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
2019-05-07 15:41:15 +03:00

271 lines
6.2 KiB
C

/*
* Copyright (c) 2017 Intel Corporation.
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @brief IEEE 802.15.4 Management
*/
#ifndef __IEEE802154_UTILS_H__
#define __IEEE802154_UTILS_H__
#include <net/ieee802154_radio.h>
static inline
enum ieee802154_hw_caps ieee802154_get_hw_capabilities(struct net_if *iface)
{
const struct ieee802154_radio_api *radio =
net_if_get_device(iface)->driver_api;
if (!radio) {
return 0;
}
return radio->get_capabilities(net_if_get_device(iface));
}
static inline int ieee802154_cca(struct net_if *iface)
{
const struct ieee802154_radio_api *radio =
net_if_get_device(iface)->driver_api;
if (!radio) {
return -ENOENT;
}
return radio->cca(net_if_get_device(iface));
}
static inline int ieee802154_set_channel(struct net_if *iface, u16_t channel)
{
const struct ieee802154_radio_api *radio =
net_if_get_device(iface)->driver_api;
if (!radio) {
return -ENOENT;
}
return radio->set_channel(net_if_get_device(iface), channel);
}
static inline int ieee802154_set_tx_power(struct net_if *iface, s16_t dbm)
{
const struct ieee802154_radio_api *radio =
net_if_get_device(iface)->driver_api;
if (!radio) {
return -ENOENT;
}
return radio->set_txpower(net_if_get_device(iface), dbm);
}
static inline int ieee802154_tx(struct net_if *iface,
struct net_pkt *pkt, struct net_buf *buf)
{
const struct ieee802154_radio_api *radio =
net_if_get_device(iface)->driver_api;
if (!radio) {
return -ENOENT;
}
return radio->tx(net_if_get_device(iface), pkt, buf);
}
static inline int ieee802154_start(struct net_if *iface)
{
const struct ieee802154_radio_api *radio =
net_if_get_device(iface)->driver_api;
if (!radio) {
return -ENOENT;
}
return radio->start(net_if_get_device(iface));
}
static inline int ieee802154_stop(struct net_if *iface)
{
const struct ieee802154_radio_api *radio =
net_if_get_device(iface)->driver_api;
if (!radio) {
return -ENOENT;
}
return radio->stop(net_if_get_device(iface));
}
static inline void ieee802154_filter_ieee_addr(struct net_if *iface,
u8_t *ieee_addr)
{
const struct ieee802154_radio_api *radio =
net_if_get_device(iface)->driver_api;
if (radio && (radio->get_capabilities(net_if_get_device(iface)) &
IEEE802154_HW_FILTER)) {
struct ieee802154_filter filter;
filter.ieee_addr = ieee_addr;
if (radio->filter(net_if_get_device(iface), true,
IEEE802154_FILTER_TYPE_IEEE_ADDR,
&filter) != 0) {
NET_WARN("Could not apply IEEE address filter");
}
}
}
static inline void ieee802154_filter_short_addr(struct net_if *iface,
u16_t short_addr)
{
const struct ieee802154_radio_api *radio =
net_if_get_device(iface)->driver_api;
if (radio && (radio->get_capabilities(net_if_get_device(iface)) &
IEEE802154_HW_FILTER)) {
struct ieee802154_filter filter;
filter.short_addr = short_addr;
if (radio->filter(net_if_get_device(iface), true,
IEEE802154_FILTER_TYPE_SHORT_ADDR,
&filter) != 0) {
NET_WARN("Could not apply short address filter");
}
}
}
static inline void ieee802154_filter_pan_id(struct net_if *iface,
u16_t pan_id)
{
const struct ieee802154_radio_api *radio =
net_if_get_device(iface)->driver_api;
if (radio && (radio->get_capabilities(net_if_get_device(iface)) &
IEEE802154_HW_FILTER)) {
struct ieee802154_filter filter;
filter.pan_id = pan_id;
if (radio->filter(net_if_get_device(iface), true,
IEEE802154_FILTER_TYPE_PAN_ID,
&filter) != 0) {
NET_WARN("Could not apply PAN ID filter");
}
}
}
static inline void ieee802154_filter_src_ieee_addr(struct net_if *iface,
u8_t *ieee_addr)
{
const struct ieee802154_radio_api *radio =
net_if_get_device(iface)->driver_api;
if (radio && (radio->get_capabilities(net_if_get_device(iface)) &
IEEE802154_HW_FILTER)) {
struct ieee802154_filter filter;
filter.ieee_addr = ieee_addr;
if (radio->filter(net_if_get_device(iface), true,
IEEE802154_FILTER_TYPE_SRC_IEEE_ADDR,
&filter) != 0) {
NET_WARN("Could not apply SRC IEEE address filter");
}
}
}
static inline void ieee802154_filter_src_short_addr(struct net_if *iface,
u16_t short_addr)
{
const struct ieee802154_radio_api *radio =
net_if_get_device(iface)->driver_api;
if (radio && (radio->get_capabilities(net_if_get_device(iface)) &
IEEE802154_HW_FILTER)) {
struct ieee802154_filter filter;
filter.short_addr = short_addr;
if (radio->filter(net_if_get_device(iface), true,
IEEE802154_FILTER_TYPE_SRC_SHORT_ADDR,
&filter) != 0) {
NET_WARN("Could not apply SRC short address filter");
}
}
}
static inline void ieee802154_remove_src_ieee_addr(struct net_if *iface,
u8_t *ieee_addr)
{
const struct ieee802154_radio_api *radio =
net_if_get_device(iface)->driver_api;
if (radio && (radio->get_capabilities(net_if_get_device(iface)) &
IEEE802154_HW_FILTER)) {
struct ieee802154_filter filter;
filter.ieee_addr = ieee_addr;
if (radio->filter(net_if_get_device(iface), false,
IEEE802154_FILTER_TYPE_SRC_IEEE_ADDR,
&filter) != 0) {
NET_WARN("Could not remove SRC IEEE address filter");
}
}
}
static inline void ieee802154_remove_src_short_addr(struct net_if *iface,
u16_t short_addr)
{
const struct ieee802154_radio_api *radio =
net_if_get_device(iface)->driver_api;
if (radio && (radio->get_capabilities(net_if_get_device(iface)) &
IEEE802154_HW_FILTER)) {
struct ieee802154_filter filter;
filter.short_addr = short_addr;
if (radio->filter(net_if_get_device(iface), true,
IEEE802154_FILTER_TYPE_SRC_SHORT_ADDR,
&filter) != 0) {
NET_WARN("Could not remove SRC short address filter");
}
}
}
static inline bool ieee802154_verify_channel(struct net_if *iface,
u16_t channel)
{
if (channel == IEEE802154_NO_CHANNEL) {
return false;
}
#ifdef CONFIG_NET_L2_IEEE802154_SUB_GHZ
const struct ieee802154_radio_api *radio =
net_if_get_device(iface)->driver_api;
if (!radio) {
return false;
}
if (radio->get_capabilities(net_if_get_device(iface)) &
IEEE802154_HW_SUB_GHZ) {
if (channel >
radio->get_subg_channel_count(net_if_get_device(iface))) {
return false;
}
}
#endif /* CONFIG_NET_L2_IEEE802154_SUB_GHZ */
return true;
}
#endif /* __IEEE802154_UTILS_H__ */