diff --git a/boards/samr21-xpro/Makefile.dep b/boards/samr21-xpro/Makefile.dep index 9cee237662ba..09015358ab4b 100644 --- a/boards/samr21-xpro/Makefile.dep +++ b/boards/samr21-xpro/Makefile.dep @@ -1,5 +1,6 @@ ifneq (,$(filter gnrc_netdev_default netdev_default,$(USEMODULE))) USEMODULE += at86rf233 + USEMODULE += periph_i2c endif ifneq (,$(filter saul_default,$(USEMODULE))) diff --git a/boards/samr21-xpro/board.c b/boards/samr21-xpro/board.c index 0f78b8d22351..205bf9110d2a 100644 --- a/boards/samr21-xpro/board.c +++ b/boards/samr21-xpro/board.c @@ -48,3 +48,44 @@ void board_init(void) /* initialize the CPU */ cpu_init(); } + +#ifdef MODULE_PERIPH_I2C +#include "periph/i2c.h" +#include "net/l2util.h" +#include "net/netif_ids.h" + +#define DEV_I2C I2C_DEV(0) +#define EDBG_ADDR (0x28) +#define TOKEN_EUI64 (0xD2) +#define TOKEN_EXT (0xE1) + +/* EDBG provides an EUI-64 for the internal radio */ +size_t board_get_eui64(netif_id_t driver, unsigned idx, eui64_t *addr) +{ + if (driver != AT86RF2XX_DEVUID) { + return 0; + } + + if (idx != 0) { + return 0; + } + + i2c_acquire(DEV_I2C); + + /* dummy read form another token */ + if (i2c_read_regs(0, EDBG_ADDR, TOKEN_EXT, addr, 2, 0)) { + goto error; + } + + if (i2c_read_regs(0, EDBG_ADDR, TOKEN_EUI64, addr, sizeof(*addr), 0)) { + goto error; + } + + i2c_release(DEV_I2C); + return sizeof(eui64_t); + +error: + i2c_release(DEV_I2C); + return 0; +} +#endif diff --git a/drivers/at86rf2xx/at86rf2xx.c b/drivers/at86rf2xx/at86rf2xx.c index fb47b7736b60..02fb84012e1e 100644 --- a/drivers/at86rf2xx/at86rf2xx.c +++ b/drivers/at86rf2xx/at86rf2xx.c @@ -32,12 +32,13 @@ #include "at86rf2xx_registers.h" #include "at86rf2xx_internal.h" #include "at86rf2xx_netdev.h" +#include "at86rf2xx_params.h" #define ENABLE_DEBUG (0) #include "debug.h" -void at86rf2xx_setup(at86rf2xx_t *dev, const at86rf2xx_params_t *params) +void at86rf2xx_setup(at86rf2xx_t *dev, unsigned idx) { netdev_t *netdev = (netdev_t *)dev; @@ -49,13 +50,15 @@ void at86rf2xx_setup(at86rf2xx_t *dev, const at86rf2xx_params_t *params) dev->pending_tx = 0; #if defined(MODULE_AT86RFA1) || defined(MODULE_AT86RFR2) - (void) params; /* set all interrupts off */ at86rf2xx_reg_write(dev, AT86RF2XX_REG__IRQ_MASK, 0x00); #else /* initialize device descriptor */ - dev->params = *params; + dev->params = at86rf2xx_params[idx]; #endif + + l2util_generate_short_addr(AT86RF2XX_DEVUID, idx, (network_uint16_t *)dev->netdev.short_addr); + l2util_generate_eui64(AT86RF2XX_DEVUID, idx, (eui64_t *)dev->netdev.long_addr); } static void at86rf2xx_disable_clock_output(at86rf2xx_t *dev) @@ -89,8 +92,6 @@ static void at86rf2xx_enable_smart_idle(at86rf2xx_t *dev) void at86rf2xx_reset(at86rf2xx_t *dev) { - eui64_t addr_long; - at86rf2xx_hardware_reset(dev); netdev_ieee802154_reset(&dev->netdev); @@ -100,14 +101,9 @@ void at86rf2xx_reset(at86rf2xx_t *dev) at86rf2xx_set_state(dev, AT86RF2XX_STATE_FORCE_TRX_OFF); } - /* get an 8-byte unique ID to use as hardware address */ - luid_get(addr_long.uint8, IEEE802154_LONG_ADDRESS_LEN); - /* make sure we mark the address as non-multicast and not globally unique */ - addr_long.uint8[0] &= ~(0x01); - addr_long.uint8[0] |= (0x02); /* set short and long address */ - at86rf2xx_set_addr_long(dev, ntohll(addr_long.uint64.u64)); - at86rf2xx_set_addr_short(dev, ntohs(addr_long.uint16[0].u16)); + at86rf2xx_set_addr_long(dev, dev->netdev.long_addr); + at86rf2xx_set_addr_short(dev, dev->netdev.short_addr); /* set default channel */ at86rf2xx_set_chan(dev, AT86RF2XX_DEFAULT_CHANNEL); diff --git a/drivers/at86rf2xx/at86rf2xx_getset.c b/drivers/at86rf2xx/at86rf2xx_getset.c index cfe2b1e62e16..9cfd6929429a 100644 --- a/drivers/at86rf2xx/at86rf2xx_getset.c +++ b/drivers/at86rf2xx/at86rf2xx_getset.c @@ -135,15 +135,11 @@ uint16_t at86rf2xx_get_addr_short(const at86rf2xx_t *dev) return (dev->netdev.short_addr[0] << 8) | dev->netdev.short_addr[1]; } -void at86rf2xx_set_addr_short(at86rf2xx_t *dev, uint16_t addr) +void at86rf2xx_set_addr_short(at86rf2xx_t *dev, const uint8_t *addr) { - dev->netdev.short_addr[0] = (uint8_t)(addr); - dev->netdev.short_addr[1] = (uint8_t)(addr >> 8); -#ifdef MODULE_SIXLOWPAN - /* https://tools.ietf.org/html/rfc4944#section-12 requires the first bit to - * 0 for unicast addresses */ - dev->netdev.short_addr[0] &= 0x7F; -#endif + dev->netdev.short_addr[0] = addr[0]; + dev->netdev.short_addr[1] = addr[1]; + at86rf2xx_reg_write(dev, AT86RF2XX_REG__SHORT_ADDR_0, dev->netdev.short_addr[1]); at86rf2xx_reg_write(dev, AT86RF2XX_REG__SHORT_ADDR_1, @@ -161,12 +157,11 @@ uint64_t at86rf2xx_get_addr_long(const at86rf2xx_t *dev) return addr; } -void at86rf2xx_set_addr_long(at86rf2xx_t *dev, uint64_t addr) +void at86rf2xx_set_addr_long(at86rf2xx_t *dev, const uint8_t *addr) { for (int i = 0; i < 8; i++) { - dev->netdev.long_addr[i] = (uint8_t)(addr >> (i * 8)); - at86rf2xx_reg_write(dev, (AT86RF2XX_REG__IEEE_ADDR_0 + i), - (addr >> ((7 - i) * 8))); + dev->netdev.long_addr[i] = addr[i]; + at86rf2xx_reg_write(dev, (AT86RF2XX_REG__IEEE_ADDR_0 + i), addr[7-i]); } } diff --git a/drivers/at86rf2xx/at86rf2xx_netdev.c b/drivers/at86rf2xx/at86rf2xx_netdev.c index 3786e3b1cded..0532c757199f 100644 --- a/drivers/at86rf2xx/at86rf2xx_netdev.c +++ b/drivers/at86rf2xx/at86rf2xx_netdev.c @@ -470,12 +470,12 @@ static int _set(netdev_t *netdev, netopt_t opt, const void *val, size_t len) switch (opt) { case NETOPT_ADDRESS: assert(len <= sizeof(uint16_t)); - at86rf2xx_set_addr_short(dev, *((const uint16_t *)val)); + at86rf2xx_set_addr_short(dev, val); /* don't set res to set netdev_ieee802154_t::short_addr */ break; case NETOPT_ADDRESS_LONG: assert(len <= sizeof(uint64_t)); - at86rf2xx_set_addr_long(dev, *((const uint64_t *)val)); + at86rf2xx_set_addr_long(dev, val); /* don't set res to set netdev_ieee802154_t::long_addr */ break; case NETOPT_NID: diff --git a/drivers/include/at86rf2xx.h b/drivers/include/at86rf2xx.h index 6d634e80a131..dcb914204fb4 100644 --- a/drivers/include/at86rf2xx.h +++ b/drivers/include/at86rf2xx.h @@ -268,9 +268,9 @@ typedef struct { * @brief Setup an AT86RF2xx based device state * * @param[out] dev device descriptor - * @param[in] params parameters for device initialization + * @param[in] idx index in the at86rf2xx_params struct. */ -void at86rf2xx_setup(at86rf2xx_t *dev, const at86rf2xx_params_t *params); +void at86rf2xx_setup(at86rf2xx_t *dev, unsigned idx); /** * @brief Trigger a hardware reset and configure radio with default values @@ -294,7 +294,7 @@ uint16_t at86rf2xx_get_addr_short(const at86rf2xx_t *dev); * @param[in,out] dev device to write to * @param[in] addr (2-byte) short address to set */ -void at86rf2xx_set_addr_short(at86rf2xx_t *dev, uint16_t addr); +void at86rf2xx_set_addr_short(at86rf2xx_t *dev, const uint8_t *addr); /** * @brief Get the configured long address of the given device @@ -311,7 +311,7 @@ uint64_t at86rf2xx_get_addr_long(const at86rf2xx_t *dev); * @param[in,out] dev device to write to * @param[in] addr (8-byte) long address to set */ -void at86rf2xx_set_addr_long(at86rf2xx_t *dev, uint64_t addr); +void at86rf2xx_set_addr_long(at86rf2xx_t *dev, const uint8_t *addr); /** * @brief Get the configured channel number of the given device diff --git a/sys/auto_init/netif/auto_init_at86rf2xx.c b/sys/auto_init/netif/auto_init_at86rf2xx.c index 88b07672901e..5a72e20c590e 100644 --- a/sys/auto_init/netif/auto_init_at86rf2xx.c +++ b/sys/auto_init/netif/auto_init_at86rf2xx.c @@ -52,7 +52,7 @@ void auto_init_at86rf2xx(void) for (unsigned i = 0; i < AT86RF2XX_NUM; i++) { LOG_DEBUG("[auto_init_netif] initializing at86rf2xx #%u\n", i); - at86rf2xx_setup(&at86rf2xx_devs[i], &at86rf2xx_params[i]); + at86rf2xx_setup(&at86rf2xx_devs[i], i); #if defined(MODULE_GNRC_GOMACH) gnrc_netif_gomach_create(_at86rf2xx_stacks[i], AT86RF2XX_MAC_STACKSIZE, diff --git a/sys/include/luid.h b/sys/include/luid.h index b647958b4418..df5214ad5c3e 100644 --- a/sys/include/luid.h +++ b/sys/include/luid.h @@ -94,6 +94,8 @@ void luid_get(void *buf, size_t len); * * @note The resulting address will repeat after 255 calls. * + * @warning Don't call this function directly, use @ref l2util_generate_short_addr() instead. + * * @param[out] addr memory location to copy the address into. */ void luid_get_short(network_uint16_t *addr); @@ -106,6 +108,8 @@ void luid_get_short(network_uint16_t *addr); * * @note The resulting address will repeat after 255 calls. * + * @warning Don't call this function directly, use @ref l2util_generate_eui48() instead. + * * @param[out] addr memory location to copy the address into. */ void luid_get_eui48(eui48_t *addr); @@ -118,6 +122,8 @@ void luid_get_eui48(eui48_t *addr); * * @note The resulting address will repeat after 255 calls. * + * @warning Don't call this function directly, use @ref l2util_generate_eui64() instead. + * * @param[out] addr memory location to copy the address into. */ void luid_get_eui64(eui64_t *addr); diff --git a/sys/include/net/eui48.h b/sys/include/net/eui48.h index 2a5fadfa9300..d8531d1349a7 100644 --- a/sys/include/net/eui48.h +++ b/sys/include/net/eui48.h @@ -131,7 +131,6 @@ static inline void eui48_clear_group(eui48_t *addr) addr->uint8[0] &= ~EUI48_GROUP_FLAG; } - #ifdef __cplusplus } #endif diff --git a/sys/include/net/l2util.h b/sys/include/net/l2util.h index e5030b7291f4..8b20b444a0a1 100644 --- a/sys/include/net/l2util.h +++ b/sys/include/net/l2util.h @@ -27,7 +27,9 @@ #include +#include "luid.h" #include "net/eui64.h" +#include "net/netif_ids.h" #include "net/ndp.h" #ifdef __cplusplus @@ -133,6 +135,125 @@ int l2util_ipv6_iid_to_addr(int dev_type, const eui64_t *iid, uint8_t *addr); int l2util_ndp_addr_len_from_l2ao(int dev_type, const ndp_opt_t *opt); +/** + * @brief Board-specific function to supply a short address to a netdev. + * + * @note Implement this function in your board code if the board + * provides the means to supply a unique address to a netdev. + * + * @warning Don't call this function directly, use @ref l2util_generate_short_addr() instead. + * + * @param[in] driver The driver id of the netdev + * @param[in] idx The index in the _params_t struct + * @param[out] addr The dedicated address for the netdev + * + * @return The number of bytes copied. 0 if no address is available. + */ +size_t board_get_short_addr(netif_id_t driver, unsigned idx, network_uint16_t *addr); + +/** + * @brief Generates an short address for the netdev interface. + * + * @note It is possible to supply a board-specific, constant addres + * by implementing @ref board_get_short_addr. + * If no such function is availiable, this will fall back to + * @ref luid_get_short. + * + * @param[in] driver The driver id of the netdev + * Will be passed on to @ref board_get_eui48. + * @param[in] idx The index in the _params_t struct + * Will be passed on to @ref board_get_eui48. + * @param[out] addr The generated short address + * + */ +static inline void l2util_generate_short_addr(netif_id_t driver, unsigned idx, network_uint16_t *addr) +{ + if (board_get_short_addr(driver, idx, addr) == sizeof(*addr)) { + return; + } + + luid_get_short(addr); +} + +/** + * @brief Board-specific function to supply an EUI-48 to a netdev + * + * @note Implement this function in your board code if the board + * provides the means to supply a unique address to a netdev. + * + * @warning Don't call this function directly, use @ref l2util_generate_eui48() instead. + * + * @param[in] driver The driver id of the netdev + * @param[in] idx The index in the _params_t struct + * @param[out] addr The dedicated address for the netdev + * + * @return The number of bytes copied. 0 if no address is available. + */ +size_t board_get_eui48(netif_id_t driver, unsigned idx, eui48_t *addr); + +/** + * @brief Generates an EUI-48 address for the netdev interface. + * + * @note It is possible to supply a board-specific, constant addres + * by implementing @ref board_get_eui48. + * If no such function is availiable, this will fall back to + * @ref luid_get_eui48. + * + * @param[in] driver The driver id of the netdev + * Will be passed on to @ref board_get_eui48. + * @param[in] idx The index in the _params_t struct + * Will be passed on to @ref board_get_eui48. + * @param[out] addr The generated EUI-48 address + * + */ +static inline void l2util_generate_eui48(netif_id_t driver, unsigned idx, eui48_t *addr) +{ + if (board_get_eui48(driver, idx, addr) == sizeof(*addr)) { + return; + } + + luid_get_eui48(addr); +} + +/** + * @brief Board-specific function to supply an EUI-64 to a netdev + * + * @note Implement this function in your board code if the board + * provides the means to supply a unique address to a netdev. + * + * @warning Don't call this function directly, use @ref l2util_generate_eui64() instead. + * + * @param[in] driver The driver id of the netdev + * @param[in] idx The index in the _params_t struct + * @param[out] addr The dedicated address for the netdev + * + * @return The number of bytes copied. 0 if no address is available. + */ +size_t board_get_eui64(netif_id_t driver, unsigned idx, eui64_t *addr); + +/** + * @brief Generates an EUI-64 address for the netdev interface. + * + * @note It is possible to supply a board-specific, constant addres + * by implementing @ref board_get_eui64. + * If no such function is availiable, this will fall back to + * @ref luid_get_eui64. + * + * @param[in] driver The driver id of the netdev + * Will be passed on to @ref board_get_eui64. + * @param[in] idx The index in the _params_t struct + * Will be passed on to @ref board_get_eui64. + * @param[out] addr The generated EUI-64 address + * + */ +static inline void l2util_generate_eui64(netif_id_t driver, unsigned idx, eui64_t *addr) +{ + if (board_get_eui64(driver, idx, addr) == sizeof(*addr)) { + return; + } + + luid_get_eui64(addr); +} #ifdef __cplusplus } diff --git a/sys/include/net/netif_ids.h b/sys/include/net/netif_ids.h new file mode 100644 index 000000000000..02cca39eda9a --- /dev/null +++ b/sys/include/net/netif_ids.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2020 ML!PA Consulting GmbH + * + * 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 + * + * @{ + * + * @file + * @brief Unique IDs to identify netif drivers. + * + * @author Benjamin Valentin + */ +#ifndef NET_NETIF_IDS_H +#define NET_NETIF_IDS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Unique IDs for netif drivers. + */ +typedef enum { + AT86RF2XX_DEVUID, +} netif_id_t; + +#ifdef __cplusplus +} +#endif + +#endif /* NET_NETIF_IDS_H */ +/** @} */ diff --git a/sys/net/link_layer/l2util/l2util.c b/sys/net/link_layer/l2util/l2util.c index d8873847e02a..0d58704d132d 100644 --- a/sys/net/link_layer/l2util/l2util.c +++ b/sys/net/link_layer/l2util/l2util.c @@ -16,6 +16,7 @@ #include #include "log.h" +#include "luid.h" #include "net/eui48.h" #include "net/ieee802154.h" #include "net/ipv6.h" @@ -238,5 +239,28 @@ int l2util_ndp_addr_len_from_l2ao(int dev_type, return -ENOTSUP; } +size_t __attribute__((weak)) board_get_short_addr(netif_id_t driver, unsigned idx, network_uint16_t *addr) +{ + (void) driver; + (void) idx; + (void) addr; + return 0; +} + +size_t __attribute__((weak)) board_get_eui48(netif_id_t driver, unsigned idx, eui48_t *addr) +{ + (void) driver; + (void) idx; + (void) addr; + return 0; +} + +size_t __attribute__((weak)) board_get_eui64(netif_id_t driver, unsigned idx, eui64_t *addr) +{ + (void) driver; + (void) idx; + (void) addr; + return 0; +} /** @} */