Merge branch 'develop' into contrib/build-all

This commit is contained in:
Simon Duquennoy 2018-03-12 14:22:34 +01:00 committed by GitHub
commit 7fe4d913b7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 3622 additions and 21 deletions

View File

@ -120,7 +120,8 @@ PLATFORM_ACTION ?= build
MAKE_MAC_NULLMAC = 0
MAKE_MAC_CSMA = 1
MAKE_MAC_TSCH = 2
MAKE_MAC_OTHER = 3
MAKE_MAC_BLE = 3
MAKE_MAC_OTHER = 4
# Make CSMA the default MAC
MAKE_MAC ?= MAKE_MAC_CSMA
@ -140,6 +141,11 @@ ifeq ($(MAKE_MAC),MAKE_MAC_TSCH)
CFLAGS += -DMAC_CONF_WITH_TSCH=1
endif
ifeq ($(MAKE_MAC),MAKE_MAC_BLE)
MODULES += os/net/mac/ble
CFLAGS += -DMAC_CONF_WITH_BLE=1
endif
ifeq ($(MAKE_MAC),MAKE_MAC_OTHER)
CFLAGS += -DMAC_CONF_WITH_OTHER=1
endif

View File

@ -25,7 +25,7 @@ ifdef NODEID
endif
### CPU-dependent directories
CONTIKI_CPU_DIRS += . dev rf-core rf-core/api $(TI_XXWARE_STARTUP_DIR)
CONTIKI_CPU_DIRS += . dev rf-core rf-core/api rf-core/ble-hal $(TI_XXWARE_STARTUP_DIR)
### CPU-dependent source files
CONTIKI_CPU_SOURCEFILES += clock.c rtimer-arch.c soc-rtc.c uart.c
@ -34,6 +34,7 @@ CONTIKI_CPU_SOURCEFILES += putchar.c ieee-addr.c batmon-sensor.c adc-sensor.c
CONTIKI_CPU_SOURCEFILES += slip-arch.c slip.c cc26xx-uart.c lpm.c
CONTIKI_CPU_SOURCEFILES += gpio-interrupt.c gpio-hal-arch.c oscillators.c
CONTIKI_CPU_SOURCEFILES += rf-core.c rf-ble.c ieee-mode.c
CONTIKI_CPU_SOURCEFILES += ble-cc2650.c ble-hal-cc26xx.c ble-addr.c rf-ble-cmd.c
CONTIKI_CPU_SOURCEFILES += random.c soc-trng.c int-master.c
DEBUG_IO_SOURCEFILES += dbg-printf.c dbg-snprintf.c dbg-sprintf.c strformat.c

View File

@ -0,0 +1,72 @@
/*
* Copyright (c) 2016, Michael Spoerk
* 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 copyright holder 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 COPYRIGHT HOLDERS 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
* COPYRIGHT HOLDER 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.
*
*/
/**
* \file
* Driver for the retrieval of an BLE address from flash
*
* \author
* Michael Spoerk <mi.spoerk@gmail.com>
*/
/*---------------------------------------------------------------------------*/
#include "contiki-conf.h"
#include "net/linkaddr.h"
#include <string.h>
#include "ble-addr.h"
#include "os/dev/ble-hal.h"
/*---------------------------------------------------------------------------*/
void
ble_addr_cpy_to(uint8_t *dst)
{
int i;
uint8_t *location = (uint8_t *)BLE_ADDR_LOCATION;
for(i = 0; i < BLE_ADDR_SIZE; i++) {
dst[i] = location[BLE_ADDR_SIZE - 1 - i];
}
}
/*---------------------------------------------------------------------------*/
void
ble_addr_to_eui64(uint8_t *dst, uint8_t *src)
{
memcpy(dst, src, 3);
dst[3] = 0xFF;
dst[4] = 0xFE;
memcpy(&dst[5], &src[3], 3);
}
/*---------------------------------------------------------------------------*/
void
ble_eui64_addr_cpy_to(uint8_t *dst)
{
uint8_t ble_addr[BLE_ADDR_SIZE];
ble_addr_cpy_to(ble_addr);
ble_addr_to_eui64(dst, ble_addr);
}

View File

@ -0,0 +1,80 @@
/*
* Copyright (c) 2016, Michael Spoerk
* 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 copyright holder 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 COPYRIGHT HOLDERS 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
* COPYRIGHT HOLDER 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.
*
*/
/**
* \file
* Driver for the retrieval of an BLE address from flash
*
* \author
* Michael Spoerk <mi.spoerk@gmail.com>
*/
/*---------------------------------------------------------------------------*/
#ifndef BLE_ADDR_H_
#define BLE_ADDR_H_
/*---------------------------------------------------------------------------*/
#include "contiki-conf.h"
#include <stdint.h>
/*---------------------------------------------------------------------------*/
/* primary BLE address location */
#define BLE_ADDR_LOCATION 0x500012E8
/*---------------------------------------------------------------------------*/
/**
* \brief Copy the node's factory BLE address to a destination memory area
* \param dst A pointer to the destination area where the BLE address is to be
* written
*
* This function will copy 6 bytes and it will invert byte order in
* the process. The factory address on devices is normally little-endian,
* therefore you should expect dst to store the address in a big-endian order.
*/
void ble_addr_cpy_to(uint8_t *dst);
/*---------------------------------------------------------------------------*/
/**
* \brief Copy the node's BLE address to a destination memory area and converts
* it into a EUI64 address in the process
* \param dst A pointer to the destination area where the EUI64 address is to be
* written
* \param src A pointer to the BLE address that is to be copied
*/
void ble_addr_to_eui64(uint8_t *dst, uint8_t *src);
/*---------------------------------------------------------------------------*/
/**
* \brief Copy the node's EUI64 address that is based on its factory BLE address
* to a destination memory area
* \param dst A pointer to the destination area where the EUI64 address is to be
* written
*/
void ble_eui64_addr_cpy_to(uint8_t *dst);
/*---------------------------------------------------------------------------*/
#endif /* BLE_ADDR_H_ */

View File

@ -90,7 +90,9 @@
#define CSMA_CONF_SEND_SOFT_ACK 1
#else /* CC13XX_CONF_PROP_MODE */
#ifndef NETSTACK_CONF_RADIO
#define NETSTACK_CONF_RADIO ieee_mode_driver
#endif
#define CSMA_CONF_SEND_SOFT_ACK 0
#endif /* CC13XX_CONF_PROP_MODE */

View File

@ -0,0 +1,83 @@
# BLEach: a fully open-source IPv6-over-BLE stack for Constrained Embedded IoT Devices
## Overview
In 2015, the IETF released the [RFC 7668][rfc7668] that specifies how IPv6 packets
can be exchanged using BLE connections (IPv6 over BLE).
This Contiki extenstion implements [BLEach][bleachWeb], a fully open-source IPv6-over-BLE stack for Contiki.
BLEach in Contiki-NG can be used for node (BLE slave) devices.
It was developed by
* [Michael Spoerk](http://www.michaelspoerk.com), Graz University of Technology, michael.spoerk@tugraz.at, github user: [spoerk](https://github.com/spoerk)
This IPv6-over-BLE stack is presented and evaluated in the paper:
[BLEach: Exploiting the Full Potential of IPv6 over BLE in Constrained Embedded IoT Devices](http://sensys.acm.org/2017/), ACM SenSys'17.
## Features
This implementation includes:
* IPv6-over-BLE node implementation compliant to [RFC 7668][rfc7668]
* connect to a single IPv6-over-BLE border router
* maximum IPv6 packet length of 1280 bytes
* BLE L2CAP channels in LE credit-based flow control mode
* BLE link layer support for version [4.1][bleSpec]:
* BLE advertisement
* BLE connection slave
It has been tested on the TI CC2650 SensorTag and the TI CC2650 LaunchPad hardware.
## Modules
The IPv6-over-BLE stack comes with the following modules:
### BLE radio
The implementation of the BLE radio for the TI CC26xx platform is implemented in `arch/cpu/cc26xx-cc13xx/rf-core/ble-cc2650.c`
and `arch/cpu/cc26xx-cc13xx/rf-core/ble-hal/*.[ch]`.
These files contain all the hardware specific code for supporting BLE as a link layer.
### BLE L2CAP layer
The L2CAP LE credit-based flow control support is implemented in `arch/cpu/cc26xx-cc13xx/rf-core/ble-l2cap.c`.
Besides implementing rudimentary L2CAP support, this module handles fragmentation of large IPv6 packets.
## Using BLEach
A simple IPv6-over-BLE UDP-client is included under `examples/platform-specific/cc26xx/cc26xx-ble-client-demo`.
Currently, BLEach is only available for the Texas Instruments CC2650 hardware platform.
The following sections describe how to configure BLEach for IPv6-over-BLE nodes and border routers.
### IPv6-over-BLE node (BLE slave)
To enable IPv6 over BLE, the project conf needs to contain:
```
#define PACKETBUF_CONF_SIZE 1280
#define QUEUEBUF_CONF_NUM 1
#define UIP_CONF_BUFFER_SIZE 1280
#define NETSTACK_CONF_RADIO ble_cc2650_driver
#define NETSTACK_CONF_MAC ble_l2cap_driver
#define RTIMER_CONF_MULTIPLE_ACCESS 1
/* 6LoWPAN settings */
#define SICSLOWPAN_CONF_MAC_MAX_PAYLOAD 1280
#define SICSLOWPAN_CONF_COMPRESSION SICSLOWPAN_COMPRESSION_HC06
#define SICSLOWPAN_CONF_COMPRESSION_THRESHOLD 0 /* always use compression */
#define SICSLOWPAN_CONF_FRAG 0
#define SICSLOWPAN_FRAMER_HDRLEN 0
/* network stack settings */
#define UIP_CONF_ROUTER 0
#define UIP_CONF_ND6_SEND_NA 1
```
The following optional parameter can be used to configure that BLE advertisement behaviour:
```
#define BLE_CONF_DEVICE_NAME "TI CC26xx device"
#define BLE_CONF_ADV_INTERVAL 25
```
`BLE_CONF_DEVICE_NAME` holds the device name that is used for advertisement, `BLE_CONF_ADV_INTERVAL`
specifies the used advertisement interval in milliseconds.
[rfc7668]: https://tools.ietf.org/html/rfc7668
[bleSpec]: https://www.bluetooth.com/specifications/bluetooth-core-specification/legacy-specifications
[bleachWeb]: http://www.iti.tugraz.at/BLEach

View File

@ -0,0 +1,277 @@
/*
* Copyright (c) 2017, Graz University of Technology
* 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 copyright holder 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 COPYRIGHT HOLDERS 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
* COPYRIGHT HOLDER 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.
*/
/**
* \file
* BLE radio for the TI CC26xx platform
*
* \author
* Michael Spoerk <michael.spoerk@tugraz.at>
*/
/*---------------------------------------------------------------------------*/
#include "contiki.h"
#include "dev/radio.h"
#include "os/dev/ble-hal.h"
#include "rf-core/ble-hal/ble-hal-cc26xx.h"
/*---------------------------------------------------------------------------*/
#include "sys/log.h"
#define LOG_MODULE "RADIO"
#define LOG_LEVEL LOG_LEVEL_MAIN
/*---------------------------------------------------------------------------*/
static uint16_t adv_interval;
static ble_adv_type_t adv_type;
static ble_addr_type_t adv_own_addr_type;
static uint8_t adv_channel_map;
static uint16_t buffer_size = 0;
/*---------------------------------------------------------------------------*/
static uint16_t scan_interval;
static uint16_t scan_window;
static ble_scan_type_t scan_type;
static ble_addr_type_t scan_own_addr_type;
/*---------------------------------------------------------------------------*/
static ble_addr_type_t initiator_peer_addr_type;
static uint8_t initiator_peer_addr[BLE_ADDR_SIZE];
/*---------------------------------------------------------------------------*/
static uint16_t connection_interval;
static uint16_t connection_latency;
static uint16_t connection_timeout;
/*---------------------------------------------------------------------------*/
static int
init(void)
{
int result = ble_hal.reset();
return result == BLE_RESULT_OK;
}
/*---------------------------------------------------------------------------*/
static int
send(const void *payload, unsigned short payload_len)
{
uint8_t res;
res = ble_hal.send((void *)payload, payload_len);
LOG_DBG("ble-mode send() %d bytes\n", payload_len);
if(res == BLE_RESULT_OK) {
return RADIO_TX_OK;
} else {
LOG_ERR("ble-mode send() error: %d\n", res);
return RADIO_TX_ERR;
}
}
/*---------------------------------------------------------------------------*/
static int
on(void)
{
return 1;
}
/*---------------------------------------------------------------------------*/
static int
off(void)
{
ble_hal.disconnect(0, 0);
return 1;
}
/*---------------------------------------------------------------------------*/
static radio_result_t
get_value(radio_param_t param, radio_value_t *value)
{
unsigned int temp;
if(!value) {
return RADIO_RESULT_INVALID_VALUE;
}
switch(param) {
case RADIO_CONST_CHANNEL_MIN:
*value = BLE_DATA_CHANNEL_MIN;
return RADIO_RESULT_OK;
case RADIO_CONST_CHANNEL_MAX:
*value = BLE_DATA_CHANNEL_MAX;
return RADIO_RESULT_OK;
case RADIO_CONST_BLE_BUFFER_SIZE:
if(buffer_size == 0) {
ble_hal.read_buffer_size((unsigned int *)&buffer_size, &temp);
}
memcpy(value, &buffer_size, 2);
return RADIO_RESULT_OK;
case RADIO_CONST_BLE_BUFFER_AMOUNT:
ble_hal.read_buffer_size(&temp, (unsigned int *)value);
return RADIO_RESULT_OK;
case RADIO_PARAM_BLE_CONN_INTERVAL:
ble_hal.read_connection_interval(0, (unsigned int *)value);
return RADIO_RESULT_OK;
default:
return RADIO_RESULT_NOT_SUPPORTED;
}
}
/*---------------------------------------------------------------------------*/
static radio_result_t
set_value(radio_param_t param, radio_value_t value)
{
switch(param) {
case RADIO_PARAM_BLE_ADV_INTERVAL:
if((value > BLE_ADV_INTERVAL_MAX) || (value < BLE_ADV_INTERVAL_MIN)) {
return RADIO_RESULT_INVALID_VALUE;
}
adv_interval = (uint16_t)value;
return RADIO_RESULT_OK;
case RADIO_PARAM_BLE_ADV_TYPE:
adv_type = value;
return RADIO_RESULT_OK;
case RADIO_PARAM_BLE_ADV_OWN_ADDR_TYPE:
adv_own_addr_type = value;
return RADIO_RESULT_OK;
case RADIO_PARAM_BLE_ADV_CHANNEL_MAP:
adv_channel_map = value;
return RADIO_RESULT_OK;
case RADIO_PARAM_BLE_ADV_ENABLE:
if(value) {
/* set the advertisement parameter before enabling */
ble_hal.set_adv_param(adv_interval, adv_type,
adv_own_addr_type, adv_channel_map);
}
ble_hal.set_adv_enable(value);
return RADIO_RESULT_OK;
case RADIO_PARAM_BLE_SCAN_INTERVAL:
if((value > BLE_SCAN_INTERVAL_MAX) || (value < BLE_SCAN_INTERVAL_MIN)) {
return RADIO_RESULT_INVALID_VALUE;
}
scan_interval = (uint16_t)value;
return RADIO_RESULT_OK;
case RADIO_PARAM_BLE_SCAN_WINDOW:
if((value > BLE_SCAN_INTERVAL_MAX) || (value < BLE_SCAN_INTERVAL_MIN)) {
return RADIO_RESULT_INVALID_VALUE;
}
scan_window = (uint16_t)value;
return RADIO_RESULT_OK;
case RADIO_PARAM_BLE_SCAN_TYPE:
scan_type = value;
return RADIO_RESULT_OK;
case RADIO_PARAM_BLE_SCAN_OWN_ADDR_TYPE:
scan_own_addr_type = value;
return RADIO_RESULT_OK;
case RADIO_PARAM_BLE_SCAN_ENABLE:
if(value) {
ble_hal.set_scan_param(scan_type, scan_interval,
scan_window, scan_own_addr_type);
}
ble_hal.set_scan_enable(value, 0);
return RADIO_RESULT_OK;
case RADIO_PARAM_BLE_PEER_ADDR_TYPE:
initiator_peer_addr_type = value;
return RADIO_RESULT_OK;
case RADIO_PARAM_BLE_CONN_INTERVAL:
connection_interval = value;
return RADIO_RESULT_OK;
case RADIO_PARAM_BLE_CONN_LATENCY:
connection_latency = value;
return RADIO_RESULT_OK;
case RADIO_PARAM_BLE_CONN_SUPERVISION_TIMEOUT:
connection_timeout = value;
return RADIO_RESULT_OK;
case RADIO_PARAM_BLE_INITIATOR_ENABLE:
if(value) {
ble_hal.create_connection(scan_interval, scan_window,
initiator_peer_addr_type,
initiator_peer_addr,
scan_own_addr_type,
connection_interval,
connection_latency,
connection_timeout);
} else {
ble_hal.create_connection_cancel();
}
return RADIO_RESULT_OK;
case RADIO_PARAM_BLE_CONN_UPDATE:
if(value) {
return ble_hal.connection_update(0, connection_interval, connection_latency, connection_timeout);
} else {
return RADIO_RESULT_INVALID_VALUE;
}
default:
return RADIO_RESULT_NOT_SUPPORTED;
}
}
/*---------------------------------------------------------------------------*/
static radio_result_t
get_object(radio_param_t param, void *dest, size_t size)
{
switch(param) {
case RADIO_CONST_BLE_BD_ADDR:
if(size != BLE_ADDR_SIZE || !dest) {
return RADIO_RESULT_INVALID_VALUE;
}
ble_hal.read_bd_addr(dest);
return RADIO_RESULT_OK;
}
return RADIO_RESULT_NOT_SUPPORTED;
}
/*---------------------------------------------------------------------------*/
static radio_result_t
set_object(radio_param_t param, const void *src, size_t size)
{
switch(param) {
case RADIO_PARAM_BLE_ADV_PAYLOAD:
if(size <= 0 || size >= BLE_ADV_DATA_LEN || !src) {
return RADIO_RESULT_INVALID_VALUE;
}
ble_hal.set_adv_data((unsigned short)size, (char *)src);
return RADIO_RESULT_OK;
case RADIO_PARAM_BLE_ADV_SCAN_RESPONSE:
if(size <= 0 || size >= BLE_SCAN_RESP_DATA_LEN || !src) {
return RADIO_RESULT_INVALID_VALUE;
}
ble_hal.set_scan_resp_data((unsigned short)size, (char *)src);
return RADIO_RESULT_OK;
case RADIO_PARAM_BLE_PEER_ADDR:
if(size <= 0 || size > BLE_ADDR_SIZE || !src) {
return RADIO_RESULT_INVALID_VALUE;
}
memcpy(initiator_peer_addr, src, size);
return RADIO_RESULT_OK;
}
return RADIO_RESULT_NOT_SUPPORTED;
}
/*---------------------------------------------------------------------------*/
const struct radio_driver ble_cc2650_driver = {
init,
NULL,
NULL,
send,
NULL,
NULL,
NULL,
NULL,
on,
off,
get_value,
set_value,
get_object,
set_object,
};
/*---------------------------------------------------------------------------*/

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,47 @@
/*
* Copyright (c) 2017, Graz University of Technology
* 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 copyright holder 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 COPYRIGHT HOLDERS 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
* COPYRIGHT HOLDER 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.
*/
/**
* \file
* BLE radio hardware abstraction for the TI CC26XX controller
*
* \author
* Michael Spoerk <michael.spoerk@tugraz.at>
*/
/*---------------------------------------------------------------------------*/
#ifndef BLE_HAL_CC26XX_H_
#define BLE_HAL_CC26XX_H_
#include "os/dev/ble-hal.h"
extern const struct ble_hal_driver ble_hal;
#endif /* BLE_HAL_CC26XX_H_ */

View File

@ -0,0 +1,251 @@
/*
* Copyright (c) 2017, Graz University of Technology
* 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 copyright holder 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 COPYRIGHT HOLDERS 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
* COPYRIGHT HOLDER 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.
*/
/**
* \file
* BLE commands for the TI CC26xx BLE radio.
* These functions are specific to the TI CC26xx and cannot be
* reused by other BLE radios.
*
* \author
* Michael Spoerk <michael.spoerk@tugraz.at>
*/
/*---------------------------------------------------------------------------*/
#include "contiki.h"
#include "rf_ble_cmd.h"
#include "rf-core/rf-core.h"
#include "rf-core/ble-hal/rf-ble-cmd.h"
/*---------------------------------------------------------------------------*/
#include "sys/log.h"
#define LOG_MODULE "BLE-RADIO"
#define LOG_LEVEL LOG_LEVEL_MAIN
/*---------------------------------------------------------------------------*/
#define CMD_GET_STATUS(X) (((rfc_radioOp_t *)X)->status)
/*---------------------------------------------------------------------------*/
/* values for a selection of available TX powers (values from SmartRF Studio) */
/*static uint16_t tx_power = 0x9330; / * +5 dBm * / */
static uint16_t tx_power = 0x3161; /* 0 dBm */
/*static uint16_t tx_power = 0x0CCB; / * -15 dBm * / */
/*---------------------------------------------------------------------------*/
/* BLE overrides */
static uint32_t ble_overrides[] = {
0x00364038, /* Synth: Set RTRIM (POTAILRESTRIM) to 6 */
0x000784A3, /* Synth: Set FREF = 3.43 MHz (24 MHz / 7) */
0xA47E0583, /* Synth: Set loop bandwidth after lock to 80 kHz (K2) */
0xEAE00603, /* Synth: Set loop bandwidth after lock to 80 kHz (K3, LSB) */
0x00010623, /* Synth: Set loop bandwidth after lock to 80 kHz (K3, MSB) */
0x00456088, /* Adjust AGC reference level */
0x008F88B3, /* GPIO mode: https://e2e.ti.com/support/wireless_connectivity/proprietary_sub_1_ghz_simpliciti/f/156/t/488244?*/
0xFFFFFFFF, /* End of override list */
};
/*---------------------------------------------------------------------------*/
unsigned short
rf_ble_cmd_send(uint8_t *command)
{
uint32_t cmdsta;
rfc_radioOp_t *cmd = (rfc_radioOp_t *)command;
if(rf_core_send_cmd((uint32_t)cmd, &cmdsta) != RF_CORE_CMD_OK) {
LOG_ERR("rf_ble_cmd_send() could not send cmd. status: 0x%04X\n",
CMD_GET_STATUS(cmd));
return RF_BLE_CMD_ERROR;
}
return RF_BLE_CMD_OK;
}
/*---------------------------------------------------------------------------*/
unsigned short
rf_ble_cmd_wait(uint8_t *command)
{
rfc_radioOp_t *cmd = (rfc_radioOp_t *)command;
if(rf_core_wait_cmd_done((void *)cmd) != RF_CORE_CMD_OK) {
LOG_ERR("rf_ble_cmd_wait() could not wait. status: 0x%04X\n",
CMD_GET_STATUS(cmd));
return RF_BLE_CMD_ERROR;
}
return RF_BLE_CMD_OK;
}
/*---------------------------------------------------------------------------*/
unsigned short
rf_ble_cmd_setup_ble_mode(void)
{
rfc_CMD_RADIO_SETUP_t cmd;
/* Create radio setup command */
rf_core_init_radio_op((rfc_radioOp_t *)&cmd, sizeof(cmd), CMD_RADIO_SETUP);
cmd.txPower = tx_power;
cmd.pRegOverride = ble_overrides;
cmd.mode = 0;
/* Send Radio setup to RF Core */
if(rf_ble_cmd_send((uint8_t *)&cmd) != RF_BLE_CMD_OK) {
return RF_BLE_CMD_ERROR;
}
/* Wait until radio setup is done */
return rf_ble_cmd_wait((uint8_t *)&cmd);
}
/*---------------------------------------------------------------------------*/
/* ADVERTISING functions */
void
rf_ble_cmd_create_adv_cmd(uint8_t *command, uint8_t channel,
uint8_t *param, uint8_t *output)
{
rfc_CMD_BLE_ADV_t *c = (rfc_CMD_BLE_ADV_t *)command;
memset(c, 0x00, sizeof(rfc_CMD_BLE_ADV_t));
c->commandNo = CMD_BLE_ADV;
c->condition.rule = COND_NEVER;
c->whitening.bOverride = 0;
c->channel = channel;
c->pParams = (rfc_bleAdvPar_t *)param;
c->startTrigger.triggerType = TRIG_NOW;
c->pOutput = (rfc_bleAdvOutput_t *)output;
}
/*---------------------------------------------------------------------------*/
void
rf_ble_cmd_create_adv_params(uint8_t *param, dataQueue_t *rx_queue,
uint8_t adv_data_len, uint8_t *adv_data,
uint8_t scan_resp_data_len, uint8_t *scan_resp_data,
ble_addr_type_t own_addr_type, uint8_t *own_addr)
{
rfc_bleAdvPar_t *p = (rfc_bleAdvPar_t *)param;
memset(p, 0x00, sizeof(rfc_bleAdvPar_t));
p->pRxQ = rx_queue;
p->rxConfig.bAutoFlushIgnored = 1;
p->rxConfig.bAutoFlushCrcErr = 0;
p->rxConfig.bAutoFlushEmpty = 1;
p->rxConfig.bIncludeLenByte = 1;
p->rxConfig.bIncludeCrc = 0;
p->rxConfig.bAppendRssi = 1;
p->rxConfig.bAppendStatus = 1;
p->rxConfig.bAppendTimestamp = 1;
p->advConfig.advFilterPolicy = 0;
p->advConfig.bStrictLenFilter = 0;
p->advConfig.deviceAddrType = own_addr_type;
p->pDeviceAddress = (uint16_t *)own_addr;
p->advLen = adv_data_len;
p->scanRspLen = scan_resp_data_len;
p->pAdvData = adv_data;
p->pScanRspData = scan_resp_data;
p->endTrigger.triggerType = TRIG_NEVER;
}
/*---------------------------------------------------------------------------*/
/* CONNECTION slave functions */
/*---------------------------------------------------------------------------*/
void
rf_ble_cmd_create_slave_cmd(uint8_t *cmd, uint8_t channel, uint8_t *params,
uint8_t *output, uint32_t start_time)
{
rfc_CMD_BLE_SLAVE_t *c = (rfc_CMD_BLE_SLAVE_t *)cmd;
memset(c, 0x00, sizeof(rfc_CMD_BLE_SLAVE_t));
c->commandNo = CMD_BLE_SLAVE;
c->condition.rule = COND_NEVER;
c->whitening.bOverride = 0;
c->channel = channel;
c->pParams = (rfc_bleSlavePar_t *)params;
c->startTrigger.triggerType = TRIG_ABSTIME;
c->startTrigger.pastTrig = 0;
c->startTime = start_time;
c->pOutput = (rfc_bleMasterSlaveOutput_t *)output;
}
/*---------------------------------------------------------------------------*/
void
rf_ble_cmd_create_slave_params(uint8_t *params, dataQueue_t *rx_queue,
dataQueue_t *tx_queue, uint32_t access_address,
uint8_t crc_init_0, uint8_t crc_init_1,
uint8_t crc_init_2, uint32_t win_size,
uint32_t window_widening, uint8_t first_packet)
{
rfc_bleSlavePar_t *p = (rfc_bleSlavePar_t *)params;
p->pRxQ = rx_queue;
p->pTxQ = tx_queue;
p->rxConfig.bAutoFlushIgnored = 1;
p->rxConfig.bAutoFlushCrcErr = 1;
p->rxConfig.bAutoFlushEmpty = 1;
p->rxConfig.bIncludeLenByte = 1;
p->rxConfig.bIncludeCrc = 0;
p->rxConfig.bAppendRssi = 1;
p->rxConfig.bAppendStatus = 1;
p->rxConfig.bAppendTimestamp = 1;
if(first_packet) {
/* set parameters for first packet according to TI Technical Reference Manual */
p->seqStat.lastRxSn = 1;
p->seqStat.lastTxSn = 1;
p->seqStat.nextTxSn = 0;
p->seqStat.bFirstPkt = 1;
p->seqStat.bAutoEmpty = 0;
p->seqStat.bLlCtrlTx = 0;
p->seqStat.bLlCtrlAckRx = 0;
p->seqStat.bLlCtrlAckPending = 0;
}
p->maxNack = 0;
p->maxPkt = 0;
p->accessAddress = access_address;
p->crcInit0 = crc_init_0;
p->crcInit1 = crc_init_1;
p->crcInit2 = crc_init_2;
p->timeoutTrigger.triggerType = TRIG_REL_START;
if(first_packet) {
p->timeoutTime = (uint32_t)(10 * win_size);
} else {
p->timeoutTime = (uint32_t)(win_size + 2 * window_widening);
}
p->endTrigger.triggerType = TRIG_NEVER;
}
/*---------------------------------------------------------------------------*/
/* DATA queue functions */
/*---------------------------------------------------------------------------*/
unsigned short
rf_ble_cmd_add_data_queue_entry(dataQueue_t *q, uint8_t *e)
{
uint32_t cmdsta;
rfc_CMD_ADD_DATA_ENTRY_t cmd;
cmd.commandNo = CMD_ADD_DATA_ENTRY;
cmd.pQueue = q;
cmd.pEntry = e;
if(rf_core_send_cmd((uint32_t)&cmd, &cmdsta) != RF_CORE_CMD_OK) {
LOG_ERR("could not add entry to data queue. status: 0x%04X\n",
CMD_GET_STATUS(&cmd));
return RF_BLE_CMD_ERROR;
}
return RF_BLE_CMD_OK;
}

View File

@ -0,0 +1,160 @@
/*
* Copyright (c) 2017, Graz University of Technology
* 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 copyright holder 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 COPYRIGHT HOLDERS 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
* COPYRIGHT HOLDER 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.
*/
/**
* \file
* BLE commands for the TI CC26xx BLE radio.
* These functions are specific to the TI CC26xx and cannot be
* reused by other BLE radios.
*
* \author
* Michael Spoerk <michael.spoerk@tugraz.at>
*/
/*---------------------------------------------------------------------------*/
#ifndef RF_BLE_CMD_H_
#define RF_BLE_CMD_H_
#include "os/dev/ble-hal.h"
#include "../../ble-addr.h"
#include "rf_common_cmd.h"
#define RF_BLE_CMD_OK 1
#define RF_BLE_CMD_ERROR 0
/*---------------------------------------------------------------------------*/
/**
* \brief Sends a BLE radio command to the radio
* \param cmd A pointer to the command to be send
* \return RF_CORE_CMD_OK or RF_CORE_CMD_ERROR
*/
unsigned short rf_ble_cmd_send(uint8_t *cmd);
/*---------------------------------------------------------------------------*/
/**
* \brief Waits for a running BLE radio command to be finished
* \param cmd A pointer to the running command
* \return RF_CORE_CMD_OK or RF_CORE_CMD_ERROR
*/
unsigned short rf_ble_cmd_wait(uint8_t *cmd);
/*---------------------------------------------------------------------------*/
/**
* \brief Initializes the radio core to be used as a BLE radio
* \return RF_CORE_CMD_OK or RF_CORE_CMD_ERROR
*/
unsigned short rf_ble_cmd_setup_ble_mode(void);
/*---------------------------------------------------------------------------*/
/**
* \brief Creates a BLE radio command structure that enables
* BLE advertisement when sent to the radio core
* \param command A pointer to command that is created
* \param channel The BLE advertisement channel used for advertisement
* \param param A pointer to the radio command parameters
* \param output A pointer to the radio command output
*/
void rf_ble_cmd_create_adv_cmd(uint8_t *command, uint8_t channel,
uint8_t *param, uint8_t *output);
/*---------------------------------------------------------------------------*/
/**
* \brief Creates BLE radio command parameters that are used to enable
* BLE advertisement on the radio core
* \param param A pointer to parameter structure that is created
* \param rx_queue A pointer to the RX queue that is used
* \param adv_data_len
* The length of the advertisement data
* \param adv_data A pointer to the advertisement data that is advertised
* \param scan_resp_data_len
* The length of the scan response data
* \param scan_resp_data
* A pointer to the scan response data
* \param own_addr_type
* Either BLE_ADDR_TYPE_PUBLIC or BLE_ADDR_TYPE_RANDOM
* \param own_addr A pointer to the device address that is used as own address
*/
void rf_ble_cmd_create_adv_params(uint8_t *param, dataQueue_t *rx_queue,
uint8_t adv_data_len, uint8_t *adv_data,
uint8_t scan_resp_data_len, uint8_t *scan_resp_data,
ble_addr_type_t own_addr_type, uint8_t *own_addr);
/*---------------------------------------------------------------------------*/
/**
* \brief Creates a BLE radio command structure that sets up a single
* BLE connection event when sent to the radio core
* \param cmd A pointer to command that is created
* \param channel The BLE data channel used for the connection event
* \param param A pointer to the radio command parameters
* \param output A pointer to the radio command output
* \param start_time
* The time in rf_core_ticks when the connection event will start
*/
void rf_ble_cmd_create_slave_cmd(uint8_t *cmd, uint8_t channel, uint8_t *param,
uint8_t *output, uint32_t start_time);
/*---------------------------------------------------------------------------*/
/**
* \brief Creates BLE radio command parameters that are used to setup a single
* BLE connection event on the radio core
* \param param A pointer to parameter structure that is created
* \param rx_queue A pointer to the RX queue that is used
* \param tx_queue A pointer to the TX queue that is used
* \param access_address
* The access address of the used BLE connection
* \param crc_init_0
* Part of the initialization of the CRC checksum
* \param crc_init_1
* Part of the initialization of the CRC checksum
* \param crc_init_2
* Part of the initialization of the CRC checksum
* \param win_size The window size parameter of the BLE connection event
* \param window_widening
* The window widening parameter used for this connection event
* \param first_packet
* 1 for the first packet of the BLE connection so that the
* connection is properly initialized
*/
void rf_ble_cmd_create_slave_params(uint8_t *param, dataQueue_t *rx_queue,
dataQueue_t *tx_queue, uint32_t access_address,
uint8_t crc_init_0, uint8_t crc_init_1,
uint8_t crc_init_2, uint32_t win_size,
uint32_t window_widening, uint8_t first_packet);
/*---------------------------------------------------------------------------*/
/**
* \brief Adds a data buffer to a BLE transmission queue
* \param q A pointer to BLE transmission queue where the buffer
* should be added
* \param e A pointer to the data buffer that is added
*/
unsigned short rf_ble_cmd_add_data_queue_entry(dataQueue_t *q, uint8_t *e);
#endif /* RF_BLE_CMD_H_ */

View File

@ -0,0 +1,88 @@
/*
* Copyright (c) 2008, Swedish Institute of Computer Science
* 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.
*
* This file is part of the Contiki operating system.
*
*/
/**
* \file
* Coffee architecture-dependent header for the srf06-cc2650 sensortag platform.
* \author
* Dongda Lee <dongdongbhbh@gmail.com>
*/
#ifndef CFS_COFFEE_ARCH_H
#define CFS_COFFEE_ARCH_H
#include "contiki-conf.h"
#include "dev/xmem.h"
/*** MX25R8035F Memory Organization
The memory is organized as:
8Mbit = 1048576 bytes (8 bits each)
256 sectors (32 Kbits, 4096 bytes each)
4096 pages (256 bytes each).
Each page can be individually programmed (bits are programmed from 1 to 0). The device is
sector or bulk erasable (bits are erased from 0 to 1) but not page erasable
*/
#define COFFEE_XMEM_TOTAL_SIZE_KB 1024UL //Total size of the External Flash Memory in the Z1
/* Coffee configuration parameters. */
#define COFFEE_SECTOR_SIZE 4096UL
#define COFFEE_PAGE_SIZE 256UL
#define COFFEE_START 0UL //COFFEE_SECTOR_SIZE
#define COFFEE_SIZE (COFFEE_XMEM_TOTAL_SIZE_KB * 1024UL - COFFEE_START)
#define COFFEE_NAME_LENGTH 16
#define COFFEE_MAX_OPEN_FILES 6
#define COFFEE_FD_SET_SIZE 8
#define COFFEE_LOG_TABLE_LIMIT 256
#define COFFEE_DYN_SIZE 2*1024
#define COFFEE_LOG_SIZE 1024
#define COFFEE_MICRO_LOGS 1
/* Flash operations. */
#define COFFEE_WRITE(buf, size, offset) \
xmem_pwrite((char *)(buf), (size), COFFEE_START + (offset))
#define COFFEE_READ(buf, size, offset) \
xmem_pread((char *)(buf), (size), COFFEE_START + (offset))
#define COFFEE_ERASE(sector) \
xmem_erase(COFFEE_SECTOR_SIZE, COFFEE_START + (sector) * COFFEE_SECTOR_SIZE)
/* Coffee types. */
typedef int16_t coffee_page_t;
#endif /* !COFFEE_ARCH_H */

View File

@ -0,0 +1,168 @@
/*
* Copyright (c) 2006, Swedish Institute of Computer Science
* 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.
*
*/
/**
* \file
* Device driver for the MX25R8035F 1Mbyte external memory.
* \author
* Dongda Lee <dongdongbhbh@gmail.com>
*
* Data is written bit inverted (~-operator) to flash so that
* unwritten data will read as zeros (UNIX style).
*/
#include "contiki.h"
#include "ext-flash.h"
#include "dev/xmem.h"
#include "dev/watchdog.h"
#include "cfs-coffee-arch.h"
#include <stdio.h> /* For PRINTF() */
#define EXT_ERASE_UNIT_SIZE 4096UL
#define XMEM_BUFF_LENGHT 128
#if 0
#define PRINTF(...) printf(__VA_ARGS__)
#else
#define PRINTF(...) do {} while (0)
#endif
void
xmem_init(void)
{
ext_flash_open();
}
int
xmem_pread(void *_p, int size, unsigned long addr)
{
int rv;
uint8_t x;
int i;
rv = ext_flash_open();
if(!rv) {
PRINTF("Could not open flash to save config\n");
ext_flash_close();
return -1;
}
rv = ext_flash_read(addr, size, _p);
for (i = 0; i < size; i++){
x = ~*((uint8_t *)_p + i);
*((uint8_t *)_p+i) = x;
}
ext_flash_close();
if(rv)
return size;
PRINTF("Could not read flash memory!\n");
return -1;
}
int
xmem_pwrite(const void *_buf, int size, unsigned long addr)
{
int rv;
int i, j;
int remain;
uint8_t tmp_buf[XMEM_BUFF_LENGHT];
rv = ext_flash_open();
if(!rv) {
PRINTF("Could not open flash to save config!\n");
ext_flash_close();
return -1;
}
for (remain = size, j = 0; remain > 0; remain -= XMEM_BUFF_LENGHT, j += XMEM_BUFF_LENGHT) {
int to_write = MIN(XMEM_BUFF_LENGHT, remain);
for (i = 0; i < to_write; i++) {
tmp_buf[i] = ~*((uint8_t *)_buf + j + i);
}
rv = ext_flash_write(addr + j, to_write, tmp_buf);
if (!rv) {
PRINTF("Could not write flash memory!\n");
return size - remain;
}
}
ext_flash_close();
return size;
}
int
xmem_erase(long size, unsigned long addr)
{
int rv;
rv = ext_flash_open();
if(!rv) {
PRINTF("Could not open flash to save config\n");
ext_flash_close();
return -1;
}
if(size % EXT_ERASE_UNIT_SIZE != 0) {
PRINTF("xmem_erase: bad size\n");
return -1;
}
if(addr % EXT_ERASE_UNIT_SIZE != 0) {
PRINTF("xmem_erase: bad offset\n");
return -1;
}
rv = ext_flash_erase(addr, size);
ext_flash_close();
watchdog_periodic();
if(rv)
return size;
PRINTF("Could not erase flash memory\n");
return -1;
}

View File

@ -2,7 +2,7 @@ CFLAGS += -DBOARD_LAUNCHPAD=1
CONTIKI_TARGET_DIRS += launchpad common
BOARD_SOURCEFILES += board.c launchpad-sensors.c button-sensor.c
BOARD_SOURCEFILES += board.c launchpad-sensors.c button-sensor.c xmem.c
BOARD_SOURCEFILES += ext-flash.c board-spi.c
### Signal that we can be programmed with cc2538-bsl

View File

@ -52,6 +52,7 @@
#include "dev/gpio-hal.h"
#include "dev/oscillators.h"
#include "ieee-addr.h"
#include "ble-addr.h"
#include "vims.h"
#include "dev/cc26xx-uart.h"
#include "dev/soc-rtc.h"
@ -105,9 +106,13 @@ fade(leds_mask_t l)
static void
set_rf_params(void)
{
uint16_t short_addr;
uint8_t ext_addr[8];
#if MAKE_MAC == MAKE_MAC_BLE
ble_eui64_addr_cpy_to((uint8_t *)&ext_addr);
NETSTACK_RADIO.set_object(RADIO_PARAM_64BIT_ADDR, ext_addr, 8);
#else
uint16_t short_addr;
ieee_addr_cpy_to(ext_addr, 8);
short_addr = ext_addr[7];
@ -120,6 +125,7 @@ set_rf_params(void)
/* also set the global node id */
node_id = short_addr;
#endif
}
/*---------------------------------------------------------------------------*/
void
@ -175,8 +181,13 @@ platform_init_stage_two()
#endif
/* Populate linkaddr_node_addr */
#if MAKE_MAC == MAKE_MAC_BLE
uint8_t ext_addr[8];
ble_eui64_addr_cpy_to((uint8_t *)&ext_addr);
memcpy(&linkaddr_node_addr, &ext_addr[8 - LINKADDR_SIZE], LINKADDR_SIZE);
#else
ieee_addr_cpy_to(linkaddr_node_addr.u8, LINKADDR_SIZE);
#endif
fade(LEDS_GREEN);
}
/*---------------------------------------------------------------------------*/

View File

@ -5,6 +5,6 @@ CONTIKI_TARGET_DIRS += sensortag common
BOARD_SOURCEFILES += sensortag-sensors.c sensor-common.c
BOARD_SOURCEFILES += bmp-280-sensor.c tmp-007-sensor.c opt-3001-sensor.c
BOARD_SOURCEFILES += hdc-1000-sensor.c mpu-9250-sensor.c button-sensor.c
BOARD_SOURCEFILES += hdc-1000-sensor.c mpu-9250-sensor.c button-sensor.c xmem.c
BOARD_SOURCEFILES += reed-relay.c ext-flash.c buzzer.c
BOARD_SOURCEFILES += board.c board-spi.c board-i2c.c

View File

@ -0,0 +1,10 @@
DEFINES+=PROJECT_CONF_H=\"project-conf.h\"
CONTIKI_PROJECT=client
all: $(CONTIKI_PROJECT)
MAKE_MAC = MAKE_MAC_BLE
MAKE_NET = MAKE_NET_IPV6
CONTIKI = ../../..
include $(CONTIKI)/Makefile.include

View File

@ -0,0 +1,134 @@
/*
* Copyright (c) 2017, Graz University of Technology
* 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 copyright holder 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 COPYRIGHT HOLDERS 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
* COPYRIGHT HOLDER 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.
*/
/**
* \file
* A simple IPv6-over-BLE UDP-client.
*
* \author
* Michael Spoerk <michael.spoerk@tugraz.at>
*/
/*---------------------------------------------------------------------------*/
#include "contiki.h"
#include "contiki-lib.h"
#include "contiki-net.h"
#include "net/ipv6/uip-icmp6.h"
#include <string.h>
#include <stdio.h>
#include "os/dev/ble-hal.h"
/*---------------------------------------------------------------------------*/
#define SERVER_IP "::"
#define CLIENT_PORT 61617
#define SERVER_PORT 61616
#define PING_TIMEOUT (CLOCK_SECOND / 4)
#define CLIENT_SEND_INTERVAL (CLOCK_SECOND * 1)
#define UDP_LEN_MAX 255
/*---------------------------------------------------------------------------*/
static uip_ipaddr_t server_addr;
static struct uip_icmp6_echo_reply_notification icmp_notification;
static uint8_t echo_received;
static struct uip_udp_conn *conn;
static struct etimer timer;
static char buf[UDP_LEN_MAX];
static uint16_t packet_counter;
/*---------------------------------------------------------------------------*/
PROCESS(ipv6_ble_client_process, "IPv6 over BLE - client process");
AUTOSTART_PROCESSES(&ipv6_ble_client_process);
/*---------------------------------------------------------------------------*/
void
icmp_reply_handler(uip_ipaddr_t *source, uint8_t ttl,
uint8_t *data, uint16_t datalen)
{
if(uip_ip6addr_cmp(source, &server_addr)) {
printf("echo response received\n");
echo_received = 1;
}
}
/*---------------------------------------------------------------------------*/
static void
tcpip_handler(void)
{
char data[UDP_LEN_MAX];
if(uip_newdata()) {
strncpy(data, uip_appdata, uip_datalen());
data[uip_datalen()] = '\0';
printf("rec. message: <%s>\n", data);
}
}
/*---------------------------------------------------------------------------*/
static void
timeout_handler(void)
{
sprintf(buf, "Hello server %04u!", packet_counter);
printf("send message: <%s>\n", buf);
uip_udp_packet_send(conn, buf, strlen(buf));
packet_counter++;
}
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(ipv6_ble_client_process, ev, data)
{
PROCESS_BEGIN();
printf("IPv6-over-BLE client started\n");
uiplib_ipaddrconv(SERVER_IP, &server_addr);
uip_icmp6_echo_reply_callback_add(&icmp_notification, icmp_reply_handler);
printf("pinging the IPv6-over-BLE server\n");
do {
etimer_set(&timer, PING_TIMEOUT);
PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&timer));
uip_icmp6_send(&server_addr, ICMP6_ECHO_REQUEST, 0, 20);
} while(!echo_received);
conn = udp_new(&server_addr, UIP_HTONS(SERVER_PORT), NULL);
udp_bind(conn, UIP_HTONS(CLIENT_PORT));
etimer_set(&timer, CLIENT_SEND_INTERVAL);
while(1) {
PROCESS_YIELD();
if((ev == PROCESS_EVENT_TIMER) && (data == &timer)) {
timeout_handler();
etimer_set(&timer, CLIENT_SEND_INTERVAL);
} else if(ev == tcpip_event) {
tcpip_handler();
}
}
PROCESS_END();
}
/*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,70 @@
/*
* Copyright (c) 2017, Graz University of Technology
* 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 copyright holder 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 COPYRIGHT HOLDERS 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
* COPYRIGHT HOLDER 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.
*/
/**
* \author
* Michael Spoerk <michael.spoerk@tugraz.at>
*/
/*---------------------------------------------------------------------------*/
#ifndef PROJECT_CONF_H_
#define PROJECT_CONF_H_
/*---------------------------------------------------------------------------*/
/* Disable button shutdown functionality */
#define BUTTON_SENSOR_CONF_ENABLE_SHUTDOWN 0
/*---------------------------------------------------------------------------*/
/* Change to match your configuration */
#define BOARD_CONF_DEBUGGER_DEVPACK 1
/*---------------------------------------------------------------------------*/
#define PACKETBUF_CONF_SIZE 1280
#define QUEUEBUF_CONF_NUM 1
#define UIP_CONF_BUFFER_SIZE 1280
#define NETSTACK_CONF_RADIO ble_cc2650_driver
#define LOG_CONF_LEVEL_MAC LOG_LEVEL_INFO
/* BLE L2CAP settings */
#define BLE_CONF_DEVICE_NAME "TI CC26xx device"
#define BLE_CONF_ADV_INTERVAL 25
/*/ * 6LoWPAN settings * / */
#define SICSLOWPAN_CONF_MAC_MAX_PAYLOAD 1280
#define SICSLOWPAN_CONF_COMPRESSION SICSLOWPAN_COMPRESSION_6LORH
#define SICSLOWPAN_CONF_COMPRESSION_THRESHOLD 0 /* always use compression */
#define SICSLOWPAN_CONF_FRAG 0
#define SICSLOWPAN_FRAMER_HDRLEN 0
/* */
/*/ * network stack settings * / */
#define UIP_CONF_ROUTER 0
#define UIP_CONF_ND6_SEND_NA 1
/*---------------------------------------------------------------------------*/
#endif /* PROJECT_CONF_H_ */
/*---------------------------------------------------------------------------*/

View File

@ -3,6 +3,7 @@ CONTIKI = ../../..
PLATFORMS_ONLY= cc2538 sky
MODULES += os/services/unit-test
MODULES += os/storage/cfs
CONTIKI_PROJECT = test-cfs test-coffee example-coffee
all: $(CONTIKI_PROJECT)

View File

@ -23,6 +23,9 @@ Supported Hardware (tested or known to work)
* cc2538dk
* openmote-cc2538
* zoul
* TI srf06-cc26xx
- sensortag
- launchpad
The examples are known to build for the 'avr-raven' platform. However,
some of them currently fail at runtime due to file system overflow.

404
os/dev/ble-hal.h Normal file
View File

@ -0,0 +1,404 @@
/*
* Copyright (c) 2017, Graz University of Technology
* 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 copyright holder 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 COPYRIGHT HOLDERS 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
* COPYRIGHT HOLDER 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.
*/
/**
* \file
* hardware abstraction for a BLE controller
*
* \author
* Michael Spoerk <michael.spoerk@tugraz.at>
*/
/*---------------------------------------------------------------------------*/
#ifndef BLE_HAL_H_
#define BLE_HAL_H_
#include <stddef.h>
/*---------------------------------------------------------------------------*/
/* BLE device address size */
#define BLE_ADDR_SIZE 6
/*---------------------------------------------------------------------------*/
/* Advertisement channel definitions */
#define BLE_ADV_DATA_LEN 31
#define BLE_SCAN_RESP_DATA_LEN 31
#define BLE_ADV_CHANNEL_1 37
#define BLE_ADV_CHANNEL_1_MASK 0b001
#define BLE_ADV_CHANNEL_2 38
#define BLE_ADV_CHANNEL_2_MASK 0b010
#define BLE_ADV_CHANNEL_3 39
#define BLE_ADV_CHANNEL_3_MASK 0b100
#define BLE_ADV_INTERVAL_MIN 20
#define BLE_ADV_INTERVAL_MAX 0x4000
#define BLE_SCAN_INTERVAL_MIN 0x0004
#define BLE_SCAN_INTERVAL_MAX 0x4000
/*---------------------------------------------------------------------------*/
/* Data channel definitions */
#define BLE_DATA_CHANNEL_MIN 0
#define BLE_DATA_CHANNEL_MAX 36
/* Types of data PDU frames */
#define BLE_DATA_PDU_LLID_DATA_FRAGMENT 0b01
#define BLE_DATA_PDU_LLID_DATA_MESSAGE 0b10
#define BLE_DATA_PDU_LLID_CONTROL 0b11
/*---------------------------------------------------------------------------*/
/* Types of LL control PDUs */
#define BLE_LL_CONN_UPDATE_REQ 0x00
#define BLE_LL_CHANNEL_MAP_REQ 0x01
#define BLE_LL_TERMINATE_IND 0x02
#define BLE_LL_ENC_REQ 0x03
#define BLE_LL_ENC_RSP 0x04
#define BLE_LL_START_ENC_REQ 0x05
#define BLE_LL_START_ENC_RSP 0x06
#define BLE_LL_UNKNOWN_RSP 0x07
#define BLE_LL_FEATURE_REQ 0x08
#define BLE_LL_FEATURE_RSP 0x09
#define BLE_LL_PAUSE_ENC_REQ 0x0A
#define BLE_LL_PAUSE_ENC_RSP 0x0B
#define BLE_LL_VERSION_IND 0x0C
#define BLE_LL_REJECT_IND 0x0D
#define BLE_LL_SLAVE_FEATURE_REQ 0x0E
#define BLE_LL_CONN_PARAM_REQ 0x0F
#define BLE_LL_CONN_PARAM_RSP 0x10
#define BLE_LL_REJECT_IND_EXT 0x11
#define BLE_LL_PING_REQ 0x12
#define BLE_LL_PING_RSP 0x13
/*---------------------------------------------------------------------------*/
#define FRAME_BLE_RX_EVENT 0x00 /* signaling that data was received (standard) */
#define FRAME_BLE_TX_EVENT 0x10 /* signaling that data was successfully sent */
#define FRAME_BLE_CONNECTION_EVENT 0x20 /* signaling that a new BLE connection was established */
#define FRAME_BLE_CONNECTION_UPDATED 0x30 /* signaling that the BLE connection parameter were successfully updated */
/*---------------------------------------------------------------------------*/
/* Return values for functions of ble_controller_driver implementations */
typedef enum {
BLE_RESULT_OK,
BLE_RESULT_NOT_SUPPORTED,
BLE_RESULT_INVALID_PARAM,
BLE_RESULT_ERROR
} ble_result_t;
/*---------------------------------------------------------------------------*/
/* Type of BLE device address */
typedef enum {
BLE_ADDR_TYPE_PUBLIC,
BLE_ADDR_TYPE_RANDOM
} ble_addr_type_t;
/*---------------------------------------------------------------------------*/
/* Advertising modes of BLE */
typedef enum {
/* connectable undirected advertising */
BLE_ADV_IND,
/* connectable directed advertising (high duty cycle) */
BLE_ADV_DIR_IND_HDC,
/* scannable undirected advertising */
BLE_ADV_SCAN_IND,
/* non connectable undirected advertising */
BLE_ADV_NONCONN_IND,
/* connectable directed advertising (low duty cycle) */
BLE_ADV_DIR_IND_LDC
} ble_adv_type_t;
/*---------------------------------------------------------------------------*/
/* Scanning modes of BLE */
typedef enum {
/* no SCAN REQUESTS are sent */
BLE_SCAN_PASSIVE,
/* SCAN REQUESTS may be sent */
BLE_SCAN_ACTIVE
} ble_scan_type_t;
/*---------------------------------------------------------------------------*/
/* Scanning filter policy */
typedef enum {
/* accept all advertisement packets */
BLE_SCAN_FILTER_POLICY_ACCEPT,
/* ignore all advertisement packets from devices not on the white list */
BLE_SCAN_FILTER_POLICY_IGNORE
} ble_scan_filter_policy_t;
/*---------------------------------------------------------------------------*/
/* List of packets to be sent by RDC layer */
struct ble_buf_list {
struct ble_buf_list *next;
struct queuebuf *buf;
void *ptr;
};
/*---------------------------------------------------------------------------*/
/* Extension of the RADIO_PARAM fields for the BLE radios */
enum {
/* start with 100 to be sure to not interfere with the standard values*/
/*-----------------------------------------------------------------------*/
/* BLE controller general */
/* The bluetooth device address */
RADIO_CONST_BLE_BD_ADDR = 100,
/* the size of a single BLE command buffer */
RADIO_CONST_BLE_BUFFER_SIZE,
/* the amount of single BLE command buffers */
RADIO_CONST_BLE_BUFFER_AMOUNT,
/*-----------------------------------------------------------------------*/
/* BLE advertisement */
/* advertisement interval */
RADIO_PARAM_BLE_ADV_INTERVAL,
/* BLE advertisement type (directed/undirected, ...) */
RADIO_PARAM_BLE_ADV_TYPE,
/* type of own address during advertisement */
RADIO_PARAM_BLE_ADV_OWN_ADDR_TYPE,
/* advertisement channel map */
RADIO_PARAM_BLE_ADV_CHANNEL_MAP,
/* advertisement payload */
RADIO_PARAM_BLE_ADV_PAYLOAD,
/* scan response payload */
RADIO_PARAM_BLE_ADV_SCAN_RESPONSE,
/* 1: enable advertisement / 0: disable advertisement */
RADIO_PARAM_BLE_ADV_ENABLE,
/*-----------------------------------------------------------------------*/
/* BLE scanning */
/* scanning interval */
RADIO_PARAM_BLE_SCAN_INTERVAL,
/* scanning window */
RADIO_PARAM_BLE_SCAN_WINDOW,
/* BLE scanning type (active/passive) */
RADIO_PARAM_BLE_SCAN_TYPE,
/* type of own address during scanning */
RADIO_PARAM_BLE_SCAN_OWN_ADDR_TYPE,
/* scanning channel */
RADIO_PARAM_BLE_SCAN_CHANNEL,
/* 1: enable scanning / 0: disable scanning */
RADIO_PARAM_BLE_SCAN_ENABLE,
/*-----------------------------------------------------------------------*/
/* BLE initiating */
/* The initiating command uses some parameters from scanning */
/* (scan interval, window, address type) */
/* address type of the advertising device */
RADIO_PARAM_BLE_PEER_ADDR_TYPE,
/* address of the advertising device */
RADIO_PARAM_BLE_PEER_ADDR,
/* connection interval */
RADIO_PARAM_BLE_CONN_INTERVAL,
/* slave latency */
RADIO_PARAM_BLE_CONN_LATENCY,
/* supervision timeout */
RADIO_PARAM_BLE_CONN_SUPERVISION_TIMEOUT,
/* 1: start connection / 0: cancel connection creation */
RADIO_PARAM_BLE_INITIATOR_ENABLE,
RADIO_PARAM_BLE_CONN_UPDATE
};
/*---------------------------------------------------------------------------*/
/**
* The structure of a ble radio controller driver in Contiki.
*/
struct ble_hal_driver {
/*------------------------------------------------------------------------*/
/* GENERAL COMMANDS */
/**
* Resets the BLE controller
*/
ble_result_t (*reset)(void);
/**
* Reads the static BLE device address.
*
* \param addr the static device address
*/
ble_result_t (*read_bd_addr)(uint8_t *addr);
/**
* Reads the size of the data buffers.
*
* \param buf_len the length of a single data buffer
* \param num_buf the number of data buffers
*/
ble_result_t (*read_buffer_size) (unsigned int *buf_len,
unsigned int *num_buf);
/*------------------------------------------------------------------------*/
/* ADVERTISING COMMANDS */
/**
* Sets the parameter for advertising.
*
* \param adv_interval advertising interval
* (interval = adv_interval * 0.625 ms)
* \param type type of advertising
* \param own_addr_type indicator if own address is public/random
* \param adv_channel_map map of advertising channels to use
*/
ble_result_t (*set_adv_param) (unsigned int adv_interval,
ble_adv_type_t type,
ble_addr_type_t own_addr_type,
unsigned short adv_channel_map);
/**
* Reads the used power on the advertisement channels.
*
* \param power the used power in dBm
*/
ble_result_t (*read_adv_channel_tx_power) (short *power);
/**
* Sets the advertising data.
*
* \param data_len the length of the advertising data
* \param data the data to advertise
*/
ble_result_t (*set_adv_data) (unsigned short data_len,
char *data);
/**
* Sets the scan response data.
*
* \param data_len the length of the scan response data
* \param data the data of a scan response
*/
ble_result_t (*set_scan_resp_data) (unsigned short data_len,
char *data);
/**
* Enables/disables advertising.
*
* \param enable if 1 then enable advertising, otherwise disable
*/
ble_result_t (*set_adv_enable) (unsigned short enable);
/*------------------------------------------------------------------------*/
/* SCANNING COMMANDS */
/**
* Sets the parameter for scanning.
*
* \param type scan mode
* \param scan_interval scan interval (interval = scan_interval * 0.625 ms)
* \param scan_window scan window (window = scan_window * 0.625 ms)
* \param own_addr_type indicator if own address is public/random
*/
ble_result_t (*set_scan_param) (ble_scan_type_t type,
unsigned int scan_interval,
unsigned int scan_window,
ble_addr_type_t own_addr_type);
/**
* Enables/disables scanning.
*
* \param enable 1: enable scanning, otherwise disable
* \param filter_duplicates: 1: filter duplicates, otherwise no filtering
*/
ble_result_t (*set_scan_enable) (unsigned short enable,
unsigned short filter_duplicates);
/*------------------------------------------------------------------------*/
/* INITIATING COMMANDS */
/**
* Initiates the creation of a BLE connection.
*
* \param scan_interval scan interval (interval = scan_interval * 0.625 ms)
* \param scan_window scan window (window = scan_window * 0.625 ms)
* \param peer_addr_type indicator if peer address is public/random
* \param peer_addr ble address of the device to connect to
* \param own_addr_type indicator if own address is public/random
* \param conn_interval connection interval
* (interval = conn_interval * 1.25 ms)
* \param conn_latency slave latency
* \param supervision_timeout (timeout = supervision_timeout * 10 ms)
*/
ble_result_t (*create_connection) (unsigned int scan_interval,
unsigned int scan_window,
ble_addr_type_t peer_addr_type,
uint8_t *peer_addr,
ble_addr_type_t own_addr_type,
unsigned int conn_interval,
unsigned int conn_latency,
unsigned int supervision_timeout);
/**
* Cancels the initiation of a BLE connection.
*/
ble_result_t (*create_connection_cancel) (void);
/*------------------------------------------------------------------------*/
/* CONNECTION COMMANDS */
/**
* Updates the connection parameters.
* \param conn_interval connection interval
* (interval = conn_interval * 1.25 ms)
* \param conn_latency slave latency
* \param supervision_timeout (timeout = supervision_timeout * 10 ms)
*/
ble_result_t (*connection_update) (unsigned int connection_handle,
unsigned int conn_interval,
unsigned int conn_latency,
unsigned int supervision_timeout);
/**
* Disconnects the connection.
*
* \param connection_handle
* \param reason see error codes of Bluetooth specification
*/
ble_result_t (*disconnect) (unsigned int connection_handle,
unsigned short reason);
ble_result_t (*send) (void *buf, unsigned short buf_len);
ble_result_t (*send_list) (struct ble_buf_list *list);
ble_result_t (*read_connection_interval) (unsigned int conn_handle,
unsigned int *conn_interval_ms);
};
#endif /* BLE_HAL_H_ */

590
os/net/mac/ble/ble-l2cap.c Normal file
View File

@ -0,0 +1,590 @@
/*
* Copyright (c) 2017, Graz University of Technology
* 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 copyright holder 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 COPYRIGHT HOLDERS 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
* COPYRIGHT HOLDER 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.
*/
/**
* \file
* MAC layer that implements BLE L2CAP credit-based flow control
* channels to support IPv6 over BLE (RFC 7668)
*
* \author
* Michael Spoerk <michael.spoerk@tugraz.at>
*/
/*---------------------------------------------------------------------------*/
#include "net/mac/ble/ble-l2cap.h"
#include "net/packetbuf.h"
#include "net/netstack.h"
#include "lib/memb.h"
#include "lib/list.h"
#include <string.h>
#include "../../../dev/ble-hal.h"
/*---------------------------------------------------------------------------*/
#include "sys/log.h"
#define LOG_MODULE "L2CAP"
#define LOG_LEVEL LOG_LEVEL_MAC
/*---------------------------------------------------------------------------*/
#define MS_TO_CLOCK_SECONDS(X) ((int)(((double)((X)*CLOCK_SECOND)) / 1000.0))
/*---------------------------------------------------------------------------*/
/* BLE controller */
/* public device address of BLE controller */
static uint8_t ble_addr[BLE_ADDR_SIZE];
/*---------------------------------------------------------------------------*/
/* L2CAP fragmentation buffers and utilities */
typedef struct {
/* L2CAP Service Data Unit (SDU) (= packet data)*/
uint8_t sdu[BLE_L2CAP_NODE_MTU];
/* length of the L2CAP SDU */
uint16_t sdu_length;
/* index of the first byte not sent yet */
uint16_t current_index;
} l2cap_buffer_t;
/*---------------------------------------------------------------------------*/
typedef struct {
uint16_t cid;
uint16_t mtu;
uint16_t mps;
uint16_t credits;
} ble_mac_l2cap_channel_t;
/*---------------------------------------------------------------------------*/
typedef struct {
ble_mac_l2cap_channel_t channel_own;
ble_mac_l2cap_channel_t channel_peer;
l2cap_buffer_t tx_buffer;
l2cap_buffer_t rx_buffer;
linkaddr_t peer_addr;
} l2cap_channel_t;
static uint8_t l2cap_channel_count;
static l2cap_channel_t l2cap_channels[L2CAP_CHANNELS];
static process_event_t l2cap_tx_event;
/*---------------------------------------------------------------------------*/
static l2cap_channel_t *
get_channel_for_addr(const linkaddr_t *peer_addr)
{
uint8_t i;
l2cap_channel_t *channel;
for(i = 0; i < l2cap_channel_count; i++) {
channel = &l2cap_channels[i];
if(linkaddr_cmp(peer_addr, &channel->peer_addr) != 0) {
return channel;
}
}
return NULL;
}
/*---------------------------------------------------------------------------*/
static l2cap_channel_t *
get_channel_for_cid(uint16_t own_cid)
{
uint8_t i = own_cid - L2CAP_FLOW_CHANNEL;
if(i >= 0 && i < l2cap_channel_count) {
return &l2cap_channels[own_cid - L2CAP_FLOW_CHANNEL];
} else {
return NULL;
}
}
/*---------------------------------------------------------------------------*/
PROCESS(ble_l2cap_tx_process, "BLE L2CAP TX process");
/*---------------------------------------------------------------------------*/
static uint8_t
init_adv_data(char *adv_data)
{
uint8_t adv_data_len = 0;
memset(adv_data, 0x00, BLE_ADV_DATA_LEN);
/* BLE flags */
adv_data[adv_data_len++] = 2;
adv_data[adv_data_len++] = 0x01;
adv_data[adv_data_len++] = 0x05; /* LE limited (no BR/EDR support) */
/* TX power level */
adv_data[adv_data_len++] = 2;
adv_data[adv_data_len++] = 0x0A;
adv_data[adv_data_len++] = 0; /* 0 dBm */
/* service UUIDs (16-bit identifiers) */
adv_data[adv_data_len++] = 3;
adv_data[adv_data_len++] = 0x03;
adv_data[adv_data_len++] = 0x20;
adv_data[adv_data_len++] = 0x18; /* only IP support service exposed */
/* service UUIDs (32-bit identifiers) */
adv_data[adv_data_len++] = 1;
adv_data[adv_data_len++] = 0x05; /* empty list */
/* service UUIDs (128-bit identifiers) */
adv_data[adv_data_len++] = 1;
adv_data[adv_data_len++] = 0x07; /* empty list */
return adv_data_len;
}
/*---------------------------------------------------------------------------*/
static uint8_t
init_scan_resp_data(char *scan_resp_data)
{
uint8_t scan_resp_data_len = 0;
memset(scan_resp_data, 0x00, BLE_SCAN_RESP_DATA_LEN);
/* complete device name */
scan_resp_data[scan_resp_data_len++] = 1 + strlen(BLE_DEVICE_NAME);
scan_resp_data[scan_resp_data_len++] = 0x09;
memcpy(&scan_resp_data[scan_resp_data_len],
BLE_DEVICE_NAME, strlen(BLE_DEVICE_NAME));
scan_resp_data_len += strlen(BLE_DEVICE_NAME);
/* slave connection interval range */
scan_resp_data[scan_resp_data_len++] = 5;
scan_resp_data[scan_resp_data_len++] = 0x12;
scan_resp_data[scan_resp_data_len++] = (BLE_SLAVE_CONN_INTERVAL_MIN & 0xFF);
scan_resp_data[scan_resp_data_len++] = ((BLE_SLAVE_CONN_INTERVAL_MIN >> 8) & 0xFF);
scan_resp_data[scan_resp_data_len++] = (BLE_SLAVE_CONN_INTERVAL_MAX & 0xFF);
scan_resp_data[scan_resp_data_len++] = ((BLE_SLAVE_CONN_INTERVAL_MAX >> 8) & 0xFF);
return scan_resp_data_len;
}
/*---------------------------------------------------------------------------*/
void
input_l2cap_conn_req(uint8_t *data)
{
uint8_t identifier = data[0];
uint16_t len;
uint16_t le_psm;
uint8_t resp_data[18];
l2cap_channel_t *channel;
memcpy(&len, &data[1], 2);
if(len != 10) {
LOG_WARN("l2cap_conn_req: invalid len: %d\n", len);
return;
}
/* create a new L2CAP connection because of this request */
if(l2cap_channel_count >= L2CAP_CHANNELS) {
LOG_WARN("l2cap_conn_req: maximum supported L2CAP channels reached\n");
return;
}
channel = &l2cap_channels[l2cap_channel_count];
/* parse L2CAP connection data */
memcpy(&le_psm, &data[3], 2);
memset(&channel->channel_peer, 0x00, sizeof(ble_mac_l2cap_channel_t));
memcpy(&channel->channel_peer.cid, &data[5], 2);
memcpy(&channel->channel_peer.mtu, &data[7], 2);
memcpy(&channel->channel_peer.mps, &data[9], 2);
memcpy(&channel->channel_peer.credits, &data[11], 2);
linkaddr_copy(&channel->peer_addr, packetbuf_addr(PACKETBUF_ADDR_SENDER));
LOG_INFO("recv CONN_REQ (MTU: %4d, MPS: %4d, credits: %4d)\n",
channel->channel_peer.mtu, channel->channel_peer.mps, channel->channel_peer.credits);
l2cap_channel_count++;
/* create L2CAP connection response */
/* length */
resp_data[0] = 0x0E;
resp_data[1] = 0x00;
/* channel ID */
resp_data[2] = 0x05;
resp_data[3] = 0x00;
/* code */
resp_data[4] = L2CAP_CODE_CONN_RSP;
/* identifier */
resp_data[5] = identifier;
/* cmd length */
resp_data[6] = 0x0A;
resp_data[7] = 0x00;
/* node channel information */
memcpy(&resp_data[8], &channel->channel_own.cid, 2);
memcpy(&resp_data[10], &channel->channel_own.mtu, 2);
memcpy(&resp_data[12], &channel->channel_own.mps, 2);
memcpy(&resp_data[14], &channel->channel_own.credits, 2);
/* result */
memset(&resp_data[16], 0x00, 2);
packetbuf_copyfrom((void *)resp_data, 18);
packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &linkaddr_node_addr);
packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &channel->peer_addr);
NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen());
}
/*---------------------------------------------------------------------------*/
static void
init(void)
{
uint8_t i;
l2cap_tx_event = process_alloc_event();
LOG_DBG("init()\n");
/* initialize the L2CAP connection parameter */
for(i = 0; i < L2CAP_CHANNELS; i++) {
l2cap_channels[i].channel_own.cid = L2CAP_FLOW_CHANNEL + i;
l2cap_channels[i].channel_own.credits = L2CAP_CREDIT_NEW;
l2cap_channels[i].channel_own.mps = (BLE_L2CAP_NODE_FRAG_LEN - L2CAP_SUBSEQ_HEADER_SIZE);
l2cap_channels[i].channel_own.mtu = BLE_L2CAP_NODE_MTU;
}
/* Initialize the BLE controller */
NETSTACK_RADIO.init();
NETSTACK_RADIO.get_object(RADIO_CONST_BLE_BD_ADDR, &ble_addr, BLE_ADDR_SIZE);
uint8_t adv_data_len, scan_resp_data_len;
char adv_data[BLE_ADV_DATA_LEN];
char scan_resp_data[BLE_SCAN_RESP_DATA_LEN];
/* set the advertisement parameter */
NETSTACK_RADIO.set_value(RADIO_PARAM_BLE_ADV_INTERVAL, BLE_ADV_INTERVAL);
NETSTACK_RADIO.set_value(RADIO_PARAM_BLE_ADV_TYPE, BLE_ADV_DIR_IND_LDC);
NETSTACK_RADIO.set_value(RADIO_PARAM_BLE_ADV_OWN_ADDR_TYPE, BLE_ADDR_TYPE_PUBLIC);
NETSTACK_RADIO.set_value(RADIO_PARAM_BLE_ADV_CHANNEL_MAP, 0x01);
adv_data_len = init_adv_data(adv_data);
scan_resp_data_len = init_scan_resp_data(scan_resp_data);
/* set advertisement payload & scan response */
NETSTACK_RADIO.set_object(RADIO_PARAM_BLE_ADV_PAYLOAD, adv_data, adv_data_len);
NETSTACK_RADIO.set_object(RADIO_PARAM_BLE_ADV_SCAN_RESPONSE, scan_resp_data, scan_resp_data_len);
/* enable advertisement */
NETSTACK_RADIO.set_value(RADIO_PARAM_BLE_ADV_ENABLE, 1);
NETSTACK_MAC.on();
}
/*---------------------------------------------------------------------------*/
static uint16_t
check_own_l2cap_credits(l2cap_channel_t *channel)
{
uint16_t credits_new = 0;
uint16_t credits_current;
credits_current = channel->channel_own.credits;
if(credits_current < L2CAP_CREDIT_THRESHOLD) {
credits_new = L2CAP_CREDIT_NEW;
}
LOG_DBG("check for new credits: current credits: %2d, new credits: %2d\n", credits_current, credits_new);
return credits_new;
}
/*---------------------------------------------------------------------------*/
static void
send_l2cap_credit(l2cap_channel_t *channel, uint16_t credits)
{
uint8_t len = 4;
uint8_t data[12];
/* create L2CAP credit */
/* length */
data[0] = len + 4;
data[1] = 0x00;
/* channel ID */
data[2] = 0x05;
data[3] = 0x00;
/* code */
data[4] = L2CAP_CODE_CREDIT;
/* identifier */
data[5] = 0xFF;
/* cmd length */
data[6] = len;
data[7] = 0x00;
memcpy(&data[8], &channel->channel_own.cid, 2);
data[10] = credits & 0xFF;
data[11] = credits >> 8;
channel->channel_own.credits += credits;
packetbuf_copyfrom((void *)data, len + 8);
packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &linkaddr_node_addr);
packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &channel->peer_addr);
NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen());
}
/*---------------------------------------------------------------------------*/
static void
send(mac_callback_t sent_callback, void *ptr)
{
uint8_t i;
l2cap_channel_t *channel;
uint16_t data_len = packetbuf_datalen();
LOG_DBG("send %d\n", data_len);
/* packet is too long */
if(data_len > BLE_L2CAP_NODE_MTU) {
LOG_WARN("send message is too long\n");
mac_call_sent_callback(sent_callback, ptr, MAC_TX_ERR, 0);
return;
}
for(i = 0; i < l2cap_channel_count; i++) {
channel = &l2cap_channels[i];
if((linkaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &linkaddr_null) != 0)
|| (linkaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &channel->peer_addr) != 0)) {
if(channel->tx_buffer.sdu_length > 0) {
LOG_WARN("send() another L2CAP message active (trying to send %4d bytes)\n", data_len);
mac_call_sent_callback(sent_callback, ptr, MAC_TX_COLLISION, 0);
return;
}
LOG_DBG("send() adding to L2CAP CID: %2d\n", channel->channel_own.cid);
channel->tx_buffer.sdu_length = data_len;
if(channel->tx_buffer.sdu_length > 0) {
memcpy(&channel->tx_buffer.sdu, packetbuf_dataptr(), data_len);
mac_call_sent_callback(sent_callback, ptr, MAC_TX_DEFERRED, 1);
process_post(&ble_l2cap_tx_process, l2cap_tx_event, (void *)channel);
}
}
}
}
/*---------------------------------------------------------------------------*/
void
input_l2cap_connection_udate_resp(uint8_t *data)
{
uint16_t len;
uint16_t result;
memcpy(&len, &data[1], 2);
if(len != 2) {
LOG_WARN("input_l2cap_connection_update_resp: invalid len: %d\n", len);
return;
}
memcpy(&result, &data[3], 2);
if(result != 0x0000) {
LOG_WARN("input_l2cap_connection_update_resp: result: 0x%04X\n", result);
return;
}
}
/*---------------------------------------------------------------------------*/
void
input_l2cap_credit(uint8_t *data)
{
uint16_t len;
uint16_t cid;
uint16_t credits;
l2cap_channel_t *channel = get_channel_for_addr(packetbuf_addr(PACKETBUF_ADDR_SENDER));
/* uint8_t identifier = data[0]; */
memcpy(&len, &data[1], 2);
if(len != 4) {
LOG_WARN("process_l2cap_credit: invalid len: %d\n", len);
return;
}
/* parse L2CAP credit data */
memcpy(&cid, &data[3], 2);
memcpy(&credits, &data[5], 2);
channel->channel_peer.credits += credits;
}
/*---------------------------------------------------------------------------*/
static void
input_l2cap_frame_signal_channel(uint8_t *data, uint8_t data_len)
{
if(data[4] == L2CAP_CODE_CREDIT) {
input_l2cap_credit(&data[5]);
} else if(data[4] == L2CAP_CODE_CONN_REQ) {
input_l2cap_conn_req(&data[5]);
} else if(data[4] == L2CAP_CODE_CONN_UPDATE_RSP) {
input_l2cap_connection_udate_resp(&data[5]);
} else {
LOG_WARN("l2cap_frame_signal_channel: unknown signal channel code: %d\n", data[4]);
}
}
/*---------------------------------------------------------------------------*/
static void
input_l2cap_frame_flow_channel(l2cap_channel_t *channel, uint8_t *data, uint16_t data_len)
{
uint16_t frame_len;
uint16_t payload_len;
if(data_len < 4) {
LOG_WARN("l2cap_frame: illegal L2CAP frame data_len: %d\n", data_len);
/* a L2CAP frame has a minimum length of 4 */
return;
}
if(channel->rx_buffer.sdu_length == 0) {
/* handle first fragment */
memcpy(&frame_len, &data[0], 2);
memcpy(&channel->rx_buffer.sdu_length, &data[4], 2);
payload_len = frame_len - 2;
memcpy(channel->rx_buffer.sdu, &data[6], payload_len);
channel->rx_buffer.current_index = payload_len;
} else {
/* subsequent fragment */
memcpy(&frame_len, &data[0], 2);
payload_len = frame_len;
memcpy(&channel->rx_buffer.sdu[channel->rx_buffer.current_index], &data[4], payload_len);
channel->rx_buffer.current_index += payload_len;
}
if((channel->rx_buffer.sdu_length > 0) &&
(channel->rx_buffer.sdu_length == channel->rx_buffer.current_index)) {
/* do not use packetbuf_copyfrom here because the packetbuf_attr
* must not be cleared */
memcpy(packetbuf_dataptr(), channel->rx_buffer.sdu, channel->rx_buffer.sdu_length);
packetbuf_set_datalen(channel->rx_buffer.sdu_length);
NETSTACK_NETWORK.input();
/* reset counters */
channel->rx_buffer.sdu_length = 0;
channel->rx_buffer.current_index = 0;
}
}
/*---------------------------------------------------------------------------*/
static void
input(void)
{
uint8_t *data = (uint8_t *)packetbuf_dataptr();
uint16_t len = packetbuf_datalen();
uint8_t frame_type = packetbuf_attr(PACKETBUF_ATTR_FRAME_TYPE);
uint16_t channel_id;
l2cap_channel_t *channel;
uint16_t credits;
if(frame_type == FRAME_BLE_RX_EVENT) {
memcpy(&channel_id, &data[2], 2);
channel = get_channel_for_cid(channel_id);
LOG_DBG("input %d bytes\n", len);
if(channel_id == L2CAP_SIGNAL_CHANNEL) {
input_l2cap_frame_signal_channel(data, len);
} else if(channel == NULL) {
LOG_WARN("input (RX_EVENT): no channel found for CID: %d\n", channel_id);
return;
} else {
input_l2cap_frame_flow_channel(channel, data, len);
channel->channel_own.credits--;
credits = check_own_l2cap_credits(channel);
if(credits > 0) {
send_l2cap_credit(channel, credits);
}
}
}
/* check if there are still fragments left to be transmitted */
if(frame_type == FRAME_BLE_TX_EVENT) {
channel = get_channel_for_addr(packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
if(channel == NULL) {
LOG_WARN("input (TX_EVENT): no channel found for CID: %d\n", channel_id);
} else if(channel->tx_buffer.sdu_length > 0) {
process_post(&ble_l2cap_tx_process, l2cap_tx_event, (void *)channel);
}
}
}
/*---------------------------------------------------------------------------*/
static int
on(void)
{
LOG_DBG("on()\n");
process_start(&ble_l2cap_tx_process, NULL);
return 0;
}
/*---------------------------------------------------------------------------*/
static int
off(void)
{
LOG_DBG("off()\n");
process_exit(&ble_l2cap_tx_process);
return 0;
}
/*---------------------------------------------------------------------------*/
const struct mac_driver ble_l2cap_driver = {
"ble-l2cap",
init,
send,
input,
on,
off,
NULL,
};
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(ble_l2cap_tx_process, ev, data)
{
uint16_t data_len;
uint16_t frame_len;
uint16_t num_buffer;
l2cap_channel_t *channel = (l2cap_channel_t *)data;
uint8_t first_fragment;
uint16_t used_mps;
uint16_t credits;
PROCESS_BEGIN();
LOG_DBG("starting ble_mac_tx_process\n");
while(1) {
PROCESS_YIELD_UNTIL(ev == l2cap_tx_event);
if(channel != NULL) {
NETSTACK_RADIO.get_value(RADIO_CONST_BLE_BUFFER_AMOUNT, (radio_value_t *)&num_buffer);
first_fragment = (channel->tx_buffer.current_index == 0);
used_mps = MIN(channel->channel_own.mps, channel->channel_peer.mps);
credits = channel->channel_peer.credits;
LOG_DBG("process: sending - first: %d, used_mps: %3d, num_buffers: %2d, credits: %2d\n",
first_fragment, used_mps, num_buffer, credits);
if((channel->tx_buffer.sdu_length > 0) && (num_buffer > 0) && (credits > 0)) {
packetbuf_clear();
if(first_fragment) {
packetbuf_hdralloc(L2CAP_FIRST_HEADER_SIZE);
used_mps -= L2CAP_FIRST_HEADER_SIZE;
data_len = MIN(channel->tx_buffer.sdu_length, used_mps);
frame_len = data_len + 2;
/* set L2CAP header fields */
memcpy(packetbuf_hdrptr(), &frame_len, 2); /* fragment size */
memcpy(packetbuf_hdrptr() + 2, &channel->channel_peer.cid, 2); /* L2CAP channel id*/
memcpy(packetbuf_hdrptr() + 4, &channel->tx_buffer.sdu_length, 2); /* overall packet size */
} else {
packetbuf_hdralloc(L2CAP_SUBSEQ_HEADER_SIZE);
used_mps -= L2CAP_SUBSEQ_HEADER_SIZE;
data_len = MIN((channel->tx_buffer.sdu_length - channel->tx_buffer.current_index), used_mps);
frame_len = data_len;
/* set L2CAP header fields */
memcpy(packetbuf_hdrptr(), &frame_len, 2); /* fragment size */
memcpy(packetbuf_hdrptr() + 2, &channel->channel_peer.cid, 2); /* L2CAP channel id*/
}
/* copy payload */
memcpy(packetbuf_dataptr(),
&channel->tx_buffer.sdu[channel->tx_buffer.current_index],
data_len);
packetbuf_set_datalen(data_len);
channel->tx_buffer.current_index += data_len;
/* send the fragment */
packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &channel->peer_addr);
packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &linkaddr_node_addr);
NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen());
channel->channel_peer.credits--;
/* reset the L2CAP TX buffer if packet is finished */
if(channel->tx_buffer.current_index == channel->tx_buffer.sdu_length) {
channel->tx_buffer.current_index = 0;
channel->tx_buffer.sdu_length = 0;
}
}
} else {
LOG_WARN("process. channel is NULL\n");
}
}
PROCESS_END();
LOG_DBG("stopped ble_mac_tx_process\n");
}

127
os/net/mac/ble/ble-l2cap.h Normal file
View File

@ -0,0 +1,127 @@
/*
* Copyright (c) 2017, Graz University of Technology
* 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 copyright holder 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 COPYRIGHT HOLDERS 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
* COPYRIGHT HOLDER 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.
*/
/**
* \file
* MAC layer that implements BLE L2CAP credit-based flow control
* channels to support IPv6 over BLE (RFC 7668)
*
* \author
* Michael Spoerk <michael.spoerk@tugraz.at>
*/
/*---------------------------------------------------------------------------*/
#ifndef BLE_L2CAP_H_
#define BLE_L2CAP_H_
#include "contiki.h"
#include "net/mac/mac.h"
#include "dev/radio.h"
/*---------------------------------------------------------------------------*/
/* device name used for BLE advertisement */
#ifdef BLE_CONF_DEVICE_NAME
#define BLE_DEVICE_NAME BLE_CONF_DEVICE_NAME
#else
#define BLE_DEVICE_NAME "BLE device name"
#endif
/* BLE advertisement in milliseconds */
#ifdef BLE_CONF_ADV_INTERVAL
#define BLE_ADV_INTERVAL BLE_CONF_ADV_INTERVAL
#else
#define BLE_ADV_INTERVAL 50
#endif
#define BLE_SLAVE_CONN_INTERVAL_MIN 0x0150
#define BLE_SLAVE_CONN_INTERVAL_MAX 0x01F0
#define L2CAP_SIGNAL_CHANNEL 0x0005
#define L2CAP_FLOW_CHANNEL 0x0041
#define L2CAP_CODE_CONN_UPDATE_REQ 0x12
#define L2CAP_CODE_CONN_UPDATE_RSP 0x13
#define L2CAP_CODE_CONN_REQ 0x14
#define L2CAP_CODE_CONN_RSP 0x15
#define L2CAP_CODE_CREDIT 0x16
#define L2CAP_IPSP_PSM 0x0023
/* the maximum MTU size of the L2CAP channel */
#ifdef BLE_L2CAP_CONF_NODE_MTU
#define BLE_L2CAP_NODE_MTU BLE_L2CAP_CONF_NODE_MTU
#else
#define BLE_L2CAP_NODE_MTU 1280
#endif
/* the max. supported L2CAP fragment length */
#ifdef BLE_L2CAP_CONF_NODE_FRAG_LEN
#define BLE_L2CAP_NODE_FRAG_LEN BLE_L2CAP_CONF_NODE_FRAG_LEN
#else
#ifdef BLE_MODE_CONF_CONN_MAX_PACKET_SIZE
#define BLE_L2CAP_NODE_FRAG_LEN BLE_MODE_CONF_CONN_MAX_PACKET_SIZE
#else
#define BLE_L2CAP_NODE_FRAG_LEN 256
#endif
#endif
#define L2CAP_CREDIT_NEW (BLE_L2CAP_NODE_MTU / BLE_L2CAP_NODE_FRAG_LEN)
#define L2CAP_CREDIT_THRESHOLD 2
#define L2CAP_INIT_INTERVAL (2 * CLOCK_SECOND)
/* BLE connection interval in milliseconds */
#ifdef BLE_CONF_CONNECTION_INTERVAL
#define CONNECTION_INTERVAL_MS BLE_CONF_CONNECTION_INTERVAL
#else
#define CONNECTION_INTERVAL_MS 125
#endif
/* BLE slave latency */
#ifdef BLE_CONF_CONNECTION_SLAVE_LATENCY
#define CONNECTION_SLAVE_LATENCY BLE_CONF_CONNECTION_SLAVE_LATENCY
#else
#define CONNECTION_SLAVE_LATENCY 0
#endif
/* BLE supervision timeout */
#define CONNECTION_TIMEOUT 42
#define L2CAP_FIRST_HEADER_SIZE 6
#define L2CAP_SUBSEQ_HEADER_SIZE 4
#if UIP_CONF_ROUTER
#ifdef BLE_MODE_CONF_MAX_CONNECTIONS
#define L2CAP_CHANNELS BLE_MODE_CONF_MAX_CONNECTIONS
#else
#define L2CAP_CHANNELS 1
#endif
#else
#define L2CAP_CHANNELS 1
#endif
extern const struct mac_driver ble_l2cap_driver;
#endif /* BLE_L2CAP_H_ */

View File

@ -84,6 +84,8 @@
#define NETSTACK_MAC csma_driver
#elif MAC_CONF_WITH_TSCH
#define NETSTACK_MAC tschmac_driver
#elif MAC_CONF_WITH_BLE
#define NETSTACK_MAC ble_l2cap_driver
#else
#error Unknown MAC configuration
#endif
@ -116,25 +118,23 @@ struct network_driver {
char *name;
/** Initialize the network driver */
void (* init)(void);
void (*init)(void);
/** Callback for getting notified of incoming packet in packetbuf. */
void (* input)(void);
void (*input)(void);
/** Output funtion, sends from uipbuf. */
uint8_t (* output)(const linkaddr_t *localdest);
uint8_t (*output)(const linkaddr_t *localdest);
};
extern const struct routing_driver NETSTACK_ROUTING;
extern const struct network_driver NETSTACK_NETWORK;
extern const struct mac_driver NETSTACK_MAC;
extern const struct radio_driver NETSTACK_RADIO;
extern const struct framer NETSTACK_FRAMER;
extern const struct mac_driver NETSTACK_MAC;
extern const struct radio_driver NETSTACK_RADIO;
extern const struct framer NETSTACK_FRAMER;
void netstack_init(void);
/* Netstack ip_packet_processor - for implementing packet filters, firewalls,
debuggin info, etc */
@ -150,8 +150,8 @@ enum netstack_ip_callback_type {
struct netstack_ip_packet_processor {
struct netstack_ip_packet_processor *next;
enum netstack_ip_action (* process_input)(void);
enum netstack_ip_action (* process_output)(const linkaddr_t *localdest);
enum netstack_ip_action (*process_input)(void);
enum netstack_ip_action (*process_output)(const linkaddr_t * localdest);
};
/* This function is intended for the IP stack to call whenever input/output
@ -161,18 +161,16 @@ enum netstack_ip_action netstack_process_ip_callback(uint8_t type, const linkadd
void netstack_ip_packet_processor_add(struct netstack_ip_packet_processor *p);
void netstack_ip_packet_processor_remove(struct netstack_ip_packet_processor *p);
/* Netstack sniffer - this will soon be deprecated... */
struct netstack_sniffer {
struct netstack_sniffer *next;
void (* input_callback)(void);
void (* output_callback)(int mac_status);
void (*input_callback)(void);
void (*output_callback)(int mac_status);
};
#define NETSTACK_SNIFFER(name, input_callback, output_callback) \
static struct netstack_sniffer name = { NULL, input_callback, output_callback }
static struct netstack_sniffer name = { NULL, input_callback, output_callback }
void netstack_sniffer_add(struct netstack_sniffer *s);
void netstack_sniffer_remove(struct netstack_sniffer *s);

View File

@ -29,6 +29,7 @@ dev/leds/srf06-cc26xx:BOARD=launchpad/cc1310 \
dev/leds/srf06-cc26xx:BOARD=launchpad/cc1350 \
dev/leds/srf06-cc26xx:BOARD=launchpad/cc2650 \
6tisch/etsi-plugtest-2017/srf06-cc26xx:BOARD=launchpad/cc2650 \
ble/ipv6-client/srf06-cc26xx:BOARD=launchpad/cc2650 \
storage/cfs-coffee/cc2538dk \
sensniff/cc2538dk \
rpl-udp/cc2538dk \