nes-proj/arch/cpu/cc26x0-cc13x0/rf-core/ble-cc2650.c

281 lines
9.3 KiB
C

/*
* 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 <stdint.h>
#include <string.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,
};
/*---------------------------------------------------------------------------*/