Browse Source

nrf52dk: add BLE/6lowpan support utilizing Nordic's SoftDevice

pr/spi.typo
Kaspar Schleiser 6 years ago
parent
commit
0182bbd6fd
  1. 11
      Makefile.dep
  2. 4
      boards/nrf52dk/Makefile.dep
  3. 7
      boards/nrf52dk/Makefile.include
  4. 10
      boards/nrf52dk/include/periph_conf.h
  5. 24
      cpu/nrf52/cpu.c
  6. 17
      cpu/nrf52/include/cpu_conf.h
  7. 27
      cpu/nrf52/ldscripts/nrf52xxaa_sd.ld
  8. 28
      cpu/nrf52/vectors.c
  9. 49
      pkg/nordic_softdevice_ble/Makefile
  10. 32
      pkg/nordic_softdevice_ble/Makefile.include
  11. 1
      pkg/nordic_softdevice_ble/Makefile.module
  12. 100
      pkg/nordic_softdevice_ble/README-BLE-6LoWPAN.md
  13. 30
      pkg/nordic_softdevice_ble/README.md
  14. 2
      pkg/nordic_softdevice_ble/src/Makefile
  15. 9
      pkg/nordic_softdevice_ble/src/app_error.c
  16. 235
      pkg/nordic_softdevice_ble/src/ble-core.c
  17. 61
      pkg/nordic_softdevice_ble/src/ble-core.h
  18. 305
      pkg/nordic_softdevice_ble/src/ble-mac.c
  19. 50
      pkg/nordic_softdevice_ble/src/ble-mac.h
  20. 318
      pkg/nordic_softdevice_ble/src/gnrc_nordic_ble_6lowpan.c
  21. 43
      pkg/nordic_softdevice_ble/src/gnrc_nordic_ble_6lowpan.h
  22. 5
      sys/auto_init/auto_init.c

11
Makefile.dep

@ -31,6 +31,17 @@ ifneq (,$(filter gnrc_uhcpc,$(USEMODULE)))
USEMODULE += fmt
endif
ifneq (,$(filter nordic_softdevice_ble,$(USEPKG)))
USEMODULE += softdevice_handler
USEMODULE += ble_common
USEMODULE += ble_6lowpan
USEMODULE += gnrc_sixlowpan
USEMODULE += gnrc_sixlowpan_iphc
USEMODULE += gnrc_ipv6_default
USEMODULE += gnrc_netdev2
USEMODULE += gnrc_ipv6_netif
endif
ifneq (,$(filter gnrc_%,$(filter-out gnrc_netapi gnrc_netreg gnrc_netif% gnrc_pktbuf,$(USEMODULE))))
USEMODULE += gnrc
endif

4
boards/nrf52dk/Makefile.dep

@ -1,3 +1,7 @@
ifneq (,$(filter saul_default,$(USEMODULE)))
USEMODULE += saul_gpio
endif
ifneq (,$(filter gnrc_netdev_default,$(USEMODULE)))
USEPKG += nordic_softdevice_ble
endif

7
boards/nrf52dk/Makefile.include

@ -11,6 +11,13 @@ include $(RIOTBOARD)/$(BOARD)/Makefile.dep
# setup JLink for flashing
export JLINK_DEVICE := nrf52
# special options when using SoftDevice
ifneq (,$(filter nordic_softdevice_ble,$(USEPKG)))
export JLINK_PRE_FLASH := loadfile $(BINDIR)/softdevice.hex
export JLINK_FLASH_ADDR := 0x1f000
export LINKER_SCRIPT ?= $(RIOTCPU)/$(CPU)/ldscripts/$(CPU_MODEL)_sd.ld
endif
include $(RIOTBOARD)/Makefile.include.jlink
# setup serial terminal

10
boards/nrf52dk/include/periph_conf.h

@ -44,10 +44,10 @@ extern "C" {
*/
static const timer_conf_t timer_config[] = {
/* dev, channels, width, IRQn */
{ NRF_TIMER0, 3, TIMER_BITMODE_BITMODE_32Bit, TIMER0_IRQn }
{ NRF_TIMER1, 3, TIMER_BITMODE_BITMODE_32Bit, TIMER1_IRQn }
};
#define TIMER_0_ISR isr_timer0
#define TIMER_0_ISR isr_timer1
#define TIMER_NUMOF (sizeof(timer_config) / sizeof(timer_config[0]))
/** @} */
@ -57,9 +57,9 @@ static const timer_conf_t timer_config[] = {
* @{
*/
#define RTT_NUMOF (1U)
#define RTT_DEV NRF_RTC0
#define RTT_IRQ RTC0_IRQn
#define RTT_ISR isr_rtc0
#define RTT_DEV NRF_RTC1
#define RTT_IRQ RTC1_IRQn
#define RTT_ISR isr_rtc1
#define RTT_MAX_VALUE (0xffffff)
#define RTT_FREQUENCY (10) /* in Hz */
#define RTT_PRESCALER (3275U) /* run with 10 Hz */

24
cpu/nrf52/cpu.c

@ -20,6 +20,8 @@
* @}
*/
#define DONT_OVERRIDE_NVIC
#include "cpu.h"
#include "periph_conf.h"
@ -28,14 +30,16 @@ static bool ftpan_32(void);
static bool ftpan_37(void);
static bool ftpan_36(void);
#ifdef SOFTDEVICE_PRESENT
#include "softdevice_handler.h"
uint8_t _ble_evt_buffer[BLE_STACK_EVT_MSG_BUF_SIZE];
#endif
/**
* @brief Initialize the CPU, set IRQ priorities
*/
void cpu_init(void)
{
/* set pendSV interrupt to lowest possible priority */
NVIC_SetPriority(PendSV_IRQn, 0xff);
/* Workaround for FTPAN-32
* "DIF: Debug session automatically enables TracePort pins." */
if (ftpan_32()) {
@ -64,6 +68,20 @@ void cpu_init(void)
while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0);
#endif
/* softdevice needs to be enabled from ISR context */
#ifdef SOFTDEVICE_PRESENT
softdevice_handler_init(NRF_CLOCK_LFCLKSRC_XTAL_20_PPM, &_ble_evt_buffer,
BLE_STACK_EVT_MSG_BUF_SIZE, NULL);
#endif
/* call cortexm default initialization */
cortexm_init();
#ifdef SOFTDEVICE_PRESENT
/* fixup swi0 (used as softdevice PendSV trampoline) */
NVIC_EnableIRQ(SWI0_EGU0_IRQn);
NVIC_SetPriority(SWI0_EGU0_IRQn, 6);
#endif
}
/**

17
cpu/nrf52/include/cpu_conf.h

@ -32,11 +32,24 @@ extern "C" {
* @brief ARM Cortex-M specific CPU configuration
* @{
*/
#define CPU_DEFAULT_IRQ_PRIO (1U)
#define CPU_IRQ_NUMOF (38)
#define CPU_DEFAULT_IRQ_PRIO (2U)
#define CPU_IRQ_NUMOF (38U)
#define CPU_FLASH_BASE (0x00000000)
/** @} */
/**
* @brief SoftDevice settings
* @{
*/
#ifdef SOFTDEVICE_PRESENT
#ifndef DONT_OVERRIDE_NVIC
#include "nrf_soc.h"
#undef NVIC_SetPriority
#define NVIC_SetPriority sd_nvic_SetPriority
#endif /* DONT_OVERRIDE_NVIC */
#endif /* SOFTDEVICE_PRESENT */
/** @} */
#ifdef __cplusplus
}
#endif

27
cpu/nrf52/ldscripts/nrf52xxaa_sd.ld

@ -0,0 +1,27 @@
/*
* Copyright (C) 2016 Freie Universität Berlin
*
* 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.
*/
/**
* @addtogroup cpu_nrf52
* @{
*
* @file
* @brief Memory definitions for the NRF52832XXAA
*
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
*
* @}
*/
MEMORY
{
rom (rx) : ORIGIN = 0x1f000, LENGTH = 0x61000
ram (rwx) : ORIGIN = 0x20002800, LENGTH = 0xD800
}
INCLUDE cortexm_base.ld

28
cpu/nrf52/vectors.c

@ -58,7 +58,21 @@ WEAK_DEFAULT void isr_wdt(void);
WEAK_DEFAULT void isr_rtc1(void);
WEAK_DEFAULT void isr_qdec(void);
WEAK_DEFAULT void isr_lpcomp(void);
#ifndef SOFTDEVICE_PRESENT
WEAK_DEFAULT void isr_swi0(void);
#else
/* For unknown reasons, setting PendSV pending within
* the softdevice ISRs leads to a crash. This workaround
* uses swi0 as trampoline.
*/
extern void thread_arch_yield(void);
void isr_swi0(void)
{
thread_arch_yield();
}
#endif
WEAK_DEFAULT void isr_swi1(void);
WEAK_DEFAULT void isr_swi2(void);
WEAK_DEFAULT void isr_swi3(void);
@ -76,6 +90,10 @@ WEAK_DEFAULT void isr_rtc2(void);
WEAK_DEFAULT void isr_i2s(void);
#ifdef SOFTDEVICE_PRESENT
extern void SWI2_EGU2_IRQHandler(void);
#endif
/* interrupt vector table */
ISR_VECTORS const void *interrupt_vector[] = {
/* Exception stack pointer */
@ -121,10 +139,14 @@ ISR_VECTORS const void *interrupt_vector[] = {
(void *) isr_lpcomp, /* lpcomp */
(void *) isr_swi0, /* swi0 */
(void *) isr_swi1, /* swi1 */
#ifdef SOFTDEVICE_PRESENT
(void *) SWI2_EGU2_IRQHandler, /* softdevice swi handler */
#else
(void *) isr_swi2, /* swi2 */
(void *) isr_swi3, /* swi3 */
(void *) isr_swi4, /* swi4 */
(void *) isr_swi5, /* swi5 */
#endif
(void *) (0UL), /* swi3 */
(void *) (0UL), /* swi4 */
(void *) (0UL), /* swi5 */
(void *) isr_timer3, /* timer 3 */
(void *) isr_timer4, /* timer 4 */
(void *) isr_pwm0, /* pwm 0 */

49
pkg/nordic_softdevice_ble/Makefile

@ -0,0 +1,49 @@
PKG_NAME = nordic_softdevice_ble
PKG_VERSION = 3288530
PKG_FILE = nrf5_iot_sdk_$(PKG_VERSION).zip
PKG_URL = https://developer.nordicsemi.com/nRF5_IoT_SDK/nRF5_IoT_SDK_v0.9.x/$(PKG_FILE)
PKG_DIR=$(CURDIR)
PKG_BUILDDIR=$(BINDIRBASE)/pkg/$(BOARD)/$(PKG_NAME)
PKG_SRCDIR=$(PKG_BUILDDIR)/src
SOFTDEVICE := components/softdevice/s1xx_iot/s1xx-iot-prototype3_nrf52_softdevice.hex
BLE_6LOWPAN_LIB := components/iot/ble_6lowpan/lib/ble_6lowpan.a
MODULE_MAKEFILE := $(PKG_DIR)/Makefile.module
.PHONY: all clean distclean
all: $(BINDIR)/ble_6lowpan.a $(BINDIR)/softdevice.hex
$(BINDIR)/ble_6lowpan.a: $(PKG_SRCDIR)/.extracted
cp $(PKG_SRCDIR)/$(BLE_6LOWPAN_LIB) $@
$(BINDIR)/softdevice.hex: $(PKG_SRCDIR)/.extracted
cp $(PKG_SRCDIR)/$(SOFTDEVICE) $@
$(PKG_SRCDIR)/.extracted: $(PKG_BUILDDIR)/$(PKG_FILE)
rm -rf $(@D)
mkdir -p $(@D)
$(AD)cd $(@D) && $(UNZIP_HERE) $(PKG_BUILDDIR)/$(PKG_FILE)
# this file doesn't compile with RIOT, but is not needed either
rm $(PKG_BUILDDIR)/src/components/ble/common/ble_conn_params.c
# setup RIOT module makefiles for nordic SDK components
cat $(MODULE_MAKEFILE) > $(PKG_SRCDIR)/components/softdevice/common/softdevice_handler/Makefile
echo "MODULE=ble_common" > $(PKG_SRCDIR)/components/ble/common/Makefile
cat $(MODULE_MAKEFILE) >> $(PKG_SRCDIR)/components/ble/common/Makefile
cat $(MODULE_MAKEFILE) > $(PKG_SRCDIR)/components/iot/ble_ipsp/Makefile
touch $@
$(PKG_BUILDDIR)/$(PKG_FILE):
@mkdir -p $(@D)
$(AD)$(DOWNLOAD_TO_FILE) $@ $(PKG_URL)
clean::
rm -rf $(PKG_SRCDIR)/
distclean::
rm -rf $(PKG_BUILDDIR)/

32
pkg/nordic_softdevice_ble/Makefile.include

@ -0,0 +1,32 @@
NORDIC_SRCS := $(BINDIRBASE)/pkg/$(BOARD)/nordic_softdevice_ble/src
INCLUDES += \
-I$(RIOTBASE)/pkg/nordic_softdevice_ble/src \
-I$(NORDIC_SRCS)/components/ble/common \
-I$(NORDIC_SRCS)/components/device \
-I$(NORDIC_SRCS)/components/iot/ble_6lowpan \
-I$(NORDIC_SRCS)/components/iot/ble_ipsp \
-I$(NORDIC_SRCS)/components/iot/common \
-I$(NORDIC_SRCS)/components/libraries/scheduler \
-I$(NORDIC_SRCS)/components/libraries/util \
-I$(NORDIC_SRCS)/components/softdevice/common/softdevice_handler \
-I$(NORDIC_SRCS)/components/softdevice/s1xx_iot/headers \
-I$(NORDIC_SRCS)/components/softdevice/s1xx_iot/headers/nrf52 \
-I$(NORDIC_SRCS)/components/toolchain
CFLAGS += -DNRF52 \
-DBLE_STACK_SUPPORT_REQD \
-DISR_STACKSIZE=8192 \
-DSOFTDEVICE_PRESENT \
-DS132
# Nordic's ble_6lowpan.a is compiled with hard-float
# so set this, otherwise linking fails
CFLAGS_FPU := -mfloat-abi=hard -mfpu=fpv4-sp-d16
DIRS += \
$(RIOTBASE)/pkg/nordic_softdevice_ble/src \
$(NORDIC_SRCS)/components/softdevice/common/softdevice_handler \
$(NORDIC_SRCS)/components/ble/common \
$(NORDIC_SRCS)/components/iot/ble_ipsp

1
pkg/nordic_softdevice_ble/Makefile.module

@ -0,0 +1 @@
include $(RIOTBASE)/Makefile.base

100
pkg/nordic_softdevice_ble/README-BLE-6LoWPAN.md

@ -0,0 +1,100 @@
This README contains information how to establish an IPv6 connecton between
Linux BLE router and an IPSP enabled BLE device.
Prerequisites
=============
In general, any device capable of running Linux operating system, can be used
as a BLE router provided the following conditions are met:
* Linux Kernel >3.18 is used
* bluez, libcap-ng0, radvd tools are present.
If a built-in Bluetooth device is not available then Bluetooth 4.0 compatible
USB dongle can be used.
The following procedures have been tested on Ubuntu 15.10.
Establishing an IPv6 connection
===============================
Use the following procedure to establish a connection between an nRF52 device
and Linux router:
First enable 6LoWPAN module. This is neccessary only once per session:
# Log in as a root user.
sudo su
# Mount debugfs file system.
mount -t debugfs none /sys/kernel/debug
# Load 6LoWPAN module.
modprobe bluetooth_6lowpan
# Enable the bluetooth 6lowpan module.
echo 1 > /sys/kernel/debug/bluetooth/6lowpan_enable
# Look for available HCI devices.
hciconfig
# Reset HCI device - for example hci0 device.
hciconfig hci0 reset
# Read 00:AA:BB:XX:YY:ZZ address of the nRF5x device.
hcitool lescan
If you see device name and address in lescan output then you can connect to the
device:
echo "connect 00:AA:BB:XX:YY:ZZ 1" > /sys/kernel/debug/bluetooth/6lowpan_control
If above is successful then LED1 will stop blinking and LED2 will switch on.
You can then check the connection using the following commands:
# Check if bt0 interface is present and up
ifconfig
# Try to ping the device using its link-local address, for example, on bt0 interface.
ping6 fe80::2aa:bbff:fexx:yyzz%bt0
If you'd like to learn more about the procedure please refer to
[Connecting devices to the router].
Distributing routable IPv6 prefix
=================================
In Linux, Router Advertisement Daemon (RADVD) can be used to distribute prefixes
in the network, hance configure routable IPv6 address.
To configure RADVD create `/etc/radvd.conf` file and paste the following contents:
interface bt0
{
AdvSendAdvert on;
prefix 2001:db8::/64
{
AdvOnLink off;
AdvAutonomous on;
AdvRouterAddr on;
};
};
Next, start RADVD daemon:
# Set IPv6 forwarding (must be present).
sudo echo 1 > /proc/sys/net/ipv6/conf/all/forwarding
# Run radvd daemon.
sudo service radvd restart
If successfull then all devices connected to the host will receive
a routable `2001:db8` prefix.
This can be verified by sending echo request to the full address:
ping6 -I bt0 2001:db8::2aa:bbff:fexx:yyzz
where `aa:bbff:fexx:yyzz` is device Bluetooth address.
If you'd like to learn more about the procedure please refer to
[Distributing a global IPv6 prefix].
* [Connecting devices to the router]: http://developer.nordicsemi.com/nRF5_IoT_SDK/doc/0.9.0/html/a00089.html
* [Distributing a global IPv6 prefix]: http://developer.nordicsemi.com/nRF5_IoT_SDK/doc/0.9.0/html/a00090.html

30
pkg/nordic_softdevice_ble/README.md

@ -0,0 +1,30 @@
# Overview
This package provides necessary Makefiles and glue code to use the Nordic S132
SoftDevice as Bluetooth BLE transport for RIOT's 6lowpan stack.
# Usage
"gnrc_netdev_default" has a dependency to "nordic_softdevice_ble", so all
examples automatically download the SDK and compile / link / flash all needed
code.
If you want to manually set up included modules, add "USEPKG +=
nordic_softdevice_ble" to your application's Makefile.
See README-BLE-6LoWPAN.md for instructions on how to set up 6lowpan over BLE on
Linux.
# Known issues
- floating point ABI mismatch
The Nordic binaries are compiled using hard float ABI, which RIOT currently
doesn't support (RIOT's context switching code doesn't preserve the floating
point registers). If the softdevice is compiled in, RIOT will be compiled with
hard float ABI in order for the linking to succeed. This works for some
application, but will lead to serious and hard-to-find bugs for code using
floating point instructions.
Hopefully, either the RIOT community adds hard-float support, or Nordic
releases a soft-float version of the used binaries.

2
pkg/nordic_softdevice_ble/src/Makefile

@ -0,0 +1,2 @@
MODULE = nordic_softdevice_ble
include $(RIOTBASE)/Makefile.base

9
pkg/nordic_softdevice_ble/src/app_error.c

@ -0,0 +1,9 @@
#include "app_error.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
void app_error_handler(uint32_t error_code, uint32_t line_num, const uint8_t *p_file_name)
{
puts("nordic softdevice app_error_handler()");
}

235
pkg/nordic_softdevice_ble/src/ble-core.c

@ -0,0 +1,235 @@
/*
* Copyright (c) 2016, Nordic Semiconductor
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
/**
* @addtogroup cpu
* @{
*
* @addtogroup nrf52832
* @{
*
* @addtogroup nrf52832-ble Bluetooth Low Energy drivers
* @{
*
* @file
* Basic BLE functions.
* @author
* Wojciech Bober <wojciech.bober@nordicsemi.no>
* Kaspar Schleiser <kaspar@schleiser.de>
*
*/
#include <stdbool.h>
#include <stdint.h>
//#include "boards.h"
//#include "nordic_common.h"
//#include "nrf_delay.h"
#include "nrf_sdm.h"
#include "ble_advdata.h"
#include "ble_srv_common.h"
#include "ble_ipsp.h"
#include "softdevice_handler.h"
#include "app_error.h"
#include "iot_defines.h"
#include "ble-core.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
#define IS_SRVC_CHANGED_CHARACT_PRESENT 1
#define APP_ADV_TIMEOUT 0 /**< Time for which the device must be advertising in non-connectable mode (in seconds). 0 disables timeout. */
#define APP_ADV_ADV_INTERVAL MSEC_TO_UNITS(333, UNIT_0_625_MS) /**< The advertising interval. This value can vary between 100ms to 10.24s). */
static ble_gap_adv_params_t m_adv_params; /**< Parameters to be passed to the stack when starting advertising. */
static void
ble_evt_dispatch(ble_evt_t * p_ble_evt);
/*---------------------------------------------------------------------------*/
/**
* @brief Initialize and enable the BLE stack.
*/
void
ble_stack_init(void)
{
uint32_t err_code;
// Enable BLE stack.
ble_enable_params_t ble_enable_params;
memset(&ble_enable_params, 0, sizeof(ble_enable_params));
ble_enable_params.gatts_enable_params.attr_tab_size =
BLE_GATTS_ATTR_TAB_SIZE_DEFAULT;
ble_enable_params.gatts_enable_params.service_changed =
IS_SRVC_CHANGED_CHARACT_PRESENT;
err_code = sd_ble_enable(&ble_enable_params);
APP_ERROR_CHECK(err_code);
// Register with the SoftDevice handler module for BLE events.
err_code = softdevice_ble_evt_handler_set(ble_evt_dispatch);
APP_ERROR_CHECK(err_code);
// Setup address
ble_gap_addr_t ble_addr;
err_code = sd_ble_gap_address_get(&ble_addr);
APP_ERROR_CHECK(err_code);
ble_addr.addr[5] = 0x00;
ble_addr.addr_type = BLE_GAP_ADDR_TYPE_PUBLIC;
err_code = sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_NONE, &ble_addr);
APP_ERROR_CHECK(err_code);
}
/*---------------------------------------------------------------------------*/
/**
* @brief Return device EUI64 MAC address
* @param addr pointer to a buffer to store the address
*/
void
ble_get_mac(uint8_t addr[8])
{
uint32_t err_code;
ble_gap_addr_t ble_addr;
err_code = sd_ble_gap_address_get(&ble_addr);
APP_ERROR_CHECK(err_code);
IPV6_EUI64_CREATE_FROM_EUI48(addr, ble_addr.addr, ble_addr.addr_type);
}
/*---------------------------------------------------------------------------*/
/**
* @brief Initialize BLE advertising data.
* @param name Human readable device name that will be advertised
*/
void
ble_advertising_init(const char *name)
{
uint32_t err_code;
ble_advdata_t advdata;
uint8_t flags = BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED;
ble_gap_conn_sec_mode_t sec_mode;
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);
err_code = sd_ble_gap_device_name_set(&sec_mode, (const uint8_t *)name,
strlen(name));
APP_ERROR_CHECK(err_code);
ble_uuid_t adv_uuids[] = {{BLE_UUID_IPSP_SERVICE, BLE_UUID_TYPE_BLE}};
// Build and set advertising data.
memset(&advdata, 0, sizeof(advdata));
advdata.name_type = BLE_ADVDATA_FULL_NAME;
advdata.flags = flags;
advdata.uuids_complete.uuid_cnt = sizeof(adv_uuids) / sizeof(adv_uuids[0]);
advdata.uuids_complete.p_uuids = adv_uuids;
err_code = ble_advdata_set(&advdata, NULL);
APP_ERROR_CHECK(err_code);
// Initialize advertising parameters (used when starting advertising).
memset(&m_adv_params, 0, sizeof(m_adv_params));
m_adv_params.type = BLE_GAP_ADV_TYPE_ADV_IND;
m_adv_params.p_peer_addr = NULL; // Undirected advertisement.
m_adv_params.fp = BLE_GAP_ADV_FP_ANY;
m_adv_params.interval = APP_ADV_ADV_INTERVAL;
m_adv_params.timeout = APP_ADV_TIMEOUT;
}
/*---------------------------------------------------------------------------*/
/**
* @brief Start BLE advertising.
*/
void
ble_advertising_start(void)
{
uint32_t err_code;
err_code = sd_ble_gap_adv_start(&m_adv_params);
APP_ERROR_CHECK(err_code);
DEBUG("ble-core: advertising started\n");
}
/*---------------------------------------------------------------------------*/
/**
* @brief Print GAP address.
* @param addr a pointer to address
*/
void
ble_gap_addr_print(const ble_gap_addr_t *addr)
{
unsigned int i;
for(i = 0; i < sizeof(addr->addr); i++) {
if(i > 0) {
DEBUG(":");
}DEBUG("%02x", addr->addr[i]);
}DEBUG(" (%d)", addr->addr_type);
}
/*---------------------------------------------------------------------------*/
/**
* @brief Function for handling the Application's BLE Stack events.
* @param[in] p_ble_evt Bluetooth stack event.
*/
static void
on_ble_evt(ble_evt_t *p_ble_evt)
{
switch(p_ble_evt->header.evt_id) {
case BLE_GAP_EVT_CONNECTED:
DEBUG("ble-core: connected [handle:%d, peer: ", p_ble_evt->evt.gap_evt.conn_handle);
ble_gap_addr_print(&(p_ble_evt->evt.gap_evt.params.connected.peer_addr));
DEBUG("]\n");
sd_ble_gap_rssi_start(p_ble_evt->evt.gap_evt.conn_handle,
BLE_GAP_RSSI_THRESHOLD_INVALID,
0);
break;
case BLE_GAP_EVT_DISCONNECTED:
DEBUG("ble-core: disconnected [handle:%d]\n", p_ble_evt->evt.gap_evt.conn_handle);
ble_advertising_start();
break;
default:
break;
}
}
/*---------------------------------------------------------------------------*/
/**
* @brief SoftDevice BLE event callback.
* @param[in] p_ble_evt Bluetooth stack event.
*/
static void
ble_evt_dispatch(ble_evt_t *p_ble_evt)
{
ble_ipsp_evt_handler(p_ble_evt);
on_ble_evt(p_ble_evt);
}
/*---------------------------------------------------------------------------*/
/**
* @}
* @}
* @}
*/

61
pkg/nordic_softdevice_ble/src/ble-core.h

@ -0,0 +1,61 @@
/*
* Copyright (c) 2015, Nordic Semiconductor
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
/**
* \addtogroup cpu
* @{
*
* \addtogroup nrf52832
* @{
*
* \addtogroup nrf52832-ble Bluetooth Low Energy drivers
* @{
*
* \file
* Basic BLE functions.
* \author
* Wojciech Bober <wojciech.bober@nordicsemi.no>
*/
#ifndef DEV_BLE_H_
#define DEV_BLE_H_
#include <stdint.h>
void ble_stack_init(void);
void ble_advertising_init(const char *name);
void ble_advertising_start(void);
void ble_get_mac(uint8_t addr[8]);
#endif /* DEV_BLE_H_ */
/**
* @}
* @}
* @}
*/

305
pkg/nordic_softdevice_ble/src/ble-mac.c

@ -0,0 +1,305 @@
/*
* Copyright (c) 2016, Nordic Semiconductor
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include <stdint.h>
#include <string.h>
#define DONT_OVERRIDE_NVIC
#include "ble-core.h"
#include "ble_ipsp.h"
#include "ble_gap.h"
#include "ble-mac.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
#if defined(MODULE_OD) && ENABLE_DEBUG
#include "od.h"
#endif
#ifndef BLE_MAC_MAX_INTERFACE_NUM
#define BLE_MAC_MAX_INTERFACE_NUM (1U) /**< Maximum number of interfaces, i.e.,
connection to master devices */
#endif
typedef struct {
uint8_t peer_addr[8];
ble_ipsp_handle_t handle;
} ble_mac_interface_t;
static ble_mac_interface_t interfaces[BLE_MAC_MAX_INTERFACE_NUM];
volatile int ble_mac_busy_tx;
volatile int ble_mac_busy_rx;
static ble_mac_inbuf_t inbuf;
static ble_mac_callback_t _callback;
/**
* @brief Lookup interface by IPSP connection.
*
* @param[in] handle a pointer to IPSP handle.
* @return a pointer to interface structure
* @return NULL if no interface has been found for a given handle
*/
static ble_mac_interface_t *ble_mac_interface_lookup(ble_ipsp_handle_t *handle)
{
for (int i = 0; i < BLE_MAC_MAX_INTERFACE_NUM; i++) {
if (interfaces[i].handle.conn_handle == handle->conn_handle &&
interfaces[i].handle.cid == handle->cid) {
return &interfaces[i];
}
}
return NULL;
}
/**
* @brief Add IPSP connection to the interface table.
*
* This function binds IPSP connection with peer address.
*
* @param[in] peer a pointer to eui64 address
* @param[in] handle a pointer to IPSP handle
*
* @return a pointer to an interface structure on success
* @return NULL if interface table is full
*/
static ble_mac_interface_t *ble_mac_interface_add(uint8_t peer[8],
ble_ipsp_handle_t *handle)
{
DEBUG("ble_mac_interface_add()");
for (int i = 0; i < BLE_MAC_MAX_INTERFACE_NUM; i++) {
if (interfaces[i].handle.conn_handle == 0 && interfaces[i].handle.cid == 0) {
memcpy(&interfaces[i].handle, handle, sizeof(ble_ipsp_handle_t));
memcpy(&interfaces[i].peer_addr, peer, 8);
/* notify handler thread */
/* msg_t m = { .type = BLE_IFACE_ADDED, .content.ptr = &interfaces[i] }; */
/* msg_send(&m, gnrc_nordic_ble_6lowpan_pid); */
return &interfaces[i];
}
}
return NULL;
}
/**
* @brief Remove interface from the interface table.
* @param[in] interface a pointer to interface
*/
static void ble_mac_interface_delete(ble_mac_interface_t *interface)
{
DEBUG("ble_mac_interface_delete()");
memset(interface, 0, sizeof(ble_mac_interface_t));
}
/**
* @brief Lookup IPSP handle by peer address.
*
* @param[in] addr a pointer to eui64 address.
* @retval a pointer to IPSP handle on success
* @retval NULL if an IPSP handle for given address haven't been found
*/
static ble_ipsp_handle_t *_find_handle(const uint8_t *addr)
{
for (int i = 0; i < BLE_MAC_MAX_INTERFACE_NUM; i++) {
if (memcmp(interfaces[i].peer_addr, addr, BLE_SIXLOWPAN_L2_ADDR_LEN) == 0) {
return &interfaces[i].handle;
}
}
return NULL;
}
/**
* @brief Send packet on a given IPSP handle.
*
* @param[in] handle a pointer to IPSP handle.
* @return 1 on success, 0 otherwise
*/
static int _send_to_peer(ble_ipsp_handle_t *handle, void *data, size_t len)
{
DEBUG("ble-mac: sending packet[GAP handle:%d CID:0x%04X]\n",
handle->conn_handle, handle->cid);
return ble_ipsp_send(handle, data, len);
}
static int _is_broadcast(uint8_t dest[8])
{
uint32_t *_dest = (uint32_t*)dest;
for (int i = 0; i < 2; i++) {
if (_dest[i]) {
return 0;
}
}
return 1;
}
int ble_mac_send(uint8_t dest[8], void *data, size_t len)
{
DEBUG("ble_mac_send(): sending pkt with len %u\n", (unsigned)len);
#if defined(MODULE_OD) && ENABLE_DEBUG
od_hex_dump(dest, 8, OD_WIDTH_DEFAULT);
od_hex_dump(data, len, OD_WIDTH_DEFAULT);
#endif
int i;
ble_ipsp_handle_t *handle;
int ret = -1;
if ((!dest) || _is_broadcast(dest)) {
DEBUG("broadcast\n");
for (i = 0; i < BLE_MAC_MAX_INTERFACE_NUM; i++) {
if (interfaces[i].handle.cid != 0 && interfaces[i].handle.conn_handle != 0) {
ret = _send_to_peer(&interfaces[i].handle, data, len);
DEBUG("ret=%i\n", ret);
}
}
}
else if ((handle = _find_handle(dest)) != NULL) {
DEBUG("unicast\n");
ret = _send_to_peer(handle, data, len);
}
else {
DEBUG("ble-mac: no connection found for peer\n");
}
if (ret == NRF_SUCCESS) {
ble_mac_busy_tx = 1;
return 0;
}
else {
DEBUG("ble-mac: send error: %i\n", ret);
return -1;
}
}
static uint32_t ble_mac_ipsp_evt_handler_irq(ble_ipsp_handle_t *p_handle, ble_ipsp_evt_t *p_evt)
{
uint32_t retval = NRF_SUCCESS;
ble_mac_interface_t *p_instance = NULL;
p_instance = ble_mac_interface_lookup(p_handle);
if (p_handle) {
DEBUG("ble-mac: IPSP event [handle:%d CID 0x%04X]\n", p_handle->conn_handle, p_handle->cid);
}
switch (p_evt->evt_id) {
case BLE_IPSP_EVT_CHANNEL_CONNECTED: {
uint8_t peer_addr[8];
DEBUG("ble-mac: channel connected\n");
ble_eui64_from_eui48(peer_addr, p_evt->evt_param->params.ch_conn_request.peer_addr.addr,
p_evt->evt_param->params.ch_conn_request.peer_addr.addr_type ==
BLE_GAP_ADDR_TYPE_PUBLIC);
p_instance = ble_mac_interface_add(peer_addr, p_handle);
if (p_instance != NULL) {
DEBUG("ble-mac: added new IPSP interface\n");
}
else {
DEBUG("ble-mac: cannot add new interface. Table is full\n");
ble_ipsp_disconnect(p_handle);
}
break;
}
case BLE_IPSP_EVT_CHANNEL_DISCONNECTED: {
DEBUG("ble-mac: channel disconnected\n");
if (p_instance != NULL) {
DEBUG("ble-mac: removed IPSP interface\n");
ble_mac_interface_delete(p_instance);
}
break;
}
case BLE_IPSP_EVT_CHANNEL_DATA_RX: {
DEBUG("ble-mac: data received\n");
if (p_instance != NULL) {
if (ble_mac_busy_rx) {
DEBUG("ble-mac: packet dropped as input buffer is busy\n");
break;
}
if (p_evt->evt_param->params.ch_rx.len > BLE_SIXLOWPAN_MTU) {
DEBUG("ble-mac: packet buffer is too small!\n");
break;
}
ble_mac_busy_rx = 1;
inbuf.len = p_evt->evt_param->params.ch_rx.len;
memcpy(inbuf.payload, p_evt->evt_param->params.ch_rx.p_data, inbuf.len);
memcpy(inbuf.src, p_instance->peer_addr, 8);
sd_ble_gap_rssi_get(p_handle->conn_handle, &inbuf.rssi);
_callback(BLE_EVENT_RX_DONE, &inbuf);
}
else {
DEBUG("ble-mac: got data to unknown interface!\n");
}
break;
}
case BLE_IPSP_EVT_CHANNEL_DATA_TX_COMPLETE: {
DEBUG("ble-mac: data transmitted\n");
ble_mac_busy_tx = 0;
//_callback(BLE_EVENT_TX_DONE, NULL);
break;
}
}
if (sched_context_switch_request) {
NVIC_SetPendingIRQ( SWI0_EGU0_IRQn );
}
return retval;
}
void ble_mac_init(ble_mac_callback_t callback)
{
assert(callback);
uint32_t res;
ble_ipsp_init_t ipsp_init_params = {
.evt_handler = ble_mac_ipsp_evt_handler_irq
};
_callback = callback;
res = ble_ipsp_init(&ipsp_init_params);
DEBUG("ble_ipsp_init() res = %" PRIu32 "\n", res);
(void)res;
}

50
pkg/nordic_softdevice_ble/src/ble-mac.h

@ -0,0 +1,50 @@
#ifndef BLE_MAC_H
#define BLE_MAC_H
typedef enum {
BLE_EVENT_RX_DONE = 20000,
} ble_mac_event_enum_t;
#define BLE_IFACE_ADDED (10000)
#define BLE_SIXLOWPAN_MTU (1280U)
#define BLE_SIXLOWPAN_L2_ADDR_LEN (8)
#define IPV6_IID_FLIP_VALUE (0x02)
#include "net/eui64.h"
static inline void ble_eui64_from_eui48(uint8_t eui64[8], uint8_t eui48[6], int _public)
{
eui64[0] = eui48[5];
eui64[1] = eui48[4];
eui64[2] = eui48[3];
eui64[3] = 0xFF;
eui64[4] = 0xFE;
eui64[5] = eui48[2];
eui64[6] = eui48[1];
eui64[7] = eui48[0];
if (_public) {
eui64[0] &= ~(IPV6_IID_FLIP_VALUE);
}
else {
eui64[0] |= IPV6_IID_FLIP_VALUE;
}
}
typedef struct {
uint8_t src[8];
uint8_t payload[BLE_SIXLOWPAN_MTU];
uint16_t len;
int8_t rssi;
} ble_mac_inbuf_t;
typedef void (*ble_mac_callback_t)(ble_mac_event_enum_t event, void*arg);
void ble_mac_init(ble_mac_callback_t callback);
int ble_mac_send(uint8_t dest[8], void *data, size_t len);
extern volatile int ble_mac_busy_tx; /**< Flag is set to 1 when the driver
is busy transmitting a packet. */
extern volatile int ble_mac_busy_rx; /**< Flag is set to 1 when there is a
received packet pending. */
#endif /* BLE_MAC_H */

318
pkg/nordic_softdevice_ble/src/gnrc_nordic_ble_6lowpan.c

@ -0,0 +1,318 @@
/*
* Copyright (c) 2016, Nordic Semiconductor
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
/**
* @{
* @ingroup net
* @file
* @brief Glue for Nordic's SoftDevice BLE 6lowpan blob to netapi
*
* @author Kaspar Schleiser <kaspar@schleiser.de>
* @}
*/
#include <assert.h>
#include <errno.h>
#include "msg.h"
#include "thread.h"
#include "net/gnrc.h"
#include "net/gnrc/nettype.h"
#include "ble-core.h"
#include "softdevice_handler.h"
#include "ble-mac.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
#if defined(MODULE_OD) && ENABLE_DEBUG
#include "od.h"
#endif
#define BLE_NETAPI_MSG_QUEUE_SIZE (8U)
#define BLE_PRIO (THREAD_PRIORITY_MAIN - 1)
kernel_pid_t gnrc_nordic_ble_6lowpan_pid;
static char _stack[(THREAD_STACKSIZE_DEFAULT + DEBUG_EXTRA_STACKSIZE)];
static uint8_t _own_mac_addr[BLE_SIXLOWPAN_L2_ADDR_LEN];
static uint8_t _sendbuf[BLE_SIXLOWPAN_MTU];
static void _ble_mac_callback(ble_mac_event_enum_t event, void* arg)
{
msg_t m = { .type=event, .content.ptr=arg };
if (!msg_send_int(&m, gnrc_nordic_ble_6lowpan_pid)) {
puts("_ble_mac_callback(): possibly lost interrupt");
}
}
static void _handle_raw_sixlowpan(ble_mac_inbuf_t *inbuf)
{
gnrc_pktsnip_t *pkt = NULL;
pkt = gnrc_pktbuf_add(NULL, inbuf->payload,
inbuf->len,
GNRC_NETTYPE_SIXLOWPAN);
if(!pkt) {
DEBUG("_handle_raw_sixlowpan(): no space left in packet buffer.\n");
return;
}
/* create netif header */
gnrc_pktsnip_t *netif_hdr;
netif_hdr = gnrc_pktbuf_add(NULL, NULL,
sizeof(gnrc_netif_hdr_t) + (2 * sizeof(eui64_t)),
GNRC_NETTYPE_NETIF);
if (netif_hdr == NULL) {
DEBUG("_handle_raw_sixlowpan(): no space left in packet buffer.\n");
gnrc_pktbuf_release(pkt);
return;
}
gnrc_netif_hdr_init(netif_hdr->data, BLE_SIXLOWPAN_L2_ADDR_LEN, BLE_SIXLOWPAN_L2_ADDR_LEN);
gnrc_netif_hdr_set_src_addr(netif_hdr->data, inbuf->src, BLE_SIXLOWPAN_L2_ADDR_LEN);
gnrc_netif_hdr_set_dst_addr(netif_hdr->data, _own_mac_addr, BLE_SIXLOWPAN_L2_ADDR_LEN);
((gnrc_netif_hdr_t *)netif_hdr->data)->if_pid = gnrc_nordic_ble_6lowpan_pid;
DEBUG("_handle_raw_sixlowpan(): received packet from %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x "
"of length %d\n",
inbuf->src[0], inbuf->src[1], inbuf->src[2], inbuf->src[3], inbuf->src[4],
inbuf->src[5], inbuf->src[6], inbuf->src[7], inbuf->len);
#if defined(MODULE_OD) && ENABLE_DEBUG
od_hex_dump(inbuf->payload, inbuf->len, OD_WIDTH_DEFAULT);
#endif
LL_APPEND(pkt, netif_hdr);
/* throw away packet if no one is interested */
if (!gnrc_netapi_dispatch_receive(pkt->type, GNRC_NETREG_DEMUX_CTX_ALL, pkt)) {
DEBUG("_handle_raw_sixlowpan: unable to forward packet of type %i\n", pkt->type);
gnrc_pktbuf_release(pkt);
}
}
static int _send(gnrc_pktsnip_t *pkt)
{
gnrc_netif_hdr_t *netif_hdr;
gnrc_pktsnip_t *payload = pkt->next;
uint8_t *dst;
if (ble_mac_busy_tx) {
DEBUG("_send(): ble_mac_busy_tx\n");
return -EBUSY;
}
uint8_t *buf = _sendbuf;
unsigned len = 0;
if (pkt == NULL) {
DEBUG("_send_ble: pkt was NULL\n");
return -EINVAL;
}
if (pkt->type != GNRC_NETTYPE_NETIF) {
DEBUG("_send_ble: first header is not generic netif header\n");
return -EBADMSG;
}
netif_hdr = pkt->data;
/* prepare destination address */
if (netif_hdr->flags &
(GNRC_NETIF_HDR_FLAGS_BROADCAST | GNRC_NETIF_HDR_FLAGS_MULTICAST)) {
dst = NULL;
}
else {
dst = gnrc_netif_hdr_get_dst_addr(netif_hdr);
}
/* prepare packet for sending */
while (payload) {
memcpy(buf, payload->data, payload->size);
len += payload->size;
buf += payload->size;
payload = payload->next;
}
gnrc_pktbuf_release(pkt);
if (ble_mac_send(dst, _sendbuf, len) == -1) {
return -EBADMSG;
}
return 0;
}
static int _handle_get(gnrc_netapi_opt_t *_opt)
{
int res = -ENOTSUP;
uint8_t *value = _opt->data;
switch (_opt->opt) {
case NETOPT_ACK_REQ:
case NETOPT_CHANNEL:
case NETOPT_NID:
case NETOPT_ADDRESS:
/* -ENOTSUP */
break;
case NETOPT_ADDRESS_LONG:
assert(_opt->data_len >= BLE_SIXLOWPAN_L2_ADDR_LEN);
memcpy(value, _own_mac_addr, BLE_SIXLOWPAN_L2_ADDR_LEN);
value[0] = IPV6_IID_FLIP_VALUE;
res = BLE_SIXLOWPAN_L2_ADDR_LEN;
break;
case NETOPT_ADDR_LEN:
case NETOPT_SRC_LEN:
assert(_opt->data_len == sizeof(uint16_t));
*((uint16_t *)value) = BLE_SIXLOWPAN_L2_ADDR_LEN;
res = sizeof(uint16_t);
break;
#ifdef MODULE_GNRC
case NETOPT_PROTO:
assert(_opt->data_len == sizeof(gnrc_nettype_t));
*((gnrc_nettype_t *)value) = GNRC_NETTYPE_SIXLOWPAN;
res = sizeof(gnrc_nettype_t);
break;
#endif
/* case NETOPT_DEVICE_TYPE:
assert(_opt->data_len == sizeof(uint16_t));
*((uint16_t *)value) = NETDEV2_TYPE_IEEE802154;
res = sizeof(uint16_t);
break;*/
case NETOPT_IPV6_IID:
memcpy(value, _own_mac_addr, BLE_SIXLOWPAN_L2_ADDR_LEN);
value[0] = IPV6_IID_FLIP_VALUE;
res = BLE_SIXLOWPAN_L2_ADDR_LEN;
break;
default:
break;
}
return res;
}
/**
* @brief Startup code and event loop of the gnrc_nordic_ble_6lowpan layer
*
* @return never returns
*/
static void *_gnrc_nordic_ble_6lowpan_thread(void *args)
{
(void)args;
DEBUG("gnrc_nordic_ble_6lowpan: starting thread\n");
gnrc_nordic_ble_6lowpan_pid = thread_getpid();
gnrc_netapi_opt_t *opt;
int res;
msg_t msg, reply, msg_queue[BLE_NETAPI_MSG_QUEUE_SIZE];
/* setup the message queue */
msg_init_queue(msg_queue, BLE_NETAPI_MSG_QUEUE_SIZE);
/* initialize BLE stack */
assert((unsigned)softdevice_handler_isEnabled());
ble_stack_init();
ble_get_mac(_own_mac_addr);
ble_mac_init(_ble_mac_callback);
ble_advertising_init("RIOT BLE");
ble_advertising_start();
/* register the device to the network stack*/
gnrc_netif_add(thread_getpid());
/* start the event loop */
while (1) {
// DEBUG("gnrc_nordic_ble_6lowpan: waiting for incoming messages\n");
msg_receive(&msg);
/* dispatch NETDEV and NETAPI messages */
switch (msg.type) {
case BLE_EVENT_RX_DONE:
{
DEBUG("ble rx:\n");
_handle_raw_sixlowpan(msg.content.ptr);
ble_mac_busy_rx = 0;
break;
}
case GNRC_NETAPI_MSG_TYPE_SND:
DEBUG("gnrc_nordic_ble_6lowpan: GNRC_NETAPI_MSG_TYPE_SND received\n");
_send(msg.content.ptr);
break;
case GNRC_NETAPI_MSG_TYPE_SET:
/* read incoming options */
opt = msg.content.ptr;
DEBUG("gnrc_nordic_ble_6lowpan: GNRC_NETAPI_MSG_TYPE_SET received. opt=%s\n",
netopt2str(opt->opt));
/* set option for device driver */
res = ENOTSUP;
DEBUG("gnrc_nordic_ble_6lowpan: response of netdev->set: %i\n", res);