Merge pull request #198 from JF002/update-nimble-1_3-master

Update to nimble 1.3 master branch
This commit is contained in:
JF002 2021-02-04 17:34:28 +01:00 committed by GitHub
commit 6259b81628
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
286 changed files with 31459 additions and 9391 deletions

View file

@ -1,3 +1,4 @@
#include <nrf_log.h>
#include "BatteryInformationService.h"
#include "components/battery/BatteryController.h"

View file

@ -1,5 +1,6 @@
#include "CurrentTimeClient.h"
#include <hal/nrf_rtc.h>
#include <nrf_log.h>
#include "components/datetime/DateTimeController.h"
using namespace Pinetime::Controllers;

View file

@ -1,5 +1,6 @@
#include "CurrentTimeService.h"
#include <hal/nrf_rtc.h>
#include <nrf_log.h>
using namespace Pinetime::Controllers;

View file

@ -14,8 +14,8 @@ HeartRateTask::HeartRateTask(Drivers::Hrs3300 &heartRateSensor, Controllers::Hea
}
void HeartRateTask::Start() {
if (pdPASS != xTaskCreate(HeartRateTask::Process, "Heartrate", 500, this, 0, &taskHandle))
APP_ERROR_HANDLER(NRF_ERROR_NO_MEM);
//if (pdPASS != xTaskCreate(HeartRateTask::Process, "Heartrate", 500, this, 0, &taskHandle))
// APP_ERROR_HANDLER(NRF_ERROR_NO_MEM);
}
void HeartRateTask::Process(void *instance) {

View file

@ -0,0 +1,54 @@
<!--
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
-->
# Sample applications
## advertiser
This is the simplest example of advertising. Application sets NRPA, configures
advertisement parameters: general discoverable and not connectable and fills
advertisement fields. Transmited data contains only flags, tx power level and
device name, which fits in 31B limit of single package. With this data set,
device advertises for 10 seconds, terminates advertisement and repeats process
again infinitely.
## scanner
This application shows how to perform simple scan. Device performs discovery
procedure, during which receives advertising reports (if any devices are
advertising nearby). These reports are being parsed and results are printed to
serial port. Applicaton starts new discovery every second.
## peripheral
Peripheral application is based on advertiser, but has added capability of
connecting with other devices. As peripheral, device doesn't initiate any
connection by itself; instead, advertises infinitely and accepts any connection
request it receives. Because we cannot use any 16 or 32 bit UUIDs, as these are
reserved by Bluetooth SIG, we are forced to use 128-bit one. Including such
long UUID in advertising data consumes large part of available payload, so this
data is split in advertising data and response data.
## central
This application works in pair with peripheral. It's based on scanner
application - the difference is, that if there was detected device with UUID
fitting to the one predefined in central application, connection is initiated.

View file

@ -42,26 +42,6 @@ static int recent_test_id = STANDARD_TEST_ID;
static bool has_reg_fault = true;
static struct bt_mesh_cfg_srv cfg_srv = {
.relay = BT_MESH_RELAY_DISABLED,
.beacon = BT_MESH_BEACON_ENABLED,
#if MYNEWT_VAL(BLE_MESH_FRIEND)
.frnd = BT_MESH_FRIEND_ENABLED,
#else
.gatt_proxy = BT_MESH_GATT_PROXY_NOT_SUPPORTED,
#endif
#if MYNEWT_VAL(BLE_MESH_GATT_PROXY)
.gatt_proxy = BT_MESH_GATT_PROXY_ENABLED,
#else
.gatt_proxy = BT_MESH_GATT_PROXY_NOT_SUPPORTED,
#endif
.default_ttl = 7,
/* 3 transmissions with 20ms interval */
.net_transmit = BT_MESH_TRANSMIT(2, 20),
.relay_retransmit = BT_MESH_TRANSMIT(2, 20),
};
static int
fault_get_cur(struct bt_mesh_model *model,
uint8_t *test_id,
@ -327,7 +307,7 @@ static const struct bt_mesh_model_op gen_level_op[] = {
};
static struct bt_mesh_model root_models[] = {
BT_MESH_MODEL_CFG_SRV(&cfg_srv),
BT_MESH_MODEL_CFG_SRV,
BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub),
BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_ONOFF_SRV, gen_onoff_op,
&gen_onoff_pub, NULL),
@ -385,7 +365,7 @@ static int output_number(bt_mesh_output_action_t action, uint32_t number)
return 0;
}
static void prov_complete(u16_t net_idx, u16_t addr)
static void prov_complete(uint16_t net_idx, uint16_t addr)
{
console_printf("Local node provisioned, primary address 0x%04x\n", addr);
}

View file

@ -48,10 +48,10 @@ static uint16_t top_val;
static uint32_t neopixel[WS2812_NUM_LED];
#endif
static u8_t gen_onoff_state;
static s16_t gen_level_state;
static uint8_t gen_onoff_state;
static int16_t gen_level_state;
static void light_set_lightness(u8_t percentage)
static void light_set_lightness(uint8_t percentage)
{
#if (!MYNEWT_VAL(USE_NEOPIXEL))
int rc;
@ -76,10 +76,10 @@ static void light_set_lightness(u8_t percentage)
#endif
#else
int i;
u32_t lightness;
u8_t max_lightness = 0x1f;
uint32_t lightness;
uint8_t max_lightness = 0x1f;
lightness = (u8_t) (percentage * max_lightness / 100);
lightness = (uint8_t) (percentage * max_lightness / 100);
for (i = 0; i < WS2812_NUM_LED; i++) {
neopixel[i] = (lightness | lightness << 8 | lightness << 16);
@ -90,7 +90,7 @@ static void light_set_lightness(u8_t percentage)
static void update_light_state(void)
{
u16_t level = (u16_t)gen_level_state;
uint16_t level = (uint16_t)gen_level_state;
int percent = 100 * level / 0xffff;
if (gen_onoff_state == 0) {
@ -99,44 +99,44 @@ static void update_light_state(void)
light_set_lightness((uint8_t) percent);
}
int light_model_gen_onoff_get(struct bt_mesh_model *model, u8_t *state)
int light_model_gen_onoff_get(struct bt_mesh_model *model, uint8_t *state)
{
*state = gen_onoff_state;
return 0;
}
int light_model_gen_onoff_set(struct bt_mesh_model *model, u8_t state)
int light_model_gen_onoff_set(struct bt_mesh_model *model, uint8_t state)
{
gen_onoff_state = state;
update_light_state();
return 0;
}
int light_model_gen_level_get(struct bt_mesh_model *model, s16_t *level)
int light_model_gen_level_get(struct bt_mesh_model *model, int16_t *level)
{
*level = gen_level_state;
return 0;
}
int light_model_gen_level_set(struct bt_mesh_model *model, s16_t level)
int light_model_gen_level_set(struct bt_mesh_model *model, int16_t level)
{
gen_level_state = level;
if ((u16_t)gen_level_state > 0x0000) {
if ((uint16_t)gen_level_state > 0x0000) {
gen_onoff_state = 1;
}
if ((u16_t)gen_level_state == 0x0000) {
if ((uint16_t)gen_level_state == 0x0000) {
gen_onoff_state = 0;
}
update_light_state();
return 0;
}
int light_model_light_lightness_get(struct bt_mesh_model *model, s16_t *lightness)
int light_model_light_lightness_get(struct bt_mesh_model *model, int16_t *lightness)
{
return light_model_gen_level_get(model, lightness);
}
int light_model_light_lightness_set(struct bt_mesh_model *model, s16_t lightness)
int light_model_light_lightness_set(struct bt_mesh_model *model, int16_t lightness)
{
return light_model_gen_level_set(model, lightness);
}

View file

@ -26,12 +26,12 @@
#include "syscfg/syscfg.h"
#include "mesh/mesh.h"
int light_model_gen_onoff_get(struct bt_mesh_model *model, u8_t *state);
int light_model_gen_onoff_set(struct bt_mesh_model *model, u8_t state);
int light_model_gen_level_get(struct bt_mesh_model *model, s16_t *level);
int light_model_gen_level_set(struct bt_mesh_model *model, s16_t level);
int light_model_light_lightness_get(struct bt_mesh_model *model, s16_t *lightness);
int light_model_light_lightness_set(struct bt_mesh_model *model, s16_t lightness);
int light_model_gen_onoff_get(struct bt_mesh_model *model, uint8_t *state);
int light_model_gen_onoff_set(struct bt_mesh_model *model, uint8_t state);
int light_model_gen_level_get(struct bt_mesh_model *model, int16_t *level);
int light_model_gen_level_set(struct bt_mesh_model *model, int16_t level);
int light_model_light_lightness_get(struct bt_mesh_model *model, int16_t *lightness);
int light_model_light_lightness_set(struct bt_mesh_model *model, int16_t lightness);
int light_model_init(void);
#endif

View file

@ -31,8 +31,8 @@
#include "light_model.h"
static void model_bound_cb(u16_t addr, struct bt_mesh_model *model,
u16_t key_idx)
static void model_bound_cb(uint16_t addr, struct bt_mesh_model *model,
uint16_t key_idx)
{
int rc;

View file

@ -84,30 +84,6 @@ static void gen_onoff_status(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf);
/*
* Server Configuration Declaration
*/
static struct bt_mesh_cfg_srv cfg_srv = {
.relay = BT_MESH_RELAY_DISABLED,
.beacon = BT_MESH_BEACON_ENABLED,
#if defined(CONFIG_BT_MESH_FRIEND)
.frnd = BT_MESH_FRIEND_ENABLED,
#else
.frnd = BT_MESH_FRIEND_NOT_SUPPORTED,
#endif
#if defined(CONFIG_BT_MESH_GATT_PROXY)
.gatt_proxy = BT_MESH_GATT_PROXY_ENABLED,
#else
.gatt_proxy = BT_MESH_GATT_PROXY_NOT_SUPPORTED,
#endif
.default_ttl = 7,
/* 3 transmissions with 20ms interval */
.net_transmit = BT_MESH_TRANSMIT(2, 20),
.relay_retransmit = BT_MESH_TRANSMIT(2, 20),
};
/*
* Client Configuration Declaration
*/
@ -213,9 +189,9 @@ static const struct bt_mesh_model_op gen_onoff_cli_op[] = {
};
struct onoff_state {
u8_t current;
u8_t previous;
u8_t led_gpio_pin;
uint8_t current;
uint8_t previous;
uint8_t led_gpio_pin;
};
/*
@ -238,7 +214,7 @@ static struct onoff_state onoff_state_arr[] = {
*/
static struct bt_mesh_model root_models[] = {
BT_MESH_MODEL_CFG_SRV(&cfg_srv),
BT_MESH_MODEL_CFG_SRV,
BT_MESH_MODEL_CFG_CLI(&cfg_cli),
BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub),
BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_ONOFF_SRV, gen_onoff_srv_op,
@ -320,20 +296,20 @@ static const struct bt_mesh_comp comp = {
};
struct sw {
u8_t sw_num;
u8_t onoff_state;
uint8_t sw_num;
uint8_t onoff_state;
struct os_callout button_work;
struct os_callout button_timer;
};
static u8_t button_press_cnt;
static uint8_t button_press_cnt;
static struct sw sw;
static u8_t trans_id;
static u32_t time, last_time;
static u16_t primary_addr;
static u16_t primary_net_idx;
static uint8_t trans_id;
static uint32_t time, last_time;
static uint16_t primary_addr;
static uint16_t primary_net_idx;
/*
* Generic OnOff Model Server Message Handlers
@ -416,7 +392,7 @@ static void gen_onoff_status(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
u8_t state;
uint8_t state;
state = net_buf_simple_pull_u8(buf);
@ -424,7 +400,7 @@ static void gen_onoff_status(struct bt_mesh_model *model,
bt_mesh_model_elem(model)->addr, ctx->addr, state);
}
static int output_number(bt_mesh_output_action_t action, u32_t number)
static int output_number(bt_mesh_output_action_t action, uint32_t number)
{
BT_INFO("OOB Number %u", number);
return 0;
@ -436,7 +412,7 @@ static int output_string(const char *str)
return 0;
}
static void prov_complete(u16_t net_idx, u16_t addr)
static void prov_complete(uint16_t net_idx, uint16_t addr)
{
BT_INFO("provisioning complete for net_idx 0x%04x addr 0x%04x",
net_idx, addr);
@ -449,7 +425,7 @@ static void prov_reset(void)
bt_mesh_prov_enable(BT_MESH_PROV_ADV | BT_MESH_PROV_GATT);
}
static u8_t dev_uuid[16] = MYNEWT_VAL(BLE_MESH_DEV_UUID);
static uint8_t dev_uuid[16] = MYNEWT_VAL(BLE_MESH_DEV_UUID);
#define BUTTON_DEBOUNCE_DELAY_MS 250
@ -528,7 +504,7 @@ static void button_pressed_worker(struct os_event *work)
struct bt_mesh_model *mod_cli, *mod_srv;
struct bt_mesh_model_pub *pub_cli, *pub_srv;
struct sw *sw = work->ev_arg;
u8_t sw_idx = sw->sw_num;
uint8_t sw_idx = sw->sw_num;
int err;
mod_cli = mod_cli_sw[sw_idx];
@ -599,7 +575,7 @@ static const struct bt_mesh_prov prov = {
.reset = prov_reset,
};
void init_led(u8_t dev)
void init_led(uint8_t dev)
{
hal_gpio_init_out(onoff_state_arr[dev].led_gpio_pin, 1);
}

View file

@ -34,7 +34,7 @@
#ifdef OOB_AUTH_ENABLE
static int output_number(bt_mesh_output_action_t action, u32_t number)
static int output_number(bt_mesh_output_action_t action, uint32_t number)
{
printk("OOB Number: %lu\n", number);
return 0;
@ -48,7 +48,7 @@ static int output_string(const char *str)
#endif
static void prov_complete(u16_t net_idx, u16_t addr)
static void prov_complete(uint16_t net_idx, uint16_t addr)
{
printk("Local node provisioned, primary address 0x%04x\n", addr);
}
@ -58,7 +58,7 @@ static void prov_reset(void)
bt_mesh_prov_enable(BT_MESH_PROV_ADV | BT_MESH_PROV_GATT);
}
static u8_t dev_uuid[16] = MYNEWT_VAL(BLE_MESH_DEV_UUID);
static uint8_t dev_uuid[16] = MYNEWT_VAL(BLE_MESH_DEV_UUID);
static const struct bt_mesh_prov prov = {
.uuid = dev_uuid,

View file

@ -36,31 +36,6 @@
#include "state_binding.h"
#include "transition.h"
static struct bt_mesh_cfg_srv cfg_srv = {
.relay = BT_MESH_RELAY_ENABLED,
.beacon = BT_MESH_BEACON_ENABLED,
#if defined(CONFIG_BT_MESH_FRIEND)
.frnd = BT_MESH_FRIEND_ENABLED,
#else
.frnd = BT_MESH_FRIEND_NOT_SUPPORTED,
#endif
#if defined(CONFIG_BT_MESH_GATT_PROXY)
.gatt_proxy = BT_MESH_GATT_PROXY_ENABLED,
#else
.gatt_proxy = BT_MESH_GATT_PROXY_NOT_SUPPORTED,
#endif
.default_ttl = 7,
/* 2 transmissions with 20ms interval */
.net_transmit = BT_MESH_TRANSMIT(2, 20),
/* 3 transmissions with 20ms interval */
.relay_retransmit = BT_MESH_TRANSMIT(3, 20),
};
static struct bt_mesh_health_srv health_srv = {
};
@ -224,8 +199,8 @@ static void gen_onoff_set_unack(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
u8_t tid, onoff, tt, delay;
s64_t now;
uint8_t tid, onoff, tt, delay;
int64_t now;
struct generic_onoff_state *state = model->user_data;
onoff = net_buf_simple_pull_u8(buf);
@ -290,8 +265,8 @@ static void gen_onoff_set(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
u8_t tid, onoff, tt, delay;
s64_t now;
uint8_t tid, onoff, tt, delay;
int64_t now;
struct generic_onoff_state *state = model->user_data;
onoff = net_buf_simple_pull_u8(buf);
@ -422,12 +397,12 @@ static void gen_level_set_unack(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
u8_t tid, tt, delay;
s16_t level;
s64_t now;
uint8_t tid, tt, delay;
int16_t level;
int64_t now;
struct generic_level_state *state = model->user_data;
level = (s16_t) net_buf_simple_pull_le16(buf);
level = (int16_t) net_buf_simple_pull_le16(buf);
tid = net_buf_simple_pull_u8(buf);
now = k_uptime_get();
@ -494,12 +469,12 @@ static void gen_level_set(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
u8_t tid, tt, delay;
s16_t level;
s64_t now;
uint8_t tid, tt, delay;
int16_t level;
int64_t now;
struct generic_level_state *state = model->user_data;
level = (s16_t) net_buf_simple_pull_le16(buf);
level = (int16_t) net_buf_simple_pull_le16(buf);
tid = net_buf_simple_pull_u8(buf);
now = k_uptime_get();
@ -569,12 +544,12 @@ static void gen_delta_set_unack(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
u8_t tid, tt, delay;
s32_t tmp32, delta;
s64_t now;
uint8_t tid, tt, delay;
int32_t tmp32, delta;
int64_t now;
struct generic_level_state *state = model->user_data;
delta = (s32_t) net_buf_simple_pull_le32(buf);
delta = (int32_t) net_buf_simple_pull_le32(buf);
tid = net_buf_simple_pull_u8(buf);
now = k_uptime_get();
@ -658,12 +633,12 @@ static void gen_delta_set(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
u8_t tid, tt, delay;
s32_t tmp32, delta;
s64_t now;
uint8_t tid, tt, delay;
int32_t tmp32, delta;
int64_t now;
struct generic_level_state *state = model->user_data;
delta = (s32_t) net_buf_simple_pull_le32(buf);
delta = (int32_t) net_buf_simple_pull_le32(buf);
tid = net_buf_simple_pull_u8(buf);
now = k_uptime_get();
@ -805,13 +780,13 @@ static void gen_move_set_unack(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
u8_t tid, tt, delay;
s16_t delta;
s32_t tmp32;
s64_t now;
uint8_t tid, tt, delay;
int16_t delta;
int32_t tmp32;
int64_t now;
struct generic_level_state *state = model->user_data;
delta = (s16_t) net_buf_simple_pull_le16(buf);
delta = (int16_t) net_buf_simple_pull_le16(buf);
tid = net_buf_simple_pull_u8(buf);
now = k_uptime_get();
@ -886,13 +861,13 @@ static void gen_move_set(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
u8_t tid, tt, delay;
s16_t delta;
s32_t tmp32;
s64_t now;
uint8_t tid, tt, delay;
int16_t delta;
int32_t tmp32;
int64_t now;
struct generic_level_state *state = model->user_data;
delta = (s16_t) net_buf_simple_pull_le16(buf);
delta = (int16_t) net_buf_simple_pull_le16(buf);
tid = net_buf_simple_pull_u8(buf);
now = k_uptime_get();
@ -1021,7 +996,7 @@ static bool gen_def_trans_time_setunack(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
u8_t tt;
uint8_t tt;
struct gen_def_trans_time_state *state = model->user_data;
tt = net_buf_simple_pull_u8(buf);
@ -1122,7 +1097,7 @@ static bool gen_onpowerup_setunack(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
u8_t onpowerup;
uint8_t onpowerup;
struct generic_onpowerup_state *state = model->user_data;
onpowerup = net_buf_simple_pull_u8(buf);
@ -1187,9 +1162,9 @@ static void vnd_set_unack(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
u8_t tid;
uint8_t tid;
int current;
s64_t now;
int64_t now;
struct vendor_state *state = model->user_data;
current = net_buf_simple_pull_le16(buf);
@ -1290,9 +1265,9 @@ static void light_lightness_set_unack(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
u8_t tid, tt, delay;
u16_t actual;
s64_t now;
uint8_t tid, tt, delay;
uint16_t actual;
int64_t now;
struct light_lightness_state *state = model->user_data;
actual = net_buf_simple_pull_le16(buf);
@ -1360,9 +1335,9 @@ static void light_lightness_set(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
u8_t tid, tt, delay;
u16_t actual;
s64_t now;
uint8_t tid, tt, delay;
uint16_t actual;
int64_t now;
struct light_lightness_state *state = model->user_data;
actual = net_buf_simple_pull_le16(buf);
@ -1483,9 +1458,9 @@ static void light_lightness_linear_set_unack(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
u8_t tid, tt, delay;
u16_t linear;
s64_t now;
uint8_t tid, tt, delay;
uint16_t linear;
int64_t now;
struct light_lightness_state *state = model->user_data;
linear = net_buf_simple_pull_le16(buf);
@ -1546,9 +1521,9 @@ static void light_lightness_linear_set(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
u8_t tid, tt, delay;
u16_t linear;
s64_t now;
uint8_t tid, tt, delay;
uint16_t linear;
int64_t now;
struct light_lightness_state *state = model->user_data;
linear = net_buf_simple_pull_le16(buf);
@ -1690,7 +1665,7 @@ static void light_lightness_default_set_unack(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
u16_t lightness;
uint16_t lightness;
struct light_lightness_state *state = model->user_data;
lightness = net_buf_simple_pull_le16(buf);
@ -1741,7 +1716,7 @@ static bool light_lightness_range_setunack(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
u16_t min, max;
uint16_t min, max;
struct light_lightness_state *state = model->user_data;
min = net_buf_simple_pull_le16(buf);
@ -1908,15 +1883,15 @@ static void light_ctl_set_unack(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
u8_t tid, tt, delay;
s16_t delta_uv;
u16_t lightness, temp;
s64_t now;
uint8_t tid, tt, delay;
int16_t delta_uv;
uint16_t lightness, temp;
int64_t now;
struct light_ctl_state *state = model->user_data;
lightness = net_buf_simple_pull_le16(buf);
temp = net_buf_simple_pull_le16(buf);
delta_uv = (s16_t) net_buf_simple_pull_le16(buf);
delta_uv = (int16_t) net_buf_simple_pull_le16(buf);
tid = net_buf_simple_pull_u8(buf);
if (temp < TEMP_MIN || temp > TEMP_MAX) {
@ -1991,15 +1966,15 @@ static void light_ctl_set(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
u8_t tid, tt, delay;
s16_t delta_uv;
u16_t lightness, temp;
s64_t now;
uint8_t tid, tt, delay;
int16_t delta_uv;
uint16_t lightness, temp;
int64_t now;
struct light_ctl_state *state = model->user_data;
lightness = net_buf_simple_pull_le16(buf);
temp = net_buf_simple_pull_le16(buf);
delta_uv = (s16_t) net_buf_simple_pull_le16(buf);
delta_uv = (int16_t) net_buf_simple_pull_le16(buf);
tid = net_buf_simple_pull_u8(buf);
if (temp < TEMP_MIN || temp > TEMP_MAX) {
@ -2140,13 +2115,13 @@ static bool light_ctl_default_setunack(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
u16_t lightness, temp;
s16_t delta_uv;
uint16_t lightness, temp;
int16_t delta_uv;
struct light_ctl_state *state = model->user_data;
lightness = net_buf_simple_pull_le16(buf);
temp = net_buf_simple_pull_le16(buf);
delta_uv = (s16_t) net_buf_simple_pull_le16(buf);
delta_uv = (int16_t) net_buf_simple_pull_le16(buf);
/* Here, Model specification is silent about tid implementation */
@ -2216,7 +2191,7 @@ static bool light_ctl_temp_range_setunack(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
u16_t min, max;
uint16_t min, max;
struct light_ctl_state *state = model->user_data;
min = net_buf_simple_pull_le16(buf);
@ -2384,14 +2359,14 @@ static void light_ctl_temp_set_unack(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
u8_t tid, tt, delay;
s16_t delta_uv;
u16_t temp;
s64_t now;
uint8_t tid, tt, delay;
int16_t delta_uv;
uint16_t temp;
int64_t now;
struct light_ctl_state *state = model->user_data;
temp = net_buf_simple_pull_le16(buf);
delta_uv = (s16_t) net_buf_simple_pull_le16(buf);
delta_uv = (int16_t) net_buf_simple_pull_le16(buf);
tid = net_buf_simple_pull_u8(buf);
if (temp < TEMP_MIN || temp > TEMP_MAX) {
@ -2463,14 +2438,14 @@ static void light_ctl_temp_set(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
u8_t tid, tt, delay;
s16_t delta_uv;
u16_t temp;
s64_t now;
uint8_t tid, tt, delay;
int16_t delta_uv;
uint16_t temp;
int64_t now;
struct light_ctl_state *state = model->user_data;
temp = net_buf_simple_pull_le16(buf);
delta_uv = (s16_t) net_buf_simple_pull_le16(buf);
delta_uv = (int16_t) net_buf_simple_pull_le16(buf);
tid = net_buf_simple_pull_u8(buf);
if (temp < TEMP_MIN || temp > TEMP_MAX) {
@ -2689,7 +2664,7 @@ static const struct bt_mesh_model_op vnd_ops[] = {
};
struct bt_mesh_model root_models[] = {
BT_MESH_MODEL_CFG_SRV(&cfg_srv),
BT_MESH_MODEL_CFG_SRV,
BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub),
BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_ONOFF_SRV,

View file

@ -46,109 +46,109 @@
#define CANNOT_SET_RANGE_MAX 0x02
struct generic_onoff_state {
u8_t onoff;
u8_t target_onoff;
uint8_t onoff;
uint8_t target_onoff;
u8_t last_tid;
u16_t last_src_addr;
u16_t last_dst_addr;
s64_t last_msg_timestamp;
uint8_t last_tid;
uint16_t last_src_addr;
uint16_t last_dst_addr;
int64_t last_msg_timestamp;
s32_t tt_delta;
int32_t tt_delta;
struct transition *transition;
};
struct generic_level_state {
s16_t level;
s16_t target_level;
int16_t level;
int16_t target_level;
s16_t last_level;
s32_t last_delta;
int16_t last_level;
int32_t last_delta;
u8_t last_tid;
u16_t last_src_addr;
u16_t last_dst_addr;
s64_t last_msg_timestamp;
uint8_t last_tid;
uint16_t last_src_addr;
uint16_t last_dst_addr;
int64_t last_msg_timestamp;
s32_t tt_delta;
int32_t tt_delta;
struct transition *transition;
};
struct generic_onpowerup_state {
u8_t onpowerup;
uint8_t onpowerup;
};
struct gen_def_trans_time_state {
u8_t tt;
uint8_t tt;
};
struct vendor_state {
int current;
u32_t response;
u8_t last_tid;
u16_t last_src_addr;
u16_t last_dst_addr;
s64_t last_msg_timestamp;
uint32_t response;
uint8_t last_tid;
uint16_t last_src_addr;
uint16_t last_dst_addr;
int64_t last_msg_timestamp;
};
struct light_lightness_state {
u16_t linear;
u16_t target_linear;
uint16_t linear;
uint16_t target_linear;
u16_t actual;
u16_t target_actual;
uint16_t actual;
uint16_t target_actual;
u16_t last;
u16_t def;
uint16_t last;
uint16_t def;
u8_t status_code;
u16_t light_range_min;
u16_t light_range_max;
u32_t lightness_range;
uint8_t status_code;
uint16_t light_range_min;
uint16_t light_range_max;
uint32_t lightness_range;
u8_t last_tid;
u16_t last_src_addr;
u16_t last_dst_addr;
s64_t last_msg_timestamp;
uint8_t last_tid;
uint16_t last_src_addr;
uint16_t last_dst_addr;
int64_t last_msg_timestamp;
s32_t tt_delta_actual;
s32_t tt_delta_linear;
int32_t tt_delta_actual;
int32_t tt_delta_linear;
struct transition *transition;
};
struct light_ctl_state {
u16_t lightness;
u16_t target_lightness;
uint16_t lightness;
uint16_t target_lightness;
u16_t temp;
u16_t target_temp;
uint16_t temp;
uint16_t target_temp;
s16_t delta_uv;
s16_t target_delta_uv;
int16_t delta_uv;
int16_t target_delta_uv;
u8_t status_code;
u16_t temp_range_min;
u16_t temp_range_max;
u32_t temperature_range;
uint8_t status_code;
uint16_t temp_range_min;
uint16_t temp_range_max;
uint32_t temperature_range;
u16_t lightness_def;
u16_t temp_def;
u32_t lightness_temp_def;
s16_t delta_uv_def;
uint16_t lightness_def;
uint16_t temp_def;
uint32_t lightness_temp_def;
int16_t delta_uv_def;
u32_t lightness_temp_last;
uint32_t lightness_temp_last;
u8_t last_tid;
u16_t last_src_addr;
u16_t last_dst_addr;
s64_t last_msg_timestamp;
uint8_t last_tid;
uint16_t last_src_addr;
uint16_t last_dst_addr;
int64_t last_msg_timestamp;
s32_t tt_delta_lightness;
s32_t tt_delta_temp;
s32_t tt_delta_duv;
int32_t tt_delta_lightness;
int32_t tt_delta_temp;
int32_t tt_delta_duv;
struct transition *transition;
};

View file

@ -59,14 +59,14 @@ static void light_default_var_init(void)
light_ctl_srv_user_data.temp_def = TEMP_MIN;
light_ctl_srv_user_data.lightness_temp_last =
(u32_t) ((LIGHTNESS_MAX << 16) | TEMP_MIN);
(uint32_t) ((LIGHTNESS_MAX << 16) | TEMP_MIN);
}
static void light_default_status_init(void)
{
u16_t lightness;
uint16_t lightness;
lightness = (u16_t) (light_ctl_srv_user_data.lightness_temp_last >> 16);
lightness = (uint16_t) (light_ctl_srv_user_data.lightness_temp_last >> 16);
if (lightness) {
gen_onoff_srv_root_user_data.onoff = STATE_ON;
@ -77,10 +77,10 @@ static void light_default_status_init(void)
/* Retrieve Default Lightness & Temperature Values */
if (light_ctl_srv_user_data.lightness_temp_def) {
light_ctl_srv_user_data.lightness_def = (u16_t)
light_ctl_srv_user_data.lightness_def = (uint16_t)
(light_ctl_srv_user_data.lightness_temp_def >> 16);
light_ctl_srv_user_data.temp_def = (u16_t)
light_ctl_srv_user_data.temp_def = (uint16_t)
(light_ctl_srv_user_data.lightness_temp_def);
}
@ -92,18 +92,18 @@ static void light_default_status_init(void)
/* Retrieve Range of Lightness & Temperature */
if (light_lightness_srv_user_data.lightness_range) {
light_lightness_srv_user_data.light_range_max = (u16_t)
light_lightness_srv_user_data.light_range_max = (uint16_t)
(light_lightness_srv_user_data.lightness_range >> 16);
light_lightness_srv_user_data.light_range_min = (u16_t)
light_lightness_srv_user_data.light_range_min = (uint16_t)
(light_lightness_srv_user_data.lightness_range);
}
if (light_ctl_srv_user_data.temperature_range) {
light_ctl_srv_user_data.temp_range_max = (u16_t)
light_ctl_srv_user_data.temp_range_max = (uint16_t)
(light_ctl_srv_user_data.temperature_range >> 16);
light_ctl_srv_user_data.temp_range_min = (u16_t)
light_ctl_srv_user_data.temp_range_min = (uint16_t)
(light_ctl_srv_user_data.temperature_range);
}
@ -117,11 +117,11 @@ static void light_default_status_init(void)
state_binding(ONOFF, ONOFF_TEMP);
break;
case STATE_RESTORE:
light_lightness_srv_user_data.last = (u16_t)
light_lightness_srv_user_data.last = (uint16_t)
(light_ctl_srv_user_data.lightness_temp_last >> 16);
light_ctl_srv_user_data.temp =
(u16_t) (light_ctl_srv_user_data.lightness_temp_last);
(uint16_t) (light_ctl_srv_user_data.lightness_temp_last);
state_binding(ONPOWERUP, ONOFF_TEMP);
break;
@ -132,7 +132,7 @@ static void light_default_status_init(void)
void update_light_state(void)
{
u8_t power, color;
uint8_t power, color;
power = 100 * ((float) lightness / 65535);
color = 100 * ((float) (temperature + 32768) / 65535);

View file

@ -41,12 +41,12 @@
static bool is_randomization_of_TIDs_done;
#if (defined(ONOFF) || defined(ONOFF_TT))
static u8_t tid_onoff;
static uint8_t tid_onoff;
#elif defined(VND_MODEL_TEST)
static u8_t tid_vnd;
static uint8_t tid_vnd;
#endif
static u8_t tid_level;
static uint8_t tid_level;
void randomize_publishers_TID(void)
{
@ -61,7 +61,7 @@ void randomize_publishers_TID(void)
is_randomization_of_TIDs_done = true;
}
static u32_t button_read(int button)
static uint32_t button_read(int button)
{
return (uint32_t) hal_gpio_read(button);
}

View file

@ -32,14 +32,14 @@
#include "transition.h"
u16_t lightness, target_lightness;
s16_t temperature, target_temperature;
uint16_t lightness, target_lightness;
int16_t temperature, target_temperature;
static s32_t ceiling(float num)
static int32_t ceiling(float num)
{
s32_t inum;
int32_t inum;
inum = (s32_t) num;
inum = (int32_t) num;
if (num == (float) inum) {
return inum;
}
@ -47,21 +47,21 @@ static s32_t ceiling(float num)
return inum + 1;
}
u16_t actual_to_linear(u16_t val)
uint16_t actual_to_linear(uint16_t val)
{
float tmp;
tmp = ((float) val / 65535);
return (u16_t) ceiling(65535 * tmp * tmp);
return (uint16_t) ceiling(65535 * tmp * tmp);
}
u16_t linear_to_actual(u16_t val)
uint16_t linear_to_actual(uint16_t val)
{
return (u16_t) (65535 * sqrt(((float) val / 65535)));
return (uint16_t) (65535 * sqrt(((float) val / 65535)));
}
static void constrain_lightness(u16_t var)
static void constrain_lightness(uint16_t var)
{
if (var > 0 && var < light_lightness_srv_user_data.light_range_min) {
var = light_lightness_srv_user_data.light_range_min;
@ -72,7 +72,7 @@ static void constrain_lightness(u16_t var)
lightness = var;
}
static void constrain_lightness2(u16_t var)
static void constrain_lightness2(uint16_t var)
{
/* This is as per Mesh Model Specification 3.3.2.2.3 */
if (var > 0 && var < light_lightness_srv_user_data.light_range_min) {
@ -88,7 +88,7 @@ static void constrain_lightness2(u16_t var)
lightness = var;
}
static void constrain_target_lightness(u16_t var)
static void constrain_target_lightness(uint16_t var)
{
if (var > 0 &&
var < light_lightness_srv_user_data.light_range_min) {
@ -100,7 +100,7 @@ static void constrain_target_lightness(u16_t var)
target_lightness = var;
}
static s16_t light_ctl_temp_to_level(u16_t temp)
static int16_t light_ctl_temp_to_level(uint16_t temp)
{
float tmp;
@ -111,14 +111,14 @@ static s16_t light_ctl_temp_to_level(u16_t temp)
tmp = tmp / (light_ctl_srv_user_data.temp_range_max -
light_ctl_srv_user_data.temp_range_min);
return (s16_t) (tmp - 32768);
return (int16_t) (tmp - 32768);
/* 6.1.3.1.1 2nd formula end */
}
static u16_t level_to_light_ctl_temp(s16_t level)
static uint16_t level_to_light_ctl_temp(int16_t level)
{
u16_t tmp;
uint16_t tmp;
float diff;
/* Mesh Model Specification 6.1.3.1.1 1st formula start */
@ -126,14 +126,14 @@ static u16_t level_to_light_ctl_temp(s16_t level)
light_ctl_srv_user_data.temp_range_min) / 65535;
tmp = (u16_t) ((level + 32768) * diff);
tmp = (uint16_t) ((level + 32768) * diff);
return (light_ctl_srv_user_data.temp_range_min + tmp);
/* 6.1.3.1.1 1st formula end */
}
void state_binding(u8_t light, u8_t temp)
void state_binding(uint8_t light, uint8_t temp)
{
switch (temp) {
case ONOFF_TEMP:
@ -211,10 +211,10 @@ jump:
light_ctl_srv_user_data.lightness = lightness;
}
void calculate_lightness_target_values(u8_t type)
void calculate_lightness_target_values(uint8_t type)
{
bool set_light_ctl_temp_target_value;
u16_t tmp;
uint16_t tmp;
set_light_ctl_temp_target_value = true;
@ -274,7 +274,7 @@ void calculate_lightness_target_values(u8_t type)
}
}
void calculate_temp_target_values(u8_t type)
void calculate_temp_target_values(uint8_t type)
{
bool set_light_ctl_delta_uv_target_value;

View file

@ -43,11 +43,11 @@ enum state_binding {
IGNORE_TEMP
};
extern u16_t lightness, target_lightness;
extern s16_t temperature, target_temperature;
extern uint16_t lightness, target_lightness;
extern int16_t temperature, target_temperature;
void state_binding(u8_t lightness, u8_t temperature);
void calculate_lightness_target_values(u8_t type);
void calculate_temp_target_values(u8_t type);
void state_binding(uint8_t lightness, uint8_t temperature);
void calculate_lightness_target_values(uint8_t type);
void calculate_temp_target_values(uint8_t type);
#endif

View file

@ -32,8 +32,8 @@
#include "device_composition.h"
#include "storage.h"
static u8_t storage_id;
u8_t reset_counter;
static uint8_t storage_id;
uint8_t reset_counter;
static void save_reset_counter(void)
{
@ -76,7 +76,7 @@ static void save_lightness_temp_def_state(void)
char buf[12];
light_ctl_srv_user_data.lightness_temp_def =
(u32_t) ((light_ctl_srv_user_data.lightness_def << 16) |
(uint32_t) ((light_ctl_srv_user_data.lightness_def << 16) |
light_ctl_srv_user_data.temp_def);
settings_str_from_bytes(&light_ctl_srv_user_data.lightness_temp_def,
@ -91,7 +91,7 @@ static void save_lightness_temp_last_state(void)
char buf[12];
light_ctl_srv_user_data.lightness_temp_last =
(u32_t) ((light_ctl_srv_user_data.lightness << 16) |
(uint32_t) ((light_ctl_srv_user_data.lightness << 16) |
light_ctl_srv_user_data.temp);
settings_str_from_bytes(&light_ctl_srv_user_data.lightness_temp_last,
@ -108,7 +108,7 @@ static void save_lightness_range(void)
char buf[12];
light_lightness_srv_user_data.lightness_range =
(u32_t) ((light_lightness_srv_user_data.light_range_max << 16) |
(uint32_t) ((light_lightness_srv_user_data.light_range_max << 16) |
light_lightness_srv_user_data.light_range_min);
settings_str_from_bytes(&light_lightness_srv_user_data.lightness_range,
@ -123,7 +123,7 @@ static void save_temperature_range(void)
char buf[12];
light_ctl_srv_user_data.temperature_range =
(u32_t) ((light_ctl_srv_user_data.temp_range_max << 16) |
(uint32_t) ((light_ctl_srv_user_data.temp_range_max << 16) |
light_ctl_srv_user_data.temp_range_min);
settings_str_from_bytes(&light_ctl_srv_user_data.temperature_range,
@ -162,7 +162,7 @@ static void storage_work_handler(struct os_event *work)
struct os_callout storage_work;
void save_on_flash(u8_t id)
void save_on_flash(uint8_t id)
{
storage_id = id;
os_callout_reset(&storage_work, 0);

View file

@ -37,11 +37,11 @@ enum ps_variables_id {
TEMPERATURE_RANGE
};
extern u8_t reset_counter;
extern uint8_t reset_counter;
extern struct os_callout storage_work;
int ps_settings_init(void);
void save_on_flash(u8_t id);
void save_on_flash(uint8_t id);
#endif

View file

@ -40,8 +40,8 @@ struct os_callout light_ctl_temp_work;
struct os_callout dummy_timer;
u8_t transition_type, default_tt;
u32_t *ptr_counter;
uint8_t transition_type, default_tt;
uint32_t *ptr_counter;
struct os_callout *ptr_timer = &dummy_timer;
struct transition lightness_transition, temp_transition;
@ -50,9 +50,9 @@ struct transition lightness_transition, temp_transition;
void calculate_rt(struct transition *transition)
{
u8_t steps, resolution;
s32_t duration_remainder;
s64_t now;
uint8_t steps, resolution;
int32_t duration_remainder;
int64_t now;
if (transition->just_started) {
transition->rt = transition->tt;
@ -88,7 +88,7 @@ void calculate_rt(struct transition *transition)
/* Function to calculate Remaining Time (End) */
static void bound_states_transition_type_reassignment(u8_t type)
static void bound_states_transition_type_reassignment(uint8_t type)
{
switch (type) {
case ONOFF:
@ -113,7 +113,7 @@ static void bound_states_transition_type_reassignment(u8_t type)
static void tt_values_calculator(struct transition *transition)
{
u8_t steps_multiplier, resolution;
uint8_t steps_multiplier, resolution;
resolution = (transition->tt >> 6);
steps_multiplier = (transition->tt & 0x3F);
@ -142,7 +142,7 @@ static void tt_values_calculator(struct transition *transition)
ptr_counter = &transition->counter;
}
void onoff_tt_values(struct generic_onoff_state *state, u8_t tt, u8_t delay)
void onoff_tt_values(struct generic_onoff_state *state, uint8_t tt, uint8_t delay)
{
bound_states_transition_type_reassignment(ONOFF);
calculate_lightness_target_values(ONOFF);
@ -162,7 +162,7 @@ void onoff_tt_values(struct generic_onoff_state *state, u8_t tt, u8_t delay)
state->transition->counter);
}
void level_tt_values(struct generic_level_state *state, u8_t tt, u8_t delay)
void level_tt_values(struct generic_level_state *state, uint8_t tt, uint8_t delay)
{
if (state == &gen_level_srv_root_user_data) {
bound_states_transition_type_reassignment(LEVEL);
@ -188,7 +188,7 @@ void level_tt_values(struct generic_level_state *state, u8_t tt, u8_t delay)
}
void light_lightness_actual_tt_values(struct light_lightness_state *state,
u8_t tt, u8_t delay)
uint8_t tt, uint8_t delay)
{
bound_states_transition_type_reassignment(ACTUAL);
calculate_lightness_target_values(ACTUAL);
@ -210,7 +210,7 @@ void light_lightness_actual_tt_values(struct light_lightness_state *state,
}
void light_lightness_linear_tt_values(struct light_lightness_state *state,
u8_t tt, u8_t delay)
uint8_t tt, uint8_t delay)
{
bound_states_transition_type_reassignment(LINEAR);
calculate_lightness_target_values(LINEAR);
@ -231,7 +231,7 @@ void light_lightness_linear_tt_values(struct light_lightness_state *state,
state->transition->counter);
}
void light_ctl_tt_values(struct light_ctl_state *state, u8_t tt, u8_t delay)
void light_ctl_tt_values(struct light_ctl_state *state, uint8_t tt, uint8_t delay)
{
bound_states_transition_type_reassignment(CTL);
calculate_lightness_target_values(CTL);
@ -261,7 +261,7 @@ void light_ctl_tt_values(struct light_ctl_state *state, u8_t tt, u8_t delay)
}
void light_ctl_temp_tt_values(struct light_ctl_state *state,
u8_t tt, u8_t delay)
uint8_t tt, uint8_t delay)
{
bound_states_transition_type_reassignment(CTL_TEMP);
calculate_temp_target_values(CTL_TEMP);
@ -331,7 +331,7 @@ static void onoff_work_handler(struct os_event *work)
static void level_lightness_work_handler(struct os_event *work)
{
u8_t level;
uint8_t level;
struct generic_level_state *state = &gen_level_srv_root_user_data;
switch (transition_type) {

View file

@ -42,19 +42,19 @@ enum level_transition_types {
struct transition {
bool just_started;
u8_t tt;
u8_t rt;
u8_t delay;
u32_t quo_tt;
u32_t counter;
u32_t total_duration;
s64_t start_timestamp;
uint8_t tt;
uint8_t rt;
uint8_t delay;
uint32_t quo_tt;
uint32_t counter;
uint32_t total_duration;
int64_t start_timestamp;
struct os_callout timer;
};
extern u8_t transition_type, default_tt;
extern u32_t *ptr_counter;
extern uint8_t transition_type, default_tt;
extern uint32_t *ptr_counter;
extern struct os_callout *ptr_timer;
extern struct transition lightness_transition, temp_transition;
@ -64,15 +64,15 @@ extern struct os_callout dummy_timer;
void calculate_rt(struct transition *transition);
void onoff_tt_values(struct generic_onoff_state *state, u8_t tt, u8_t delay);
void level_tt_values(struct generic_level_state *state, u8_t tt, u8_t delay);
void onoff_tt_values(struct generic_onoff_state *state, uint8_t tt, uint8_t delay);
void level_tt_values(struct generic_level_state *state, uint8_t tt, uint8_t delay);
void light_lightness_actual_tt_values(struct light_lightness_state *state,
u8_t tt, u8_t delay);
uint8_t tt, uint8_t delay);
void light_lightness_linear_tt_values(struct light_lightness_state *state,
u8_t tt, u8_t delay);
void light_ctl_tt_values(struct light_ctl_state *state, u8_t tt, u8_t delay);
uint8_t tt, uint8_t delay);
void light_ctl_tt_values(struct light_ctl_state *state, uint8_t tt, uint8_t delay);
void light_ctl_temp_tt_values(struct light_ctl_state *state,
u8_t tt, u8_t delay);
uint8_t tt, uint8_t delay);
void onoff_handler(struct generic_onoff_state *state);
void level_lightness_handler(struct generic_level_state *state);

View file

@ -44,21 +44,21 @@ void net_recv_ev(uint8_t ttl, uint8_t ctl, uint16_t src, uint16_t dst,
payload_len);
}
static void model_bound_cb(u16_t addr, struct bt_mesh_model *model,
u16_t key_idx)
static void model_bound_cb(uint16_t addr, struct bt_mesh_model *model,
uint16_t key_idx)
{
console_printf("Model bound: remote addr 0x%04x key_idx 0x%04x model %p\n",
addr, key_idx, model);
}
static void model_unbound_cb(u16_t addr, struct bt_mesh_model *model,
u16_t key_idx)
static void model_unbound_cb(uint16_t addr, struct bt_mesh_model *model,
uint16_t key_idx)
{
console_printf("Model unbound: remote addr 0x%04x key_idx 0x%04x "
"model %p\n", addr, key_idx, model);
}
static void invalid_bearer_cb(u8_t opcode)
static void invalid_bearer_cb(uint8_t opcode)
{
console_printf("Invalid bearer: opcode 0x%02x\n", opcode);
}

View file

@ -837,14 +837,6 @@ rx_stress_10_l2cap_event(struct ble_l2cap_event *event, void *arg)
MODLOG_DFLT(INFO, "Data buf %s\n", data_buf ? "OK" : "NOK");
assert(data_buf != NULL);
/* The first 2 bytes of data is the size of appended pattern data. */
rc = os_mbuf_append(data_buf, (uint8_t[]) {data_len >> 8, data_len},
2);
if (rc) {
os_mbuf_free_chain(data_buf);
assert(0);
}
/* Fill mbuf with the pattern */
stress_fill_mbuf_with_pattern(data_buf, data_len);
@ -852,8 +844,13 @@ rx_stress_10_l2cap_event(struct ble_l2cap_event *event, void *arg)
rc = ble_l2cap_send(rx_stress_ctx->chan, data_buf);
MODLOG_DFLT(INFO, "Return code=%d\n", rc);
if (rc) {
if (rc == BLE_HS_ESTALLED) {
MODLOG_DFLT(INFO, "L2CAP stalled - waiting\n");
stalled = true;
} else {
MODLOG_DFLT(INFO, "Sending data via L2CAP failed with error "
"code %d\n", rc);
}
}
MODLOG_DFLT(INFO, " %d, %d\n", ++send_cnt, data_len);
@ -1365,7 +1362,7 @@ rx_stress_start(int test_num)
break;
case 10:
console_printf("Stress L2CAP send\033[0m\n");
rc = ble_l2cap_create_server(1, STRESS_COC_MTU,
rc = ble_l2cap_create_server(TEST_PSM, STRESS_COC_MTU,
rx_stress_10_l2cap_event, NULL);
assert(rc == 0);
rx_stress_simple_adv(&rx_stress_adv_sets[10]);

View file

@ -19,6 +19,8 @@
#include "stress.h"
static struct os_callout stress_timer_callout;
void
com_stress_print_report(const struct com_stress_test_ctx *test_ctxs)
{
@ -119,7 +121,7 @@ stress_fill_mbuf_with_pattern(struct os_mbuf *om, uint16_t len)
rest = len % STRESS_PAT_LEN;
for (i = 0; i < mul; ++i) {
rc = os_mbuf_append(om, &test_6_pattern[29], STRESS_PAT_LEN);
rc = os_mbuf_append(om, &test_6_pattern[0], STRESS_PAT_LEN);
if (rc) {
os_mbuf_free_chain(om);
@ -127,7 +129,7 @@ stress_fill_mbuf_with_pattern(struct os_mbuf *om, uint16_t len)
}
}
rc = os_mbuf_append(om, &test_6_pattern[29], rest);
rc = os_mbuf_append(om, &test_6_pattern[0], rest);
if (rc) {
os_mbuf_free_chain(om);
@ -176,6 +178,7 @@ void
stress_start_timer(uint32_t timeout_ms, os_event_fn *ev_cb)
{
int rc;
os_callout_stop(&stress_timer_callout);
os_callout_init(&stress_timer_callout, os_eventq_dflt_get(), ev_cb, NULL);

View file

@ -44,8 +44,9 @@ extern "C" {
#define STRESS_FIND_SRV 1
#define STRESS_FIND_CHR 2
#define STRESS_FIND_DSC 3
/* L2CAP PSM */
#define TEST_PSM 0x80
struct os_callout stress_timer_callout;
struct stress_gatt_search_ctx;
typedef void stress_gatt_disc_end_fn(struct stress_gatt_search_ctx *search_ctx);

View file

@ -1127,7 +1127,7 @@ tx_stress_10_gap_event(struct ble_gap_event *event, void *arg)
assert(sdu_rx != NULL);
tx_stress_ctx->conn_handle = event->connect.conn_handle;
rc = ble_l2cap_connect(event->connect.conn_handle, 1,
rc = ble_l2cap_connect(event->connect.conn_handle, TEST_PSM,
STRESS_COC_MTU, sdu_rx,
tx_stress_10_l2cap_event, NULL);
assert(rc == 0);
@ -1292,17 +1292,16 @@ tx_stress_14_subs_cb(uint16_t conn_handle, const struct ble_gatt_error *error,
assert(error->status == 0);
/* If the first subscription after finding cccd */
if(arg == NULL) {
if (arg == NULL) {
return 0;
}
sub = (bool*)arg;
sub = (bool *)arg;
/* Enable notifications */
if(*sub == 0) {
if (*sub == 0) {
*sub = true;
om = ble_hs_mbuf_from_flat(
(uint8_t[]) {0x01, 0x00}, 2);
om = ble_hs_mbuf_from_flat((uint8_t[]) {0x01, 0x00}, 2);
tx_stress_ctx->begin_us = tx_stress_ctx->end_us;
@ -1464,7 +1463,7 @@ tx_stress_15_gap_event(struct ble_gap_event *event, void *arg)
case BLE_GAP_EVENT_DISCONNECT:
/* Perform use case specified number of times */
if(tx_stress_ctx->con_stat[15].num >= MYNEWT_VAL(BLE_STRESS_REPEAT)) {
if (tx_stress_ctx->con_stat[15].num >= MYNEWT_VAL(BLE_STRESS_REPEAT)) {
tx_stress_on_test_finish(15);
return 0;
}
@ -1607,7 +1606,8 @@ tx_stress_test_perform(int test_num)
}
static void
tx_stress_read_command_cb(void) {
tx_stress_read_command_cb(void)
{
console_printf("Start testing\n");
os_sem_release(&tx_stress_main_sem);
}
@ -1642,7 +1642,7 @@ tx_stress_main_task_fn(void *arg)
/* Wait for the scan to find the test. Then 1 token will be
* released allowing to pass through semaphore. */
os_sem_pend(&tx_stress_main_sem, OS_TIMEOUT_NEVER);
if(tx_stress_ctx->scan_timeout) {
if (tx_stress_ctx->scan_timeout) {
break;
}

View file

@ -2691,15 +2691,28 @@ cmd_security_unpair(int argc, char **argv)
{
ble_addr_t peer;
int rc;
int oldest;
rc = parse_arg_all(argc - 1, argv + 1);
if (rc != 0) {
return rc;
}
rc = parse_arg_bool_dflt("oldest", 0, &oldest);
if (rc != 0) {
console_printf("invalid 'oldest' parameter\n");
return rc;
}
if (oldest) {
rc = ble_gap_unpair_oldest_peer();
console_printf("Unpair oldest status: 0x%02x\n", rc);
return 0;
}
rc = parse_dev_addr("peer_", cmd_peer_addr_types, &peer);
if (rc != 0) {
console_printf("invalid 'peer_addr' parameter\n");
console_printf("invalid peer address\n");
return rc;
}
@ -2714,6 +2727,7 @@ cmd_security_unpair(int argc, char **argv)
#if MYNEWT_VAL(SHELL_CMD_HELP)
static const struct shell_param security_unpair_params[] = {
{"oldest", "usage: =[true|false], default: false"},
{"peer_addr_type", "usage: =[public|random|public_id|random_id], default: public"},
{"peer_addr", "usage: =[XX:XX:XX:XX:XX:XX]"},
{NULL, NULL}

View file

@ -37,7 +37,7 @@ pkg.deps:
- "@apache-mynewt-nimble/nimble/host/services/gap"
- "@apache-mynewt-nimble/nimble/host/services/gatt"
- "@apache-mynewt-nimble/nimble/host/services/dis"
- "@apache-mynewt-nimble/nimble/host/store/ram"
- "@apache-mynewt-nimble/nimble/host/store/config"
- "@apache-mynewt-nimble/nimble/transport/ram"
- "@apache-mynewt-core/hw/drivers/uart"
- "@apache-mynewt-core/hw/drivers/rtt"

View file

@ -44,16 +44,16 @@ static struct os_event bttester_ev[CMD_QUEUED];
struct btp_buf {
struct os_event *ev;
union {
u8_t data[BTP_MTU];
uint8_t data[BTP_MTU];
struct btp_hdr hdr;
};
};
static struct btp_buf cmd_buf[CMD_QUEUED];
static void supported_commands(u8_t *data, u16_t len)
static void supported_commands(uint8_t *data, uint16_t len)
{
u8_t buf[1];
uint8_t buf[1];
struct core_read_supported_commands_rp *rp = (void *) buf;
memset(buf, 0, sizeof(buf));
@ -64,12 +64,12 @@ static void supported_commands(u8_t *data, u16_t len)
tester_set_bit(buf, CORE_UNREGISTER_SERVICE);
tester_send(BTP_SERVICE_ID_CORE, CORE_READ_SUPPORTED_COMMANDS,
BTP_INDEX_NONE, (u8_t *) rp, sizeof(buf));
BTP_INDEX_NONE, (uint8_t *) rp, sizeof(buf));
}
static void supported_services(u8_t *data, u16_t len)
static void supported_services(uint8_t *data, uint16_t len)
{
u8_t buf[1];
uint8_t buf[1];
struct core_read_supported_services_rp *rp = (void *) buf;
memset(buf, 0, sizeof(buf));
@ -85,13 +85,13 @@ static void supported_services(u8_t *data, u16_t len)
#endif /* MYNEWT_VAL(BLE_MESH) */
tester_send(BTP_SERVICE_ID_CORE, CORE_READ_SUPPORTED_SERVICES,
BTP_INDEX_NONE, (u8_t *) rp, sizeof(buf));
BTP_INDEX_NONE, (uint8_t *) rp, sizeof(buf));
}
static void register_service(u8_t *data, u16_t len)
static void register_service(uint8_t *data, uint16_t len)
{
struct core_register_service_cmd *cmd = (void *) data;
u8_t status;
uint8_t status;
switch (cmd->id) {
case BTP_SERVICE_ID_GAP:
@ -124,10 +124,10 @@ rsp:
status);
}
static void unregister_service(u8_t *data, u16_t len)
static void unregister_service(uint8_t *data, uint16_t len)
{
struct core_unregister_service_cmd *cmd = (void *) data;
u8_t status;
uint8_t status;
switch (cmd->id) {
case BTP_SERVICE_ID_GAP:
@ -155,8 +155,8 @@ static void unregister_service(u8_t *data, u16_t len)
status);
}
static void handle_core(u8_t opcode, u8_t index, u8_t *data,
u16_t len)
static void handle_core(uint8_t opcode, uint8_t index, uint8_t *data,
uint16_t len)
{
if (index != BTP_INDEX_NONE) {
tester_rsp(BTP_SERVICE_ID_CORE, opcode, index,
@ -186,7 +186,7 @@ static void handle_core(u8_t opcode, u8_t index, u8_t *data,
static void cmd_handler(struct os_event *ev)
{
u16_t len;
uint16_t len;
struct btp_buf *cmd;
if (!ev || !ev->ev_arg) {
@ -241,12 +241,12 @@ static void cmd_handler(struct os_event *ev)
os_eventq_put(&avail_queue, ev);
}
static u8_t *recv_cb(u8_t *buf, size_t *off)
static uint8_t *recv_cb(uint8_t *buf, size_t *off)
{
struct btp_hdr *cmd = (void *) buf;
struct os_event *new_ev;
struct btp_buf *new_buf, *old_buf;
u16_t len;
uint16_t len;
if (*off < sizeof(*cmd)) {
return buf;
@ -319,7 +319,7 @@ void tester_init(void)
NULL, 0);
}
void tester_send(u8_t service, u8_t opcode, u8_t index, u8_t *data,
void tester_send(uint8_t service, uint8_t opcode, uint8_t index, uint8_t *data,
size_t len)
{
struct btp_hdr msg;
@ -329,7 +329,7 @@ void tester_send(u8_t service, u8_t opcode, u8_t index, u8_t *data,
msg.index = index;
msg.len = len;
bttester_pipe_send((u8_t *)&msg, sizeof(msg));
bttester_pipe_send((uint8_t *)&msg, sizeof(msg));
if (data && len) {
bttester_pipe_send(data, len);
}
@ -344,7 +344,7 @@ void tester_send(u8_t service, u8_t opcode, u8_t index, u8_t *data,
}
}
void tester_send_buf(u8_t service, u8_t opcode, u8_t index,
void tester_send_buf(uint8_t service, uint8_t opcode, uint8_t index,
struct os_mbuf *data)
{
struct btp_hdr msg;
@ -354,13 +354,13 @@ void tester_send_buf(u8_t service, u8_t opcode, u8_t index,
msg.index = index;
msg.len = os_mbuf_len(data);
bttester_pipe_send((u8_t *)&msg, sizeof(msg));
bttester_pipe_send((uint8_t *)&msg, sizeof(msg));
if (data && msg.len) {
bttester_pipe_send_buf(data);
}
}
void tester_rsp(u8_t service, u8_t opcode, u8_t index, u8_t status)
void tester_rsp(uint8_t service, uint8_t opcode, uint8_t index, uint8_t status)
{
struct btp_status s;
@ -370,5 +370,5 @@ void tester_rsp(u8_t service, u8_t opcode, u8_t index, u8_t status)
}
s.code = status;
tester_send(service, BTP_STATUS, index, (u8_t *) &s, sizeof(s));
tester_send(service, BTP_STATUS, index, (uint8_t *) &s, sizeof(s));
}

File diff suppressed because it is too large Load diff

View file

@ -27,9 +27,9 @@
extern "C" {
#endif
typedef u8_t *(*bttester_pipe_recv_cb)(u8_t *buf, size_t *off);
void bttester_pipe_register(u8_t *buf, size_t len, bttester_pipe_recv_cb cb);
int bttester_pipe_send(const u8_t *data, int len);
typedef uint8_t *(*bttester_pipe_recv_cb)(uint8_t *buf, size_t *off);
void bttester_pipe_register(uint8_t *buf, size_t len, bttester_pipe_recv_cb cb);
int bttester_pipe_send(const uint8_t *data, int len);
int bttester_pipe_send_buf(struct os_mbuf *buf);
int bttester_pipe_init(void);

View file

@ -51,7 +51,7 @@ static struct ble_sm_sc_oob_data oob_data_local;
static struct ble_sm_sc_oob_data oob_data_remote;
static uint16_t current_settings;
u8_t own_addr_type;
uint8_t own_addr_type;
static ble_addr_t peer_id_addr;
static ble_addr_t peer_ota_addr;
static bool encrypted = false;
@ -109,9 +109,9 @@ static int gap_conn_find_by_addr(const ble_addr_t *dev_addr,
static int gap_event_cb(struct ble_gap_event *event, void *arg);
static void supported_commands(u8_t *data, u16_t len)
static void supported_commands(uint8_t *data, uint16_t len)
{
u8_t cmds[3];
uint8_t cmds[3];
struct gap_read_supported_commands_rp *rp = (void *) &cmds;
SYS_LOG_DBG("");
@ -143,13 +143,13 @@ static void supported_commands(u8_t *data, u16_t len)
tester_set_bit(cmds, GAP_SET_MITM);
tester_send(BTP_SERVICE_ID_GAP, GAP_READ_SUPPORTED_COMMANDS,
CONTROLLER_INDEX, (u8_t *) rp, sizeof(cmds));
CONTROLLER_INDEX, (uint8_t *) rp, sizeof(cmds));
}
static void controller_index_list(u8_t *data, u16_t len)
static void controller_index_list(uint8_t *data, uint16_t len)
{
struct gap_read_controller_index_list_rp *rp;
u8_t buf[sizeof(*rp) + 1];
uint8_t buf[sizeof(*rp) + 1];
SYS_LOG_DBG("");
@ -159,7 +159,7 @@ static void controller_index_list(u8_t *data, u16_t len)
rp->index[0] = CONTROLLER_INDEX;
tester_send(BTP_SERVICE_ID_GAP, GAP_READ_CONTROLLER_INDEX_LIST,
BTP_INDEX_NONE, (u8_t *) rp, sizeof(buf));
BTP_INDEX_NONE, (uint8_t *) rp, sizeof(buf));
}
static int check_pub_addr_unassigned(void)
@ -174,10 +174,10 @@ static int check_pub_addr_unassigned(void)
#endif
}
static void controller_info(u8_t *data, u16_t len)
static void controller_info(uint8_t *data, uint16_t len)
{
struct gap_read_controller_info_rp rp;
u32_t supported_settings = 0;
uint32_t supported_settings = 0;
ble_addr_t addr;
int rc;
@ -240,7 +240,7 @@ static void controller_info(u8_t *data, u16_t len)
memcpy(rp.name, CONTROLLER_NAME, sizeof(CONTROLLER_NAME));
tester_send(BTP_SERVICE_ID_GAP, GAP_READ_CONTROLLER_INFO,
CONTROLLER_INDEX, (u8_t *) &rp, sizeof(rp));
CONTROLLER_INDEX, (uint8_t *) &rp, sizeof(rp));
}
static struct ble_gap_adv_params adv_params = {
@ -248,7 +248,7 @@ static struct ble_gap_adv_params adv_params = {
.disc_mode = BLE_GAP_DISC_MODE_NON,
};
static void set_connectable(u8_t *data, u16_t len)
static void set_connectable(uint8_t *data, uint16_t len)
{
const struct gap_set_connectable_cmd *cmd = (void *) data;
struct gap_set_connectable_rp rp;
@ -266,12 +266,12 @@ static void set_connectable(u8_t *data, u16_t len)
rp.current_settings = sys_cpu_to_le32(current_settings);
tester_send(BTP_SERVICE_ID_GAP, GAP_SET_CONNECTABLE, CONTROLLER_INDEX,
(u8_t *) &rp, sizeof(rp));
(uint8_t *) &rp, sizeof(rp));
}
static u8_t ad_flags = BLE_HS_ADV_F_BREDR_UNSUP;
static uint8_t ad_flags = BLE_HS_ADV_F_BREDR_UNSUP;
static void set_discoverable(u8_t *data, u16_t len)
static void set_discoverable(uint8_t *data, uint16_t len)
{
const struct gap_set_discoverable_cmd *cmd = (void *) data;
struct gap_set_discoverable_rp rp;
@ -305,10 +305,10 @@ static void set_discoverable(u8_t *data, u16_t len)
rp.current_settings = sys_cpu_to_le32(current_settings);
tester_send(BTP_SERVICE_ID_GAP, GAP_SET_DISCOVERABLE, CONTROLLER_INDEX,
(u8_t *) &rp, sizeof(rp));
(uint8_t *) &rp, sizeof(rp));
}
static void set_bondable(const u8_t *data, u16_t len)
static void set_bondable(const uint8_t *data, uint16_t len)
{
const struct gap_set_bondable_cmd *cmd = (void *) data;
struct gap_set_bondable_rp rp;
@ -325,7 +325,7 @@ static void set_bondable(const u8_t *data, u16_t len)
rp.current_settings = sys_cpu_to_le32(current_settings);
tester_send(BTP_SERVICE_ID_GAP, GAP_SET_BONDABLE, CONTROLLER_INDEX,
(u8_t *) &rp, sizeof(rp));
(uint8_t *) &rp, sizeof(rp));
}
static struct bt_data ad[10] = {
@ -334,7 +334,7 @@ static struct bt_data ad[10] = {
static struct bt_data sd[10];
static int set_ad(const struct bt_data *ad, size_t ad_len,
u8_t *buf, u8_t *buf_len)
uint8_t *buf, uint8_t *buf_len)
{
int i;
@ -350,14 +350,14 @@ static int set_ad(const struct bt_data *ad, size_t ad_len,
return 0;
}
static void start_advertising(const u8_t *data, u16_t len)
static void start_advertising(const uint8_t *data, uint16_t len)
{
const struct gap_start_advertising_cmd *cmd = (void *) data;
struct gap_start_advertising_rp rp;
int32_t duration_ms = BLE_HS_FOREVER;
uint8_t buf[BLE_HS_ADV_MAX_SZ];
uint8_t buf_len = 0;
u8_t adv_len, sd_len;
uint8_t adv_len, sd_len;
int err;
int i;
@ -429,14 +429,14 @@ static void start_advertising(const u8_t *data, u16_t len)
rp.current_settings = sys_cpu_to_le32(current_settings);
tester_send(BTP_SERVICE_ID_GAP, GAP_START_ADVERTISING, CONTROLLER_INDEX,
(u8_t *) &rp, sizeof(rp));
(uint8_t *) &rp, sizeof(rp));
return;
fail:
tester_rsp(BTP_SERVICE_ID_GAP, GAP_START_ADVERTISING, CONTROLLER_INDEX,
BTP_STATUS_FAILED);
}
static void stop_advertising(const u8_t *data, u16_t len)
static void stop_advertising(const uint8_t *data, uint16_t len)
{
struct gap_stop_advertising_rp rp;
@ -452,12 +452,12 @@ static void stop_advertising(const u8_t *data, u16_t len)
rp.current_settings = sys_cpu_to_le32(current_settings);
tester_send(BTP_SERVICE_ID_GAP, GAP_STOP_ADVERTISING, CONTROLLER_INDEX,
(u8_t *) &rp, sizeof(rp));
(uint8_t *) &rp, sizeof(rp));
}
static u8_t get_ad_flags(const u8_t *data, u8_t data_len)
static uint8_t get_ad_flags(const uint8_t *data, uint8_t data_len)
{
u8_t len, i;
uint8_t len, i;
/* Parse advertisement to get flags */
for (i = 0; i < data_len; i += len - 1) {
@ -482,11 +482,11 @@ static u8_t get_ad_flags(const u8_t *data, u8_t data_len)
return 0;
}
static u8_t discovery_flags;
static uint8_t discovery_flags;
static struct os_mbuf *adv_buf;
static void store_adv(const ble_addr_t *addr, s8_t rssi,
const u8_t *data, u8_t len)
static void store_adv(const ble_addr_t *addr, int8_t rssi,
const uint8_t *data, uint8_t len)
{
struct gap_device_found_ev *ev;
@ -503,8 +503,8 @@ static void store_adv(const ble_addr_t *addr, s8_t rssi,
memcpy(net_buf_simple_add(adv_buf, len), data, len);
}
static void device_found(ble_addr_t *addr, s8_t rssi, u8_t evtype,
const u8_t *data, u8_t len)
static void device_found(ble_addr_t *addr, int8_t rssi, uint8_t evtype,
const uint8_t *data, uint8_t len)
{
struct gap_device_found_ev *ev;
ble_addr_t a;
@ -512,7 +512,7 @@ static void device_found(ble_addr_t *addr, s8_t rssi, u8_t evtype,
/* if General/Limited Discovery - parse Advertising data to get flags */
if (!(discovery_flags & GAP_DISCOVERY_FLAG_LE_OBSERVE) &&
(evtype != BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP)) {
u8_t flags = get_ad_flags(data, len);
uint8_t flags = get_ad_flags(data, len);
/* ignore non-discoverable devices */
if (!(flags & BLE_AD_DISCOV_MASK)) {
@ -593,11 +593,11 @@ static int discovery_cb(struct ble_gap_event *event, void *arg)
return 0;
}
static void start_discovery(const u8_t *data, u16_t len)
static void start_discovery(const uint8_t *data, uint16_t len)
{
const struct gap_start_discovery_cmd *cmd = (void *) data;
struct ble_gap_disc_params params = {0};
u8_t status;
uint8_t status;
SYS_LOG_DBG("");
@ -626,9 +626,9 @@ reply:
status);
}
static void stop_discovery(const u8_t *data, u16_t len)
static void stop_discovery(const uint8_t *data, uint16_t len)
{
u8_t status = BTP_STATUS_SUCCESS;
uint8_t status = BTP_STATUS_SUCCESS;
SYS_LOG_DBG("");
@ -680,13 +680,13 @@ static void device_connected_ev_send(struct os_event *ev)
}
tester_send(BTP_SERVICE_ID_GAP, GAP_EV_DEVICE_CONNECTED,
CONTROLLER_INDEX, (u8_t *) &connected_ev,
CONTROLLER_INDEX, (uint8_t *) &connected_ev,
sizeof(connected_ev));
periph_privacy(desc);
}
static void le_connected(u16_t conn_handle, int status)
static void le_connected(uint16_t conn_handle, int status)
{
struct ble_gap_conn_desc desc;
ble_addr_t *addr;
@ -720,7 +720,7 @@ static void le_connected(u16_t conn_handle, int status)
CONNECTED_EV_DELAY_MS(desc.conn_itvl)));
#else
tester_send(BTP_SERVICE_ID_GAP, GAP_EV_DEVICE_CONNECTED,
CONTROLLER_INDEX, (u8_t *) &connected_ev,
CONTROLLER_INDEX, (uint8_t *) &connected_ev,
sizeof(connected_ev));
#endif
}
@ -763,10 +763,10 @@ static void le_disconnected(struct ble_gap_conn_desc *conn, int reason)
ev.address_type = addr->type;
tester_send(BTP_SERVICE_ID_GAP, GAP_EV_DEVICE_DISCONNECTED,
CONTROLLER_INDEX, (u8_t *) &ev, sizeof(ev));
CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
}
static void auth_passkey_oob(u16_t conn_handle)
static void auth_passkey_oob(uint16_t conn_handle)
{
struct ble_gap_conn_desc desc;
struct ble_sm_io pk;
@ -786,7 +786,7 @@ static void auth_passkey_oob(u16_t conn_handle)
assert(rc == 0);
}
static void auth_passkey_display(u16_t conn_handle, unsigned int passkey)
static void auth_passkey_display(uint16_t conn_handle, unsigned int passkey)
{
struct ble_gap_conn_desc desc;
struct gap_passkey_display_ev ev;
@ -817,10 +817,10 @@ static void auth_passkey_display(u16_t conn_handle, unsigned int passkey)
ev.passkey = sys_cpu_to_le32(pk.passkey);
tester_send(BTP_SERVICE_ID_GAP, GAP_EV_PASSKEY_DISPLAY,
CONTROLLER_INDEX, (u8_t *) &ev, sizeof(ev));
CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
}
static void auth_passkey_entry(u16_t conn_handle)
static void auth_passkey_entry(uint16_t conn_handle)
{
struct ble_gap_conn_desc desc;
struct gap_passkey_entry_req_ev ev;
@ -840,10 +840,10 @@ static void auth_passkey_entry(u16_t conn_handle)
ev.address_type = addr->type;
tester_send(BTP_SERVICE_ID_GAP, GAP_EV_PASSKEY_ENTRY_REQ,
CONTROLLER_INDEX, (u8_t *) &ev, sizeof(ev));
CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
}
static void auth_passkey_numcmp(u16_t conn_handle, unsigned int passkey)
static void auth_passkey_numcmp(uint16_t conn_handle, unsigned int passkey)
{
struct ble_gap_conn_desc desc;
struct gap_passkey_confirm_req_ev ev;
@ -864,10 +864,10 @@ static void auth_passkey_numcmp(u16_t conn_handle, unsigned int passkey)
ev.passkey = sys_cpu_to_le32(passkey);
tester_send(BTP_SERVICE_ID_GAP, GAP_EV_PASSKEY_CONFIRM_REQ,
CONTROLLER_INDEX, (u8_t *) &ev, sizeof(ev));
CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
}
static void auth_passkey_oob_sc(u16_t conn_handle)
static void auth_passkey_oob_sc(uint16_t conn_handle)
{
int rc;
struct ble_sm_io pk;
@ -889,7 +889,7 @@ static void auth_passkey_oob_sc(u16_t conn_handle)
}
}
static void le_passkey_action(u16_t conn_handle,
static void le_passkey_action(uint16_t conn_handle,
struct ble_gap_passkey_params *params)
{
SYS_LOG_DBG("");
@ -917,7 +917,7 @@ static void le_passkey_action(u16_t conn_handle,
}
}
static void le_identity_resolved(u16_t conn_handle)
static void le_identity_resolved(uint16_t conn_handle)
{
struct ble_gap_conn_desc desc;
struct gap_identity_resolved_ev ev;
@ -941,7 +941,7 @@ static void le_identity_resolved(u16_t conn_handle)
sizeof(ev.identity_address));
tester_send(BTP_SERVICE_ID_GAP, GAP_EV_IDENTITY_RESOLVED,
CONTROLLER_INDEX, (u8_t *) &ev, sizeof(ev));
CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
}
static void le_conn_param_update(struct ble_gap_conn_desc *desc)
@ -958,7 +958,7 @@ static void le_conn_param_update(struct ble_gap_conn_desc *desc)
ev.supervision_timeout = desc->supervision_timeout;
tester_send(BTP_SERVICE_ID_GAP, GAP_EV_CONN_PARAM_UPDATE,
CONTROLLER_INDEX, (u8_t *) &ev, sizeof(ev));
CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
}
static void le_encryption_changed(struct ble_gap_conn_desc *desc)
@ -986,7 +986,7 @@ static void le_encryption_changed(struct ble_gap_conn_desc *desc)
}
tester_send(BTP_SERVICE_ID_GAP, GAP_EV_SEC_LEVEL_CHANGED,
CONTROLLER_INDEX, (u8_t *) &ev, sizeof(ev));
CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
}
static void print_bytes(const uint8_t *bytes, int len)
@ -1055,7 +1055,7 @@ static void adv_complete(void)
ev.current_settings = sys_cpu_to_le32(current_settings);
tester_send(BTP_SERVICE_ID_GAP, GAP_EV_NEW_SETTINGS, CONTROLLER_INDEX,
(u8_t *) &ev, sizeof(ev));
(uint8_t *) &ev, sizeof(ev));
}
static int gap_event_cb(struct ble_gap_event *event, void *arg)
@ -1197,9 +1197,9 @@ static int gap_event_cb(struct ble_gap_event *event, void *arg)
return 0;
}
static void connect(const u8_t *data, u16_t len)
static void connect(const uint8_t *data, uint16_t len)
{
u8_t status = BTP_STATUS_SUCCESS;
uint8_t status = BTP_STATUS_SUCCESS;
SYS_LOG_DBG("");
@ -1211,10 +1211,10 @@ static void connect(const u8_t *data, u16_t len)
tester_rsp(BTP_SERVICE_ID_GAP, GAP_CONNECT, CONTROLLER_INDEX, status);
}
static void disconnect(const u8_t *data, u16_t len)
static void disconnect(const uint8_t *data, uint16_t len)
{
struct ble_gap_conn_desc desc;
u8_t status;
uint8_t status;
int rc;
SYS_LOG_DBG("");
@ -1236,10 +1236,10 @@ rsp:
status);
}
static void set_io_cap(const u8_t *data, u16_t len)
static void set_io_cap(const uint8_t *data, uint16_t len)
{
const struct gap_set_io_cap_cmd *cmd = (void *) data;
u8_t status;
uint8_t status;
SYS_LOG_DBG("");
@ -1276,10 +1276,10 @@ rsp:
status);
}
static void pair(const u8_t *data, u16_t len)
static void pair(const uint8_t *data, uint16_t len)
{
struct ble_gap_conn_desc desc;
u8_t status;
uint8_t status;
int rc;
SYS_LOG_DBG("");
@ -1301,9 +1301,9 @@ rsp:
tester_rsp(BTP_SERVICE_ID_GAP, GAP_PAIR, CONTROLLER_INDEX, status);
}
static void unpair(const u8_t *data, u16_t len)
static void unpair(const uint8_t *data, uint16_t len)
{
u8_t status;
uint8_t status;
int err;
SYS_LOG_DBG("");
@ -1313,12 +1313,12 @@ static void unpair(const u8_t *data, u16_t len)
tester_rsp(BTP_SERVICE_ID_GAP, GAP_UNPAIR, CONTROLLER_INDEX, status);
}
static void passkey_entry(const u8_t *data, u16_t len)
static void passkey_entry(const uint8_t *data, uint16_t len)
{
const struct gap_passkey_entry_cmd *cmd = (void *) data;
struct ble_gap_conn_desc desc;
struct ble_sm_io pk;
u8_t status;
uint8_t status;
int rc;
SYS_LOG_DBG("");
@ -1345,12 +1345,12 @@ rsp:
status);
}
static void passkey_confirm(const u8_t *data, u16_t len)
static void passkey_confirm(const uint8_t *data, uint16_t len)
{
const struct gap_passkey_confirm_cmd *cmd = (void *) data;
struct ble_gap_conn_desc desc;
struct ble_sm_io pk;
u8_t status;
uint8_t status;
int rc;
SYS_LOG_DBG("");
@ -1378,7 +1378,7 @@ rsp:
status);
}
static void start_direct_adv(const u8_t *data, u16_t len)
static void start_direct_adv(const uint8_t *data, uint16_t len)
{
const struct gap_start_direct_adv_cmd *cmd = (void *) data;
struct gap_start_advertising_rp rp;
@ -1403,7 +1403,7 @@ static void start_direct_adv(const u8_t *data, u16_t len)
rp.current_settings = sys_cpu_to_le32(current_settings);
tester_send(BTP_SERVICE_ID_GAP, GAP_START_DIRECT_ADV, CONTROLLER_INDEX,
(u8_t *) &rp, sizeof(rp));
(uint8_t *) &rp, sizeof(rp));
return;
fail:
tester_rsp(BTP_SERVICE_ID_GAP, GAP_START_DIRECT_ADV, CONTROLLER_INDEX,
@ -1416,7 +1416,7 @@ static void conn_param_update_cb(uint16_t conn_handle, int status, void *arg)
conn_handle, status);
}
static int conn_param_update_slave(u16_t conn_handle,
static int conn_param_update_slave(uint16_t conn_handle,
const struct gap_conn_param_update_cmd *cmd)
{
int rc;
@ -1436,7 +1436,7 @@ static int conn_param_update_slave(u16_t conn_handle,
return 0;
}
static int conn_param_update_master(u16_t conn_handle,
static int conn_param_update_master(uint16_t conn_handle,
const struct gap_conn_param_update_cmd *cmd)
{
int rc;
@ -1489,7 +1489,7 @@ rsp:
SYS_LOG_ERR("Conn param update fail; rc=%d", rc);
}
static void conn_param_update_async(const u8_t *data, u16_t len)
static void conn_param_update_async(const uint8_t *data, uint16_t len)
{
const struct gap_conn_param_update_cmd *cmd = (void *) data;
update_params = *cmd;
@ -1500,7 +1500,7 @@ static void conn_param_update_async(const u8_t *data, u16_t len)
BTP_STATUS_SUCCESS);
}
static void oob_legacy_set_data(const u8_t *data, u16_t len)
static void oob_legacy_set_data(const uint8_t *data, uint16_t len)
{
const struct gap_oob_legacy_set_data_cmd *cmd = (void *) data;
@ -1511,7 +1511,7 @@ static void oob_legacy_set_data(const u8_t *data, u16_t len)
CONTROLLER_INDEX, BTP_STATUS_SUCCESS);
}
static void oob_sc_get_local_data(const u8_t *data, u16_t len)
static void oob_sc_get_local_data(const uint8_t *data, uint16_t len)
{
struct gap_oob_sc_get_local_data_rp rp;
@ -1519,10 +1519,10 @@ static void oob_sc_get_local_data(const u8_t *data, u16_t len)
memcpy(rp.c, oob_data_local.c, 16);
tester_send(BTP_SERVICE_ID_GAP, GAP_OOB_SC_GET_LOCAL_DATA,
CONTROLLER_INDEX, (u8_t *) &rp, sizeof(rp));
CONTROLLER_INDEX, (uint8_t *) &rp, sizeof(rp));
}
static void oob_sc_set_remote_data(const u8_t *data, u16_t len)
static void oob_sc_set_remote_data(const uint8_t *data, uint16_t len)
{
const struct gap_oob_sc_set_remote_data_cmd *cmd = (void *) data;
@ -1534,7 +1534,7 @@ static void oob_sc_set_remote_data(const u8_t *data, u16_t len)
CONTROLLER_INDEX, BTP_STATUS_SUCCESS);
}
static void set_mitm(const u8_t *data, u16_t len)
static void set_mitm(const uint8_t *data, uint16_t len)
{
const struct gap_set_mitm_cmd *cmd = (void *) data;
@ -1544,8 +1544,8 @@ static void set_mitm(const u8_t *data, u16_t len)
CONTROLLER_INDEX, BTP_STATUS_SUCCESS);
}
void tester_handle_gap(u8_t opcode, u8_t index, u8_t *data,
u16_t len)
void tester_handle_gap(uint8_t opcode, uint8_t index, uint8_t *data,
uint16_t len)
{
switch (opcode) {
case GAP_READ_SUPPORTED_COMMANDS:
@ -1664,7 +1664,7 @@ static void tester_init_gap_cb(int err)
BTP_STATUS_SUCCESS);
}
u8_t tester_init_gap(void)
uint8_t tester_init_gap(void)
{
#if MYNEWT_VAL(BLE_SM_SC)
int rc;
@ -1682,7 +1682,7 @@ u8_t tester_init_gap(void)
return BTP_STATUS_SUCCESS;
}
u8_t tester_unregister_gap(void)
uint8_t tester_unregister_gap(void)
{
return BTP_STATUS_SUCCESS;
}

View file

@ -76,8 +76,8 @@
static uint8_t gatt_svr_pts_static_long_val[300];
static uint8_t gatt_svr_pts_static_val[30];
static uint8_t gatt_svr_pts_static_short_val;
static u8_t notify_state;
static u8_t indicate_state;
static uint8_t notify_state;
static uint8_t indicate_state;
static uint16_t myconn_handle;
static struct os_callout notify_tx_timer;
uint16_t notify_handle;
@ -253,7 +253,7 @@ static const struct ble_gatt_svc_def gatt_svr_svcs[] = {
},
};
static void attr_value_changed_ev(u16_t handle, struct os_mbuf *data)
static void attr_value_changed_ev(uint16_t handle, struct os_mbuf *data)
{
struct gatt_attr_value_changed_ev *ev;
struct os_mbuf *buf = os_msys_get(0, 0);
@ -569,7 +569,7 @@ gatt_svr_rel_write_test(uint16_t conn_handle, uint16_t attr_handle,
}
}
static void start_server(u8_t *data, u16_t len)
static void start_server(uint8_t *data, uint16_t len)
{
struct gatt_start_server_rp rp;
@ -583,14 +583,14 @@ static void start_server(u8_t *data, u16_t len)
rp.db_attr_cnt = 0;
tester_send(BTP_SERVICE_ID_GATT, GATT_START_SERVER, CONTROLLER_INDEX,
(u8_t *) &rp, sizeof(rp));
(uint8_t *) &rp, sizeof(rp));
}
/* Convert UUID from BTP command to bt_uuid */
static u8_t btp2bt_uuid(const u8_t *uuid, u8_t len,
static uint8_t btp2bt_uuid(const uint8_t *uuid, uint8_t len,
ble_uuid_any_t *bt_uuid)
{
u16_t le16;
uint16_t le16;
switch (len) {
case 0x02: /* UUID 16 */
@ -614,8 +614,8 @@ static u8_t btp2bt_uuid(const u8_t *uuid, u8_t len,
* It is not intended to be used by client and server at the same time.
*/
static struct {
u16_t len;
u8_t buf[MAX_BUFFER_SIZE];
uint16_t len;
uint8_t buf[MAX_BUFFER_SIZE];
} gatt_buf;
static void *gatt_buf_add(const void *data, size_t len)
@ -665,7 +665,7 @@ static int read_cb(uint16_t conn_handle,
void *arg)
{
struct gatt_read_rp *rp = (void *) gatt_buf.buf;
u8_t btp_opcode = (uint8_t) (int) arg;
uint8_t btp_opcode = (uint8_t) (int) arg;
SYS_LOG_DBG("status=%d", error->status);
@ -692,7 +692,7 @@ static int read_cb(uint16_t conn_handle,
return 0;
}
static void read(u8_t *data, u16_t len)
static void read(uint8_t *data, uint16_t len)
{
const struct gatt_read_cmd *cmd = (void *) data;
struct ble_gap_conn_desc conn;
@ -731,7 +731,7 @@ static int read_long_cb(uint16_t conn_handle,
void *arg)
{
struct gatt_read_rp *rp = (void *) gatt_buf.buf;
u8_t btp_opcode = (uint8_t) (int) arg;
uint8_t btp_opcode = (uint8_t) (int) arg;
SYS_LOG_DBG("status=%d", error->status);
@ -762,7 +762,7 @@ static int read_long_cb(uint16_t conn_handle,
return 0;
}
static void read_long(u8_t *data, u16_t len)
static void read_long(uint8_t *data, uint16_t len)
{
const struct gatt_read_long_cmd *cmd = (void *) data;
struct ble_gap_conn_desc conn;
@ -797,10 +797,10 @@ fail:
BTP_STATUS_FAILED);
}
static void read_multiple(u8_t *data, u16_t len)
static void read_multiple(uint8_t *data, uint16_t len)
{
const struct gatt_read_multiple_cmd *cmd = (void *) data;
u16_t handles[cmd->handles_count];
uint16_t handles[cmd->handles_count];
struct ble_gap_conn_desc conn;
int rc, i;
@ -836,11 +836,11 @@ fail:
BTP_STATUS_FAILED);
}
static void write_without_rsp(u8_t *data, u16_t len, u8_t op, bool sign)
static void write_without_rsp(uint8_t *data, uint16_t len, uint8_t op, bool sign)
{
const struct gatt_write_without_rsp_cmd *cmd = (void *) data;
struct ble_gap_conn_desc conn;
u8_t status = BTP_STATUS_SUCCESS;
uint8_t status = BTP_STATUS_SUCCESS;
int rc;
SYS_LOG_DBG("");
@ -866,7 +866,7 @@ static int write_rsp(uint16_t conn_handle, const struct ble_gatt_error *error,
void *arg)
{
uint8_t err = (uint8_t) error->status;
u8_t btp_opcode = (uint8_t) (int) arg;
uint8_t btp_opcode = (uint8_t) (int) arg;
SYS_LOG_DBG("");
@ -875,7 +875,7 @@ static int write_rsp(uint16_t conn_handle, const struct ble_gatt_error *error,
return 0;
}
static void write(u8_t *data, u16_t len)
static void write(uint8_t *data, uint16_t len)
{
const struct gatt_write_cmd *cmd = (void *) data;
struct ble_gap_conn_desc conn;
@ -901,7 +901,7 @@ fail:
BTP_STATUS_FAILED);
}
static void write_long(u8_t *data, u16_t len)
static void write_long(uint8_t *data, uint16_t len)
{
const struct gatt_write_long_cmd *cmd = (void *) data;
struct ble_gap_conn_desc conn;
@ -952,7 +952,7 @@ static int reliable_write_rsp(uint16_t conn_handle,
return 0;
}
static void reliable_write(u8_t *data, u16_t len)
static void reliable_write(uint8_t *data, uint16_t len)
{
const struct gatt_reliable_write_cmd *cmd = (void *) data;
struct ble_gap_conn_desc conn;
@ -994,12 +994,12 @@ fail:
}
static struct bt_gatt_subscribe_params {
u16_t ccc_handle;
u16_t value;
u16_t value_handle;
uint16_t ccc_handle;
uint16_t value;
uint16_t value_handle;
} subscribe_params;
static void read_uuid(u8_t *data, u16_t len)
static void read_uuid(uint8_t *data, uint16_t len)
{
const struct gatt_read_uuid_cmd *cmd = (void *) data;
struct ble_gap_conn_desc conn;
@ -1046,8 +1046,8 @@ static int disc_prim_uuid_cb(uint16_t conn_handle,
struct gatt_disc_prim_uuid_rp *rp = (void *) gatt_buf.buf;
struct gatt_service *service;
const ble_uuid_any_t *uuid;
u8_t uuid_length;
u8_t opcode = (u8_t) (int) arg;
uint8_t uuid_length;
uint8_t opcode = (uint8_t) (int) arg;
SYS_LOG_DBG("");
@ -1081,7 +1081,7 @@ static int disc_prim_uuid_cb(uint16_t conn_handle,
service->uuid_length = uuid_length;
if (uuid->u.type == BLE_UUID_TYPE_16) {
u16_t u16 = sys_cpu_to_le16(BLE_UUID16(uuid)->value);
uint16_t u16 = sys_cpu_to_le16(BLE_UUID16(uuid)->value);
memcpy(service->uuid, &u16, uuid_length);
} else {
memcpy(service->uuid, BLE_UUID128(uuid)->value,
@ -1102,7 +1102,7 @@ static int disc_all_desc_cb(uint16_t conn_handle,
struct gatt_disc_all_desc_rp *rp = (void *) gatt_buf.buf;
struct gatt_descriptor *dsc;
const ble_uuid_any_t *uuid;
u8_t uuid_length;
uint8_t uuid_length;
SYS_LOG_DBG("");
@ -1135,7 +1135,7 @@ static int disc_all_desc_cb(uint16_t conn_handle,
dsc->uuid_length = uuid_length;
if (uuid->u.type == BLE_UUID_TYPE_16) {
u16_t u16 = sys_cpu_to_le16(BLE_UUID16(uuid)->value);
uint16_t u16 = sys_cpu_to_le16(BLE_UUID16(uuid)->value);
memcpy(dsc->uuid, &u16, uuid_length);
} else {
memcpy(dsc->uuid, BLE_UUID128(uuid)->value, uuid_length);
@ -1146,7 +1146,7 @@ static int disc_all_desc_cb(uint16_t conn_handle,
return 0;
}
static void disc_all_prim_svcs(u8_t *data, u16_t len)
static void disc_all_prim_svcs(uint8_t *data, uint16_t len)
{
struct ble_gap_conn_desc conn;
int rc;
@ -1175,7 +1175,7 @@ fail:
CONTROLLER_INDEX, BTP_STATUS_FAILED);
}
static void disc_all_desc(u8_t *data, u16_t len)
static void disc_all_desc(uint8_t *data, uint16_t len)
{
const struct gatt_disc_all_desc_cmd *cmd = (void *) data;
struct ble_gap_conn_desc conn;
@ -1221,7 +1221,7 @@ static int find_included_cb(uint16_t conn_handle,
struct gatt_included *included;
const ble_uuid_any_t *uuid;
int service_handle = (int) arg;
u8_t uuid_length;
uint8_t uuid_length;
SYS_LOG_DBG("");
@ -1259,7 +1259,7 @@ static int find_included_cb(uint16_t conn_handle,
included->service.uuid_length = uuid_length;
if (uuid->u.type == BLE_UUID_TYPE_16) {
u16_t u16 = sys_cpu_to_le16(BLE_UUID16(uuid)->value);
uint16_t u16 = sys_cpu_to_le16(BLE_UUID16(uuid)->value);
memcpy(included->service.uuid, &u16, uuid_length);
} else {
memcpy(included->service.uuid, BLE_UUID128(uuid)->value,
@ -1278,8 +1278,8 @@ static int disc_chrc_cb(uint16_t conn_handle,
struct gatt_disc_chrc_rp *rp = (void *) gatt_buf.buf;
struct gatt_characteristic *chrc;
const ble_uuid_any_t *uuid;
u8_t btp_opcode = (uint8_t) (int) arg;
u8_t uuid_length;
uint8_t btp_opcode = (uint8_t) (int) arg;
uint8_t uuid_length;
SYS_LOG_DBG("");
@ -1314,7 +1314,7 @@ static int disc_chrc_cb(uint16_t conn_handle,
chrc->uuid_length = uuid_length;
if (uuid->u.type == BLE_UUID_TYPE_16) {
u16_t u16 = sys_cpu_to_le16(BLE_UUID16(uuid)->value);
uint16_t u16 = sys_cpu_to_le16(BLE_UUID16(uuid)->value);
memcpy(chrc->uuid, &u16, uuid_length);
} else {
memcpy(chrc->uuid, BLE_UUID128(uuid)->value,
@ -1326,7 +1326,7 @@ static int disc_chrc_cb(uint16_t conn_handle,
return 0;
}
static void disc_chrc_uuid(u8_t *data, u16_t len)
static void disc_chrc_uuid(uint8_t *data, uint16_t len)
{
const struct gatt_disc_chrc_uuid_cmd *cmd = (void *) data;
struct ble_gap_conn_desc conn;
@ -1366,7 +1366,7 @@ fail:
BTP_STATUS_FAILED);
}
static void disc_prim_uuid(u8_t *data, u16_t len)
static void disc_prim_uuid(uint8_t *data, uint16_t len)
{
const struct gatt_disc_prim_uuid_cmd *cmd = (void *) data;
struct ble_gap_conn_desc conn;
@ -1402,7 +1402,7 @@ fail:
BTP_STATUS_FAILED);
}
static void disc_all_chrc(u8_t *data, u16_t len)
static void disc_all_chrc(uint8_t *data, uint16_t len)
{
const struct gatt_disc_all_chrc_cmd *cmd = (void *) data;
struct ble_gap_conn_desc conn;
@ -1439,7 +1439,7 @@ fail:
BTP_STATUS_FAILED);
}
static void find_included(u8_t *data, u16_t len)
static void find_included(uint8_t *data, uint16_t len)
{
const struct gatt_find_included_cmd *cmd = (void *) data;
struct ble_gap_conn_desc conn;
@ -1495,7 +1495,7 @@ static int exchange_func(uint16_t conn_handle,
return 0;
}
static void exchange_mtu(u8_t *data, u16_t len)
static void exchange_mtu(uint8_t *data, uint16_t len)
{
struct ble_gap_conn_desc conn;
int rc;
@ -1517,10 +1517,10 @@ fail:
CONTROLLER_INDEX, BTP_STATUS_FAILED);
}
static int enable_subscription(u16_t conn_handle, u16_t ccc_handle,
u16_t value)
static int enable_subscription(uint16_t conn_handle, uint16_t ccc_handle,
uint16_t value)
{
u8_t op;
uint8_t op;
SYS_LOG_DBG("");
@ -1538,9 +1538,9 @@ static int enable_subscription(u16_t conn_handle, u16_t ccc_handle,
return 0;
}
static int disable_subscription(u16_t conn_handle, u16_t ccc_handle)
static int disable_subscription(uint16_t conn_handle, uint16_t ccc_handle)
{
u16_t value = 0x00;
uint16_t value = 0x00;
SYS_LOG_DBG("");
@ -1559,12 +1559,12 @@ static int disable_subscription(u16_t conn_handle, u16_t ccc_handle)
return 0;
}
static void config_subscription(u8_t *data, u16_t len, u8_t op)
static void config_subscription(uint8_t *data, uint16_t len, uint8_t op)
{
const struct gatt_cfg_notify_cmd *cmd = (void *) data;
struct ble_gap_conn_desc conn;
u16_t ccc_handle = sys_le16_to_cpu(cmd->ccc_handle);
u8_t status;
uint16_t ccc_handle = sys_le16_to_cpu(cmd->ccc_handle);
uint8_t status;
int rc;
SYS_LOG_DBG("");
@ -1577,7 +1577,7 @@ static void config_subscription(u8_t *data, u16_t len, u8_t op)
}
if (cmd->enable) {
u16_t value;
uint16_t value;
if (op == GATT_CFG_NOTIFY) {
value = 0x0001;
@ -1625,10 +1625,10 @@ static int flags_hs2btp_map[] = {
BTP_PERM_F_WRITE_AUTHOR,
};
static u8_t flags_hs2btp(u8_t flags)
static uint8_t flags_hs2btp(uint8_t flags)
{
int i;
u8_t ret = 0;
uint8_t ret = 0;
for (i = 0; i < 8; ++i) {
if (flags & BIT(i)) {
@ -1639,17 +1639,17 @@ static u8_t flags_hs2btp(u8_t flags)
return ret;
}
static void get_attrs(u8_t *data, u16_t len)
static void get_attrs(uint8_t *data, uint16_t len)
{
const struct gatt_get_attributes_cmd *cmd = (void *) data;
struct gatt_get_attributes_rp *rp;
struct gatt_attr *gatt_attr;
struct os_mbuf *buf = os_msys_get(0, 0);
u16_t start_handle, end_handle;
uint16_t start_handle, end_handle;
struct ble_att_svr_entry *entry = NULL;
ble_uuid_any_t uuid;
ble_uuid_t *uuid_ptr = NULL;
u8_t count = 0;
uint8_t count = 0;
char str[BLE_UUID_STR_LEN];
SYS_LOG_DBG("");
@ -1718,13 +1718,13 @@ free:
os_mbuf_free_chain(buf);
}
static void get_attr_val(u8_t *data, u16_t len)
static void get_attr_val(uint8_t *data, uint16_t len)
{
const struct gatt_get_attribute_value_cmd *cmd = (void *) data;
struct gatt_get_attribute_value_rp *rp;
struct ble_gap_conn_desc conn;
struct os_mbuf *buf = os_msys_get(0, 0);
u16_t handle = sys_cpu_to_le16(cmd->handle);
uint16_t handle = sys_cpu_to_le16(cmd->handle);
uint8_t out_att_err;
int conn_status;
@ -1766,7 +1766,7 @@ free:
os_mbuf_free_chain(buf);
}
static void change_database(u8_t *data, u16_t len)
static void change_database(uint8_t *data, uint16_t len)
{
const struct gatt_change_database *cmd = (void *) data;
@ -1782,9 +1782,9 @@ static void change_database(u8_t *data, u16_t len)
return;
}
static void supported_commands(u8_t *data, u16_t len)
static void supported_commands(uint8_t *data, uint16_t len)
{
u8_t cmds[4];
uint8_t cmds[4];
struct gatt_read_supported_commands_rp *rp = (void *) cmds;
SYS_LOG_DBG("");
@ -1816,7 +1816,7 @@ static void supported_commands(u8_t *data, u16_t len)
tester_set_bit(cmds, GATT_CHANGE_DATABASE);
tester_send(BTP_SERVICE_ID_GATT, GATT_READ_SUPPORTED_COMMANDS,
CONTROLLER_INDEX, (u8_t *) rp, sizeof(cmds));
CONTROLLER_INDEX, (uint8_t *) rp, sizeof(cmds));
}
enum attr_type {
@ -1825,8 +1825,8 @@ enum attr_type {
BLE_GATT_ATTR_DSC,
};
void tester_handle_gatt(u8_t opcode, u8_t index, u8_t *data,
u16_t len)
void tester_handle_gatt(uint8_t opcode, uint8_t index, uint8_t *data,
uint16_t len)
{
switch (opcode) {
case GATT_READ_SUPPORTED_COMMANDS:
@ -1905,8 +1905,8 @@ void tester_handle_gatt(u8_t opcode, u8_t index, u8_t *data,
}
}
int tester_gatt_notify_rx_ev(u16_t conn_handle, u16_t attr_handle,
u8_t indication, struct os_mbuf *om)
int tester_gatt_notify_rx_ev(uint16_t conn_handle, uint16_t attr_handle,
uint8_t indication, struct os_mbuf *om)
{
struct gatt_notification_ev *ev;
struct ble_gap_conn_desc conn;
@ -1930,7 +1930,7 @@ int tester_gatt_notify_rx_ev(u16_t conn_handle, u16_t attr_handle,
ev->address_type = addr->type;
memcpy(ev->address, addr->val, sizeof(ev->address));
ev->type = (u8_t) (indication ? 0x02 : 0x01);
ev->type = (uint8_t) (indication ? 0x02 : 0x01);
ev->handle = sys_cpu_to_le16(attr_handle);
ev->data_length = sys_cpu_to_le16(os_mbuf_len(om));
os_mbuf_appendfrom(buf, om, 0, os_mbuf_len(om));
@ -1988,9 +1988,9 @@ void notify_test(struct os_event *ev)
}
}
int tester_gatt_subscribe_ev(u16_t conn_handle, u16_t attr_handle, u8_t reason,
u8_t prev_notify, u8_t cur_notify,
u8_t prev_indicate, u8_t cur_indicate)
int tester_gatt_subscribe_ev(uint16_t conn_handle, uint16_t attr_handle, uint8_t reason,
uint8_t prev_notify, uint8_t cur_notify,
uint8_t prev_indicate, uint8_t cur_indicate)
{
SYS_LOG_DBG("");
myconn_handle = conn_handle;
@ -2084,7 +2084,7 @@ int gatt_svr_init(void)
return 0;
}
u8_t tester_init_gatt(void)
uint8_t tester_init_gatt(void)
{
os_callout_init(&notify_tx_timer, os_eventq_dflt_get(),
notify_test, NULL);
@ -2092,7 +2092,7 @@ u8_t tester_init_gatt(void)
return BTP_STATUS_SUCCESS;
}
u8_t tester_unregister_gatt(void)
uint8_t tester_unregister_gatt(void)
{
return BTP_STATUS_SUCCESS;
}

View file

@ -33,8 +33,8 @@ const char *bt_hex(const void *buf, size_t len)
{
static const char hex[] = "0123456789abcdef";
static char hexbufs[4][137];
static u8_t curbuf;
const u8_t *b = buf;
static uint8_t curbuf;
const uint8_t *b = buf;
char *str;
int i;

View file

@ -22,11 +22,11 @@
#include "os/endian.h"
#define u8_t uint8_t
#define s8_t int8_t
#define u16_t uint16_t
#define u32_t uint32_t
#define s32_t int32_t
#define uint8_t uint8_t
#define int8_t int8_t
#define uint16_t uint16_t
#define uint32_t uint32_t
#define int32_t int32_t
#ifndef BIT
#define BIT(n) (1UL << (n))
@ -37,16 +37,16 @@
#define sys_le16_to_cpu le16toh
struct bt_data {
u8_t type;
u8_t data_len;
const u8_t *data;
uint8_t type;
uint8_t data_len;
const uint8_t *data;
};
#define BT_DATA(_type, _data, _data_len) \
{ \
.type = (_type), \
.data_len = (_data_len), \
.data = (const u8_t *)(_data), \
.data = (const uint8_t *)(_data), \
}
struct os_mbuf * NET_BUF_SIMPLE(uint16_t size);

View file

@ -33,11 +33,13 @@
#include "host/ble_gap.h"
#include "host/ble_l2cap.h"
#include "../../../nimble/host/src/ble_l2cap_priv.h"
#include "bttester.h"
#define CONTROLLER_INDEX 0
#define CHANNELS MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM)
#define TESTER_COC_MTU (230)
#define TESTER_COC_MTU MYNEWT_VAL(BTTESTER_L2CAP_COC_MTU)
#define TESTER_COC_BUF_COUNT (3 * MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM))
static os_membuf_t tester_sdu_coc_mem[
@ -48,14 +50,34 @@ struct os_mbuf_pool sdu_os_mbuf_pool;
static struct os_mempool sdu_coc_mbuf_mempool;
static struct channel {
u8_t chan_id; /* Internal number that identifies L2CAP channel. */
u8_t state;
uint8_t chan_id; /* Internal number that identifies L2CAP channel. */
uint8_t state;
struct ble_l2cap_chan *chan;
} channels[CHANNELS];
static u8_t recv_cb_buf[TESTER_COC_MTU + sizeof(struct l2cap_data_received_ev)];
static uint8_t recv_cb_buf[TESTER_COC_MTU + sizeof(struct l2cap_data_received_ev)];
struct channel *find_channel(struct ble_l2cap_chan *chan) {
static struct channel *get_free_channel(void)
{
uint8_t i;
struct channel *chan;
for (i = 0; i < CHANNELS; i++) {
if (channels[i].state) {
continue;
}
chan = &channels[i];
chan->chan_id = i;
return chan;
}
return NULL;
}
struct channel *find_channel(struct ble_l2cap_chan *chan)
{
int i;
for (i = 0; i < CHANNELS; ++i) {
@ -67,6 +89,15 @@ struct channel *find_channel(struct ble_l2cap_chan *chan) {
return NULL;
}
struct channel *get_channel(uint8_t chan_id)
{
if (chan_id >= CHANNELS) {
return NULL;
}
return &channels[chan_id];
}
static void
tester_l2cap_coc_recv(struct ble_l2cap_chan *chan, struct os_mbuf *sdu)
{
@ -84,14 +115,20 @@ static void recv_cb(uint16_t conn_handle, struct ble_l2cap_chan *chan,
struct os_mbuf *buf, void *arg)
{
struct l2cap_data_received_ev *ev = (void *) recv_cb_buf;
struct channel *channel = arg;
struct channel *channel = find_channel(chan);
assert(channel != NULL);
ev->chan_id = channel->chan_id;
ev->data_length = buf->om_len;
memcpy(ev->data, buf->om_data, buf->om_len);
ev->data_length = OS_MBUF_PKTLEN(buf);
if (ev->data_length > TESTER_COC_MTU) {
SYS_LOG_ERR("Too large sdu received, truncating data");
ev->data_length = TESTER_COC_MTU;
}
os_mbuf_copydata(buf, 0, ev->data_length, ev->data);
tester_send(BTP_SERVICE_ID_L2CAP, L2CAP_EV_DATA_RECEIVED,
CONTROLLER_INDEX, recv_cb_buf, sizeof(*ev) + buf->om_len);
CONTROLLER_INDEX, recv_cb_buf, sizeof(*ev) + ev->data_length);
tester_l2cap_coc_recv(chan, buf);
}
@ -108,44 +145,49 @@ static void unstalled_cb(uint16_t conn_handle, struct ble_l2cap_chan *chan,
}
}
static struct channel *get_free_channel(void)
static void reconfigured_ev(uint16_t conn_handle, struct ble_l2cap_chan *chan,
struct ble_l2cap_chan_info *chan_info,
int status)
{
u8_t i;
struct channel *chan;
struct l2cap_reconfigured_ev ev;
struct channel *channel;
for (i = 0; i < CHANNELS; i++) {
if (channels[i].state) {
continue;
if (status != 0) {
return;
}
chan = &channels[i];
chan->chan_id = i;
channel = find_channel(chan);
assert(channel != NULL);
return chan;
}
ev.chan_id = channel->chan_id;
ev.peer_mtu = chan_info->peer_coc_mtu;
ev.peer_mps = chan_info->peer_l2cap_mtu;
ev.our_mtu = chan_info->our_coc_mtu;
ev.our_mps = chan_info->our_l2cap_mtu;
return NULL;
tester_send(BTP_SERVICE_ID_L2CAP, L2CAP_EV_RECONFIGURED,
CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
}
static void connected_cb(uint16_t conn_handle, struct ble_l2cap_chan *chan,
void *arg)
struct ble_l2cap_chan_info *chan_info, void *arg)
{
struct l2cap_connected_ev ev;
struct ble_gap_conn_desc desc;
struct channel *channel;
struct channel *channel = find_channel(chan);
if (channel == NULL) {
channel = get_free_channel();
if (!channel) {
assert(0);
}
channel->chan = chan;
channel->state = 0;
ev.chan_id = channel->chan_id;
ev.psm = chan_info->psm;
ev.peer_mtu = chan_info->peer_coc_mtu;
ev.peer_mps = chan_info->peer_l2cap_mtu;
ev.our_mtu = chan_info->our_coc_mtu;
ev.our_mps = chan_info->our_l2cap_mtu;
channel->state = 1;
channel->chan = chan;
/* TODO: ev.psm */
if (!ble_gap_conn_find(conn_handle, &desc)) {
ev.address_type = desc.peer_ota_addr.type;
@ -154,11 +196,11 @@ static void connected_cb(uint16_t conn_handle, struct ble_l2cap_chan *chan,
}
tester_send(BTP_SERVICE_ID_L2CAP, L2CAP_EV_CONNECTED, CONTROLLER_INDEX,
(u8_t *) &ev, sizeof(ev));
(uint8_t *) &ev, sizeof(ev));
}
static void disconnected_cb(uint16_t conn_handle, struct ble_l2cap_chan *chan,
void *arg)
struct ble_l2cap_chan_info *chan_info, void *arg)
{
struct l2cap_disconnected_ev ev;
struct ble_gap_conn_desc desc;
@ -167,14 +209,12 @@ static void disconnected_cb(uint16_t conn_handle, struct ble_l2cap_chan *chan,
memset(&ev, 0, sizeof(struct l2cap_disconnected_ev));
channel = find_channel(chan);
if (channel != NULL) {
assert(channel != NULL);
channel->state = 0;
channel->chan = chan;
ev.chan_id = channel->chan_id;
/* TODO: ev.result */
/* TODO: ev.psm */
}
ev.psm = chan_info->psm;
if (!ble_gap_conn_find(conn_handle, &desc)) {
ev.address_type = desc.peer_ota_addr.type;
@ -183,7 +223,7 @@ static void disconnected_cb(uint16_t conn_handle, struct ble_l2cap_chan *chan,
}
tester_send(BTP_SERVICE_ID_L2CAP, L2CAP_EV_DISCONNECTED,
CONTROLLER_INDEX, (u8_t *) &ev, sizeof(ev));
CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
}
static int accept_cb(uint16_t conn_handle, uint16_t peer_mtu,
@ -208,39 +248,51 @@ static int
tester_l2cap_event(struct ble_l2cap_event *event, void *arg)
{
struct ble_l2cap_chan_info chan_info;
int accept_response;
switch (event->type) {
case BLE_L2CAP_EVENT_COC_CONNECTED:
if (ble_l2cap_get_chan_info(event->connect.chan, &chan_info)) {
assert(0);
}
if (event->connect.status) {
console_printf("LE COC error: %d\n", event->connect.status);
disconnected_cb(event->connect.conn_handle,
event->connect.chan, arg);
event->connect.chan, &chan_info, arg);
return 0;
}
ble_l2cap_get_chan_info(event->connect.chan, &chan_info);
console_printf("LE COC connected, conn: %d, chan: 0x%08lx, scid: 0x%04x, "
"dcid: 0x%04x, our_mtu: 0x%04x, peer_mtu: 0x%04x\n",
event->connect.conn_handle,
(uint32_t) event->connect.chan,
chan_info.scid,
chan_info.dcid,
chan_info.our_l2cap_mtu,
chan_info.peer_l2cap_mtu);
console_printf("LE COC connected, conn: %d, chan: 0x%08lx, "
"psm: 0x%02x, scid: 0x%04x, dcid: 0x%04x, "
"our_mps: %d, our_mtu: %d, peer_mps: %d, "
"peer_mtu: %d\n", event->connect.conn_handle,
(uint32_t) event->connect.chan, chan_info.psm,
chan_info.scid, chan_info.dcid,
chan_info.our_l2cap_mtu, chan_info.our_coc_mtu,
chan_info.peer_l2cap_mtu, chan_info.peer_coc_mtu);
connected_cb(event->connect.conn_handle,
event->connect.chan, arg);
event->connect.chan, &chan_info, arg);
return 0;
case BLE_L2CAP_EVENT_COC_DISCONNECTED:
if (ble_l2cap_get_chan_info(event->disconnect.chan,
&chan_info)) {
assert(0);
}
console_printf("LE CoC disconnected, chan: 0x%08lx\n",
(uint32_t) event->disconnect.chan);
disconnected_cb(event->disconnect.conn_handle,
event->disconnect.chan, arg);
event->disconnect.chan, &chan_info, arg);
return 0;
case BLE_L2CAP_EVENT_COC_ACCEPT:
accept_response = POINTER_TO_INT(arg);
if (accept_response) {
return accept_response;
}
console_printf("LE CoC accept, chan: 0x%08lx, handle: %u, sdu_size: %u\n",
(uint32_t) event->accept.chan,
event->accept.conn_handle,
@ -254,7 +306,8 @@ tester_l2cap_event(struct ble_l2cap_event *event, void *arg)
console_printf("LE CoC data received, chan: 0x%08lx, handle: %u, sdu_len: %u\n",
(uint32_t) event->receive.chan,
event->receive.conn_handle,
event->receive.sdu_rx->om_len);
OS_MBUF_PKTLEN(event->receive.sdu_rx));
recv_cb(event->receive.conn_handle, event->receive.chan,
event->receive.sdu_rx, arg);
return 0;
@ -263,57 +316,118 @@ tester_l2cap_event(struct ble_l2cap_event *event, void *arg)
(uint32_t) event->tx_unstalled.chan,
event->tx_unstalled.conn_handle,
event->tx_unstalled.status);
unstalled_cb(event->tx_unstalled.conn_handle,
event->tx_unstalled.chan,
event->tx_unstalled.status, arg);
return 0;
case BLE_L2CAP_EVENT_COC_RECONFIG_COMPLETED:
if (ble_l2cap_get_chan_info(event->reconfigured.chan,
&chan_info)) {
assert(0);
}
console_printf("LE CoC reconfigure completed status 0x%02x, "
"chan: 0x%08lx\n", event->reconfigured.status,
(uint32_t) event->reconfigured.chan);
if (event->reconfigured.status == 0) {
console_printf("\t our_mps: %d our_mtu %d\n",
chan_info.our_l2cap_mtu, chan_info.our_coc_mtu);
}
reconfigured_ev(event->reconfigured.conn_handle,
event->reconfigured.chan,
&chan_info,
event->reconfigured.status);
return 0;
case BLE_L2CAP_EVENT_COC_PEER_RECONFIGURED:
if (ble_l2cap_get_chan_info(event->reconfigured.chan,
&chan_info)) {
assert(0);
}
console_printf("LE CoC peer reconfigured status 0x%02x, "
"chan: 0x%08lx\n", event->reconfigured.status,
(uint32_t) event->reconfigured.chan);
if (event->reconfigured.status == 0) {
console_printf("\t peer_mps: %d peer_mtu %d\n",
chan_info.peer_l2cap_mtu, chan_info.peer_coc_mtu);
}
reconfigured_ev(event->reconfigured.conn_handle,
event->reconfigured.chan,
&chan_info,
event->reconfigured.status);
return 0;
default:
return 0;
}
}
static void connect(u8_t *data, u16_t len)
static void connect(uint8_t *data, uint16_t len)
{
const struct l2cap_connect_cmd *cmd = (void *) data;
struct l2cap_connect_rp rp;
uint8_t rp_buf[sizeof(struct l2cap_connect_rp) + cmd->num];
struct l2cap_connect_rp *rp = (void *) rp_buf;
struct ble_gap_conn_desc desc;
struct channel *chan;
struct os_mbuf *sdu_rx;
struct os_mbuf *sdu_rx[cmd->num];
ble_addr_t *addr = (void *) data;
uint16_t mtu = htole16(cmd->mtu);
int rc;
int i;
SYS_LOG_DBG("connect: type: %d addr: %s", addr->type, bt_hex(addr->val, 6));
if (mtu == 0 || mtu > TESTER_COC_MTU) {
mtu = TESTER_COC_MTU;
}
rc = ble_gap_conn_find_by_addr(addr, &desc);
if (rc) {
SYS_LOG_ERR("GAP conn find failed");
goto fail;
}
rp->num = cmd->num;
for (i = 0; i < cmd->num; i++) {
chan = get_free_channel();
if (!chan) {
SYS_LOG_ERR("No free channels");
goto fail;
}
sdu_rx = os_mbuf_get_pkthdr(&sdu_os_mbuf_pool, 0);
if (sdu_rx == NULL) {
rp->chan_ids[i] = chan->chan_id;
sdu_rx[i] = os_mbuf_get_pkthdr(&sdu_os_mbuf_pool, 0);
if (sdu_rx[i] == NULL) {
SYS_LOG_ERR("Failed to alloc buf");
goto fail;
}
}
if (cmd->num == 1) {
rc = ble_l2cap_connect(desc.conn_handle, htole16(cmd->psm),
TESTER_COC_MTU, sdu_rx,
tester_l2cap_event, chan);
mtu, sdu_rx[0],
tester_l2cap_event, NULL);
} else if (cmd->num > 1) {
rc = ble_l2cap_enhanced_connect(desc.conn_handle,
htole16(cmd->psm), mtu,
cmd->num, sdu_rx,
tester_l2cap_event, NULL);
} else {
SYS_LOG_ERR("Invalid 'num' parameter value");
goto fail;
}
if (rc) {
SYS_LOG_ERR("L2CAP connect failed\n");
goto fail;
}
rp.chan_id = chan->chan_id;
tester_send(BTP_SERVICE_ID_L2CAP, L2CAP_CONNECT, CONTROLLER_INDEX,
(u8_t *) &rp, sizeof(rp));
(uint8_t *) rp, sizeof(rp_buf));
return;
@ -322,16 +436,17 @@ fail:
BTP_STATUS_FAILED);
}
static void disconnect(u8_t *data, u16_t len)
static void disconnect(const uint8_t *data, uint16_t len)
{
const struct l2cap_disconnect_cmd *cmd = (void *) data;
struct channel *chan;
u8_t status;
uint8_t status;
int err;
SYS_LOG_DBG("");
chan = &channels[cmd->chan_id];
chan = get_channel(cmd->chan_id);
assert(chan != NULL);
err = ble_l2cap_disconnect(chan->chan);
if (err) {
@ -346,16 +461,21 @@ rsp:
status);
}
static void send_data(u8_t *data, u16_t len)
static void send_data(const uint8_t *data, uint16_t len)
{
const struct l2cap_send_data_cmd *cmd = (void *) data;
struct channel *chan = &channels[cmd->chan_id];
struct os_mbuf *sdu_tx = NULL;
int rc;
u16_t data_len = sys_le16_to_cpu(cmd->data_len);
uint16_t data_len = sys_le16_to_cpu(cmd->data_len);
struct channel *chan = get_channel(cmd->chan_id);
SYS_LOG_DBG("cmd->chan_id=%d", cmd->chan_id);
if (!chan) {
SYS_LOG_ERR("Invalid channel\n");
goto fail;
}
/* FIXME: For now, fail if data length exceeds buffer length */
if (data_len > TESTER_COC_MTU) {
SYS_LOG_ERR("Data length exceeds buffer length");
@ -386,16 +506,48 @@ fail:
BTP_STATUS_FAILED);
}
static void listen(u8_t *data, u16_t len)
static int
l2cap_coc_err2hs_err(uint16_t coc_err)
{
switch (coc_err) {
case BLE_L2CAP_COC_ERR_UNKNOWN_LE_PSM:
return BLE_HS_ENOTSUP;
case BLE_L2CAP_COC_ERR_NO_RESOURCES:
return BLE_HS_ENOMEM;
case BLE_L2CAP_COC_ERR_INSUFFICIENT_AUTHEN:
return BLE_HS_EAUTHEN;
case BLE_L2CAP_COC_ERR_INSUFFICIENT_AUTHOR:
return BLE_HS_EAUTHOR;
case BLE_L2CAP_COC_ERR_INSUFFICIENT_ENC:
return BLE_HS_EENCRYPT;
case BLE_L2CAP_COC_ERR_INSUFFICIENT_KEY_SZ:
return BLE_HS_EENCRYPT_KEY_SZ;
case BLE_L2CAP_COC_ERR_UNACCEPTABLE_PARAMETERS:
return BLE_HS_EINVAL;
default:
return 0;
}
}
static void listen(const uint8_t *data, uint16_t len)
{
const struct l2cap_listen_cmd *cmd = (void *) data;
uint16_t mtu = htole16(cmd->mtu);
uint16_t rsp = htole16(cmd->response);
int rc;
SYS_LOG_DBG("");
if (mtu == 0 || mtu > TESTER_COC_MTU) {
mtu = TESTER_COC_MTU;
}
rsp = l2cap_coc_err2hs_err(rsp);
/* TODO: Handle cmd->transport flag */
rc = ble_l2cap_create_server(cmd->psm, TESTER_COC_MTU,
tester_l2cap_event, NULL);
rc = ble_l2cap_create_server(cmd->psm, mtu, tester_l2cap_event,
INT_TO_POINTER(rsp));
if (rc) {
goto fail;
}
@ -409,9 +561,54 @@ fail:
BTP_STATUS_FAILED);
}
static void supported_commands(u8_t *data, u16_t len)
static void reconfigure(const uint8_t *data, uint16_t len)
{
u8_t cmds[1];
const struct l2cap_reconfigure_cmd *cmd = (void *) data;
uint16_t mtu = htole16(cmd->mtu);
struct ble_gap_conn_desc desc;
ble_addr_t *addr = (void *) data;
struct ble_l2cap_chan *chans[cmd->num];
struct channel *channel;
int rc;
int i;
SYS_LOG_DBG("");
if (mtu == 0 || mtu > TESTER_COC_MTU) {
mtu = TESTER_COC_MTU;
}
rc = ble_gap_conn_find_by_addr(addr, &desc);
if (rc) {
SYS_LOG_ERR("GAP conn find failed");
goto fail;
}
for (i = 0; i < cmd->num; ++i) {
channel = get_channel(cmd->idxs[i]);
if (channel == NULL) {
goto fail;
}
chans[i] = channel->chan;
}
rc = ble_l2cap_reconfig(chans, cmd->num, mtu);
if (rc) {
goto fail;
}
tester_rsp(BTP_SERVICE_ID_L2CAP, L2CAP_RECONFIGURE, CONTROLLER_INDEX,
BTP_STATUS_SUCCESS);
return;
fail:
tester_rsp(BTP_SERVICE_ID_L2CAP, L2CAP_RECONFIGURE, CONTROLLER_INDEX,
BTP_STATUS_FAILED);
}
static void supported_commands(uint8_t *data, uint16_t len)
{
uint8_t cmds[1];
struct l2cap_read_supported_commands_rp *rp = (void *) cmds;
memset(cmds, 0, sizeof(cmds));
@ -421,13 +618,14 @@ static void supported_commands(u8_t *data, u16_t len)
tester_set_bit(cmds, L2CAP_DISCONNECT);
tester_set_bit(cmds, L2CAP_LISTEN);
tester_set_bit(cmds, L2CAP_SEND_DATA);
tester_set_bit(cmds, L2CAP_RECONFIGURE);
tester_send(BTP_SERVICE_ID_L2CAP, L2CAP_READ_SUPPORTED_COMMANDS,
CONTROLLER_INDEX, (u8_t *) rp, sizeof(cmds));
CONTROLLER_INDEX, (uint8_t *) rp, sizeof(cmds));
}
void tester_handle_l2cap(u8_t opcode, u8_t index, u8_t *data,
u16_t len)
void tester_handle_l2cap(uint8_t opcode, uint8_t index, uint8_t *data,
uint16_t len)
{
switch (opcode) {
case L2CAP_READ_SUPPORTED_COMMANDS:
@ -445,6 +643,9 @@ void tester_handle_l2cap(u8_t opcode, u8_t index, u8_t *data,
case L2CAP_LISTEN:
listen(data, len);
return;
case L2CAP_RECONFIGURE:
reconfigure(data, len);
return;
default:
tester_rsp(BTP_SERVICE_ID_L2CAP, opcode, index,
BTP_STATUS_UNKNOWN_CMD);
@ -452,7 +653,7 @@ void tester_handle_l2cap(u8_t opcode, u8_t index, u8_t *data,
}
}
u8_t tester_init_l2cap(void)
uint8_t tester_init_l2cap(void)
{
int rc;
@ -469,7 +670,7 @@ u8_t tester_init_l2cap(void)
return BTP_STATUS_SUCCESS;
}
u8_t tester_unregister_l2cap(void)
uint8_t tester_unregister_l2cap(void)
{
return BTP_STATUS_SUCCESS;
}

View file

@ -38,7 +38,7 @@
#include "bttester.h"
extern u8_t own_addr_type;
extern uint8_t own_addr_type;
#define CONTROLLER_INDEX 0
#define CID_LOCAL 0xffff
@ -47,21 +47,21 @@ extern u8_t own_addr_type;
#define CUR_FAULTS_MAX 4
#define HEALTH_TEST_ID 0x00
static u8_t cur_faults[CUR_FAULTS_MAX];
static u8_t reg_faults[CUR_FAULTS_MAX * 2];
static uint8_t cur_faults[CUR_FAULTS_MAX];
static uint8_t reg_faults[CUR_FAULTS_MAX * 2];
/* Provision node data */
static u8_t net_key[16];
static u16_t net_key_idx;
static u8_t flags;
static u32_t iv_index;
static u16_t addr;
static u8_t dev_key[16];
static u8_t input_size;
static uint8_t net_key[16];
static uint16_t net_key_idx;
static uint8_t flags;
static uint32_t iv_index;
static uint16_t addr;
static uint8_t dev_key[16];
static uint8_t input_size;
/* Configured provisioning data */
static u8_t dev_uuid[16];
static u8_t static_auth[16];
static uint8_t dev_uuid[16];
static uint8_t static_auth[16];
/* Vendor Model data */
#define VND_MODEL_ID_1 0x1234
@ -71,20 +71,20 @@ static u8_t static_auth[16];
static struct model_data {
struct bt_mesh_model *model;
u16_t addr;
u16_t appkey_idx;
uint16_t addr;
uint16_t appkey_idx;
} model_bound[MODEL_BOUNDS_MAX];
static struct {
u16_t local;
u16_t dst;
u16_t net_idx;
uint16_t local;
uint16_t dst;
uint16_t net_idx;
} net = {
.local = BT_MESH_ADDR_UNASSIGNED,
.dst = BT_MESH_ADDR_UNASSIGNED,
};
static void supported_commands(u8_t *data, u16_t len)
static void supported_commands(uint8_t *data, uint16_t len)
{
struct os_mbuf *buf = NET_BUF_SIMPLE(BTP_DATA_MAX_SIZE);
@ -121,29 +121,9 @@ static void supported_commands(u8_t *data, u16_t len)
CONTROLLER_INDEX, buf);
}
static struct bt_mesh_cfg_srv cfg_srv = {
.relay = BT_MESH_RELAY_ENABLED,
.beacon = BT_MESH_BEACON_ENABLED,
#if MYNEWT_VAL(BLE_MESH_FRIEND)
.frnd = BT_MESH_FRIEND_ENABLED,
#else
.frnd = BT_MESH_FRIEND_NOT_SUPPORTED,
#endif
#if MYNEWT_VAL(BLE_MESH_GATT_PROXY)
.gatt_proxy = BT_MESH_GATT_PROXY_ENABLED,
#else
.gatt_proxy = BT_MESH_GATT_PROXY_NOT_SUPPORTED,
#endif
.default_ttl = 7,
/* 3 transmissions with 20ms interval */
.net_transmit = BT_MESH_TRANSMIT(2, 20),
.relay_retransmit = BT_MESH_TRANSMIT(2, 20),
};
static void get_faults(u8_t *faults, u8_t faults_size, u8_t *dst, u8_t *count)
static void get_faults(uint8_t *faults, uint8_t faults_size, uint8_t *dst, uint8_t *count)
{
u8_t i, limit = *count;
uint8_t i, limit = *count;
for (i = 0, *count = 0; i < faults_size && *count < limit; i++) {
if (faults[i]) {
@ -153,8 +133,8 @@ static void get_faults(u8_t *faults, u8_t faults_size, u8_t *dst, u8_t *count)
}
}
static int fault_get_cur(struct bt_mesh_model *model, u8_t *test_id,
u16_t *company_id, u8_t *faults, u8_t *fault_count)
static int fault_get_cur(struct bt_mesh_model *model, uint8_t *test_id,
uint16_t *company_id, uint8_t *faults, uint8_t *fault_count)
{
SYS_LOG_DBG("");
@ -166,8 +146,8 @@ static int fault_get_cur(struct bt_mesh_model *model, u8_t *test_id,
return 0;
}
static int fault_get_reg(struct bt_mesh_model *model, u16_t company_id,
u8_t *test_id, u8_t *faults, u8_t *fault_count)
static int fault_get_reg(struct bt_mesh_model *model, uint16_t company_id,
uint8_t *test_id, uint8_t *faults, uint8_t *fault_count)
{
SYS_LOG_DBG("company_id 0x%04x", company_id);
@ -229,7 +209,7 @@ health_pub_init(void)
static struct bt_mesh_cfg_cli cfg_cli = {
};
void show_faults(u8_t test_id, u16_t cid, u8_t *faults, size_t fault_count)
void show_faults(uint8_t test_id, uint16_t cid, uint8_t *faults, size_t fault_count)
{
size_t i;
@ -247,8 +227,8 @@ void show_faults(u8_t test_id, u16_t cid, u8_t *faults, size_t fault_count)
}
}
static void health_current_status(struct bt_mesh_health_cli *cli, u16_t addr,
u8_t test_id, u16_t cid, u8_t *faults,
static void health_current_status(struct bt_mesh_health_cli *cli, uint16_t addr,
uint8_t test_id, uint16_t cid, uint8_t *faults,
size_t fault_count)
{
SYS_LOG_DBG("Health Current Status from 0x%04x", addr);
@ -260,7 +240,7 @@ static struct bt_mesh_health_cli health_cli = {
};
static struct bt_mesh_model root_models[] = {
BT_MESH_MODEL_CFG_SRV(&cfg_srv),
BT_MESH_MODEL_CFG_SRV,
BT_MESH_MODEL_CFG_CLI(&cfg_cli),
BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub),
BT_MESH_MODEL_HEALTH_CLI(&health_cli),
@ -295,7 +275,7 @@ static void link_open(bt_mesh_prov_bearer_t bearer)
}
tester_send(BTP_SERVICE_ID_MESH, MESH_EV_PROV_LINK_OPEN,
CONTROLLER_INDEX, (u8_t *) &ev, sizeof(ev));
CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
}
static void link_close(bt_mesh_prov_bearer_t bearer)
@ -318,10 +298,10 @@ static void link_close(bt_mesh_prov_bearer_t bearer)
}
tester_send(BTP_SERVICE_ID_MESH, MESH_EV_PROV_LINK_CLOSED,
CONTROLLER_INDEX, (u8_t *) &ev, sizeof(ev));
CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
}
static int output_number(bt_mesh_output_action_t action, u32_t number)
static int output_number(bt_mesh_output_action_t action, uint32_t number)
{
struct mesh_out_number_action_ev ev;
@ -331,7 +311,7 @@ static int output_number(bt_mesh_output_action_t action, u32_t number)
ev.number = sys_cpu_to_le32(number);
tester_send(BTP_SERVICE_ID_MESH, MESH_EV_OUT_NUMBER_ACTION,
CONTROLLER_INDEX, (u8_t *) &ev, sizeof(ev));
CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
return 0;
}
@ -357,7 +337,7 @@ static int output_string(const char *str)
return 0;
}
static int input(bt_mesh_input_action_t action, u8_t size)
static int input(bt_mesh_input_action_t action, uint8_t size)
{
struct mesh_in_action_ev ev;
@ -369,12 +349,15 @@ static int input(bt_mesh_input_action_t action, u8_t size)
ev.size = size;
tester_send(BTP_SERVICE_ID_MESH, MESH_EV_IN_ACTION, CONTROLLER_INDEX,
(u8_t *) &ev, sizeof(ev));
(uint8_t *) &ev, sizeof(ev));
return 0;
}
static void prov_complete(u16_t net_idx, u16_t addr)
static uint8_t vnd_app_key[16];
static uint16_t vnd_app_key_idx = 0x000f;
static void prov_complete(uint16_t net_idx, uint16_t addr)
{
SYS_LOG_DBG("net_idx 0x%04x addr 0x%04x", net_idx, addr);
@ -412,7 +395,7 @@ static struct bt_mesh_prov prov = {
.reset = prov_reset,
};
static void config_prov(u8_t *data, u16_t len)
static void config_prov(uint8_t *data, uint16_t len)
{
const struct mesh_config_provisioning_cmd *cmd = (void *) data;
@ -430,7 +413,7 @@ static void config_prov(u8_t *data, u16_t len)
CONTROLLER_INDEX, BTP_STATUS_SUCCESS);
}
static void provision_node(u8_t *data, u16_t len)
static void provision_node(uint8_t *data, uint16_t len)
{
const struct mesh_provision_node_cmd *cmd = (void *) data;
@ -448,9 +431,9 @@ static void provision_node(u8_t *data, u16_t len)
CONTROLLER_INDEX, BTP_STATUS_SUCCESS);
}
static void init(u8_t *data, u16_t len)
static void init(uint8_t *data, uint16_t len)
{
u8_t status = BTP_STATUS_SUCCESS;
uint8_t status = BTP_STATUS_SUCCESS;
int err;
SYS_LOG_DBG("");
@ -475,15 +458,12 @@ static void init(u8_t *data, u16_t len)
}
}
/* Set device key for vendor model */
vnd_models[0].keys[0] = BT_MESH_KEY_DEV;
rsp:
tester_rsp(BTP_SERVICE_ID_MESH, MESH_INIT, CONTROLLER_INDEX,
status);
}
static void reset(u8_t *data, u16_t len)
static void reset(uint8_t *data, uint16_t len)
{
SYS_LOG_DBG("");
@ -493,11 +473,11 @@ static void reset(u8_t *data, u16_t len)
BTP_STATUS_SUCCESS);
}
static void input_number(u8_t *data, u16_t len)
static void input_number(uint8_t *data, uint16_t len)
{
const struct mesh_input_number_cmd *cmd = (void *) data;
u8_t status = BTP_STATUS_SUCCESS;
u32_t number;
uint8_t status = BTP_STATUS_SUCCESS;
uint32_t number;
int err;
number = sys_le32_to_cpu(cmd->number);
@ -513,11 +493,11 @@ static void input_number(u8_t *data, u16_t len)
status);
}
static void input_string(u8_t *data, u16_t len)
static void input_string(uint8_t *data, uint16_t len)
{
const struct mesh_input_string_cmd *cmd = (void *) data;
u8_t status = BTP_STATUS_SUCCESS;
u8_t str_auth[16];
uint8_t status = BTP_STATUS_SUCCESS;
uint8_t str_auth[16];
int err;
SYS_LOG_DBG("");
@ -544,7 +524,7 @@ rsp:
status);
}
static void ivu_test_mode(u8_t *data, u16_t len)
static void ivu_test_mode(uint8_t *data, uint16_t len)
{
const struct mesh_ivu_test_mode_cmd *cmd = (void *) data;
@ -556,7 +536,7 @@ static void ivu_test_mode(u8_t *data, u16_t len)
BTP_STATUS_SUCCESS);
}
static void ivu_toggle_state(u8_t *data, u16_t len)
static void ivu_toggle_state(uint8_t *data, uint16_t len)
{
bool result;
@ -571,7 +551,7 @@ static void ivu_toggle_state(u8_t *data, u16_t len)
result ? BTP_STATUS_SUCCESS : BTP_STATUS_FAILED);
}
static void lpn(u8_t *data, u16_t len)
static void lpn(uint8_t *data, uint16_t len)
{
struct mesh_lpn_set_cmd *cmd = (void *) data;
bool enable;
@ -589,7 +569,7 @@ static void lpn(u8_t *data, u16_t len)
err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS);
}
static void lpn_poll(u8_t *data, u16_t len)
static void lpn_poll(uint8_t *data, uint16_t len)
{
int err;
@ -604,13 +584,13 @@ static void lpn_poll(u8_t *data, u16_t len)
err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS);
}
static void net_send(u8_t *data, u16_t len)
static void net_send(uint8_t *data, uint16_t len)
{
struct mesh_net_send_cmd *cmd = (void *) data;
struct os_mbuf *msg = NET_BUF_SIMPLE(UINT8_MAX);
struct bt_mesh_msg_ctx ctx = {
.net_idx = net.net_idx,
.app_idx = BT_MESH_KEY_DEV,
.app_idx = vnd_app_key_idx,
.addr = sys_le16_to_cpu(cmd->dst),
.send_ttl = cmd->ttl,
};
@ -619,6 +599,12 @@ static void net_send(u8_t *data, u16_t len)
SYS_LOG_DBG("ttl 0x%02x dst 0x%04x payload_len %d", ctx.send_ttl,
ctx.addr, cmd->payload_len);
if (!bt_mesh_app_key_get(vnd_app_key_idx)) {
(void)bt_mesh_app_key_add(vnd_app_key_idx, net.net_idx,
vnd_app_key);
vnd_models[0].keys[0] = vnd_app_key_idx;
}
net_buf_simple_add_mem(msg, cmd->payload, cmd->payload_len);
err = bt_mesh_model_send(&vnd_models[0], &ctx, msg, NULL, NULL);
@ -632,13 +618,13 @@ static void net_send(u8_t *data, u16_t len)
os_mbuf_free_chain(msg);
}
static void health_generate_faults(u8_t *data, u16_t len)
static void health_generate_faults(uint8_t *data, uint16_t len)
{
struct mesh_health_generate_faults_rp *rp;
struct os_mbuf *buf = NET_BUF_SIMPLE(sizeof(*rp) + sizeof(cur_faults) +
sizeof(reg_faults));
u8_t some_faults[] = { 0x01, 0x02, 0x03, 0xff, 0x06 };
u8_t cur_faults_count, reg_faults_count;
uint8_t some_faults[] = { 0x01, 0x02, 0x03, 0xff, 0x06 };
uint8_t cur_faults_count, reg_faults_count;
rp = net_buf_simple_add(buf, sizeof(*rp));
@ -658,7 +644,7 @@ static void health_generate_faults(u8_t *data, u16_t len)
CONTROLLER_INDEX, buf);
}
static void health_clear_faults(u8_t *data, u16_t len)
static void health_clear_faults(uint8_t *data, uint16_t len)
{
SYS_LOG_DBG("");
@ -671,7 +657,7 @@ static void health_clear_faults(u8_t *data, u16_t len)
CONTROLLER_INDEX, BTP_STATUS_SUCCESS);
}
static void model_send(u8_t *data, u16_t len)
static void model_send(uint8_t *data, uint16_t len)
{
struct mesh_model_send_cmd *cmd = (void *) data;
struct os_mbuf *msg = NET_BUF_SIMPLE(UINT8_MAX);
@ -683,7 +669,7 @@ static void model_send(u8_t *data, u16_t len)
};
struct bt_mesh_model *model = NULL;
int err, i;
u16_t src = sys_le16_to_cpu(cmd->src);
uint16_t src = sys_le16_to_cpu(cmd->src);
/* Lookup source address */
for (i = 0; i < ARRAY_SIZE(model_bound); i++) {
@ -720,10 +706,10 @@ fail:
}
#if MYNEWT_VAL(BLE_MESH_TESTING)
static void lpn_subscribe(u8_t *data, u16_t len)
static void lpn_subscribe(uint8_t *data, uint16_t len)
{
struct mesh_lpn_subscribe_cmd *cmd = (void *) data;
u16_t address = sys_le16_to_cpu(cmd->address);
uint16_t address = sys_le16_to_cpu(cmd->address);
int err;
SYS_LOG_DBG("address 0x%04x", address);
@ -737,10 +723,10 @@ static void lpn_subscribe(u8_t *data, u16_t len)
err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS);
}
static void lpn_unsubscribe(u8_t *data, u16_t len)
static void lpn_unsubscribe(uint8_t *data, uint16_t len)
{
struct mesh_lpn_unsubscribe_cmd *cmd = (void *) data;
u16_t address = sys_le16_to_cpu(cmd->address);
uint16_t address = sys_le16_to_cpu(cmd->address);
int err;
SYS_LOG_DBG("address 0x%04x", address);
@ -754,7 +740,7 @@ static void lpn_unsubscribe(u8_t *data, u16_t len)
err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS);
}
static void rpl_clear(u8_t *data, u16_t len)
static void rpl_clear(uint8_t *data, uint16_t len)
{
int err;
@ -770,7 +756,7 @@ static void rpl_clear(u8_t *data, u16_t len)
}
#endif /* MYNEWT_VAL(BLE_MESH_TESTING) */
static void proxy_identity_enable(u8_t *data, u16_t len)
static void proxy_identity_enable(uint8_t *data, uint16_t len)
{
int err;
@ -785,7 +771,7 @@ static void proxy_identity_enable(u8_t *data, u16_t len)
err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS);
}
void tester_handle_mesh(u8_t opcode, u8_t index, u8_t *data, u16_t len)
void tester_handle_mesh(uint8_t opcode, uint8_t index, uint8_t *data, uint16_t len)
{
switch (opcode) {
case MESH_READ_SUPPORTED_COMMANDS:
@ -854,7 +840,7 @@ void tester_handle_mesh(u8_t opcode, u8_t index, u8_t *data, u16_t len)
}
}
void net_recv_ev(u8_t ttl, u8_t ctl, u16_t src, u16_t dst, const void *payload,
void net_recv_ev(uint8_t ttl, uint8_t ctl, uint16_t src, uint16_t dst, const void *payload,
size_t payload_len)
{
struct os_mbuf *buf = NET_BUF_SIMPLE(UINT8_MAX);
@ -883,8 +869,8 @@ done:
os_mbuf_free_chain(buf);
}
static void model_bound_cb(u16_t addr, struct bt_mesh_model *model,
u16_t key_idx)
static void model_bound_cb(uint16_t addr, struct bt_mesh_model *model,
uint16_t key_idx)
{
int i;
@ -904,8 +890,8 @@ static void model_bound_cb(u16_t addr, struct bt_mesh_model *model,
SYS_LOG_ERR("model_bound is full");
}
static void model_unbound_cb(u16_t addr, struct bt_mesh_model *model,
u16_t key_idx)
static void model_unbound_cb(uint16_t addr, struct bt_mesh_model *model,
uint16_t key_idx)
{
int i;
@ -925,7 +911,7 @@ static void model_unbound_cb(u16_t addr, struct bt_mesh_model *model,
SYS_LOG_INF("model not found");
}
static void invalid_bearer_cb(u8_t opcode)
static void invalid_bearer_cb(uint8_t opcode)
{
struct mesh_invalid_bearer_ev ev = {
.opcode = opcode,
@ -934,7 +920,7 @@ static void invalid_bearer_cb(u8_t opcode)
SYS_LOG_DBG("opcode 0x%02x", opcode);
tester_send(BTP_SERVICE_ID_MESH, MESH_EV_INVALID_BEARER,
CONTROLLER_INDEX, (u8_t *) &ev, sizeof(ev));
CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
}
static void incomp_timer_exp_cb(void)
@ -951,7 +937,7 @@ static struct bt_test_cb bt_test_cb = {
.mesh_trans_incomp_timer_exp = incomp_timer_exp_cb,
};
u8_t tester_init_mesh(void)
uint8_t tester_init_mesh(void)
{
health_pub_init();
@ -962,7 +948,7 @@ u8_t tester_init_mesh(void)
return BTP_STATUS_SUCCESS;
}
u8_t tester_unregister_mesh(void)
uint8_t tester_unregister_mesh(void)
{
return BTP_STATUS_SUCCESS;
}

View file

@ -31,7 +31,7 @@ static struct hal_timer rtt_timer;
static bttester_pipe_recv_cb app_cb;
static u8_t *recv_buf;
static uint8_t *recv_buf;
static size_t recv_buf_len;
static size_t recv_off;
@ -74,7 +74,7 @@ rtt_pipe_poll_func(void *arg)
itvl_ms = min(itvl_ms, RTT_INPUT_POLL_INTERVAL_MAX);
} else {
while (key >= 0 && avail > 0) {
recv_buf[recv_off] = (u8_t) key;
recv_buf[recv_off] = (uint8_t) key;
recv_off++;
avail = recv_buf_len - recv_off;
key = rtt_pipe_get_char((unsigned int) rtt_index_down);
@ -93,14 +93,14 @@ rtt_pipe_poll_func(void *arg)
}
int
bttester_pipe_send(const u8_t *data, int len)
bttester_pipe_send(const uint8_t *data, int len)
{
SEGGER_RTT_Write((unsigned int) rtt_index_up, data, (unsigned int) len);
return 0;
}
void
bttester_pipe_register(u8_t *buf, size_t len, bttester_pipe_recv_cb cb)
bttester_pipe_register(uint8_t *buf, size_t len, bttester_pipe_recv_cb cb)
{
recv_buf = buf;
recv_buf_len = len;

View file

@ -26,7 +26,7 @@
#include "bttester_pipe.h"
static u8_t *recv_buf;
static uint8_t *recv_buf;
static size_t recv_buf_len;
static bttester_pipe_recv_cb app_cb;
static size_t recv_off;
@ -144,7 +144,7 @@ uart_console_rx_char(void *arg, uint8_t byte)
static int
uart_pipe_handle_char(int key)
{
recv_buf[recv_off] = (u8_t) key;
recv_buf[recv_off] = (uint8_t) key;
recv_off++;
return 0;
@ -194,7 +194,7 @@ uart_console_rx_char_event(struct os_event *ev)
}
int
bttester_pipe_send(const u8_t *data, int len)
bttester_pipe_send(const uint8_t *data, int len)
{
int i;
@ -272,7 +272,7 @@ bttester_pipe_init(void)
}
void
bttester_pipe_register(u8_t *buf, size_t len, bttester_pipe_recv_cb cb)
bttester_pipe_register(uint8_t *buf, size_t len, bttester_pipe_recv_cb cb)
{
recv_buf = buf;
recv_buf_len = len;

View file

@ -53,7 +53,7 @@ syscfg.defs:
BTTESTER_CONN_RETRY:
description: Retry connections when connection failed to be established
value: 3
value: 0
BTTESTER_BTP_DATA_SIZE_MAX:
description: Maximum BTP payload
@ -71,12 +71,16 @@ syscfg.defs:
description: Enable logging BTP traffic
value: 0
BTTESTER_L2CAP_COC_MTU:
description: Maximum MTU size the application can handle
value: 230
syscfg.vals:
OS_MAIN_STACK_SIZE: 512
SHELL_TASK: 0
SHELL_NEWTMGR: 0
LOG_LEVEL: 12
MSYS_1_BLOCK_COUNT: 48
MSYS_1_BLOCK_COUNT: 80
BLE_MONITOR_RTT: 1
CONSOLE_RTT: 0
@ -86,6 +90,8 @@ syscfg.vals:
BLE_L2CAP_COC_MAX_NUM: 2
BLE_L2CAP_SIG_MAX_PROCS: 2
BLE_L2CAP_ENHANCED_COC: 1
BLE_VERSION: 52
# Some testcases require MPS < MTU
BLE_L2CAP_COC_MPS: 100
BLE_RPA_TIMEOUT: 30
@ -98,6 +104,9 @@ syscfg.vals:
BLE_SVC_GAP_PPCP_MIN_CONN_INTERVAL: 9
BLE_SVC_GAP_PPCP_MAX_CONN_INTERVAL: 30
BLE_SVC_GAP_PPCP_SUPERVISION_TMO: 2000
BLE_SVC_GAP_APPEARANCE_WRITE_PERM: 0
BLE_SVC_GAP_DEVICE_NAME_WRITE_PERM: 0
BLE_STORE_CONFIG_PERSIST: 0
BLE_MESH: 1
BLE_MESH_SHELL: 0
@ -117,6 +126,11 @@ syscfg.vals:
BLE_MESH_FRIEND: 1
BLE_MESH_CFG_CLI: 1
BLE_MESH_RX_SDU_MAX: 110
BLE_MESH_HEALTH_CLI: 1
BLE_MESH_FRIEND_QUEUE_SIZE: 32
BLE_MESH_RX_SEG_MAX: 13
BLE_MESH_TX_SEG_MSG_COUNT: 2
BLE_MAX_CONNECTIONS: 8
BLE_MESH_ADV_BUF_COUNT: 20
BLE_MESH_TX_SEG_MAX: 6

View file

@ -0,0 +1,34 @@
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
pkg.name: "apps/central"
pkg.type: app
pkg.description: "Basic central application"
pkg.author: "Krzysztof Kopyściński <krzysztof.kopyscinski@codecoup.pl>"
pkg.deps:
- "@apache-mynewt-core/kernel/os"
- "@apache-mynewt-core/sys/console/full"
- "@apache-mynewt-core/sys/log/full"
- "@apache-mynewt-core/sys/stats/full"
- "@apache-mynewt-core/sys/log/modlog"
- "@apache-mynewt-nimble/nimble/host"
- "@apache-mynewt-nimble/nimble/host/util/"
- "@apache-mynewt-nimble/nimble/host/store/config"
- "@apache-mynewt-nimble/nimble/transport"

View file

@ -0,0 +1,186 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#include "sysinit/sysinit.h"
#include "os/os.h"
#include "console/console.h"
#include "host/ble_hs.h"
#include "host/util/util.h"
#include "console/console.h"
#include "log/log.h"
static uint8_t g_own_addr_type;
static void
ble_app_set_addr(void)
{
ble_addr_t addr;
int rc;
/* generate new non-resolvable private address */
rc = ble_hs_id_gen_rnd(0, &addr);
assert(rc == 0);
/* set generated address */
rc = ble_hs_id_set_rnd(addr.val);
assert(rc == 0);
}
/* scan_event() calls scan(), so forward declaration is required */
static void scan(void);
/* connection has separate event handler from scan */
static int
conn_event(struct ble_gap_event *event, void *arg)
{
switch (event->type) {
case BLE_GAP_EVENT_CONNECT:
if (event->connect.status == 0) {
MODLOG_DFLT(INFO,"Connection was established\n");
ble_gap_terminate(event->connect.conn_handle, 0x13);
} else {
MODLOG_DFLT(INFO,"Connection failed, error code: %i\n",
event->connect.status);
}
break;
case BLE_GAP_EVENT_DISCONNECT:
MODLOG_DFLT(INFO,"Disconnected, reason code: %i\n",
event->disconnect.reason);
scan();
break;
case BLE_GAP_EVENT_CONN_UPDATE_REQ:
MODLOG_DFLT(INFO,"Connection update request received\n");
break;
case BLE_GAP_EVENT_CONN_UPDATE:
if (event->conn_update.status == 0) {
MODLOG_DFLT(INFO,"Connection update successful\n");
} else {
MODLOG_DFLT(INFO,"Connection update failed; reson: %d\n",
event->conn_update.status);
}
break;
default:
MODLOG_DFLT(INFO,"Connection event type not supported, %d\n",
event->type);
break;
}
return 0;
}
static int
scan_event(struct ble_gap_event *event, void *arg)
{
/* predef_uuid stores information about UUID of device,
that we connect to */
const ble_uuid128_t predef_uuid =
BLE_UUID128_INIT(0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff);
struct ble_hs_adv_fields parsed_fields;
int uuid_cmp_result;
memset(&parsed_fields, 0, sizeof(parsed_fields));
switch (event->type) {
/* advertising report has been received during discovery procedure */
case BLE_GAP_EVENT_DISC:
MODLOG_DFLT(INFO, "Advertising report received! Checking UUID...\n");
ble_hs_adv_parse_fields(&parsed_fields, event->disc.data,
event->disc.length_data);
/* Predefined UUID is compared to recieved one;
if doesn't fit - end procedure and go back to scanning,
else - connect. */
uuid_cmp_result = ble_uuid_cmp(&predef_uuid.u, &parsed_fields.uuids128->u);
if (uuid_cmp_result) {
MODLOG_DFLT(INFO, "UUID doesn't fit\n");
} else {
MODLOG_DFLT(INFO, "UUID fits, connecting...\n");
ble_gap_disc_cancel();
ble_gap_connect(g_own_addr_type, &(event->disc.addr), 10000,
NULL, conn_event, NULL);
}
break;
case BLE_GAP_EVENT_DISC_COMPLETE:
MODLOG_DFLT(INFO,"Discovery completed, reason: %d\n",
event->disc_complete.reason);
scan();
break;
default:
MODLOG_DFLT(ERROR, "Discovery event not handled\n");
break;
}
return 0;
}
static void
scan(void)
{
int rc;
/* set scan parameters:
- scan interval in 0.625ms units
- scan window in 0.625ms units
- filter policy - 0 if whitelisting not used
- limited - should limited discovery be used
- passive - should passive scan be used
- filter duplicates - 1 enables filtering duplicated advertisements */
const struct ble_gap_disc_params scan_params = {10000, 200, 0, 0, 0, 1};
/* performs discovery procedure */
rc = ble_gap_disc(g_own_addr_type, 10000, &scan_params,scan_event, NULL);
assert(rc == 0);
}
static void
on_sync(void)
{
int rc;
/* Generate a non-resolvable private address. */
ble_app_set_addr();
/* g_own_addr_type will store type of addres our BSP uses */
rc = ble_hs_util_ensure_addr(0);
rc = ble_hs_id_infer_auto(0, &g_own_addr_type);
assert(rc == 0);
/* begin scanning */
scan();
}
static void
on_reset(int reason)
{
console_printf("Resetting state; reason=%d\n", reason);
}
int
main(int argc, char **argv)
{
/* Initialize all packages. */
sysinit();
ble_hs_cfg.sync_cb = on_sync;
ble_hs_cfg.reset_cb = on_reset;
/* As the last thing, process events from default event queue. */
while (1) {
os_eventq_run(os_eventq_dflt_get());
}
return 0;
}

View file

@ -0,0 +1,48 @@
### Mesh Badge
##### Overview
********
This sample app for the reel board showcases Bluetooth Mesh
The app starts off as a regular Bluetooth GATT peripheral application.
Install the the "nRF Connect" app on your phone (available both for
Android and iOS) to access the service that the app exposes. The service
can also be accessed with any Bluetooth LE GATT client from your PC,
however these instructions focus on the necessary steps for phones.
##### Steps to set up
***************
* On your phone, use the nRF Connect app to Scan for devices and look
for "reel board"
* Connect to the device. You'll see a single service - select it
* Request to write to the characteristic by pressing on the upward pointing
arrow symbol
* Select "Text" to enter text instead of hex
* Enter your name (or any other arbitrary text). Multiple words
separated by spaces are possible. The font used on the reel display
allows three rows of up to 12 characters
wide text. You can force line breaks with a comma.
* Press "Send" - this will trigger pairing since this is a protected
characteristic. The passkey for the pairing will be shown on the board's
display. Enter the passkey in your phone.
* Once pairing is complete the board will show the text you sent. If
you're not happy with it you can try writing something else.
* When you're happy with the text, disconnect from the board (exit the app or
go back to the device scan page)
* Once disconnected the board switches over to Bluetooth Mesh mode, and you
can't connect to it anymore over GATT.
If you configure multiple boards like this they can communicate with
each other over mesh: by pressing the user button on the board the first
word (name) of the stored text will be sent to all other boards in
the network and cause the other boards to display "<name> says hi!".
To reset a board to its initial state (disable mesh, erase the stored
text, and make it connectable over GATT):
* Keep the user button pressed when powering on (or press the reset button
when powered)
* Wait until "Reseting Device" is shown

View file

@ -0,0 +1,39 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
pkg.name: apps/mesh_badge
pkg.type: app
pkg.description: Sample app for the reel board that showcases Bluetooth Mesh
pkg.author: "Apache Mynewt <dev@mynewt.apache.org>"
pkg.homepage: "http://mynewt.apache.org/"
pkg.keywords:
pkg.deps:
- "@apache-mynewt-core/hw/drivers/display/cfb"
- "@apache-mynewt-core/hw/drivers/display/ssd1673"
- "@apache-mynewt-core/kernel/os"
- "@apache-mynewt-core/sys/console/full"
- "@apache-mynewt-core/sys/log/full"
- "@apache-mynewt-core/sys/log/modlog"
- "@apache-mynewt-core/sys/stats/full"
- "@apache-mynewt-core/sys/shell"
- nimble/controller
- nimble/host
- nimble/host/services/gap
- nimble/host/services/gatt
- nimble/host/store/config
- nimble/transport/ram

View file

@ -0,0 +1,15 @@
/*
* Copyright (c) 2018 Phytec Messtechnik GmbH
* Copyright (c) 2018 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "mesh/mesh.h"
void board_refresh_display(void);
void board_show_text(const char *text, bool center, int32_t duration);
void board_blink_leds(void);
void board_add_hello(uint16_t addr, const char *name);
void board_add_heartbeat(uint16_t addr, uint8_t hops);
int board_init(void);

View file

@ -0,0 +1,226 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include "services/gap/ble_svc_gap.h"
#include "bsp/bsp.h"
#include "host/ble_hs.h"
#include "host/ble_uuid.h"
#include "mesh.h"
#include "board.h"
#include "mesh_badge.h"
static const ble_uuid16_t gatt_cud_uuid = BLE_UUID16_INIT(0x2901);
static const ble_uuid16_t gatt_cpf_uuid = BLE_UUID16_INIT(0x2904);
/** @brief GATT Characteristic Presentation Format Attribute Value. */
struct bt_gatt_cpf {
/** Format of the value of the characteristic */
uint8_t format;
/** Exponent field to determine how the value of this characteristic is further formatted */
int8_t exponent;
/** Unit of the characteristic */
uint16_t unit;
/** Name space of the description */
uint8_t name_space;
/** Description of the characteristic as defined in a higher layer profile */
uint16_t description;
} __packed;
#define CPF_FORMAT_UTF8 0x19
static const struct bt_gatt_cpf name_cpf = {
.format = CPF_FORMAT_UTF8,
};
static const ble_uuid128_t name_uuid = BLE_UUID128_INIT(
0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12,
0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12);
static const ble_uuid128_t name_enc_uuid = BLE_UUID128_INIT(
0xf1, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12,
0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12);
static int
gatt_svr_chr_access(uint16_t conn_handle, uint16_t attr_handle,
struct ble_gatt_access_ctxt *ctxt,
void *arg);
static const struct ble_gatt_svc_def gatt_svr_svcs[] = {
{
.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid = &name_uuid.u,
.characteristics = (struct ble_gatt_chr_def[]) { {
.uuid = &name_enc_uuid.u,
.access_cb = gatt_svr_chr_access,
.flags = BLE_GATT_CHR_F_READ |
BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_WRITE_ENC,
.descriptors = (struct ble_gatt_dsc_def[]) { {
.uuid = &gatt_cud_uuid.u,
.access_cb = gatt_svr_chr_access,
.att_flags = BLE_ATT_F_READ,
}, {
.uuid = &gatt_cpf_uuid.u,
.access_cb = gatt_svr_chr_access,
.att_flags = BLE_ATT_F_READ,
}, {
0, /* No more descriptors in this characteristic. */
} }
}, {
0, /* No more characteristics in this service. */
} },
},
{
0, /* No more services. */
},
};
static int read_name(struct os_mbuf *om)
{
const char *value = bt_get_name();
int rc;
rc = os_mbuf_append(om, value, (uint16_t) strlen(value));
return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
}
static int write_name(struct os_mbuf *om)
{
char name[MYNEWT_VAL(BLE_SVC_GAP_DEVICE_NAME_MAX_LENGTH)];
uint16_t len;
uint16_t om_len;
int rc;
om_len = OS_MBUF_PKTLEN(om);
if (om_len >= sizeof(name)) {
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
}
rc = ble_hs_mbuf_to_flat(om, name, sizeof(name) - 1, &len);
if (rc != 0) {
return BLE_ATT_ERR_UNLIKELY;
}
name[len] = '\0';
rc = bt_set_name(name);
if (rc) {
return BLE_ATT_ERR_INSUFFICIENT_RES;
}
board_refresh_display();
return 0;
}
static int
gatt_svr_chr_access(uint16_t conn_handle, uint16_t attr_handle,
struct ble_gatt_access_ctxt *ctxt,
void *arg)
{
const ble_uuid_t *uuid;
int rc;
uuid = ctxt->chr->uuid;
if (ble_uuid_cmp(uuid, &name_enc_uuid.u) == 0) {
switch (ctxt->op) {
case BLE_GATT_ACCESS_OP_READ_CHR:
rc = read_name(ctxt->om);
return rc;
case BLE_GATT_ACCESS_OP_WRITE_CHR:
rc = write_name(ctxt->om);
return rc;
default:
assert(0);
return BLE_ATT_ERR_UNLIKELY;
}
} else if (ble_uuid_cmp(uuid, &gatt_cud_uuid.u) == 0) {
rc = os_mbuf_append(ctxt->om, "Badge Name",
(uint16_t) strlen("Badge Name"));
return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
} else if (ble_uuid_cmp(uuid, &gatt_cpf_uuid.u) == 0) {
rc = os_mbuf_append(ctxt->om, &name_cpf,
(uint16_t) sizeof(name_cpf));
return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
}
/* Unknown characteristic; the nimble stack should not have called this
* function.
*/
assert(0);
return BLE_ATT_ERR_UNLIKELY;
}
void
gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg)
{
char buf[BLE_UUID_STR_LEN];
switch (ctxt->op) {
case BLE_GATT_REGISTER_OP_SVC:
MODLOG_DFLT(DEBUG, "registered service %s with handle=%d\n",
ble_uuid_to_str(ctxt->svc.svc_def->uuid, buf),
ctxt->svc.handle);
break;
case BLE_GATT_REGISTER_OP_CHR:
MODLOG_DFLT(DEBUG, "registering characteristic %s with "
"def_handle=%d val_handle=%d\n",
ble_uuid_to_str(ctxt->chr.chr_def->uuid, buf),
ctxt->chr.def_handle,
ctxt->chr.val_handle);
break;
case BLE_GATT_REGISTER_OP_DSC:
MODLOG_DFLT(DEBUG, "registering descriptor %s with handle=%d\n",
ble_uuid_to_str(ctxt->dsc.dsc_def->uuid, buf),
ctxt->dsc.handle);
break;
default:
assert(0);
break;
}
}
int
gatt_svr_init(void)
{
int rc;
rc = ble_gatts_count_cfg(gatt_svr_svcs);
if (rc != 0) {
return rc;
}
rc = ble_gatts_add_svcs(gatt_svr_svcs);
if (rc != 0) {
return rc;
}
return 0;
}

View file

@ -0,0 +1,393 @@
/*
* Copyright (c) 2018 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "console/console.h"
#include "host/ble_gap.h"
#include "mesh/glue.h"
#include "services/gap/ble_svc_gap.h"
#include "base64/base64.h"
#include "mesh_badge.h"
#include "mesh.h"
#include "board.h"
static char badge_name[MYNEWT_VAL(BLE_SVC_GAP_DEVICE_NAME_MAX_LENGTH)];
#define MESH_BADGE_NAME_ENCODE_SIZE \
BASE64_ENCODE_SIZE(sizeof(badge_name))
static bool reset_mesh;
void print_addr(const void *addr)
{
const uint8_t *u8p;
u8p = addr;
MODLOG_DFLT(INFO, "%02x:%02x:%02x:%02x:%02x:%02x",
u8p[5], u8p[4], u8p[3], u8p[2], u8p[1], u8p[0]);
}
static void
print_conn_desc(struct ble_gap_conn_desc *desc)
{
MODLOG_DFLT(INFO, "handle=%d our_ota_addr_type=%d our_ota_addr=",
desc->conn_handle, desc->our_ota_addr.type);
print_addr(desc->our_ota_addr.val);
MODLOG_DFLT(INFO, " our_id_addr_type=%d our_id_addr=",
desc->our_id_addr.type);
print_addr(desc->our_id_addr.val);
MODLOG_DFLT(INFO, " peer_ota_addr_type=%d peer_ota_addr=",
desc->peer_ota_addr.type);
print_addr(desc->peer_ota_addr.val);
MODLOG_DFLT(INFO, " peer_id_addr_type=%d peer_id_addr=",
desc->peer_id_addr.type);
print_addr(desc->peer_id_addr.val);
MODLOG_DFLT(INFO, " conn_itvl=%d conn_latency=%d supervision_timeout=%d "
"encrypted=%d authenticated=%d bonded=%d\n",
desc->conn_itvl, desc->conn_latency,
desc->supervision_timeout,
desc->sec_state.encrypted,
desc->sec_state.authenticated,
desc->sec_state.bonded);
}
static int gap_event(struct ble_gap_event *event, void *arg);
static void advertise(void)
{
uint8_t own_addr_type;
struct ble_gap_adv_params adv_params;
struct ble_hs_adv_fields fields;
const char *name;
int rc;
/* Figure out address to use while advertising (no privacy for now) */
rc = ble_hs_id_infer_auto(0, &own_addr_type);
if (rc != 0) {
MODLOG_DFLT(ERROR, "error determining address type; rc=%d\n", rc);
return;
}
/**
* Set the advertisement data included in our advertisements:
* o Flags (indicates advertisement type and other general info).
* o Advertising tx power.
* o Device name.
* o 16-bit service UUIDs (alert notifications).
*/
memset(&fields, 0, sizeof fields);
/* Advertise two flags:
* o Discoverability in forthcoming advertisement (general)
* o BLE-only (BR/EDR unsupported).
*/
fields.flags = BLE_HS_ADV_F_DISC_GEN |
BLE_HS_ADV_F_BREDR_UNSUP;
#if 0
/* Indicate that the TX power level field should be included; have the
* stack fill this value automatically. This is done by assiging the
* special value BLE_HS_ADV_TX_PWR_LVL_AUTO.
*/
fields.tx_pwr_lvl_is_present = 1;
fields.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO;
#endif
name = ble_svc_gap_device_name();
fields.name = (uint8_t *)name;
fields.name_len = (uint8_t) strlen(name);
fields.name_is_complete = 1;
rc = ble_gap_adv_set_fields(&fields);
if (rc != 0) {
MODLOG_DFLT(ERROR, "error setting advertisement data; rc=%d\n", rc);
return;
}
/* Begin advertising. */
memset(&adv_params, 0, sizeof adv_params);
adv_params.conn_mode = BLE_GAP_CONN_MODE_UND;
adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN;
rc = ble_gap_adv_start(own_addr_type, NULL, BLE_HS_FOREVER,
&adv_params, gap_event, NULL);
if (rc != 0) {
MODLOG_DFLT(ERROR, "error enabling advertisement; rc=%d\n", rc);
return;
}
}
static void passkey_display(uint16_t conn_handle)
{
char buf[20];
struct ble_sm_io pk;
int rc;
bt_rand(&pk.passkey, sizeof(pk.passkey));
/* Max value is 999999 */
pk.passkey %= 1000000;
pk.action = BLE_SM_IOACT_DISP;
rc = ble_sm_inject_io(conn_handle, &pk);
assert(rc == 0);
snprintk(buf, sizeof(buf), "Passkey:\n%06lu", pk.passkey);
printk("%s\n", buf);
board_show_text(buf, false, K_FOREVER);
}
static void pairing_complete(uint16_t conn_handle, bool bonded)
{
printk("Pairing Complete\n");
board_show_text("Pairing Complete", false, K_SECONDS(2));
}
static void pairing_failed(uint16_t conn_handle)
{
printk("Pairing Failed\n");
board_show_text("Pairing Failed", false, K_SECONDS(2));
}
static void connected(uint16_t conn_handle, int err)
{
printk("Connected (err 0x%02x)\n", err);
if (err) {
board_show_text("Connection failed", false, K_SECONDS(2));
} else {
board_show_text("Connected", false, K_FOREVER);
}
}
static void disconnected(uint16_t conn_handle, int reason)
{
printk("Disconnected (reason 0x%02x)\n", reason);
if (strcmp(MYNEWT_VAL(BLE_SVC_GAP_DEVICE_NAME), bt_get_name()) != 0 &&
!mesh_is_initialized()) {
/* Mesh will take over advertising control */
ble_gap_adv_stop();
mesh_start();
} else {
board_show_text("Disconnected", false, K_SECONDS(2));
}
}
static int gap_event(struct ble_gap_event *event, void *arg)
{
struct ble_gap_conn_desc desc;
int rc;
switch (event->type) {
case BLE_GAP_EVENT_CONNECT:
/* A new connection was established or a connection attempt failed. */
MODLOG_DFLT(INFO, "connection %s; status=%d ",
event->connect.status == 0 ? "established" : "failed",
event->connect.status);
if (event->connect.status == 0) {
rc = ble_gap_conn_find(event->connect.conn_handle, &desc);
assert(rc == 0);
print_conn_desc(&desc);
connected(event->connect.conn_handle,
event->connect.status);
}
MODLOG_DFLT(INFO, "\n");
if (event->connect.status != 0) {
/* Connection failed; resume advertising. */
advertise();
}
return 0;
case BLE_GAP_EVENT_DISCONNECT:
MODLOG_DFLT(INFO, "disconnect; reason=%d ", event->disconnect.reason);
print_conn_desc(&event->disconnect.conn);
MODLOG_DFLT(INFO, "\n");
/* Connection terminated; resume advertising. */
advertise();
disconnected(event->disconnect.conn.conn_handle,
event->disconnect.reason);
return 0;
case BLE_GAP_EVENT_CONN_UPDATE:
/* The central has updated the connection parameters. */
MODLOG_DFLT(INFO, "connection updated; status=%d ",
event->conn_update.status);
rc = ble_gap_conn_find(event->connect.conn_handle, &desc);
assert(rc == 0);
print_conn_desc(&desc);
MODLOG_DFLT(INFO, "\n");
return 0;
case BLE_GAP_EVENT_ENC_CHANGE:
/* Encryption has been enabled or disabled for this connection. */
MODLOG_DFLT(INFO, "encryption change event; status=%d ",
event->enc_change.status);
rc = ble_gap_conn_find(event->connect.conn_handle, &desc);
assert(rc == 0);
print_conn_desc(&desc);
MODLOG_DFLT(INFO, "\n");
if (desc.sec_state.bonded) {
pairing_complete(event->enc_change.conn_handle, true);
} else if(desc.sec_state.encrypted) {
pairing_complete(event->enc_change.conn_handle, false);
} else {
pairing_failed(event->enc_change.conn_handle);
}
return 0;
case BLE_GAP_EVENT_PASSKEY_ACTION:
MODLOG_DFLT(INFO, "passkey action event; conn_handle=%d action=%d numcmp=%d\n",
event->passkey.conn_handle,
event->passkey.params.action,
event->passkey.params.numcmp);
passkey_display(event->passkey.conn_handle);
return 0;
case BLE_GAP_EVENT_REPEAT_PAIRING:
/* We already have a bond with the peer, but it is attempting to
* establish a new secure link. This app sacrifices security for
* convenience: just throw away the old bond and accept the new link.
*/
/* Delete the old bond. */
rc = ble_gap_conn_find(event->repeat_pairing.conn_handle, &desc);
assert(rc == 0);
ble_store_util_delete_peer(&desc.peer_id_addr);
/* Return BLE_GAP_REPEAT_PAIRING_RETRY to indicate that the host should
* continue with the pairing operation.
*/
return BLE_GAP_REPEAT_PAIRING_RETRY;
}
return 0;
}
static void on_sync(void)
{
int err;
ble_addr_t addr;
/* Use NRPA */
err = ble_hs_id_gen_rnd(1, &addr);
assert(err == 0);
err = ble_hs_id_set_rnd(addr.val);
assert(err == 0);
printk("Bluetooth initialized\n");
err = mesh_init(addr.type);
if (err) {
printk("Initializing mesh failed (err %d)\n", err);
return;
}
printk("Mesh initialized\n");
if (IS_ENABLED(CONFIG_SETTINGS)) {
settings_load();
}
if (reset_mesh) {
bt_mesh_reset();
reset_mesh = false;
}
if (!mesh_is_initialized()) {
advertise();
} else {
printk("Already provisioned\n");
ble_svc_gap_device_name_set(bt_get_name());
}
board_refresh_display();
printk("Board started\n");
}
void schedule_mesh_reset(void)
{
reset_mesh = true;
}
static void on_reset(int reason)
{
MODLOG_DFLT(ERROR, "Resetting state; reason=%d\n", reason);
}
const char *bt_get_name(void)
{
char buf[MESH_BADGE_NAME_ENCODE_SIZE];
int rc, len;
rc = conf_get_stored_value("mesh_badge/badge_name",
buf, sizeof(buf));
if (rc == OS_ENOENT) {
bt_set_name(MYNEWT_VAL(BLE_SVC_GAP_DEVICE_NAME));
} else {
assert(rc == 0);
}
memset(badge_name, '\0', sizeof(badge_name));
len = base64_decode(buf, badge_name);
if (len < 0) {
bt_set_name(MYNEWT_VAL(BLE_SVC_GAP_DEVICE_NAME));
}
return badge_name;
}
int bt_set_name(const char *name)
{
char buf[MESH_BADGE_NAME_ENCODE_SIZE];
int rc;
memset(badge_name, '\0', sizeof(badge_name));
memcpy(badge_name, name, strlen(name));
base64_encode(badge_name, sizeof(badge_name), buf, 1);
rc = conf_save_one("mesh_badge/badge_name", buf);
assert(rc == 0);
return 0;
}
int main(void)
{
int err;
/* Initialize OS */
sysinit();
err = board_init();
if (err) {
printk("board init failed (err %d)\n", err);
assert(err == 0);
}
/* Initialize the NimBLE host configuration. */
ble_hs_cfg.reset_cb = on_reset;
ble_hs_cfg.sync_cb = on_sync;
ble_hs_cfg.gatts_register_cb = gatt_svr_register_cb;
ble_hs_cfg.store_status_cb = ble_store_util_status_rr;
ble_hs_cfg.sm_io_cap = BLE_SM_IO_CAP_DISP_ONLY;
err = gatt_svr_init();
assert(err == 0);
/*
* As the last thing, process events from default event queue.
*/
while (1) {
os_eventq_run(os_eventq_dflt_get());
}
return 0;
}

View file

@ -0,0 +1,313 @@
/*
* Copyright (c) 2018 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "console/console.h"
#include "mesh/mesh.h"
#include "mesh_badge.h"
#include "mesh.h"
#include "board.h"
#define BT_COMP_ID_LF 0x05f1
#define MOD_LF 0x0000
#define OP_HELLO 0xbb
#define OP_HEARTBEAT 0xbc
#define OP_VND_HELLO BT_MESH_MODEL_OP_3(OP_HELLO, BT_COMP_ID_LF)
#define OP_VND_HEARTBEAT BT_MESH_MODEL_OP_3(OP_HEARTBEAT, BT_COMP_ID_LF)
#define DEFAULT_TTL 31
#define GROUP_ADDR 0xc123
#define NET_IDX 0x000
#define APP_IDX 0x000
#define FLAGS 0
static struct ble_npl_callout hello_work;
static struct ble_npl_callout mesh_start_work;
static void heartbeat(const struct bt_mesh_hb_sub *sub, uint8_t hops,
uint16_t feat)
{
board_show_text("Heartbeat Received", false, K_SECONDS(2));
}
static struct bt_mesh_cfg_cli cfg_cli = {
};
static void attention_on(struct bt_mesh_model *model)
{
board_show_text("Attention!", false, K_SECONDS(2));
}
static void attention_off(struct bt_mesh_model *model)
{
board_refresh_display();
}
static const struct bt_mesh_health_srv_cb health_srv_cb = {
.attn_on = attention_on,
.attn_off = attention_off,
};
static struct bt_mesh_health_srv health_srv = {
.cb = &health_srv_cb,
};
static struct os_mbuf *bt_mesh_pub_msg_health_pub;
static struct bt_mesh_model_pub health_pub;
static struct bt_mesh_model root_models[] = {
BT_MESH_MODEL_CFG_SRV,
BT_MESH_MODEL_CFG_CLI(&cfg_cli),
BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub),
};
static void vnd_hello(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
char str[32];
size_t len;
printk("Hello message from 0x%04x\n", ctx->addr);
if (ctx->addr == bt_mesh_model_elem(model)->addr) {
printk("Ignoring message from self\n");
return;
}
len = min(buf->om_len, 8);
memcpy(str, buf->om_data, len);
str[len] = '\0';
board_add_hello(ctx->addr, str);
strcpy(str + len, " says hi!");
board_show_text(str, false, K_SECONDS(3));
board_blink_leds();
}
static void vnd_heartbeat(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *ctx,
struct os_mbuf *buf)
{
uint8_t init_ttl, hops;
/* Ignore messages from self */
if (ctx->addr == bt_mesh_model_elem(model)->addr) {
return;
}
init_ttl = net_buf_simple_pull_u8(buf);
hops = init_ttl - ctx->recv_ttl + 1;
printk("Heartbeat from 0x%04x over %u hop%s\n", ctx->addr,
hops, hops == 1 ? "" : "s");
board_add_heartbeat(ctx->addr, hops);
}
static const struct bt_mesh_model_op vnd_ops[] = {
{ OP_VND_HELLO, 1, vnd_hello },
{ OP_VND_HEARTBEAT, 1, vnd_heartbeat },
BT_MESH_MODEL_OP_END,
};
static int pub_update(struct bt_mesh_model *mod)
{
struct os_mbuf *msg = mod->pub->msg;
printk("Preparing to send heartbeat\n");
bt_mesh_model_msg_init(msg, OP_VND_HEARTBEAT);
net_buf_simple_add_u8(msg, DEFAULT_TTL);
return 0;
}
static struct os_mbuf *bt_mesh_pub_msg_vnd_pub;
static struct bt_mesh_model_pub vnd_pub;
static struct bt_mesh_model vnd_models[] = {
BT_MESH_MODEL_VND(BT_COMP_ID_LF, MOD_LF, vnd_ops, &vnd_pub, NULL),
};
static struct bt_mesh_elem elements[] = {
BT_MESH_ELEM(0, root_models, vnd_models),
};
static const struct bt_mesh_comp comp = {
.cid = BT_COMP_ID_LF,
.elem = elements,
.elem_count = ARRAY_SIZE(elements),
};
static size_t first_name_len(const char *name)
{
size_t len;
for (len = 0; *name; name++, len++) {
switch (*name) {
case ' ':
case ',':
case '\n':
return len;
}
}
return len;
}
static void send_hello(struct ble_npl_event *work)
{
struct os_mbuf *msg = NET_BUF_SIMPLE(3 + 8 + 4);
struct bt_mesh_msg_ctx ctx = {
.net_idx = NET_IDX,
.app_idx = APP_IDX,
.addr = GROUP_ADDR,
.send_ttl = DEFAULT_TTL,
};
const char *name = bt_get_name();
bt_mesh_model_msg_init(msg, OP_VND_HELLO);
net_buf_simple_add_mem(msg, name, first_name_len(name));
if (bt_mesh_model_send(&vnd_models[0], &ctx, msg, NULL, NULL) == 0) {
board_show_text("Saying \"hi!\" to everyone", false,
K_SECONDS(2));
} else {
board_show_text("Sending Failed!", false, K_SECONDS(2));
}
os_mbuf_free_chain(msg);
}
void mesh_send_hello(void)
{
k_work_submit(&hello_work);
}
static int provision_and_configure(void)
{
static const uint8_t net_key[16] = {
0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
};
static const uint8_t app_key[16] = {
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
};
static const uint16_t iv_index;
struct bt_mesh_cfg_mod_pub pub = {
.addr = GROUP_ADDR,
.app_idx = APP_IDX,
.ttl = DEFAULT_TTL,
.period = BT_MESH_PUB_PERIOD_SEC(10),
};
uint8_t dev_key[16];
uint16_t addr;
int err;
err = bt_rand(dev_key, sizeof(dev_key));
if (err) {
return err;
}
do {
err = bt_rand(&addr, sizeof(addr));
if (err) {
return err;
}
} while (!addr);
/* Make sure it's a unicast address (highest bit unset) */
addr &= ~0x8000;
err = bt_mesh_provision(net_key, NET_IDX, FLAGS, iv_index, addr,
dev_key);
if (err) {
return err;
}
printk("Configuring...\n");
/* Add Application Key */
bt_mesh_cfg_app_key_add(NET_IDX, addr, NET_IDX, APP_IDX, app_key, NULL);
/* Bind to vendor model */
bt_mesh_cfg_mod_app_bind_vnd(NET_IDX, addr, addr, APP_IDX,
MOD_LF, BT_COMP_ID_LF, NULL);
/* Bind to Health model */
bt_mesh_cfg_mod_app_bind(NET_IDX, addr, addr, APP_IDX,
BT_MESH_MODEL_ID_HEALTH_SRV, NULL);
/* Add model subscription */
bt_mesh_cfg_mod_sub_add_vnd(NET_IDX, addr, addr, GROUP_ADDR,
MOD_LF, BT_COMP_ID_LF, NULL);
bt_mesh_cfg_mod_pub_set_vnd(NET_IDX, addr, addr, MOD_LF, BT_COMP_ID_LF,
&pub, NULL);
printk("Configuration complete\n");
return addr;
}
static void start_mesh(struct ble_npl_event *work)
{
int err;
err = provision_and_configure();
if (err < 0) {
board_show_text("Starting Mesh Failed", false,
K_SECONDS(2));
} else {
char buf[32];
snprintk(buf, sizeof(buf),
"Mesh Started\nAddr: 0x%04x", err);
board_show_text(buf, false, K_SECONDS(4));
}
}
void mesh_start(void)
{
k_work_submit(&mesh_start_work);
}
bool mesh_is_initialized(void)
{
return bt_mesh_is_provisioned();
}
uint16_t mesh_get_addr(void)
{
return elements[0].addr;
}
int mesh_init(uint8_t addr_type)
{
static const uint8_t dev_uuid[16] = { 0xc0, 0xff, 0xee };
static const struct bt_mesh_prov prov = {
.uuid = dev_uuid,
};
hb_cb = { .recv = heartbeat };
bt_mesh_pub_msg_health_pub = NET_BUF_SIMPLE(0);
health_pub.msg = bt_mesh_pub_msg_health_pub;
bt_mesh_pub_msg_vnd_pub = NET_BUF_SIMPLE(3 + 1);
vnd_pub.msg = bt_mesh_pub_msg_vnd_pub;
vnd_pub.update = pub_update;
k_work_init(&hello_work, send_hello);
k_work_init(&mesh_start_work, start_mesh);
return bt_mesh_init(addr_type, &prov, &comp);
}

View file

@ -0,0 +1,14 @@
/*
* Copyright (c) 2018 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "mesh/mesh.h"
void mesh_send_hello(void);
uint16_t mesh_get_addr(void);
bool mesh_is_initialized(void);
void mesh_start(void);
int mesh_init(uint8_t addr_type);

View file

@ -0,0 +1,28 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
struct ble_gatt_register_ctxt;
void gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg);
int gatt_svr_init(void);
void schedule_mesh_reset(void);
const char *bt_get_name(void);
int bt_set_name(const char *);

View file

@ -0,0 +1,508 @@
/*
* Copyright (c) 2018 Phytec Messtechnik GmbH
* Copyright (c) 2018 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "os/mynewt.h"
#include "bsp/bsp.h"
#include "console/console.h"
#include "hal/hal_flash.h"
#include "hal/hal_gpio.h"
#include "mesh/glue.h"
#include "services/gap/ble_svc_gap.h"
#include "mesh_badge.h"
#include "display/cfb.h"
#include "mesh.h"
#include "board.h"
#define printk console_printf
enum font_size {
FONT_BIG = 0,
FONT_MEDIUM = 1,
FONT_SMALL = 2,
};
struct font_info {
uint8_t columns;
} fonts[] = {
[FONT_BIG] = { .columns = 12 },
[FONT_MEDIUM] = { .columns = 16 },
[FONT_SMALL] = { .columns = 25 },
};
#define LONG_PRESS_TIMEOUT K_SECONDS(1)
#define STAT_COUNT 128
#define EDGE (GPIO_INT_EDGE | GPIO_INT_DOUBLE_EDGE)
#ifdef SW0_GPIO_FLAGS
#define PULL_UP SW0_GPIO_FLAGS
#else
#define PULL_UP 0
#endif
static struct os_dev *epd_dev;
static bool pressed;
static bool stats_view;
static struct k_delayed_work epd_work;
static struct k_delayed_work long_press_work;
static struct {
int pin;
} leds[] = {
{ .pin = LED_1, },
{ .pin = RGB_LED_RED, },
{ .pin = RGB_LED_GRN, },
{ .pin = RGB_LED_BLU, },
};
struct k_delayed_work led_timer;
static size_t print_line(enum font_size font_size, int row, const char *text,
size_t len, bool center)
{
uint8_t font_height, font_width;
char line[fonts[FONT_SMALL].columns + 1];
int pad;
cfb_framebuffer_set_font(epd_dev, font_size);
len = min(len, fonts[font_size].columns);
memcpy(line, text, len);
line[len] = '\0';
if (center) {
pad = (fonts[font_size].columns - len) / 2;
} else {
pad = 0;
}
cfb_get_font_size(epd_dev, font_size, &font_width, &font_height);
if (cfb_print(epd_dev, line, font_width * pad, font_height * row)) {
printk("Failed to print a string\n");
}
return len;
}
static size_t get_len(enum font_size font, const char *text)
{
const char *space = NULL;
size_t i;
for (i = 0; i <= fonts[font].columns; i++) {
switch (text[i]) {
case '\n':
case '\0':
return i;
case ' ':
space = &text[i];
break;
default:
continue;
}
}
/* If we got more characters than fits a line, and a space was
* encountered, fall back to the last space.
*/
if (space) {
return space - text;
}
return fonts[font].columns;
}
void board_blink_leds(void)
{
k_delayed_work_submit(&led_timer, K_MSEC(100));
}
void board_show_text(const char *text, bool center, int32_t duration)
{
int i;
cfb_framebuffer_clear(epd_dev, false);
for (i = 0; i < 3; i++) {
size_t len;
while (*text == ' ' || *text == '\n') {
text++;
}
len = get_len(FONT_BIG, text);
if (!len) {
break;
}
text += print_line(FONT_BIG, i, text, len, center);
if (!*text) {
break;
}
}
cfb_framebuffer_finalize(epd_dev);
if (duration != K_FOREVER) {
k_delayed_work_submit(&epd_work, duration);
}
}
static struct stat {
uint16_t addr;
char name[9];
uint8_t min_hops;
uint8_t max_hops;
uint16_t hello_count;
uint16_t heartbeat_count;
} stats[STAT_COUNT] = {
[0 ... (STAT_COUNT - 1)] = {
.min_hops = BT_MESH_TTL_MAX,
.max_hops = 0,
},
};
static uint32_t stat_count;
#define NO_UPDATE -1
static int add_hello(uint16_t addr, const char *name)
{
int i;
for (i = 0; i < ARRAY_SIZE(stats); i++) {
struct stat *stat = &stats[i];
if (!stat->addr) {
stat->addr = addr;
strncpy(stat->name, name, sizeof(stat->name) - 1);
stat->hello_count = 1;
stat_count++;
return i;
}
if (stat->addr == addr) {
/* Update name, incase it has changed */
strncpy(stat->name, name, sizeof(stat->name) - 1);
if (stat->hello_count < 0xffff) {
stat->hello_count++;
return i;
}
return NO_UPDATE;
}
}
return NO_UPDATE;
}
static int add_heartbeat(uint16_t addr, uint8_t hops)
{
int i;
for (i = 0; i < ARRAY_SIZE(stats); i++) {
struct stat *stat = &stats[i];
if (!stat->addr) {
stat->addr = addr;
stat->heartbeat_count = 1;
stat->min_hops = hops;
stat->max_hops = hops;
stat_count++;
return i;
}
if (stat->addr == addr) {
if (hops < stat->min_hops) {
stat->min_hops = hops;
} else if (hops > stat->max_hops) {
stat->max_hops = hops;
}
if (stat->heartbeat_count < 0xffff) {
stat->heartbeat_count++;
return i;
}
return NO_UPDATE;
}
}
return NO_UPDATE;
}
void board_add_hello(uint16_t addr, const char *name)
{
uint32_t sort_i;
sort_i = add_hello(addr, name);
if (sort_i != NO_UPDATE) {
}
}
void board_add_heartbeat(uint16_t addr, uint8_t hops)
{
uint32_t sort_i;
sort_i = add_heartbeat(addr, hops);
if (sort_i != NO_UPDATE) {
}
}
static void show_statistics(void)
{
int top[4] = { -1, -1, -1, -1 };
int len, i, line = 0;
struct stat *stat;
char str[32];
cfb_framebuffer_clear(epd_dev, false);
len = snprintk(str, sizeof(str),
"Own Address: 0x%04x", mesh_get_addr());
print_line(FONT_SMALL, line++, str, len, false);
len = snprintk(str, sizeof(str),
"Node Count: %lu", stat_count + 1);
print_line(FONT_SMALL, line++, str, len, false);
/* Find the top sender */
for (i = 0; i < ARRAY_SIZE(stats); i++) {
int j;
stat = &stats[i];
if (!stat->addr) {
break;
}
if (!stat->hello_count) {
continue;
}
for (j = 0; j < ARRAY_SIZE(top); j++) {
if (top[j] < 0) {
top[j] = i;
break;
}
if (stat->hello_count <= stats[top[j]].hello_count) {
continue;
}
/* Move other elements down the list */
if (j < ARRAY_SIZE(top) - 1) {
memmove(&top[j + 1], &top[j],
((ARRAY_SIZE(top) - j - 1) *
sizeof(top[j])));
}
top[j] = i;
break;
}
}
if (stat_count >= 0) {
len = snprintk(str, sizeof(str), "Most messages from:");
print_line(FONT_SMALL, line++, str, len, false);
for (i = 0; i < ARRAY_SIZE(top); i++) {
if (top[i] < 0) {
break;
}
stat = &stats[top[i]];
len = snprintk(str, sizeof(str), "%-3u 0x%04x %s",
stat->hello_count, stat->addr,
stat->name);
print_line(FONT_SMALL, line++, str, len, false);
}
}
cfb_framebuffer_finalize(epd_dev);
}
static void epd_update(struct ble_npl_event *work)
{
char buf[MYNEWT_VAL(BLE_SVC_GAP_DEVICE_NAME_MAX_LENGTH)];
int i;
if (stats_view) {
show_statistics();
return;
}
strncpy(buf, bt_get_name(), sizeof(buf));
/* Convert commas to newlines */
for (i = 0; buf[i] != '\0'; i++) {
if (buf[i] == ',') {
buf[i] = '\n';
}
}
board_show_text(buf, true, K_FOREVER);
}
static void long_press(struct ble_npl_event *work)
{
/* Treat as release so actual release doesn't send messages */
pressed = false;
stats_view = !stats_view;
board_refresh_display();
}
static bool button_is_pressed(void)
{
uint32_t val;
val = (uint32_t) hal_gpio_read(BUTTON_1);
return !val;
}
static void button_interrupt(struct os_event *ev)
{
int pin_pos = (int ) ev->ev_arg;
if (button_is_pressed() == pressed) {
return;
}
pressed = !pressed;
printk("Button %s\n", pressed ? "pressed" : "released");
if (pressed) {
k_delayed_work_submit(&long_press_work, LONG_PRESS_TIMEOUT);
return;
}
k_delayed_work_cancel(&long_press_work);
if (!mesh_is_initialized()) {
return;
}
/* Short press does currently nothing in statistics view */
if (stats_view) {
return;
}
if (pin_pos == BUTTON_1) {
mesh_send_hello();
}
}
static struct os_event button_event;
static void
gpio_irq_handler(void *arg)
{
button_event.ev_arg = arg;
os_eventq_put(os_eventq_dflt_get(), &button_event);
}
static int configure_button(void)
{
button_event.ev_cb = button_interrupt;
hal_gpio_irq_init(BUTTON_1, gpio_irq_handler, (void *) BUTTON_1,
HAL_GPIO_TRIG_BOTH, HAL_GPIO_PULL_UP);
hal_gpio_irq_enable(BUTTON_1);
return 0;
}
static void led_timeout(struct ble_npl_event *work)
{
static int led_cntr;
int i;
/* Disable all LEDs */
for (i = 0; i < ARRAY_SIZE(leds); i++) {
hal_gpio_write(leds[i].pin, 1);
}
/* Stop after 5 iterations */
if (led_cntr > (ARRAY_SIZE(leds) * 5)) {
led_cntr = 0;
return;
}
/* Select and enable current LED */
i = led_cntr++ % ARRAY_SIZE(leds);
hal_gpio_write(leds[i].pin, 0);
k_delayed_work_submit(&led_timer, K_MSEC(100));
}
static int configure_leds(void)
{
int i;
for (i = 0; i < ARRAY_SIZE(leds); i++) {
hal_gpio_init_out(leds[i].pin, 1);
}
k_delayed_work_init(&led_timer, led_timeout);
return 0;
}
static int erase_storage(void)
{
bt_set_name(MYNEWT_VAL(BLE_SVC_GAP_DEVICE_NAME));
ble_store_clear();
schedule_mesh_reset();
return 0;
}
void board_refresh_display(void)
{
k_delayed_work_submit(&epd_work, K_NO_WAIT);
}
int board_init(void)
{
epd_dev = os_dev_lookup(MYNEWT_VAL(SSD1673_OS_DEV_NAME));
if (epd_dev == NULL) {
printk("SSD1673 device not found\n");
return -ENODEV;
}
if (cfb_framebuffer_init(epd_dev)) {
printk("Framebuffer initialization failed\n");
return -EIO;
}
cfb_framebuffer_clear(epd_dev, true);
if (configure_button()) {
printk("Failed to configure button\n");
return -EIO;
}
if (configure_leds()) {
printk("LED init failed\n");
return -EIO;
}
k_delayed_work_init(&epd_work, epd_update);
k_delayed_work_init(&long_press_work, long_press);
pressed = button_is_pressed();
if (pressed) {
printk("Erasing storage\n");
board_show_text("Resetting Device", false, K_SECONDS(4));
erase_storage();
}
return 0;
}

View file

@ -0,0 +1,58 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
# Package: apps/mesh_badge
syscfg.vals:
# Enable the shell task.
SHELL_TASK: 1
# Set log level to info (disable debug logging).
LOG_LEVEL: 1
# Default task settings
OS_MAIN_STACK_SIZE: 768
# Newtmgr is not supported in this app, so disable newtmgr-over-shell.
SHELL_NEWTMGR: 0
REEL_BOARD_ENABLE_ACTIVE_MODE: 1
SPI_0_MASTER: 1
BLE_MESH: 1
MSYS_1_BLOCK_COUNT: 48
BLE_SVC_GAP_DEVICE_NAME: '"reel board"'
BLE_SM_SC: 1
BLE_SM_BONDING: 1
BLE_MESH_RELAY: 1
BLE_MESH_GATT_PROXY: 0
BLE_MESH_PB_ADV: 0
BLE_MESH_PB_GATT: 0
BLE_MESH_ADV_BUF_COUNT: 30
BLE_MESH_LABEL_COUNT: 0
BLE_MESH_CFG_CLI: 1
BLE_MESH_TX_SEG_MAX: 6
BLE_MESH_TX_SEG_MSG_COUNT: 3
BLE_MESH_RX_SEG_MSG_COUNT: 3
BLE_MESH_CRPL: 128
BLE_MESH_RPL_STORE_TIMEOUT: 120
BLE_MESH_SETTINGS: 1
CONFIG_NFFS: 1
BLE_MESH_PB_ADV: 1

View file

@ -69,6 +69,29 @@ extern "C" {
/* Timing jitter as per spec is +/16 usecs */
#define BLE_LL_JITTER_USECS (16)
#if MYNEWT_VAL(BLE_LL_SCA) < 0
#error Invalid SCA value
#elif MYNEWT_VAL(BLE_LL_SCA) <= 20
#define BLE_LL_SCA_ENUM 7
#elif MYNEWT_VAL(BLE_LL_SCA) <= 30
#define BLE_LL_SCA_ENUM 6
#elif MYNEWT_VAL(BLE_LL_SCA) <= 50
#define BLE_LL_SCA_ENUM 5
#elif MYNEWT_VAL(BLE_LL_SCA) <= 75
#define BLE_LL_SCA_ENUM 4
#elif MYNEWT_VAL(BLE_LL_SCA) <= 100
#define BLE_LL_SCA_ENUM 3
#elif MYNEWT_VAL(BLE_LL_SCA) <= 150
#define BLE_LL_SCA_ENUM 2
#elif MYNEWT_VAL(BLE_LL_SCA) <= 250
#define BLE_LL_SCA_ENUM 1
#elif MYNEWT_VAL(BLE_LL_SCA) <= 500
#define BLE_LL_SCA_ENUM 0
#else
#error Invalid SCA value
#endif
/* Packet queue header definition */
STAILQ_HEAD(ble_ll_pkt_q, os_mbuf_pkthdr);
@ -373,6 +396,12 @@ struct ble_dev_addr
#define BLE_LL_LLID_DATA_START (2)
#define BLE_LL_LLID_CTRL (3)
#define BLE_LL_LLID_IS_CTRL(hdr) \
(((hdr) & BLE_LL_DATA_HDR_LLID_MASK) == BLE_LL_LLID_CTRL)
#define BLE_LL_LLID_IS_DATA(hdr) \
((((hdr) & BLE_LL_DATA_HDR_LLID_MASK) == BLE_LL_LLID_DATA_START) || \
(((hdr) & BLE_LL_DATA_HDR_LLID_MASK) == BLE_LL_LLID_DATA_FRAG))
/*
* CONNECT_REQ
* -> InitA (6 bytes)
@ -545,6 +574,7 @@ void ble_ll_rand_sample(uint8_t rnum);
int ble_ll_rand_data_get(uint8_t *buf, uint8_t len);
void ble_ll_rand_prand_get(uint8_t *prand);
int ble_ll_rand_start(void);
uint32_t ble_ll_rand(void);
static inline int
ble_ll_get_addr_type(uint8_t txrxflag)

View file

@ -58,6 +58,8 @@ extern "C" {
/* Definition for RSSI when the RSSI is unknown */
#define BLE_LL_CONN_UNKNOWN_RSSI (127)
#define BLE_LL_CONN_HANDLE_ISO_OFFSET (0x0100)
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
/*
* Encryption states for a connection
@ -69,6 +71,7 @@ extern "C" {
enum conn_enc_state {
CONN_ENC_S_UNENCRYPTED = 1,
CONN_ENC_S_ENCRYPTED,
CONN_ENC_S_ENC_RSP_TO_BE_SENT,
CONN_ENC_S_ENC_RSP_WAIT,
CONN_ENC_S_PAUSE_ENC_RSP_WAIT,
CONN_ENC_S_PAUSED,
@ -270,6 +273,10 @@ struct ble_ll_conn_sm
uint8_t last_rxd_hdr_byte; /* note: possibly can make 1 bit since we
only use the MD bit now */
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL)
uint16_t cth_flow_pending;
#endif
/* connection event mgmt */
uint8_t reject_reason;
uint8_t host_reply_opcode;

View file

@ -39,7 +39,9 @@ extern "C" {
#define BLE_LL_CTRL_PROC_LE_PING (7)
#define BLE_LL_CTRL_PROC_DATA_LEN_UPD (8)
#define BLE_LL_CTRL_PROC_PHY_UPDATE (9)
#define BLE_LL_CTRL_PROC_NUM (10)
#define BLE_LL_CTRL_PROC_SCA_UPDATE (10)
#define BLE_LL_CTRL_PROC_CIS_CREATE (11)
#define BLE_LL_CTRL_PROC_NUM (12)
#define BLE_LL_CTRL_PROC_IDLE (255)
/* Checks if a particular control procedure is running */
@ -54,45 +56,51 @@ extern "C" {
* -> Opcode (1 byte)
* -> Data (0 - 26 bytes)
*/
#define BLE_LL_CTRL_CONN_UPDATE_IND (0)
#define BLE_LL_CTRL_CHANNEL_MAP_REQ (1)
#define BLE_LL_CTRL_TERMINATE_IND (2)
#define BLE_LL_CTRL_ENC_REQ (3)
#define BLE_LL_CTRL_ENC_RSP (4)
#define BLE_LL_CTRL_START_ENC_REQ (5)
#define BLE_LL_CTRL_START_ENC_RSP (6)
#define BLE_LL_CTRL_UNKNOWN_RSP (7)
#define BLE_LL_CTRL_FEATURE_REQ (8)
#define BLE_LL_CTRL_FEATURE_RSP (9)
#define BLE_LL_CTRL_PAUSE_ENC_REQ (10)
#define BLE_LL_CTRL_PAUSE_ENC_RSP (11)
#define BLE_LL_CTRL_VERSION_IND (12)
#define BLE_LL_CTRL_REJECT_IND (13)
#define BLE_LL_CTRL_SLAVE_FEATURE_REQ (14)
#define BLE_LL_CTRL_CONN_PARM_REQ (15)
#define BLE_LL_CTRL_CONN_PARM_RSP (16)
#define BLE_LL_CTRL_REJECT_IND_EXT (17)
#define BLE_LL_CTRL_PING_REQ (18)
#define BLE_LL_CTRL_PING_RSP (19)
#define BLE_LL_CTRL_LENGTH_REQ (20)
#define BLE_LL_CTRL_LENGTH_RSP (21)
#define BLE_LL_CTRL_PHY_REQ (22)
#define BLE_LL_CTRL_PHY_RSP (23)
#define BLE_LL_CTRL_PHY_UPDATE_IND (24)
#define BLE_LL_CTRL_MIN_USED_CHAN_IND (25)
#define BLE_LL_CTRL_CTE_REQ (26)
#define BLE_LL_CTRL_CTE_RSP (27)
#define BLE_LL_CTRL_PERIODIC_SYNC_IND (28)
#define BLE_LL_CTRL_CLOCK_ACCURACY_REQ (29)
#define BLE_LL_CTRL_CLOCK_ACCURACY_RSP (30)
#define BLE_LL_CTRL_CONN_UPDATE_IND (0x00)
#define BLE_LL_CTRL_CHANNEL_MAP_REQ (0x01)
#define BLE_LL_CTRL_TERMINATE_IND (0x02)
#define BLE_LL_CTRL_ENC_REQ (0x03)
#define BLE_LL_CTRL_ENC_RSP (0x04)
#define BLE_LL_CTRL_START_ENC_REQ (0x05)
#define BLE_LL_CTRL_START_ENC_RSP (0x06)
#define BLE_LL_CTRL_UNKNOWN_RSP (0x07)
#define BLE_LL_CTRL_FEATURE_REQ (0x08)
#define BLE_LL_CTRL_FEATURE_RSP (0x09)
#define BLE_LL_CTRL_PAUSE_ENC_REQ (0x0A)
#define BLE_LL_CTRL_PAUSE_ENC_RSP (0x0B)
#define BLE_LL_CTRL_VERSION_IND (0x0C)
#define BLE_LL_CTRL_REJECT_IND (0x0D)
#define BLE_LL_CTRL_SLAVE_FEATURE_REQ (0x0E)
#define BLE_LL_CTRL_CONN_PARM_REQ (0x0F)
#define BLE_LL_CTRL_CONN_PARM_RSP (0x10)
#define BLE_LL_CTRL_REJECT_IND_EXT (0x11)
#define BLE_LL_CTRL_PING_REQ (0x12)
#define BLE_LL_CTRL_PING_RSP (0x13)
#define BLE_LL_CTRL_LENGTH_REQ (0x14)
#define BLE_LL_CTRL_LENGTH_RSP (0x15)
#define BLE_LL_CTRL_PHY_REQ (0x16)
#define BLE_LL_CTRL_PHY_RSP (0x17)
#define BLE_LL_CTRL_PHY_UPDATE_IND (0x18)
#define BLE_LL_CTRL_MIN_USED_CHAN_IND (0x19)
#define BLE_LL_CTRL_CTE_REQ (0x1A)
#define BLE_LL_CTRL_CTE_RSP (0x1B)
#define BLE_LL_CTRL_PERIODIC_SYNC_IND (0x1C)
#define BLE_LL_CTRL_CLOCK_ACCURACY_REQ (0x1D)
#define BLE_LL_CTRL_CLOCK_ACCURACY_RSP (0x1E)
#define BLE_LL_CTRL_CIS_REQ (0x1F)
#define BLE_LL_CTRL_CIS_RSP (0x20)
#define BLE_LL_CTRL_CIS_IND (0x21)
#define BLE_LL_CTRL_CIS_TERMINATE_IND (0x22)
/* Maximum opcode value */
#define BLE_LL_CTRL_OPCODES (BLE_LL_CTRL_CLOCK_ACCURACY_RSP + 1)
#define BLE_LL_CTRL_OPCODES (BLE_LL_CTRL_CIS_TERMINATE_IND + 1)
extern const uint8_t g_ble_ll_ctrl_pkt_lengths[BLE_LL_CTRL_OPCODES];
/* Maximum LL control PDU size */
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER)
#if MYNEWT_VAL(BLE_ISO)
#define BLE_LL_CTRL_MAX_PDU_LEN (42)
#elif MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER)
#define BLE_LL_CTRL_MAX_PDU_LEN (35)
#else
#define BLE_LL_CTRL_MAX_PDU_LEN (27)
@ -261,6 +269,12 @@ struct ble_ll_len_req
#define BLE_LL_CTRL_CLOCK_ACCURACY_REQ_LEN (1)
#define BLE_LL_CTRL_CLOCK_ACCURACY_RSP_LEN (1)
/* BLE ISO */
#define BLE_LL_CTRL_CIS_REQ_LEN (42)
#define BLE_LL_CTRL_CIS_RSP_LEN (8)
#define BLE_LL_CTRL_CIS_IND_LEN (15)
#define BLE_LL_CTRL_CIS_TERMINATE_LEN (3)
/* API */
struct ble_ll_conn_sm;
void ble_ll_ctrl_proc_start(struct ble_ll_conn_sm *connsm, int ctrl_proc);
@ -306,6 +320,11 @@ void ble_ll_hci_ev_send_vendor_err(const char *file, uint32_t line);
uint8_t ble_ll_ctrl_phy_tx_transition_get(uint8_t phy_mask);
uint8_t ble_ll_ctrl_phy_from_phy_mask(uint8_t phy_mask);
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
void ble_ll_hci_ev_sca_update(struct ble_ll_conn_sm *connsm,
uint8_t status, uint8_t peer_sca);
#endif
#ifdef __cplusplus
}
#endif

View file

@ -27,7 +27,7 @@ extern "C" {
#include "nimble/hci_common.h"
/* For supported commands */
#define BLE_LL_SUPP_CMD_LEN (42)
#define BLE_LL_SUPP_CMD_LEN (45)
extern const uint8_t g_ble_ll_supp_cmds[BLE_LL_SUPP_CMD_LEN];
/* The largest event the controller will send. */

View file

@ -0,0 +1,53 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#ifndef H_BLE_LL_ISO
#define H_BLE_LL_ISO
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
int ble_ll_iso_read_tx_sync(const uint8_t *cmdbuf, uint8_t len);
int ble_ll_iso_set_cig_param(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen);
int ble_ll_iso_set_cig_param_test(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen);
int ble_ll_iso_create_cis(const uint8_t *cmdbuf, uint8_t len);
int ble_ll_iso_disconnect_cmd(const struct ble_hci_lc_disconnect_cp *cmd);
int ble_ll_iso_remove_cig(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen);
int ble_ll_iso_accept_cis_req(const uint8_t *cmdbuf, uint8_t len);
int ble_ll_iso_reject_cis_req(const uint8_t *cmdbuf, uint8_t len);
int ble_ll_iso_create_big(const uint8_t *cmdbuf, uint8_t len);
int ble_ll_iso_create_big_test(const uint8_t *cmdbuf, uint8_t len);
int ble_ll_iso_terminate_big(const uint8_t *cmdbuf, uint8_t len);
int ble_ll_iso_big_create_sync(const uint8_t *cmdbuf, uint8_t len);
int ble_ll_iso_big_terminate_sync(const uint8_t *cmdbuf, uint8_t len);
int ble_ll_iso_setup_iso_data_path(const uint8_t *cmdbuf, uint8_t len);
int ble_ll_iso_remove_iso_data_path(const uint8_t *cmdbuf, uint8_t len);
int ble_ll_iso_transmit_test(const uint8_t *cmdbuf, uint8_t len);
int ble_ll_iso_receive_test(const uint8_t *cmdbuf, uint8_t len);
int ble_ll_iso_read_counters_test(const uint8_t *cmdbuf, uint8_t len);
int ble_ll_iso_end_test(const uint8_t *cmdbuf, uint8_t len);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -225,6 +225,8 @@ static inline int ble_ll_phy_to_phy_mode(int phy, int phy_options)
if (phy == BLE_PHY_CODED && phy_options == BLE_HCI_LE_PHY_CODED_S2_PREF) {
phy_mode = BLE_PHY_MODE_CODED_500KBPS;
}
#else
(void)phy_options;
#endif
return phy_mode;

View file

@ -247,9 +247,6 @@ uint8_t g_dev_addr[BLE_DEV_ADDR_LEN];
/** Our random address */
uint8_t g_random_addr[BLE_DEV_ADDR_LEN];
/** Our supported features which can be controller by the host */
uint64_t g_ble_ll_supported_host_features = 0;
static const uint16_t g_ble_ll_pdu_header_tx_time[BLE_PHY_NUM_MODE] =
{
[BLE_PHY_MODE_1M] =
@ -1206,8 +1203,6 @@ ble_ll_task(void *arg)
/* Tell the host that we are ready to receive packets */
ble_ll_hci_send_noop();
ble_ll_rand_start();
while (1) {
ev = ble_npl_eventq_get(&g_ble_ll_data.ll_evq, BLE_NPL_TIME_FOREVER);
assert(ev);
@ -1305,10 +1300,6 @@ ble_ll_set_host_feat(const uint8_t *cmdbuf, uint8_t len)
mask = (uint64_t)1 << (cmd->bit_num);
if (!(mask & BLE_LL_HOST_CONTROLLED_FEATURES)) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
if (!(mask & g_ble_ll_supported_host_features)) {
return BLE_ERR_UNSUPPORTED;
}
@ -1372,6 +1363,20 @@ ble_ll_mbuf_init(struct os_mbuf *m, uint8_t pdulen, uint8_t hdr)
ble_hdr->txinfo.hdr_byte = hdr;
}
static void
ble_ll_validate_task(void)
{
#ifdef MYNEWT
#ifndef NDEBUG
struct os_task_info oti;
os_task_info_get(&g_ble_ll_task, &oti);
BLE_LL_ASSERT(oti.oti_stkusage < oti.oti_stksize);
#endif
#endif
}
/**
* Called to reset the controller. This performs a "software reset" of the link
* layer; it does not perform a HW reset of the controller nor does it reset
@ -1388,6 +1393,9 @@ ble_ll_reset(void)
int rc;
os_sr_t sr;
/* do sanity check on LL task stack */
ble_ll_validate_task();
OS_ENTER_CRITICAL(sr);
ble_phy_disable();
ble_ll_sched_stop();
@ -1447,23 +1455,6 @@ ble_ll_reset(void)
return rc;
}
static void
ble_ll_seed_prng(void)
{
uint32_t seed;
int i;
/* Seed random number generator with least significant bytes of device
* address.
*/
seed = 0;
for (i = 0; i < 4; ++i) {
seed |= g_dev_addr[i];
seed <<= 8;
}
srand(seed);
}
uint32_t
ble_ll_pdu_tx_time_get(uint16_t payload_len, int phy_mode)
{
@ -1678,16 +1669,24 @@ ble_ll_init(void)
features |= BLE_LL_FEAT_SYNC_TRANS_SEND;
#endif
/* Initialize random number generation */
ble_ll_rand_init();
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
features |= BLE_LL_FEAT_SCA_UPDATE;
#endif
/* XXX: This really doesn't belong here, as the address probably has not
* been set yet.
*/
ble_ll_seed_prng();
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO)
features |= BLE_LL_FEAT_CIS_MASTER;
features |= BLE_LL_FEAT_CIS_SLAVE;
features |= BLE_LL_FEAT_ISO_BROADCASTER;
features |= BLE_LL_FEAT_ISO_HOST_SUPPORT;
#endif
lldata->ll_supp_features = features;
/* Initialize random number generation */
ble_ll_rand_init();
/* Start the random number generator */
ble_ll_rand_start();
rc = stats_init_and_reg(STATS_HDR(ble_ll_stats),
STATS_SIZE_INIT_PARMS(ble_ll_stats, STATS_SIZE_32),
STATS_NAME_INIT_PARMS(ble_ll_stats),

View file

@ -131,6 +131,7 @@ struct ble_ll_adv_sm
uint8_t aux_index : 1;
uint8_t aux_first_pdu : 1;
uint8_t aux_not_scanned : 1;
uint8_t aux_dropped : 1;
struct ble_mbuf_hdr *rx_ble_hdr;
struct os_mbuf **aux_data;
struct ble_ll_adv_aux aux[2];
@ -685,7 +686,7 @@ ble_ll_adv_put_syncinfo(struct ble_ll_adv_sm *advsm,
dptr[8] = advsm->periodic_chanmap[4] & 0x1f;
/* SCA (3 bits) */
dptr[8] |= MYNEWT_VAL(BLE_LL_MASTER_SCA) << 5;
dptr[8] |= BLE_LL_SCA_ENUM << 5;
/* AA (4 bytes) */
put_le32(&dptr[9], advsm->periodic_access_addr);
@ -1269,7 +1270,7 @@ ble_ll_adv_secondary_tx_start_cb(struct ble_ll_sched_item *sch)
rc = ble_phy_tx_set_start_time(txstart, sch->remainder);
if (rc) {
STATS_INC(ble_ll_stats, adv_late_starts);
goto adv_tx_done;
goto adv_aux_dropped;
}
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
@ -1304,7 +1305,7 @@ ble_ll_adv_secondary_tx_start_cb(struct ble_ll_sched_item *sch)
/* Transmit advertisement */
rc = ble_phy_tx(pducb, advsm, end_trans);
if (rc) {
goto adv_tx_done;
goto adv_aux_dropped;
}
/* Enable/disable whitelisting based on filter policy */
@ -1322,7 +1323,8 @@ ble_ll_adv_secondary_tx_start_cb(struct ble_ll_sched_item *sch)
return BLE_LL_SCHED_STATE_RUNNING;
adv_tx_done:
adv_aux_dropped:
advsm->aux_dropped = 1;
ble_ll_adv_tx_done(advsm);
return BLE_LL_SCHED_STATE_DONE;
}
@ -1377,7 +1379,7 @@ ble_ll_adv_aux_calculate(struct ble_ll_adv_sm *advsm,
g_ble_ll_conn_params.num_used_chans,
g_ble_ll_conn_params.master_chan_map);
#else
aux->chan = ble_ll_utils_remapped_channel(rand() % BLE_PHY_NUM_DATA_CHANS,
aux->chan = ble_ll_utils_remapped_channel(ble_ll_rand() % BLE_PHY_NUM_DATA_CHANS,
g_ble_ll_conn_params.master_chan_map);
#endif
@ -1554,6 +1556,7 @@ ble_ll_adv_aux_schedule_first(struct ble_ll_adv_sm *advsm)
advsm->aux_index = 0;
advsm->aux_first_pdu = 1;
advsm->aux_not_scanned = 0;
advsm->aux_dropped = 0;
aux = AUX_CURRENT(advsm);
ble_ll_adv_aux_calculate(advsm, aux, 0);
@ -1853,7 +1856,7 @@ ble_ll_adv_update_did(struct ble_ll_adv_sm *advsm)
* the previously used value.
*/
do {
advsm->adi = (advsm->adi & 0xf000) | (rand() & 0x0fff);
advsm->adi = (advsm->adi & 0xf000) | (ble_ll_rand() & 0x0fff);
} while (old_adi == advsm->adi);
}
#endif
@ -2544,11 +2547,11 @@ ble_ll_adv_sm_start_periodic(struct ble_ll_adv_sm *advsm)
advsm->periodic_num_used_chans = g_ble_ll_conn_params.num_used_chans;
advsm->periodic_event_cntr = 0;
/* for chaining we start with random counter as we share access addr */
advsm->periodic_chain_event_cntr = rand();
advsm->periodic_chain_event_cntr = ble_ll_rand();
advsm->periodic_access_addr = ble_ll_utils_calc_access_addr();
advsm->periodic_channel_id = ((advsm->periodic_access_addr & 0xffff0000) >> 16) ^
(advsm->periodic_access_addr & 0x0000ffff);
advsm->periodic_crcinit = rand() & 0xffffff;
advsm->periodic_crcinit = ble_ll_rand() & 0xffffff;
usecs = (uint32_t)advsm->periodic_adv_itvl_max * BLE_LL_ADV_PERIODIC_ITVL;
ticks = os_cputime_usecs_to_ticks(usecs);
@ -2737,7 +2740,7 @@ ble_ll_adv_sm_start(struct ble_ll_adv_sm *advsm)
*/
earliest_start_time = ble_ll_rfmgmt_enable_now();
start_delay_us = rand() % (BLE_LL_ADV_DELAY_MS_MAX * 1000);
start_delay_us = ble_ll_rand() % (BLE_LL_ADV_DELAY_MS_MAX * 1000);
advsm->adv_pdu_start_time = os_cputime_get32() +
os_cputime_usecs_to_ticks(start_delay_us);
@ -4019,8 +4022,8 @@ ble_ll_adv_periodic_send_sync_ind(struct ble_ll_adv_sm *advsm,
/* SID, AType, SCA */
sync_ind[24] = (advsm->adi >> 12);
sync_ind[24] |= !!(advsm->flags & BLE_LL_ADV_SM_FLAG_TX_ADD) << 4 ;
sync_ind[24] |= MYNEWT_VAL(BLE_LL_MASTER_SCA) << 5;
sync_ind[24] |= !!(advsm->flags & BLE_LL_ADV_SM_FLAG_TX_ADD) << 4;
sync_ind[24] |= BLE_LL_SCA_ENUM << 5;
/* PHY */
sync_ind[25] = (0x01 << (advsm->sec_phy - 1));
@ -4836,6 +4839,11 @@ ble_ll_adv_sec_done(struct ble_ll_adv_sm *advsm)
/* We don't need RF anymore */
ble_ll_rfmgmt_release();
if (advsm->aux_dropped) {
ble_ll_adv_drop_event(advsm);
return;
}
if (advsm->aux_not_scanned) {
ble_ll_sched_rmv_elem(&aux_next->sch);
}

View file

@ -225,6 +225,166 @@ STATS_NAME_END(ble_ll_conn_stats)
static void ble_ll_conn_event_end(struct ble_npl_event *ev);
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL)
struct ble_ll_conn_cth_flow {
bool enabled;
uint16_t max_buffers;
uint16_t num_buffers;
};
static struct ble_ll_conn_cth_flow g_ble_ll_conn_cth_flow;
static struct ble_npl_event g_ble_ll_conn_cth_flow_error_ev;
static bool
ble_ll_conn_cth_flow_is_enabled(void)
{
return g_ble_ll_conn_cth_flow.enabled;
}
static bool
ble_ll_conn_cth_flow_alloc_credit(struct ble_ll_conn_sm *connsm)
{
struct ble_ll_conn_cth_flow *cth = &g_ble_ll_conn_cth_flow;
os_sr_t sr;
OS_ENTER_CRITICAL(sr);
if (!cth->num_buffers) {
OS_EXIT_CRITICAL(sr);
return false;
}
connsm->cth_flow_pending++;
cth->num_buffers--;
OS_EXIT_CRITICAL(sr);
return true;
}
static void
ble_ll_conn_cth_flow_free_credit(struct ble_ll_conn_sm *connsm, uint16_t credits)
{
struct ble_ll_conn_cth_flow *cth = &g_ble_ll_conn_cth_flow;
os_sr_t sr;
OS_ENTER_CRITICAL(sr);
/*
* It's not quite clear what we should do if host gives back more credits
* that we have allocated. For now let's just set invalid values back to
* sane values and continue.
*/
cth->num_buffers += credits;
if (cth->num_buffers > cth->max_buffers) {
cth->num_buffers = cth->max_buffers;
}
if (connsm->cth_flow_pending < credits) {
connsm->cth_flow_pending = 0;
} else {
connsm->cth_flow_pending -= credits;
}
OS_EXIT_CRITICAL(sr);
}
static void
ble_ll_conn_cth_flow_error_fn(struct ble_npl_event *ev)
{
struct ble_hci_ev *hci_ev;
struct ble_hci_ev_command_complete *hci_ev_cp;
uint16_t opcode;
hci_ev = (void *)ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
if (!hci_ev) {
/* Not much we can do anyway... */
return;
}
/*
* We are here in case length of HCI_Host_Number_Of_Completed_Packets was
* invalid. We will send an error back to host and we can only hope host is
* reasonable and will do some actions to recover, e.g. it should disconnect
* all connections to guarantee that all credits are back in pool and we're
* back in sync (although spec does not really say what should happen).
*/
opcode = BLE_HCI_OP(BLE_HCI_OGF_CTLR_BASEBAND,
BLE_HCI_OCF_CB_HOST_NUM_COMP_PKTS);
hci_ev->opcode = BLE_HCI_EVCODE_COMMAND_COMPLETE;
hci_ev->length = sizeof(*hci_ev_cp);
hci_ev_cp = (void *)hci_ev->data;
hci_ev_cp->num_packets = BLE_LL_CFG_NUM_HCI_CMD_PKTS;
hci_ev_cp->opcode = htole16(opcode);
hci_ev_cp->status = BLE_ERR_INV_HCI_CMD_PARMS;
ble_ll_hci_event_send(hci_ev);
}
void
ble_ll_conn_cth_flow_set_buffers(uint16_t num_buffers)
{
BLE_LL_ASSERT(num_buffers);
g_ble_ll_conn_cth_flow.max_buffers = num_buffers;
g_ble_ll_conn_cth_flow.num_buffers = num_buffers;
}
bool
ble_ll_conn_cth_flow_enable(bool enabled)
{
struct ble_ll_conn_cth_flow *cth = &g_ble_ll_conn_cth_flow;
if (cth->enabled == enabled) {
return true;
}
if (!SLIST_EMPTY(&g_ble_ll_conn_active_list)) {
return false;
}
cth->enabled = enabled;
return true;
}
void
ble_ll_conn_cth_flow_process_cmd(const uint8_t *cmdbuf)
{
const struct ble_hci_cmd *cmd;
const struct ble_hci_cb_host_num_comp_pkts_cp *cp;
struct ble_ll_conn_sm *connsm;
int i;
cmd = (const void *)cmdbuf;
cp = (const void *)cmd->data;
if (cmd->length != sizeof(cp->handles) + cp->handles * sizeof(cp->h[0])) {
ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &g_ble_ll_conn_cth_flow_error_ev);
return;
}
for (i = 0; i < cp->handles; i++) {
/*
* It's probably ok that we do not have active connection with given
* handle - this can happen if disconnection already happened in LL but
* host sent credits back before processing disconnection event. In such
* case we can simply ignore command for that connection since credits
* are returned by LL already.
*/
connsm = ble_ll_conn_find_active_conn(cp->h[i].handle);
if (connsm) {
ble_ll_conn_cth_flow_free_credit(connsm, cp->h[i].count);
}
}
}
#endif
#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
/**
* Checks to see if we should start a PHY update procedure
@ -332,7 +492,7 @@ ble_ll_conn_is_lru(struct ble_ll_conn_sm *s1, struct ble_ll_conn_sm *s2)
int rc;
/* Set time that we last serviced the schedule */
if ((int32_t)(s1->last_scheduled - s2->last_scheduled) < 0) {
if (CPUTIME_LT(s1->last_scheduled, s2->last_scheduled)) {
rc = 1;
} else {
rc = 0;
@ -855,8 +1015,14 @@ ble_ll_conn_tx_pdu(struct ble_ll_conn_sm *connsm)
/*
* If we are encrypting, we are only allowed to send certain
* kinds of LL control PDU's. If none is enqueued, send empty pdu!
*
* In Slave role, we are allowed to send unencrypted packets until
* LL_ENC_RSP is sent.
*/
if (connsm->enc_data.enc_state > CONN_ENC_S_ENCRYPTED) {
if (((connsm->enc_data.enc_state > CONN_ENC_S_ENCRYPTED) &&
CONN_IS_MASTER(connsm)) ||
((connsm->enc_data.enc_state > CONN_ENC_S_ENC_RSP_TO_BE_SENT) &&
CONN_IS_SLAVE(connsm))) {
if (!ble_ll_ctrl_enc_allowed_pdu_tx(pkthdr)) {
CONN_F_EMPTY_PDU_TXD(connsm) = 1;
goto conn_tx_pdu;
@ -991,7 +1157,7 @@ ble_ll_conn_tx_pdu(struct ble_ll_conn_sm *connsm)
}
ticks = os_cputime_usecs_to_ticks(ticks);
if ((int32_t)((os_cputime_get32() + ticks) - next_event_time) < 0) {
if (CPUTIME_LT(os_cputime_get32() + ticks, next_event_time)) {
md = 1;
}
}
@ -1450,10 +1616,10 @@ ble_ll_conn_master_common_init(struct ble_ll_conn_sm *connsm)
*/
connsm->tx_win_size = BLE_LL_CONN_TX_WIN_MIN + 1;
connsm->tx_win_off = 0;
connsm->master_sca = MYNEWT_VAL(BLE_LL_MASTER_SCA);
connsm->master_sca = BLE_LL_SCA_ENUM;
/* Hop increment is a random value between 5 and 16. */
connsm->hop_inc = (rand() % 12) + 5;
connsm->hop_inc = (ble_ll_rand() % 12) + 5;
/* Set channel map to map requested by host */
connsm->num_used_chans = g_ble_ll_conn_params.num_used_chans;
@ -1462,7 +1628,7 @@ ble_ll_conn_master_common_init(struct ble_ll_conn_sm *connsm)
/* Calculate random access address and crc initialization value */
connsm->access_addr = ble_ll_utils_calc_access_addr();
connsm->crcinit = rand() & 0xffffff;
connsm->crcinit = ble_ll_rand() & 0xffffff;
/* Set initial schedule callback */
connsm->conn_sch.sched_cb = ble_ll_conn_event_start_cb;
@ -1861,6 +2027,10 @@ ble_ll_conn_end(struct ble_ll_conn_sm *connsm, uint8_t ble_err)
/* Remove from the active connection list */
SLIST_REMOVE(&g_ble_ll_conn_active_list, connsm, ble_ll_conn_sm, act_sle);
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL)
ble_ll_conn_cth_flow_free_credit(connsm, connsm->cth_flow_pending);
#endif
/* Free the current transmit pdu if there is one. */
if (connsm->cur_tx_pdu) {
os_mbuf_free_chain(connsm->cur_tx_pdu);
@ -3239,6 +3409,13 @@ ble_ll_init_rx_isr_end(uint8_t *rxbuf, uint8_t crcok,
*/
memcpy(init_addr, rl->rl_local_rpa, BLE_DEV_ADDR_LEN);
}
} else if (!ble_ll_is_rpa(adv_addr, adv_addr_type)) {
/* undirected with ID address, assure privacy if on RL */
rl = ble_ll_resolv_list_find(adv_addr, adv_addr_type);
if (rl && (rl->rl_priv_mode == BLE_HCI_PRIVACY_NETWORK) &&
rl->rl_has_peer) {
goto init_rx_isr_exit;
}
}
#endif
@ -3452,12 +3629,18 @@ ble_ll_conn_rx_data_pdu(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr)
uint16_t acl_hdr;
struct ble_ll_conn_sm *connsm;
if (BLE_MBUF_HDR_CRC_OK(hdr)) {
/* Packets with invalid CRC are not sent to LL */
BLE_LL_ASSERT(BLE_MBUF_HDR_CRC_OK(hdr));
/* XXX: there is a chance that the connection was thrown away and
re-used before processing packets here. Fix this. */
/* We better have a connection state machine */
connsm = ble_ll_conn_find_active_conn(hdr->rxinfo.handle);
if (connsm) {
if (!connsm) {
STATS_INC(ble_ll_conn_stats, no_conn_sm);
goto conn_rx_data_pdu_end;
}
/* Check state machine */
ble_ll_conn_chk_csm_flags(connsm);
@ -3471,8 +3654,7 @@ ble_ll_conn_rx_data_pdu(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr)
* Check that the LLID and payload length are reasonable.
* Empty payload is only allowed for LLID == 01b.
* */
if ((llid == 0) ||
((acl_len == 0) && (llid != BLE_LL_LLID_DATA_FRAG))) {
if ((llid == 0) || ((acl_len == 0) && (llid != BLE_LL_LLID_DATA_FRAG))) {
STATS_INC(ble_ll_conn_stats, rx_bad_llid);
goto conn_rx_data_pdu_end;
}
@ -3483,11 +3665,15 @@ ble_ll_conn_rx_data_pdu(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr)
*
* Reference: Core 5.0, Vol 6, Part B, 5.1.3.1
*/
if ((connsm->enc_data.enc_state > CONN_ENC_S_PAUSE_ENC_RSP_WAIT) &&
!ble_ll_ctrl_enc_allowed_pdu_rx(rxpdu)) {
if ((connsm->enc_data.enc_state > CONN_ENC_S_PAUSE_ENC_RSP_WAIT &&
CONN_IS_MASTER(connsm)) ||
(connsm->enc_data.enc_state >= CONN_ENC_S_ENC_RSP_TO_BE_SENT &&
CONN_IS_SLAVE(connsm))) {
if (!ble_ll_ctrl_enc_allowed_pdu_rx(rxpdu)) {
ble_ll_conn_timeout(connsm, BLE_ERR_CONN_TERM_MIC);
goto conn_rx_data_pdu_end;
}
}
#endif
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING)
@ -3520,7 +3706,11 @@ ble_ll_conn_rx_data_pdu(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr)
* as the last received sequence number
*/
rxd_sn = hdr_byte & BLE_LL_DATA_HDR_SN_MASK;
if (rxd_sn != connsm->last_rxd_sn) {
if (rxd_sn == connsm->last_rxd_sn) {
STATS_INC(ble_ll_conn_stats, data_pdu_rx_dup);
goto conn_rx_data_pdu_end;
}
/* Update last rxd sn */
connsm->last_rxd_sn = rxd_sn;
@ -3565,16 +3755,16 @@ ble_ll_conn_rx_data_pdu(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr)
/* NOTE: we dont free the mbuf since we handed it off! */
return;
} else {
STATS_INC(ble_ll_conn_stats, data_pdu_rx_dup);
}
} else {
STATS_INC(ble_ll_conn_stats, no_conn_sm);
}
}
/* Free buffer */
conn_rx_data_pdu_end:
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL)
/* Need to give credit back if we allocated one for this PDU */
if (hdr->rxinfo.flags & BLE_MBUF_HDR_F_CONN_CREDIT) {
ble_ll_conn_cth_flow_free_credit(connsm, 1);
}
#endif
os_mbuf_free_chain(rxpdu);
}
@ -3595,7 +3785,6 @@ int
ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr)
{
int rc;
int is_ctrl;
uint8_t hdr_byte;
uint8_t hdr_sn;
uint8_t hdr_nesn;
@ -3609,14 +3798,43 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr)
uint32_t add_usecs;
struct os_mbuf *txpdu;
struct ble_ll_conn_sm *connsm;
struct os_mbuf *rxpdu;
struct os_mbuf *rxpdu = NULL;
struct ble_mbuf_hdr *txhdr;
int rx_phy_mode;
bool alloc_rxpdu = true;
rc = -1;
connsm = g_ble_ll_conn_cur_sm;
/* Retrieve the header and payload length */
hdr_byte = rxbuf[0];
rx_pyld_len = rxbuf[1];
/*
* No need to alloc rxpdu for packets with invalid CRC, we would throw them
* away instantly from LL anyway.
*/
if (!BLE_MBUF_HDR_CRC_OK(rxhdr)) {
alloc_rxpdu = false;
}
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL)
/*
* If flow control is enabled, we need to have credit available for each
* non-empty data packet that LL may send to host. If there are no credits
* available, we don't need to allocate buffer for this packet so LL will
* nak it.
*/
if (alloc_rxpdu && ble_ll_conn_cth_flow_is_enabled() &&
BLE_LL_LLID_IS_DATA(hdr_byte) && (rx_pyld_len > 0)) {
if (ble_ll_conn_cth_flow_alloc_credit(connsm)) {
rxhdr->rxinfo.flags |= BLE_MBUF_HDR_F_CONN_CREDIT;
} else {
alloc_rxpdu = false;
}
}
#endif
/*
* We need to attempt to allocate a buffer here. The reason we do this
* now is that we should not ack the packet if we have no receive
@ -3624,14 +3842,14 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr)
* acked, but we should not ack the received frame if we cant hand it up.
* NOTE: we hand up empty pdu's to the LL task!
*/
if (alloc_rxpdu) {
rxpdu = ble_ll_rxpdu_alloc(rx_pyld_len + BLE_LL_PDU_HDR_LEN);
}
/*
* We should have a current connection state machine. If we dont, we just
* hand the packet to the higher layer to count it.
*/
rc = -1;
connsm = g_ble_ll_conn_cur_sm;
if (!connsm) {
STATS_INC(ble_ll_conn_stats, rx_data_pdu_no_conn);
goto conn_exit;
@ -3693,9 +3911,7 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr)
/* Set last received header byte */
connsm->last_rxd_hdr_byte = hdr_byte;
is_ctrl = 0;
if ((hdr_byte & BLE_LL_DATA_HDR_LLID_MASK) == BLE_LL_LLID_CTRL) {
is_ctrl = 1;
if (BLE_LL_LLID_IS_CTRL(hdr_byte)) {
opcode = rxbuf[2];
}
@ -3784,7 +4000,7 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr)
/* Adjust payload for max TX time and octets */
#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
if (is_ctrl &&
if (BLE_LL_LLID_IS_CTRL(hdr_byte) &&
(connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) &&
(opcode == BLE_LL_CTRL_PHY_UPDATE_IND)) {
connsm->phy_tx_transition =
@ -3803,8 +4019,9 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr)
/* If this is a TERMINATE_IND, we have to reply */
chk_rx_terminate_ind:
/* If we received a terminate IND, we must set some flags */
if (is_ctrl && (opcode == BLE_LL_CTRL_TERMINATE_IND)
&& (rx_pyld_len == (1 + BLE_LL_CTRL_TERMINATE_IND_LEN))) {
if (BLE_LL_LLID_IS_CTRL(hdr_byte) &&
(opcode == BLE_LL_CTRL_TERMINATE_IND) &&
(rx_pyld_len == (1 + BLE_LL_CTRL_TERMINATE_IND_LEN))) {
connsm->csmflags.cfbit.terminate_ind_rxd = 1;
connsm->rxd_disconnect_reason = rxbuf[3];
}
@ -4226,6 +4443,12 @@ ble_ll_conn_module_reset(void)
g_ble_ll_conn_sync_transfer_params.mode = 0;
g_ble_ll_conn_sync_transfer_params.sync_timeout_us = 0;
#endif
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL)
g_ble_ll_conn_cth_flow.enabled = false;
g_ble_ll_conn_cth_flow.max_buffers = 1;
g_ble_ll_conn_cth_flow.num_buffers = 1;
#endif
}
/* Initialize the connection module */
@ -4265,6 +4488,11 @@ ble_ll_conn_module_init(void)
"ble_ll_conn");
BLE_LL_ASSERT(rc == 0);
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL)
ble_npl_event_init(&g_ble_ll_conn_cth_flow_error_ev,
ble_ll_conn_cth_flow_error_fn, NULL);
#endif
/* Call reset to finish reset of initialization */
ble_ll_conn_module_reset();
}

View file

@ -1128,16 +1128,11 @@ ble_ll_conn_create_cancel(ble_ll_hci_post_cmd_complete_cb *post_cmd_cb)
* @return int
*/
int
ble_ll_conn_hci_disconnect_cmd(const uint8_t *cmdbuf, uint8_t len)
ble_ll_conn_hci_disconnect_cmd(const struct ble_hci_lc_disconnect_cp *cmd)
{
int rc;
uint16_t handle;
struct ble_ll_conn_sm *connsm;
const struct ble_hci_lc_disconnect_cp *cmd = (const void *) cmdbuf;
if (len != sizeof (*cmd)) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
/* Check for valid parameters */
handle = le16toh(cmd->conn_handle);
@ -1565,6 +1560,34 @@ ltk_key_cmd_complete:
}
#endif
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
int
ble_ll_conn_req_peer_sca(const uint8_t *cmdbuf, uint8_t len,
uint8_t *rspbuf, uint8_t *rsplen)
{
const struct ble_hci_le_request_peer_sca_cp *params = (const void *)cmdbuf;
struct ble_ll_conn_sm *connsm;
connsm = ble_ll_conn_find_active_conn(params->conn_handle);
if (!connsm) {
return BLE_ERR_UNK_CONN_ID;
}
if (!(connsm->remote_features[2] & (BLE_LL_FEAT_SCA_UPDATE >> 24))) {
return BLE_ERR_UNSUPP_REM_FEATURE;
}
if (IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_SCA_UPDATE)) {
/* Not really specified what we should return */
return BLE_ERR_CTLR_BUSY;
}
ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_SCA_UPDATE);
return 0;
}
#endif
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING)
/**
* Read authenticated payload timeout (OGF=3, OCF==0x007B)

View file

@ -164,7 +164,7 @@ bool ble_ll_conn_init_pending_aux_conn_rsp(void);
void ble_ll_disconn_comp_event_send(struct ble_ll_conn_sm *connsm,
uint8_t reason);
void ble_ll_auth_pyld_tmo_event_send(struct ble_ll_conn_sm *connsm);
int ble_ll_conn_hci_disconnect_cmd(const uint8_t *cmdbuf, uint8_t len);
int ble_ll_conn_hci_disconnect_cmd(const struct ble_hci_lc_disconnect_cp *cmd);
int ble_ll_conn_hci_rd_rem_ver_cmd(const uint8_t *cmdbuf, uint8_t len);
int ble_ll_conn_create(const uint8_t *cmdbuf, uint8_t len);
int ble_ll_conn_hci_update(const uint8_t *cmdbuf, uint8_t len);
@ -196,12 +196,23 @@ int ble_ll_conn_hci_wr_auth_pyld_tmo(const uint8_t *cmdbuf, uint8_t len,
uint8_t *rspbuf, uint8_t *rsplen);
int ble_ll_conn_hci_rd_auth_pyld_tmo(const uint8_t *cmdbuf, uint8_t len,
uint8_t *rspbuf, uint8_t *rsplen);
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
int ble_ll_conn_req_peer_sca(const uint8_t *cmdbuf, uint8_t len,
uint8_t *rspbuf, uint8_t *rsplen);
#endif
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING)
void ble_ll_conn_auth_pyld_timer_start(struct ble_ll_conn_sm *connsm);
#else
#define ble_ll_conn_auth_pyld_timer_start(x)
#endif
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL)
void ble_ll_conn_cth_flow_set_buffers(uint16_t num_buffers);
bool ble_ll_conn_cth_flow_enable(bool enabled);
void ble_ll_conn_cth_flow_process_cmd(const uint8_t *cmdbuf);
#endif
int ble_ll_hci_cmd_rx(uint8_t *cmd, void *arg);
int ble_ll_hci_acl_rx(struct os_mbuf *om, void *arg);

View file

@ -112,6 +112,10 @@ const uint8_t g_ble_ll_ctrl_pkt_lengths[BLE_LL_CTRL_OPCODES] =
BLE_LL_CTRL_PERIODIC_SYNC_IND_LEN,
BLE_LL_CTRL_CLOCK_ACCURACY_REQ_LEN,
BLE_LL_CTRL_CLOCK_ACCURACY_RSP_LEN,
BLE_LL_CTRL_CIS_REQ_LEN,
BLE_LL_CTRL_CIS_RSP_LEN,
BLE_LL_CTRL_CIS_IND_LEN,
BLE_LL_CTRL_CIS_TERMINATE_LEN
};
/**
@ -505,6 +509,12 @@ ble_ll_ctrl_proc_unk_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr, uint8_t *
ble_ll_ctrl_phy_update_cancel(connsm, BLE_ERR_UNSUPP_REM_FEATURE);
ctrl_proc = BLE_LL_CTRL_PROC_PHY_UPDATE;
break;
#endif
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
case BLE_LL_CTRL_CLOCK_ACCURACY_REQ:
ble_ll_hci_ev_sca_update(connsm, BLE_ERR_UNSUPPORTED, 0);
ctrl_proc = BLE_LL_CTRL_PROC_SCA_UPDATE;
break;
#endif
default:
ctrl_proc = BLE_LL_CTRL_PROC_NUM;
@ -836,6 +846,20 @@ ble_ll_ctrl_phy_req_rsp_make(struct ble_ll_conn_sm *connsm, uint8_t *ctrdata)
}
}
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
/**
* Create a LL_CLOCK_ACCURACY_REQ or LL_CLOCK_ACCURACY_RSP pdu
*
* @param connsm Pointer to connection state machine
* @param ctrdata: Pointer to where CtrData starts in pdu
*/
static void
ble_ll_ctrl_sca_req_rsp_make(struct ble_ll_conn_sm *connsm, uint8_t *ctrdata)
{
ctrdata[0] = BLE_LL_SCA_ENUM;
}
#endif
static uint8_t
ble_ll_ctrl_rx_phy_req(struct ble_ll_conn_sm *connsm, uint8_t *req,
uint8_t *rsp)
@ -1040,11 +1064,70 @@ ble_ll_ctrl_rx_periodic_sync_ind(struct ble_ll_conn_sm *connsm, uint8_t *dptr)
connsm->sync_transfer_skip,
connsm->sync_transfer_sync_timeout);
}
return BLE_ERR_MAX;
}
#endif
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
/**
* Called when a BLE_LL_CTRL_CLOCK_ACCURACY_REQ PDU is received
*
* @param connsm
* @param dptr
* @param rsp Pointer to CtrData of BLE_LL_CTRL_CLOCK_ACCURACY_RSP.
*
* @return uint8_t
*/
static uint8_t
ble_ll_ctrl_rx_sca_req(struct ble_ll_conn_sm *connsm, uint8_t *dptr,
uint8_t *rsp)
{
ble_ll_ctrl_sca_req_rsp_make(connsm, rsp);
return BLE_LL_CTRL_CLOCK_ACCURACY_RSP;
}
/**
* Called when a BLE_LL_CTRL_CLOCK_ACCURACY_RSP PDU is received
*
* @param connsm
* @param dptr
*
* @return uint8_t
*/
static uint8_t
ble_ll_ctrl_rx_sca_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr)
{
if (connsm->cur_ctrl_proc != BLE_LL_CTRL_PROC_SCA_UPDATE) {
return BLE_LL_CTRL_UNKNOWN_RSP;
}
ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_SCA_UPDATE);
ble_ll_hci_ev_sca_update(connsm, BLE_ERR_SUCCESS, dptr[0]);
return BLE_ERR_MAX;
}
#endif
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO)
static uint8_t
ble_ll_ctrl_rx_cis_req(struct ble_ll_conn_sm *connsm, uint8_t *dptr,
uint8_t *rspdata)
{
return BLE_LL_CTRL_UNKNOWN_RSP;
}
static uint8_t
ble_ll_ctrl_rx_cis_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr,
uint8_t *rspdata)
{
return BLE_LL_CTRL_UNKNOWN_RSP;
}
static uint8_t
ble_ll_ctrl_rx_cis_ind(struct ble_ll_conn_sm *connsm, uint8_t *dptr)
{
return BLE_LL_CTRL_UNKNOWN_RSP;
}
#endif
/**
* Create a link layer length request or length response PDU.
*
@ -1250,6 +1333,15 @@ ble_ll_ctrl_start_enc_send(struct ble_ll_conn_sm *connsm)
return rc;
}
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO)
static void
ble_ll_ctrl_cis_create(struct ble_ll_conn_sm *connsm, uint8_t *dptr)
{
/* TODO Implement */
return;
}
#endif
/**
* Create a link layer control "encrypt request" PDU.
*
@ -1351,7 +1443,7 @@ ble_ll_ctrl_rx_enc_req(struct ble_ll_conn_sm *connsm, uint8_t *dptr,
return BLE_LL_CTRL_UNKNOWN_RSP;
}
connsm->enc_data.enc_state = CONN_ENC_S_LTK_REQ_WAIT;
connsm->enc_data.enc_state = CONN_ENC_S_ENC_RSP_TO_BE_SENT;
/* In case we were already encrypted we need to reset packet counters */
connsm->enc_data.rx_pkt_cntr = 0;
@ -1676,6 +1768,12 @@ ble_ll_ctrl_rx_reject_ind(struct ble_ll_conn_sm *connsm, uint8_t *dptr,
*/
ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_DATA_LEN_UPD);
break;
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
case BLE_LL_CTRL_PROC_SCA_UPDATE:
ble_ll_hci_ev_sca_update(connsm, ble_error, 0);
ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_SCA_UPDATE);
break;
#endif
default:
break;
}
@ -2138,6 +2236,18 @@ ble_ll_ctrl_proc_init(struct ble_ll_conn_sm *connsm, int ctrl_proc)
opcode = BLE_LL_CTRL_PHY_REQ;
ble_ll_ctrl_phy_req_rsp_make(connsm, ctrdata);
break;
#endif
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
case BLE_LL_CTRL_PROC_SCA_UPDATE:
opcode = BLE_LL_CTRL_CLOCK_ACCURACY_REQ;
ble_ll_ctrl_sca_req_rsp_make(connsm, ctrdata);
break;
#endif
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO)
case BLE_LL_CTRL_PROC_CIS_CREATE:
opcode = BLE_LL_CTRL_CIS_REQ;
ble_ll_ctrl_cis_create(connsm, ctrdata);
break;
#endif
default:
BLE_LL_ASSERT(0);
@ -2568,6 +2678,26 @@ ble_ll_ctrl_rx_pdu(struct ble_ll_conn_sm *connsm, struct os_mbuf *om)
rsp_opcode = ble_ll_ctrl_rx_phy_update_ind(connsm, dptr);
break;
#endif
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
case BLE_LL_CTRL_CLOCK_ACCURACY_REQ:
rsp_opcode = ble_ll_ctrl_rx_sca_req(connsm, dptr, rspdata);
break;
case BLE_LL_CTRL_CLOCK_ACCURACY_RSP:
rsp_opcode = ble_ll_ctrl_rx_sca_rsp(connsm, dptr);
break;
#endif
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO)
case BLE_LL_CTRL_CIS_REQ:
rsp_opcode = ble_ll_ctrl_rx_cis_req(connsm, dptr, rspdata);
break;
case BLE_LL_CTRL_CIS_RSP:
rsp_opcode = ble_ll_ctrl_rx_cis_rsp(connsm, dptr, rspdata);
break;
case BLE_LL_CTRL_CIS_IND:
rsp_opcode = ble_ll_ctrl_rx_cis_ind(connsm, dptr);
break;
#endif
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER)
case BLE_LL_CTRL_PERIODIC_SYNC_IND:
rsp_opcode = ble_ll_ctrl_rx_periodic_sync_ind(connsm, dptr);
@ -2709,6 +2839,7 @@ ble_ll_ctrl_tx_done(struct os_mbuf *txpdu, struct ble_ll_conn_sm *connsm)
connsm->enc_data.enc_state = CONN_ENC_S_ENC_RSP_WAIT;
break;
case BLE_LL_CTRL_ENC_RSP:
connsm->enc_data.enc_state = CONN_ENC_S_LTK_REQ_WAIT;
connsm->csmflags.cfbit.send_ltk_req = 1;
break;
case BLE_LL_CTRL_START_ENC_RSP:

View file

@ -33,6 +33,7 @@
#include "controller/ble_ll_whitelist.h"
#include "controller/ble_ll_resolv.h"
#include "controller/ble_ll_sync.h"
#include "controller/ble_ll_iso.h"
#include "ble_ll_priv.h"
#include "ble_ll_conn_priv.h"
@ -327,6 +328,31 @@ ble_ll_hci_le_read_bufsize(uint8_t *rspbuf, uint8_t *rsplen)
return BLE_ERR_SUCCESS;
}
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO)
/**
* HCI read buffer size v2 command. Returns the ACL and ISO data packet length and
* num data packets.
*
* @param rspbuf Pointer to response buffer
* @param rsplen Length of response buffer
*
* @return int BLE error code
*/
static int
ble_ll_hci_le_read_bufsize_v2(uint8_t *rspbuf, uint8_t *rsplen)
{
struct ble_hci_le_rd_buf_size_v2_rp *rp = (void *) rspbuf;
rp->data_len = htole16(g_ble_ll_data.ll_acl_pkt_size);
rp->data_packets = g_ble_ll_data.ll_num_acl_pkts;
rp->iso_data_len = 0;
rp->iso_data_packets = 0;
*rsplen = sizeof(*rp);
return BLE_ERR_SUCCESS;
}
#endif
#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
/**
* Checks the preferred phy masks for validity and places the preferred masks
@ -618,6 +644,9 @@ ble_ll_hci_le_cmd_send_cmd_status(uint16_t ocf)
case BLE_HCI_OCF_LE_GEN_DHKEY:
case BLE_HCI_OCF_LE_SET_PHY:
case BLE_HCI_OCF_LE_PERIODIC_ADV_CREATE_SYNC:
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
case BLE_HCI_OCF_LE_REQ_PEER_SCA:
#endif
rc = 1;
break;
default:
@ -1149,10 +1178,77 @@ ble_ll_hci_le_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf,
rc = ble_ll_set_default_sync_transfer_params(cmdbuf, len);
break;
#endif
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO)
case BLE_HCI_OCF_LE_READ_ISO_TX_SYNC:
rc = ble_ll_iso_read_tx_sync(cmdbuf, len);
break;
case BLE_HCI_OCF_LE_SET_CIG_PARAM:
rc = ble_ll_iso_set_cig_param(cmdbuf, len, rspbuf, rsplen);
break;
case BLE_HCI_OCF_LE_CREATE_CIS:
rc = ble_ll_iso_create_cis(cmdbuf, len);
break;
case BLE_HCI_OCF_LE_REMOVE_CIG:
rc = ble_ll_iso_remove_cig(cmdbuf, len, rspbuf, rsplen);
break;
case BLE_HCI_OCF_LE_ACCEPT_CIS_REQ:
rc = ble_ll_iso_accept_cis_req(cmdbuf, len);
break;
case BLE_HCI_OCF_LE_REJECT_CIS_REQ:
rc = ble_ll_iso_reject_cis_req(cmdbuf, len);
break;
case BLE_HCI_OCF_LE_CREATE_BIG:
rc = ble_ll_iso_create_big(cmdbuf, len);
break;
case BLE_HCI_OCF_LE_TERMINATE_BIG:
rc = ble_ll_iso_terminate_big(cmdbuf, len);
break;
case BLE_HCI_OCF_LE_BIG_CREATE_SYNC:
rc = ble_ll_iso_big_create_sync(cmdbuf, len);
break;
case BLE_HCI_OCF_LE_BIG_TERMINATE_SYNC:
rc = ble_ll_iso_big_terminate_sync(cmdbuf,len);
break;
case BLE_HCI_OCF_LE_SETUP_ISO_DATA_PATH:
rc = ble_ll_iso_setup_iso_data_path(cmdbuf, len);
break;
case BLE_HCI_OCF_LE_REMOVE_ISO_DATA_PATH:
rc = ble_ll_iso_remove_iso_data_path(cmdbuf, len);
break;
case BLE_HCI_OCF_LE_RD_BUF_SIZE_V2:
rc = ble_ll_hci_le_read_bufsize_v2(rspbuf, rsplen);
break;
#endif
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO_TEST)
case BLE_HCI_OCF_LE_SET_CIG_PARAM_TEST:
rc = ble_ll_iso_set_cig_param_test(cmdbuf, len, rspbuf, rsplen);
break;
case BLE_HCI_OCF_LE_CREATE_BIG_TEST:
rc = ble_ll_iso_create_big_test(cmdbuf, len);
break;
case BLE_HCI_OCF_LE_ISO_TRANSMIT_TEST:
rc = ble_ll_iso_transmit_test(cmdbuf, len);
break;
case BLE_HCI_OCF_LE_ISO_RECEIVE_TEST:
rc = ble_ll_iso_receive_test(cmdbuf, len);
break;
case BLE_HCI_OCF_LE_ISO_READ_TEST_COUNTERS:
rc = ble_ll_iso_read_counters_test(cmdbuf, len);
break;
case BLE_HCI_OCF_LE_ISO_TEST_END:
rc = ble_ll_iso_end_test(cmdbuf, len);
break;
#endif
#if MYNEWT_VAL(BLE_VERSION) >= 52
case BLE_HCI_OCF_LE_SET_HOST_FEAT:
rc = ble_ll_set_host_feat(cmdbuf, len);
break;
#endif
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
case BLE_HCI_OCF_LE_REQ_PEER_SCA:
rc = ble_ll_conn_req_peer_sca(cmdbuf, len,
rspbuf, rsplen);
break;
#endif
default:
rc = BLE_ERR_UNKNOWN_HCI_CMD;
@ -1174,6 +1270,26 @@ ble_ll_hci_le_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf,
return rc;
}
static int
ble_ll_hci_disconnect(const uint8_t *cmdbuf, uint8_t len)
{
const struct ble_hci_lc_disconnect_cp *cmd;
cmd = (const void *) cmdbuf;
if (len != sizeof (*cmd)) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO)
if (le16toh(cmd->conn_handle) >= BLE_LL_CONN_HANDLE_ISO_OFFSET) {
return ble_ll_iso_disconnect_cmd(cmd);
}
#endif
return ble_ll_conn_hci_disconnect_cmd(cmd);
}
/**
* Process a link control command sent from the host to the controller. The HCI
* command has a 3 byte command header followed by data. The header is:
@ -1194,7 +1310,7 @@ ble_ll_hci_link_ctrl_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf)
switch (ocf) {
case BLE_HCI_OCF_DISCONNECT_CMD:
rc = ble_ll_conn_hci_disconnect_cmd(cmdbuf, len);
rc = ble_ll_hci_disconnect(cmdbuf, len);
/* Send command status instead of command complete */
rc += (BLE_ERR_MAX + 1);
break;
@ -1227,6 +1343,64 @@ ble_ll_hci_cb_set_event_mask(const uint8_t *cmdbuf, uint8_t len)
return BLE_ERR_SUCCESS;
}
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL)
static int
ble_ll_hci_cb_set_ctrlr_to_host_fc(const uint8_t *cmdbuf, uint8_t len)
{
const struct ble_hci_cb_ctlr_to_host_fc_cp *cmd = (const void *) cmdbuf;
if (len != sizeof (*cmd)) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
/* We only allow to either disable flow control or enable for ACL only */
if (cmd->enable > 1) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
if (!ble_ll_conn_cth_flow_enable(cmd->enable)) {
return BLE_ERR_CMD_DISALLOWED;
}
return BLE_ERR_SUCCESS;
}
static int
ble_ll_hci_cb_host_buf_size(const uint8_t *cmdbuf, uint8_t len)
{
const struct ble_hci_cb_host_buf_size_cp *cmd = (const void *) cmdbuf;
uint16_t acl_num;
uint16_t acl_data_len;
if (len != sizeof (*cmd)) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
/* We do not support SCO so those parameters should be set to 0 */
if (cmd->sco_num || cmd->sco_data_len) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
/*
* Core 5.2 Vol 4 Part E section 7.3.39 states that "Both the Host and the
* Controller shall support command and event packets, where the data portion
* (excluding header) contained in the packets is 255 octets in size.".
* This means we can basically accept any allowed value since LL does not
* reassemble incoming data thus will not send more than 255 octets in single
* data packet.
*/
acl_num = le16toh(cmd->acl_num);
acl_data_len = le16toh(cmd->acl_data_len);
if (acl_data_len < 255) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
ble_ll_conn_cth_flow_set_buffers(acl_num);
return BLE_ERR_SUCCESS;
}
#endif
static int
ble_ll_hci_cb_set_event_mask2(const uint8_t *cmdbuf, uint8_t len)
{
@ -1259,6 +1433,22 @@ ble_ll_hci_ctlr_bb_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf,
rc = ble_ll_reset();
}
break;
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL)
case BLE_HCI_OCF_CB_SET_CTLR_TO_HOST_FC:
rc = ble_ll_hci_cb_set_ctrlr_to_host_fc(cmdbuf, len);
break;
case BLE_HCI_OCF_CB_HOST_BUF_SIZE:
rc = ble_ll_hci_cb_host_buf_size(cmdbuf, len);
break;
case BLE_HCI_OCF_CB_HOST_NUM_COMP_PKTS:
/*
* HCI_Host_Number_Of_Completed_Packets is handled immediately when
* received from transport so we should never receive it here.
*/
BLE_LL_ASSERT(0);
rc = BLE_ERR_UNKNOWN_HCI_CMD;
break;
#endif
case BLE_HCI_OCF_CB_SET_EVENT_MASK2:
rc = ble_ll_hci_cb_set_event_mask2(cmdbuf, len);
break;
@ -1454,9 +1644,33 @@ ble_ll_hci_cmd_proc(struct ble_npl_event *ev)
* BLE_ERR_MEM_CAPACITY on HCI buffer exhaustion.
*/
int
ble_ll_hci_cmd_rx(uint8_t *cmd, void *arg)
ble_ll_hci_cmd_rx(uint8_t *cmdbuf, void *arg)
{
struct ble_npl_event *ev;
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL)
const struct ble_hci_cmd *cmd;
uint16_t opcode;
uint16_t ocf;
uint16_t ogf;
cmd = (const void *)cmdbuf;
opcode = le16toh(cmd->opcode);
ogf = BLE_HCI_OGF(opcode);
ocf = BLE_HCI_OCF(opcode);
/*
* HCI_Host_Number_Of_Completed_Packets is processed outside standard flow
* thus it can be sent at any time, even if another command is already
* pending. This means we should better process it here and send an event to
* LL in case of error.
*/
if ((ogf == BLE_HCI_OGF_CTLR_BASEBAND) &&
(ocf == BLE_HCI_OCF_CB_HOST_NUM_COMP_PKTS)) {
ble_ll_conn_cth_flow_process_cmd(cmdbuf);
ble_hci_trans_buf_free(cmdbuf);
return 0;
}
#endif
/* Get an event structure off the queue */
ev = &g_ble_ll_hci_cmd_ev;
@ -1465,7 +1679,7 @@ ble_ll_hci_cmd_rx(uint8_t *cmd, void *arg)
}
/* Fill out the event and post to Link Layer */
ble_npl_event_set_arg(ev, cmd);
ble_npl_event_set_arg(ev, cmdbuf);
ble_npl_eventq_put(&g_ble_ll_data.ll_evq, ev);
return 0;

View file

@ -461,6 +461,37 @@ ble_ll_hci_ev_phy_update(struct ble_ll_conn_sm *connsm, uint8_t status)
}
#endif
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
void
ble_ll_hci_ev_sca_update(struct ble_ll_conn_sm *connsm, uint8_t status,
uint8_t peer_sca)
{
struct ble_hci_ev_le_subev_peer_sca_complete *ev;
struct ble_hci_ev *hci_ev;
if (!ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_REQ_PEER_SCA_COMP)) {
return;
}
hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
if (!hci_ev) {
return;
}
hci_ev->opcode = BLE_HCI_EVCODE_LE_META;
hci_ev->length = sizeof(*ev);
ev = (void *) hci_ev->data;
ev->subev_code = BLE_HCI_LE_SUBEV_REQ_PEER_SCA_COMP;
ev->status = status;
ev->conn_handle = htole16(connsm->conn_handle);
ev->sca = peer_sca;
ble_ll_hci_event_send(hci_ev);
}
#endif
void
ble_ll_hci_ev_send_vendor_err(const char *file, uint32_t line)
{

View file

@ -0,0 +1,146 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#include <stdint.h>
#include "syscfg/syscfg.h"
#include "nimble/ble.h"
#include "nimble/hci_common.h"
#include "controller/ble_ll_iso.h"
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO)
int
ble_ll_iso_read_tx_sync(const uint8_t *cmdbuf, uint8_t len)
{
return BLE_ERR_UNSUPPORTED;
}
int
ble_ll_iso_set_cig_param(const uint8_t *cmdbuf, uint8_t len,
uint8_t *rspbuf, uint8_t *rsplen)
{
return BLE_ERR_UNSUPPORTED;
}
int
ble_ll_iso_create_cis(const uint8_t *cmdbuf, uint8_t len)
{
return BLE_ERR_UNSUPPORTED;
}
int
ble_ll_iso_disconnect_cmd(const struct ble_hci_lc_disconnect_cp *cmd)
{
return BLE_ERR_UNSUPPORTED;
}
int
ble_ll_iso_remove_cig(const uint8_t *cmdbuf, uint8_t len,
uint8_t *rspbuf, uint8_t *rsplen)
{
return BLE_ERR_UNSUPPORTED;
}
int
ble_ll_iso_accept_cis_req(const uint8_t *cmdbuf, uint8_t len)
{
return BLE_ERR_UNSUPPORTED;
}
int
ble_ll_iso_reject_cis_req(const uint8_t *cmdbuf, uint8_t len)
{
return BLE_ERR_UNSUPPORTED;
}
int
ble_ll_iso_setup_iso_data_path(const uint8_t *cmdbuf, uint8_t len)
{
return BLE_ERR_UNSUPPORTED;
}
int
ble_ll_iso_remove_iso_data_path(const uint8_t *cmdbuf, uint8_t len)
{
/* Nothing to do here for now when HCI is supported */
return 0;
}
int
ble_ll_iso_create_big(const uint8_t *cmdbuf, uint8_t len)
{
return BLE_ERR_UNSUPPORTED;
}
int
ble_ll_iso_terminate_big(const uint8_t *cmdbuf, uint8_t len)
{
return BLE_ERR_UNSUPPORTED;
}
int
ble_ll_iso_big_create_sync(const uint8_t *cmdbuf, uint8_t len)
{
return BLE_ERR_UNSUPPORTED;
}
int
ble_ll_iso_big_terminate_sync(const uint8_t *cmdbuf, uint8_t len)
{
return BLE_ERR_UNSUPPORTED;
}
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO_TEST)
int
ble_ll_iso_set_cig_param_test(const uint8_t *cmdbuf, uint8_t len,
uint8_t *rspbuf, uint8_t *rsplen)
{
return BLE_ERR_UNSUPPORTED;
}
int
ble_ll_iso_create_big_test(const uint8_t *cmdbuf, uint8_t len)
{
return BLE_ERR_UNSUPPORTED;
}
int
ble_ll_iso_transmit_test(const uint8_t *cmdbuf, uint8_t len)
{
return BLE_ERR_UNSUPPORTED;
}
int
ble_ll_iso_receive_test(const uint8_t *cmdbuf, uint8_t len)
{
return BLE_ERR_UNSUPPORTED;
}
int
ble_ll_iso_read_counters_test(const uint8_t *cmdbuf, uint8_t len)
{
return BLE_ERR_UNSUPPORTED;
}
int
ble_ll_iso_end_test(const uint8_t *cmdbuf, uint8_t len)
{
return BLE_ERR_UNSUPPORTED;
}
#endif
#endif

View file

@ -17,6 +17,9 @@
* under the License.
*/
/* for jrand48 */
#define _XOPEN_SOURCE
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>
#include <string.h>
@ -120,6 +123,21 @@ ble_ll_rand_data_get(uint8_t *buf, uint8_t len)
return BLE_ERR_SUCCESS;
}
/* Simple wrapper to allow easy replacement of rand() */
uint32_t
ble_ll_rand(void)
{
static unsigned short xsubi[3];
static bool init = true;
if (init) {
init = false;
ble_ll_rand_data_get((uint8_t *)xsubi, sizeof(xsubi));
}
return (uint32_t) jrand48(xsubi);
}
/**
* Called to obtain a "prand" as defined in core V4.2 Vol 6 Part B 1.3.2.2
*

View file

@ -293,7 +293,7 @@ ble_ll_scan_req_backoff(struct ble_ll_scan_sm *scansm, int success)
STATS_INC(ble_ll_stats, scan_req_txf);
}
scansm->backoff_count = rand() & (scansm->upper_limit - 1);
scansm->backoff_count = ble_ll_rand() & (scansm->upper_limit - 1);
++scansm->backoff_count;
BLE_LL_ASSERT(scansm->backoff_count <= 256);
}
@ -305,7 +305,7 @@ ble_ll_scan_refresh_nrpa(struct ble_ll_scan_sm *scansm)
ble_npl_time_t now;
now = ble_npl_time_get();
if ((ble_npl_stime_t)(now - scansm->scan_nrpa_timer) >= 0) {
if (CPUTIME_GEQ(now, scansm->scan_nrpa_timer)) {
/* Generate new NRPA */
ble_ll_rand_data_get(scansm->scan_nrpa, BLE_DEV_ADDR_LEN);
scansm->scan_nrpa[5] &= ~0xc0;
@ -617,7 +617,7 @@ ble_ll_scan_add_scan_rsp_adv(uint8_t *addr, uint8_t txadd,
static int
ble_ll_hci_send_legacy_ext_adv_report(uint8_t evtype,
const uint8_t *addr, uint8_t addr_type,
uint8_t rssi,
int8_t rssi,
uint8_t adv_data_len,
struct os_mbuf *adv_data,
const uint8_t *inita, uint8_t inita_type)
@ -1125,6 +1125,22 @@ ble_ll_scan_sm_stop(int chk_disable)
scansm = &g_ble_ll_scan_sm;
os_cputime_timer_stop(&scansm->scan_timer);
/* Only set state if we are currently in a scan window */
if (chk_disable) {
OS_ENTER_CRITICAL(sr);
lls = ble_ll_state_get();
if ((lls == BLE_LL_STATE_SCANNING) ||
(lls == BLE_LL_STATE_INITIATING && chk_disable == 1)) {
/* Disable phy */
ble_phy_disable();
/* Set LL state to standby */
ble_ll_state_set(BLE_LL_STATE_STANDBY);
}
OS_EXIT_CRITICAL(sr);
}
OS_ENTER_CRITICAL(sr);
/* Disable scanning state machine */
@ -1149,22 +1165,6 @@ ble_ll_scan_sm_stop(int chk_disable)
/* Count # of times stopped */
STATS_INC(ble_ll_stats, scan_stops);
/* Only set state if we are currently in a scan window */
if (chk_disable) {
OS_ENTER_CRITICAL(sr);
lls = ble_ll_state_get();
if ((lls == BLE_LL_STATE_SCANNING) ||
(lls == BLE_LL_STATE_INITIATING && chk_disable == 1)) {
/* Disable phy */
ble_phy_disable();
/* Set LL state to standby */
ble_ll_state_set(BLE_LL_STATE_STANDBY);
}
OS_EXIT_CRITICAL(sr);
}
/* No need for RF anymore */
OS_ENTER_CRITICAL(sr);
ble_ll_rfmgmt_scan_changed(false, 0);
@ -1991,10 +1991,10 @@ ble_ll_scan_rx_filter(struct ble_mbuf_hdr *hdr, struct ble_ll_scan_addr_data *ad
{
struct ble_ll_scan_sm *scansm = &g_ble_ll_scan_sm;
struct ble_ll_scan_params *scanp = scansm->scanp;
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
struct ble_ll_aux_data *aux_data = hdr->rxinfo.user_data;
#endif
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
struct ble_mbuf_hdr_rxinfo *rxinfo = &hdr->rxinfo;
struct ble_ll_resolv_entry *rl = NULL;
#endif
@ -2227,6 +2227,7 @@ ble_ll_scan_rx_isr_on_aux(uint8_t pdu_type, uint8_t *rxbuf,
*/
if (aux_data->flags & BLE_LL_AUX_IS_MATCHED) {
rxinfo->flags |= BLE_MBUF_HDR_F_DEVMATCH;
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
rxinfo->rpa_index = aux_data->rpa_index;
if (rxinfo->rpa_index >= 0) {
rxinfo->flags |= BLE_MBUF_HDR_F_RESOLVED;
@ -2234,6 +2235,7 @@ ble_ll_scan_rx_isr_on_aux(uint8_t pdu_type, uint8_t *rxbuf,
if (aux_data->flags & BLE_LL_AUX_IS_TARGETA_RESOLVED) {
rxinfo->flags |= BLE_MBUF_HDR_F_TARGETA_RESOLVED;
}
#endif
goto done;
}
@ -3019,7 +3021,8 @@ ble_ll_scan_rx_pkt_in_on_legacy(uint8_t pdu_type, struct os_mbuf *om,
if (!BLE_MBUF_HDR_DEVMATCH(hdr) ||
!BLE_MBUF_HDR_CRC_OK(hdr) ||
BLE_MBUF_HDR_IGNORED(hdr)) {
BLE_MBUF_HDR_IGNORED(hdr) ||
!scansm->scan_enabled) {
return;
}
@ -3058,10 +3061,6 @@ ble_ll_scan_rx_pkt_in_on_aux(uint8_t pdu_type, struct os_mbuf *om,
bool send_hci_report;
int rc;
if (!scansm->ext_scanning) {
goto scan_continue;
}
if (aux_data) {
aux_data->flags_ll |= aux_data->flags_isr;
}
@ -3077,7 +3076,8 @@ ble_ll_scan_rx_pkt_in_on_aux(uint8_t pdu_type, struct os_mbuf *om,
BLE_MBUF_HDR_IGNORED(hdr) ||
BLE_MBUF_HDR_AUX_INVALID(hdr) ||
(aux_data->flags_ll & BLE_LL_AUX_FLAG_SCAN_ERROR) ||
(pdu_type != BLE_ADV_PDU_TYPE_ADV_EXT_IND)) {
(pdu_type != BLE_ADV_PDU_TYPE_ADV_EXT_IND) ||
!scansm->scan_enabled) {
if (aux_data) {
ble_ll_scan_end_adv_evt(aux_data);
ble_ll_scan_aux_data_unref(aux_data);

View file

@ -83,14 +83,14 @@ ble_ll_sched_is_overlap(struct ble_ll_sched_item *s1,
int rc;
rc = 1;
if ((int32_t)(s1->start_time - s2->start_time) < 0) {
if (CPUTIME_LT(s1->start_time, s2->start_time)) {
/* Make sure this event does not overlap current event */
if ((int32_t)(s1->end_time - s2->start_time) <= 0) {
if (CPUTIME_LEQ(s1->end_time, s2->start_time)) {
rc = 0;
}
} else {
/* Check for overlap */
if ((int32_t)(s1->start_time - s2->end_time) >= 0) {
if (CPUTIME_GEQ(s1->start_time, s2->end_time)) {
rc = 0;
}
}
@ -111,7 +111,7 @@ ble_ll_sched_overlaps_current(struct ble_ll_sched_item *sch)
rc = 0;
if (ble_ll_state_get() == BLE_LL_STATE_CONNECTION) {
ce_end_time = ble_ll_conn_get_ce_end_time();
if ((int32_t)(ce_end_time - sch->start_time) > 0) {
if (CPUTIME_GT(ce_end_time, sch->start_time)) {
rc = 1;
}
}
@ -178,7 +178,7 @@ ble_ll_sched_conn_reschedule(struct ble_ll_conn_sm *connsm)
sch->end_time = connsm->ce_end_time;
/* Better be past current time or we just leave */
if ((int32_t)(sch->start_time - os_cputime_get32()) < 0) {
if (CPUTIME_LT(sch->start_time, os_cputime_get32())) {
return -1;
}
@ -216,7 +216,7 @@ ble_ll_sched_conn_reschedule(struct ble_ll_conn_sm *connsm)
end_overlap = entry;
}
} else {
if ((int32_t)(sch->end_time - entry->start_time) <= 0) {
if (CPUTIME_LEQ(sch->end_time, entry->start_time)) {
rc = 0;
TAILQ_INSERT_BEFORE(entry, sch, link);
break;
@ -468,7 +468,7 @@ ble_ll_sched_master_new(struct ble_ll_conn_sm *connsm,
sch->end_time = earliest_end;
/* We can insert if before entry in list */
if ((int32_t)(sch->end_time - entry->start_time) <= 0) {
if (CPUTIME_LEQ(sch->end_time, entry->start_time)) {
if ((earliest_start - initial_start) <= itvl_t) {
rc = 0;
TAILQ_INSERT_BEFORE(entry, sch, link);
@ -655,7 +655,7 @@ ble_ll_sched_master_new(struct ble_ll_conn_sm *connsm,
sch->end_time = earliest_end;
/* We can insert if before entry in list */
if ((int32_t)(sch->end_time - entry->start_time) <= 0) {
if (CPUTIME_LEQ(sch->end_time, entry->start_time)) {
if ((earliest_start - initial_start) <= itvl_t) {
rc = 0;
TAILQ_INSERT_BEFORE(entry, sch, link);
@ -770,7 +770,7 @@ ble_ll_sched_slave_new(struct ble_ll_conn_sm *connsm)
while (1) {
next_sch = entry->link.tqe_next;
/* Insert if event ends before next starts */
if ((int32_t)(sch->end_time - entry->start_time) <= 0) {
if (CPUTIME_LEQ(sch->end_time, entry->start_time)) {
rc = 0;
TAILQ_INSERT_BEFORE(entry, sch, link);
break;
@ -1047,7 +1047,7 @@ ble_ll_sched_adv_new(struct ble_ll_sched_item *sch, ble_ll_sched_adv_new_cb cb,
os_cputime_timer_stop(&g_ble_ll_sched_timer);
TAILQ_FOREACH(entry, &g_ble_ll_sched_q, link) {
/* We can insert if before entry in list */
if ((int32_t)(sch->end_time - entry->start_time) <= 0) {
if (CPUTIME_LEQ(sch->end_time, entry->start_time)) {
TAILQ_INSERT_BEFORE(entry, sch, link);
break;
}
@ -1111,7 +1111,7 @@ ble_ll_sched_periodic_adv(struct ble_ll_sched_item *sch, uint32_t *start,
os_cputime_timer_stop(&g_ble_ll_sched_timer);
TAILQ_FOREACH(entry, &g_ble_ll_sched_q, link) {
/* We can insert if before entry in list */
if ((int32_t)(sch->end_time - entry->start_time) <= 0) {
if (CPUTIME_LEQ(sch->end_time, entry->start_time)) {
TAILQ_INSERT_BEFORE(entry, sch, link);
break;
}
@ -1200,7 +1200,7 @@ ble_ll_sched_adv_reschedule(struct ble_ll_sched_item *sch, uint32_t *start,
end_overlap = entry;
}
} else {
if ((int32_t)(sch->end_time - entry->start_time) <= 0) {
if (CPUTIME_LEQ(sch->end_time, entry->start_time)) {
before = entry;
break;
}
@ -1233,7 +1233,7 @@ ble_ll_sched_adv_reschedule(struct ble_ll_sched_item *sch, uint32_t *start,
sch->end_time = sch->start_time + duration;
while (1) {
next_sch = entry->link.tqe_next;
if ((int32_t)(sch->end_time - entry->start_time) <= 0) {
if (CPUTIME_LEQ(sch->end_time, entry->start_time)) {
rand_ticks = entry->start_time - sch->end_time;
before = entry;
TAILQ_INSERT_BEFORE(before, sch, link);
@ -1266,7 +1266,7 @@ ble_ll_sched_adv_reschedule(struct ble_ll_sched_item *sch, uint32_t *start,
if (!rc) {
sch->enqueued = 1;
if (rand_ticks) {
sch->start_time += rand() % rand_ticks;
sch->start_time += ble_ll_rand() % rand_ticks;
}
sch->end_time = sch->start_time + duration;
*start = sch->start_time;
@ -1580,7 +1580,7 @@ ble_ll_sched_scan_req_over_aux_ptr(uint32_t chan, uint8_t phy_mode)
while (sch) {
/* Let's check if there is no scheduled item which want to start within
* given usecs.*/
if ((int32_t)(sch->start_time - now + os_cputime_usecs_to_ticks(usec_dur)) > 0) {
if (CPUTIME_GT(sch->start_time, now + os_cputime_usecs_to_ticks(usec_dur))) {
/* We are fine. Have time for scan req */
return 0;
}
@ -1670,7 +1670,7 @@ ble_ll_sched_aux_scan(struct ble_mbuf_hdr *ble_hdr,
os_cputime_timer_stop(&g_ble_ll_sched_timer);
TAILQ_FOREACH(entry, &g_ble_ll_sched_q, link) {
/* We can insert if before entry in list */
if ((int32_t)(sch->end_time - entry->start_time) <= 0) {
if (CPUTIME_LEQ(sch->end_time, entry->start_time)) {
rc = 0;
TAILQ_INSERT_BEFORE(entry, sch, link);
sch->enqueued = 1;

View file

@ -36,7 +36,22 @@
/* Octet 10 */
#define BLE_SUPP_CMD_RD_TX_PWR (0 << 2)
#define BLE_LL_SUPP_CMD_OCTET_10 (BLE_SUPP_CMD_RD_TX_PWR)
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL)
#define BLE_SUPP_CMD_SET_CTRL_TO_HOST_FLOW (1 << 5)
#define BLE_SUPP_CMD_HOST_BUFFER_SIZE (1 << 6)
#define BLE_SUPP_CMD_HOST_NUM_COMP_PACKETS (1 << 7)
#else
#define BLE_SUPP_CMD_SET_CTRL_TO_HOST_FLOW (0 << 5)
#define BLE_SUPP_CMD_HOST_BUFFER_SIZE (0 << 6)
#define BLE_SUPP_CMD_HOST_NUM_COMP_PACKETS (0 << 7)
#endif
#define BLE_LL_SUPP_CMD_OCTET_10 \
( \
BLE_SUPP_CMD_RD_TX_PWR | \
BLE_SUPP_CMD_SET_CTRL_TO_HOST_FLOW | \
BLE_SUPP_CMD_HOST_BUFFER_SIZE | \
BLE_SUPP_CMD_HOST_NUM_COMP_PACKETS \
)
/* Octet 14 */
#define BLE_SUPP_CMD_RD_LOC_VER (1 << 3)
@ -404,10 +419,77 @@
#define BLE_SUPP_CMD_LE_PADV_SYNC_TRANSFER_PARAMS (0 << 0)
#define BLE_SUPP_CMD_LE_PADV_DEFAULT_SYNC_TRANSFER_PARAMS (0 << 1)
#endif
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO)
#define BLE_SUPP_CMD_LE_READ_BUF_SIZE_V2 (1 << 5)
#define BLE_SUPP_CMD_LE_READ_ISO_TX_SYNC (1 << 6)
#define BLE_SUPP_CMD_LE_SET_CIG_PARAM (1 << 7)
#else
#define BLE_SUPP_CMD_LE_READ_BUF_SIZE_V2 (0 << 5)
#define BLE_SUPP_CMD_LE_READ_ISO_TX_SYNC (0 << 6)
#define BLE_SUPP_CMD_LE_SET_CIG_PARAM (0 << 7)
#endif
#define BLE_LL_SUPP_CMD_OCTET_41 \
( \
BLE_SUPP_CMD_LE_PADV_SYNC_TRANSFER_PARAMS | \
BLE_SUPP_CMD_LE_PADV_DEFAULT_SYNC_TRANSFER_PARAMS \
BLE_SUPP_CMD_LE_PADV_DEFAULT_SYNC_TRANSFER_PARAMS | \
BLE_SUPP_CMD_LE_READ_BUF_SIZE_V2 | \
BLE_SUPP_CMD_LE_READ_ISO_TX_SYNC | \
BLE_SUPP_CMD_LE_SET_CIG_PARAM \
)
/* Octet 42 */
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO)
#define BLE_SUPP_CMD_LE_SET_CIG_PARAM_TEST (1 << 0)
#define BLE_SUPP_CMD_LE_CREATE_CIS (1 << 1)
#define BLE_SUPP_CMD_LE_REMOVE_CIG (1 << 2)
#define BLE_SUPP_CMD_LE_ACCEPT_CIS_REQ (1 << 3)
#define BLE_SUPP_CMD_LE_REJECT_CIS_REQ (1 << 4)
#define BLE_SUPP_CMD_LE_CREATE_BIG (1 << 5)
#define BLE_SUPP_CMD_LE_CREATE_BIG_TEST (1 << 6)
#define BLE_SUPP_CMD_LE_TERMINATE_BIG (1 << 7)
#else
#define BLE_SUPP_CMD_LE_SET_CIG_PARAM_TEST (0 << 0)
#define BLE_SUPP_CMD_LE_CREATE_CIS (0 << 1)
#define BLE_SUPP_CMD_LE_REMOVE_CIG (0 << 2)
#define BLE_SUPP_CMD_LE_ACCEPT_CIS_REQ (0 << 3)
#define BLE_SUPP_CMD_LE_REJECT_CIS_REQ (0 << 4)
#define BLE_SUPP_CMD_LE_CREATE_BIG (0 << 5)
#define BLE_SUPP_CMD_LE_CREATE_BIG_TEST (0 << 6)
#define BLE_SUPP_CMD_LE_TERMINATE_BIG (0 << 7)
#endif
#define BLE_LL_SUPP_CMD_OCTET_42 \
( \
BLE_SUPP_CMD_LE_SET_CIG_PARAM_TEST | \
BLE_SUPP_CMD_LE_CREATE_CIS | \
BLE_SUPP_CMD_LE_REMOVE_CIG | \
BLE_SUPP_CMD_LE_ACCEPT_CIS_REQ | \
BLE_SUPP_CMD_LE_REJECT_CIS_REQ | \
BLE_SUPP_CMD_LE_CREATE_BIG | \
BLE_SUPP_CMD_LE_CREATE_BIG_TEST | \
BLE_SUPP_CMD_LE_TERMINATE_BIG \
)
/* Octet 43 */
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE)
#define BLE_SUPP_CMD_LE_REQUEST_PEER_SCA (1 << 2)
#else
#define BLE_SUPP_CMD_LE_REQUEST_PEER_SCA (0 << 0)
#endif
#define BLE_LL_SUPP_CMD_OCTET_43 \
( \
BLE_SUPP_CMD_LE_REQUEST_PEER_SCA \
)
/* Octet 44 */
#if MYNEWT_VAL(BLE_VERSION) >= 52
#define BLE_SUPP_CMD_LE_SET_HOST_FEATURE (1 << 0)
#else
#define BLE_SUPP_CMD_LE_SET_HOST_FEATURE (0 << 0)
#endif
#define BLE_LL_SUPP_CMD_OCTET_44 \
( \
BLE_SUPP_CMD_LE_SET_HOST_FEATURE \
)
/* Defines the array of supported commands */
@ -455,4 +537,7 @@ const uint8_t g_ble_ll_supp_cmds[BLE_LL_SUPP_CMD_LEN] =
BLE_LL_SUPP_CMD_OCTET_39,
BLE_LL_SUPP_CMD_OCTET_40, /* Octet 40 */
BLE_LL_SUPP_CMD_OCTET_41,
BLE_LL_SUPP_CMD_OCTET_42,
BLE_LL_SUPP_CMD_OCTET_43,
BLE_LL_SUPP_CMD_OCTET_44,
};

View file

@ -2091,10 +2091,10 @@ ble_ll_sync_send_sync_ind(struct ble_ll_sync_sm *syncsm,
if (syncsm->flags & BLE_LL_SYNC_SM_FLAG_ADDR_RESOLVED) {
sync_ind[24] |= 1 << 4;
} else {
sync_ind[24] |= (syncsm->adv_addr_type == BLE_ADDR_RANDOM) << 4 ;
sync_ind[24] |= (syncsm->adv_addr_type == BLE_ADDR_RANDOM) << 4;
}
sync_ind[24] |= MYNEWT_VAL(BLE_LL_MASTER_SCA) << 5;
sync_ind[24] |= BLE_LL_SCA_ENUM << 5;
/* PHY */
sync_ind[25] = (0x01 << (ble_ll_sync_phy_mode_to_hci(syncsm->phy_mode) - 1));

View file

@ -50,8 +50,8 @@ ble_ll_utils_calc_access_addr(void)
aa = 0;
while (1) {
/* Get two, 16-bit random numbers */
aa_low = rand() & 0xFFFF;
aa_high = rand() & 0xFFFF;
aa_low = ble_ll_rand() & 0xFFFF;
aa_high = ble_ll_rand() & 0xFFFF;
/* All four bytes cannot be equal */
if (aa_low == aa_high) {
@ -292,8 +292,7 @@ ble_ll_utils_calc_window_widening(uint32_t anchor_point,
time_since_last_anchor = (int32_t)(anchor_point - last_anchor_point);
if (time_since_last_anchor > 0) {
delta_msec = os_cputime_ticks_to_usecs(time_since_last_anchor) / 1000;
total_sca_ppm = g_ble_sca_ppm_tbl[master_sca] +
MYNEWT_VAL(BLE_LL_OUR_SCA);
total_sca_ppm = g_ble_sca_ppm_tbl[master_sca] + MYNEWT_VAL(BLE_LL_SCA);
window_widening = (total_sca_ppm * delta_msec) / 1000;
}

View file

@ -38,35 +38,10 @@ syscfg.defs:
type: 'task_priority'
value: 0
# Sleep clock accuracy (sca). This is the amount of drift in the system
# during when the device is sleeping (in parts per million).
#
# NOTE: 'the' master sca is an enumerated value based on the sca. Rather
# than have a piece of code calculate this value, the developer must set
# this value based on the value of the SCA using the following table:
#
# SCA between 251 and 500 ppm (inclusive); master sca = 0
# SCA between 151 and 250 ppm (inclusive); master sca = 1
# SCA between 101 and 150 ppm (inclusive); master sca = 2
# SCA between 76 and 100 ppm (inclusive); master sca = 3
# SCA between 51 and 75 ppm (inclusive); master sca = 4
# SCA between 31 and 50 ppm (inclusive); master sca = 5
# SCA between 21 and 30 ppm (inclusive); master sca = 6
# SCA between 0 and 20 ppm (inclusive); master sca = 7
#
# For example:
# if your clock drift is 101 ppm, your master should be set to 2.
# if your clock drift is 20, your master sca should be set to 7.
#
# The values provided below are merely meant to be an example and should
# be replaced by values appropriate for your platform.
BLE_LL_OUR_SCA:
description: 'The system clock accuracy of the device.'
value: '60' # in ppm
BLE_LL_MASTER_SCA:
description: 'Enumerated value based on our sca'
value: '4'
BLE_LL_SCA:
description: Sleep clock accuracy of our device (in ppm)
value: MYNEWT_VAL(BLE_LL_OUR_SCA)
range: 0..500
BLE_LL_TX_PWR_DBM:
description: 'Transmit power level.'
@ -285,6 +260,35 @@ syscfg.defs:
Advertising Sync Transfer Feature.
value: MYNEWT_VAL(BLE_PERIODIC_ADV_SYNC_TRANSFER)
BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL:
description: >
Enable controller-to-host flow control support. This allows host to
limit number of ACL packets sent at once from controller to avoid
congestion on HCI transport if feature is also supported by host.
value: 0
BLE_LL_CFG_FEAT_LL_SCA_UPDATE:
description: >
This option is used to enable/disable support for SCA update procedure
value: 0
restrictions:
- '(BLE_VERSION >= 52) if 1'
BLE_LL_CFG_FEAT_LL_ISO:
description: >
This option is used to enable/disable support for LE Isochronous Channels
as per Bluetooth v5.2 channels
value: MYNEWT_VAL(BLE_ISO)
restrictions:
- '(BLE_VERSION >= 52) if 1'
BLE_LL_CFG_FEAT_LL_ISO_TEST:
description: >
This option is used to enable/disbale test commands for ISO support
value: MYNEWT_VAL(BLE_ISO_TEST)
restrictions:
- 'BLE_LL_CFG_FEAT_LL_ISO if 1'
BLE_LL_EXT_ADV_AUX_PTR_CNT:
description: >
This option configure a max number of scheduled outstanding auxiliary
@ -404,6 +408,10 @@ syscfg.defs:
description: use BLE_LL_RFMGMT_ENABLE_TIME instead
value: 0
deprecated: 1
BLE_LL_OUR_SCA:
description: use BLE_LL_SCA instead
value: 60
deprecated: 1
# defunct settings (to be removed eventually)
BLE_DEVICE:
@ -418,6 +426,10 @@ syscfg.defs:
description: Superseded by BLE_LL_NUM_COMP_PKT_ITVL_MS
value: '(2 * OS_TICKS_PER_SEC)'
defunct: 1
BLE_LL_MASTER_SCA:
description: use BLE_LL_SCA instead
value: 4
defunct: 1
syscfg.vals.BLE_LL_CFG_FEAT_LL_EXT_ADV:

View file

@ -0,0 +1,68 @@
<!--
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
-->
## How to run NimBLE controller on Dialog DA1469x
Dialog DA1469x has separate Cortex-M0+ core inside CMAC hw block which can run
NimBLE controller. This means DA1469x can run full NimBLE stack: host is running
on M33 core while controller is running on M0+ core. Both communicate using
standard HCI H4 protocol exchanged over mailboxes located in shared memory.
### Basic setup
In order to run full NimBLE stack on DA1469x you will need two newt targets: one
for M33 (e.g. `dialog_da1469x-dk-pro` BSP) and one for M0+ (`dialog_cmac` BSP).
Once everything is configured properly, you only need to build target for M33.
Target configured for M0+ will be build automatically and image is linked with
M33 image so everything can be flashed at once just as if there is only single
target used.
Target for M33 should be set and configured as any other BLE application. In
order to use NimBLE controller on CMAC, set proper HCI transport via syscfg:
BLE_HCI_TRANSPORT: dialog_cmac
This will include proper transport, driver and add M0+ target to build process.
For M0+, there is sample target provided in `targets/dialog_cmac` and it's used
by default unless overrided by syscfg in M33 target:
CMAC_IMAGE_TARGET_NAME: "@apache-mynewt-nimble/targets/dialog_cmac"
If you wish to create own target for M0+, make sure your target is set the same
way (`app`, `bsp` and `build_profile`) as sample. Also it is recommended to use
syscfg settings from sample target in new target.
### NimBLE configuration
Since host and controller are running on different cores, they both use separate
configuration: host configuration is in M33 target, controller configuration is
in M0+ target. There is currently no way to automatically synchronize both, so
care needs to be taken when enabling features in either of targets.
A possible workaround is to use separate `.yml` file with all the NimBLE syscfg
values settings and include it in both targets using `$import` directive which
is supported by recent versions of `newt` tool.
### Advanced settings
(tbd)

View file

@ -0,0 +1,39 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#ifndef H_BLE_XCVR_
#define H_BLE_XCVR_
#ifdef __cplusplus
extern "C" {
#endif
#define XCVR_TX_SCHED_DELAY_USECS (250)
/*
* Define HW whitelist size. This is the total possible whitelist size;
* not necessarily the size that will be used (may be smaller)
*/
#define BLE_HW_WHITE_LIST_SIZE (8)
#ifdef __cplusplus
}
#endif
#endif /* H_BLE_XCVR_ */

View file

@ -0,0 +1,33 @@
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
pkg.name: nimble/drivers/dialog_cmac
pkg.description: BLE driver for Dialog CMAC
pkg.author: "Apache Mynewt <dev@mynewt.apache.org>"
pkg.homepage: "http://mynewt.apache.org/"
pkg.keywords:
- ble
- bluetooth
pkg.deps:
- "@apache-mynewt-nimble/nimble/controller"
- "@apache-mynewt-core/crypto/tinycrypt"
pkg.apis:
- ble_driver
pkg.req_apis:
- ble_transport

View file

@ -0,0 +1,340 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#include <assert.h>
#include <stdint.h>
#include "mcu/mcu.h"
#include "nimble/ble.h"
#include "controller/ble_hw.h"
#include "CMAC.h"
#include "cmac_driver/cmac_shared.h"
#include "mcu/mcu.h"
#include "tinycrypt/aes.h"
static struct tc_aes_key_sched_struct g_ctx;
int
ble_hw_rng_init(ble_rng_isr_cb_t cb, int bias)
{
cmac_rand_set_isr_cb(cb);
return 0;
}
int
ble_hw_rng_start(void)
{
/* Chime the M33 in case we need random numbers generated */
cmac_rand_start();
CMAC->CM_EV_SET_REG = CMAC_CM_EV_SET_REG_EV1C_CMAC2SYS_IRQ_SET_Msk;
return 0;
}
int
ble_hw_rng_stop(void)
{
cmac_rand_stop();
return 0;
}
#define BLE_HW_RESOLV_LIST_SIZE (MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE))
struct ble_hw_resolv_irk {
uint32_t key[4];
};
struct ble_hw_resolv_list {
uint8_t count;
struct ble_hw_resolv_irk irk[BLE_HW_RESOLV_LIST_SIZE];
};
struct ble_hw_resolv_proc {
uint32_t hash;
uint8_t f_configured;
uint8_t f_active;
uint8_t f_match;
uint8_t f_done;
struct ble_hw_resolv_irk *irk;
struct ble_hw_resolv_irk *irk_end;
uint32_t crypto_prand_in[4];
uint32_t crypto_e_out[4];
};
static struct ble_hw_resolv_list g_ble_hw_resolv_list;
static struct ble_hw_resolv_proc g_ble_hw_resolv_proc;
int
ble_hw_get_public_addr(ble_addr_t *addr)
{
return -1;
}
int
ble_hw_get_static_addr(ble_addr_t *addr)
{
return -1;
}
void
ble_hw_whitelist_clear(void)
{
}
int
ble_hw_whitelist_add(const uint8_t *addr, uint8_t addr_type)
{
return 0;
}
void
ble_hw_whitelist_rmv(const uint8_t *addr, uint8_t addr_type)
{
}
uint8_t
ble_hw_whitelist_size(void)
{
return 0;
}
void
ble_hw_whitelist_enable(void)
{
}
void
ble_hw_whitelist_disable(void)
{
}
int
ble_hw_whitelist_match(void)
{
return 0;
}
int
ble_hw_encrypt_block(struct ble_encryption_block *ecb)
{
uint32_t in_addr;
uint32_t out_addr;
/*
* The following code bears some explanation. This function is called by
* the LL task to encrypt blocks and calculate session keys. Address
* resolution also calls this function. Furthermore, during connections,
* the M0 crypto accelerator is used but this function is not called when
* using it. During the entire connection event, the M0 crypto block cannot
* be used as the crypto state (some of it) needs to remain un-changed.
* Note that this is also true when address resolution is enabled: the
* HW crypto block is set up and cannot be modified.
*
* Rather than attempt to share the M0 crypto block between the various
* controller features which require it, we decided to use software to
* perform the encryption task for anything being done at the link-layer
* (outside of an ISR). If this function is called inside an ISR, and it
* is when resolving addresses, the crypto accelerator is not being used
* by a connection event. Thus, we check to see if we are inside of an ISR.
* If so, we use the M0 crypto block. If outside of an ISR, we use the M33
*/
if (!os_arch_in_isr()) {
tc_aes128_set_encrypt_key(&g_ctx, ecb->key);
tc_aes_encrypt(ecb->cipher_text, ecb->plain_text, &g_ctx);
return 0;
}
/* Need to retain state of in/out pointers */
in_addr = CMAC->CM_CRYPTO_IN_ADR2_REG;
out_addr = CMAC->CM_CRYPTO_OUT_ADR_REG;
while (CMAC->CM_CRYPTO_STAT_REG & CMAC_CM_CRYPTO_STAT_REG_CM_CRYPTO_BUSY_Msk);
/* RECB, memory in/out, encryption */
CMAC->CM_CRYPTO_CTRL_REG = CMAC_CM_CRYPTO_CTRL_REG_CM_CRYPTO_ECB_ENC_EN_Msk |
CMAC_CM_CRYPTO_CTRL_REG_CM_CRYPTO_IN_SEL_Msk |
CMAC_CM_CRYPTO_CTRL_REG_CM_CRYPTO_OUT_SEL_Msk |
CMAC_CM_CRYPTO_CTRL_REG_CM_CRYPTO_ENC_DECN_Msk;
CMAC->CM_CRYPTO_KEY_31_0_REG = get_le32(&ecb->key[0]);
CMAC->CM_CRYPTO_KEY_63_32_REG = get_le32(&ecb->key[4]);
CMAC->CM_CRYPTO_KEY_95_64_REG = get_le32(&ecb->key[8]);
CMAC->CM_CRYPTO_KEY_127_96_REG = get_le32(&ecb->key[12]);
CMAC->CM_CRYPTO_IN_ADR2_REG = (uint32_t)ecb->plain_text;
CMAC->CM_CRYPTO_OUT_ADR_REG = (uint32_t)ecb->cipher_text;
CMAC->CM_EXC_STAT_REG = CMAC_CM_EXC_STAT_REG_EXC_CRYPTO_Msk;
CMAC->CM_EV_SET_REG = CMAC_CM_EV_SET_REG_EV_CRYPTO_START_Msk;
while (!(CMAC->CM_EXC_STAT_REG & CMAC_CM_EXC_STAT_REG_EXC_CRYPTO_Msk));
CMAC->CM_EXC_STAT_REG = CMAC_CM_EXC_STAT_REG_EXC_CRYPTO_Msk;
CMAC->CM_CRYPTO_IN_ADR2_REG = in_addr;
CMAC->CM_CRYPTO_OUT_ADR_REG = out_addr;
return 0;
}
void
ble_hw_resolv_list_clear(void)
{
g_ble_hw_resolv_list.count = 0;
}
int
ble_hw_resolv_list_add(uint8_t *irk)
{
struct ble_hw_resolv_irk *e;
if (g_ble_hw_resolv_list.count == BLE_HW_RESOLV_LIST_SIZE) {
return BLE_ERR_MEM_CAPACITY;
}
e = &g_ble_hw_resolv_list.irk[g_ble_hw_resolv_list.count];
/* Prepare key here so we do not need to do it during resolving */
e->key[0] = get_le32(&irk[0]);
e->key[1] = get_le32(&irk[4]);
e->key[2] = get_le32(&irk[8]);
e->key[3] = get_le32(&irk[12]);
g_ble_hw_resolv_list.count++;
return BLE_ERR_SUCCESS;
}
void
ble_hw_resolv_list_rmv(int index)
{
struct ble_hw_resolv_irk *e;
if (index < g_ble_hw_resolv_list.count) {
g_ble_hw_resolv_list.count--;
e = &g_ble_hw_resolv_list.irk[index];
memmove(e, e + 1, (g_ble_hw_resolv_list.count - index) * sizeof(e->key));
}
}
uint8_t
ble_hw_resolv_list_size(void)
{
return BLE_HW_RESOLV_LIST_SIZE;
}
int
ble_hw_resolv_list_match(void)
{
return g_ble_hw_resolv_proc.f_match ?
g_ble_hw_resolv_proc.irk - g_ble_hw_resolv_list.irk : -1;
}
static void
ble_hw_resolv_proc_next(void)
{
void *src = &g_ble_hw_resolv_proc.irk->key;
if (g_ble_hw_resolv_proc.irk == g_ble_hw_resolv_proc.irk_end) {
g_ble_hw_resolv_proc.f_done = 1;
g_ble_hw_resolv_proc.f_active = 0;
} else {
__asm__ volatile (".syntax unified \n"
" ldm %[ptr]!, {r1, r2, r3, r4} \n"
" ldr %[ptr], =%[reg] \n"
" stm %[ptr]!, {r1, r2, r3, r4} \n"
: [ptr] "+l" (src)
: [reg] "i" (&CMAC->CM_CRYPTO_KEY_31_0_REG)
: "r1", "r2", "r3", "r4", "memory");
CMAC->CM_EV_SET_REG = CMAC_CM_EV_SET_REG_EV_CRYPTO_START_Msk;
}
}
void
ble_hw_resolv_proc_enable(void)
{
assert(!g_ble_hw_resolv_proc.f_active);
CMAC->CM_CRYPTO_CTRL_REG = CMAC_CM_CRYPTO_CTRL_REG_CM_CRYPTO_SW_REQ_ABORT_Msk;
CMAC->CM_CRYPTO_CTRL_REG = CMAC_CM_CRYPTO_CTRL_REG_CM_CRYPTO_ECB_ENC_EN_Msk |
CMAC_CM_CRYPTO_CTRL_REG_CM_CRYPTO_IN_SEL_Msk |
CMAC_CM_CRYPTO_CTRL_REG_CM_CRYPTO_OUT_SEL_Msk |
CMAC_CM_CRYPTO_CTRL_REG_CM_CRYPTO_ENC_DECN_Msk;
CMAC->CM_CRYPTO_IN_ADR2_REG = (uint32_t)g_ble_hw_resolv_proc.crypto_prand_in;
CMAC->CM_CRYPTO_OUT_ADR_REG = (uint32_t)g_ble_hw_resolv_proc.crypto_e_out;
g_ble_hw_resolv_proc.irk = g_ble_hw_resolv_list.irk;
g_ble_hw_resolv_proc.irk_end = g_ble_hw_resolv_list.irk +
g_ble_hw_resolv_list.count;
g_ble_hw_resolv_proc.f_configured = 1;
g_ble_hw_resolv_proc.f_active = 0;
/*
* It would be better to enable IRQ in ble_hw_resolv_proc_start, but this
* would introduce a bit of latency when starting resolving procedure and
* we need to save every us possible there in order to be able to resolve
* RPA on time.
*/
NVIC_ClearPendingIRQ(CRYPTO_IRQn);
NVIC_EnableIRQ(CRYPTO_IRQn);
}
void
ble_hw_resolv_proc_disable(void)
{
g_ble_hw_resolv_proc.f_configured = 0;
g_ble_hw_resolv_proc.f_active = 0;
g_ble_hw_resolv_proc.f_match = 0;
g_ble_hw_resolv_proc.f_done = 1;
NVIC_DisableIRQ(CRYPTO_IRQn);
}
void
ble_hw_resolv_proc_start(const uint8_t *addr)
{
assert(g_ble_hw_resolv_proc.f_configured);
/* crypto_prand_in is already zeroed so prand is properly padded */
g_ble_hw_resolv_proc.crypto_prand_in[3] = get_be24(&addr[3]) << 8;
g_ble_hw_resolv_proc.hash = get_be24(&addr[0]);
g_ble_hw_resolv_proc.f_match = 0;
g_ble_hw_resolv_proc.f_done = 0;
g_ble_hw_resolv_proc.f_active = 1;
ble_hw_resolv_proc_next();
}
void
CRYPTO_IRQHandler(void)
{
uint32_t hash;
CMAC->CM_EXC_STAT_REG = CMAC_CM_EXC_STAT_REG_EXC_CRYPTO_Msk;
hash = g_ble_hw_resolv_proc.crypto_e_out[3] >> 8;
if (g_ble_hw_resolv_proc.hash == hash) {
g_ble_hw_resolv_proc.f_active = 0;
g_ble_hw_resolv_proc.f_match = 1;
g_ble_hw_resolv_proc.f_done = 1;
} else {
g_ble_hw_resolv_proc.irk++;
ble_hw_resolv_proc_next();
}
}

View file

@ -0,0 +1,29 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#ifndef _BLE_HW_PRIV_H_
#define _BLE_HW_PRIV_H_
#include <stdint.h>
void ble_hw_resolv_proc_enable(void);
void ble_hw_resolv_proc_disable(void);
void ble_hw_resolv_proc_start(const uint8_t *addr);
#endif /* _BLE_HW_PRIV_H_ */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,747 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include "mcu/mcu.h"
#include "mcu/cmac_timer.h"
#include "controller/ble_phy.h"
#include "cmac_driver/cmac_shared.h"
#include "ble_rf_priv.h"
#define RF_CALIBRATION_0 (0x01)
#define RF_CALIBRATION_1 (0x02)
#define RF_CALIBRATION_2 (0x04)
static const int8_t g_ble_rf_power_lvls[] = {
-18, -12, -8, -6, -3, -2, -1, 0, 1, 2, 3, 4, 4, 5, 6
};
struct ble_phy_rf_data {
uint8_t tx_power_cfg0;
uint8_t tx_power_cfg1;
uint8_t tx_power_cfg2;
uint8_t tx_power_cfg3;
uint32_t cal_res_1;
uint32_t cal_res_2;
uint32_t trim_val1_tx_1;
uint32_t trim_val1_tx_2;
uint32_t trim_val2_tx;
uint32_t trim_val2_rx;
uint8_t calibrate_req;
};
static struct ble_phy_rf_data g_ble_phy_rf_data;
static inline uint32_t
get_reg32(uint32_t addr)
{
volatile uint32_t *reg = (volatile uint32_t *)addr;
return *reg;
}
static inline uint32_t
get_reg32_bits(uint32_t addr, uint32_t mask)
{
volatile uint32_t *reg = (volatile uint32_t *)addr;
return (*reg & mask) >> __builtin_ctz(mask);
}
static inline void
set_reg8(uint32_t addr, uint8_t val)
{
volatile uint8_t *reg = (volatile uint8_t *)addr;
*reg = val;
}
static inline void
set_reg16(uint32_t addr, uint16_t val)
{
volatile uint16_t *reg = (volatile uint16_t *)addr;
*reg = val;
}
static inline void
set_reg32(uint32_t addr, uint32_t val)
{
volatile uint32_t *reg = (volatile uint32_t *)addr;
*reg = val;
}
static inline void
set_reg32_bits(uint32_t addr, uint32_t mask, uint32_t val)
{
volatile uint32_t *reg = (volatile uint32_t *)addr;
*reg = (*reg & (~mask)) | (val << __builtin_ctz(mask));
}
static inline void
set_reg32_mask(uint32_t addr, uint32_t mask, uint32_t val)
{
volatile uint32_t *reg = (volatile uint32_t *)addr;
*reg = (*reg & (~mask)) | (val & mask);
}
static inline void
set_reg16_mask(uint32_t addr, uint16_t mask, uint16_t val)
{
volatile uint16_t *reg = (volatile uint16_t *)addr;
*reg = (*reg & (~mask)) | (val & mask);
}
static void
delay_us(uint32_t delay_us)
{
while (delay_us--) {
__NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP();
__NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP();
__NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP();
__NOP(); __NOP(); __NOP(); __NOP();
}
}
static void
ble_rf_apply_trim(volatile uint32_t *tv, unsigned len)
{
while (len) {
*(volatile uint32_t *)tv[0] = tv[1];
len -= 2;
tv += 2;
}
}
static void
ble_rf_apply_calibration(void)
{
set_reg32(0x40020094, g_ble_phy_rf_data.cal_res_1);
if (g_ble_phy_rf_data.cal_res_2) {
set_reg32_bits(0x40022018, 0xff800000, g_ble_phy_rf_data.cal_res_2);
set_reg32_bits(0x40022018, 0x00007fc0, g_ble_phy_rf_data.cal_res_2);
}
}
static inline void
ble_rf_ldo_on(void)
{
set_reg8(0x40020004, 9);
}
static inline void
ble_rf_ldo_off(void)
{
set_reg8(0x40020004, 0);
}
static inline void
ble_rf_rfcu_enable(void)
{
set_reg32_bits(0x50000010, 0x00000020, 1);
}
static inline void
ble_rf_rfcu_disable(void)
{
set_reg32_bits(0x50000010, 0x00000020, 0);
}
static void
ble_rf_rfcu_apply_recommended_settings(void)
{
set_reg16_mask(0x400200a0, 0x0001, 0x0001);
set_reg16_mask(0x40021020, 0x03f0, 0x02f5);
set_reg32_mask(0x40021018, 0x001fffff, 0x005a5809);
set_reg32_mask(0x4002101c, 0x00001e01, 0x0040128c);
set_reg32_mask(0x40021004, 0xffffff1f, 0x64442404);
set_reg32_mask(0x40021008, 0xfcfcffff, 0x6b676665);
set_reg32_mask(0x4002100c, 0x00fcfcfc, 0x9793736f);
set_reg32_mask(0x40021010, 0x1f1f1c1f, 0x04072646);
set_reg32_mask(0x40020000, 0x001ff000, 0x0f099820);
set_reg16_mask(0x40020348, 0x00ff, 0x0855);
set_reg16(0x40020350, 0x0234);
set_reg16(0x40020354, 0x0a34);
set_reg16(0x40020358, 0x0851);
set_reg16(0x4002035c, 0x0a26);
set_reg16(0x40020360, 0x0858);
set_reg16(0x4002102c, 0xdfe7);
set_reg32_mask(0x4002103c, 0x00c00000, 0x0024a19f);
set_reg16_mask(0x40021000, 0x0008, 0x000b);
set_reg16_mask(0x40020238, 0x03e0, 0x02c0);
set_reg16_mask(0x4002023c, 0x03e0, 0x02c0);
set_reg16_mask(0x40020244, 0x03e0, 0x0250);
set_reg16_mask(0x40020248, 0x03e0, 0x02a0);
set_reg16_mask(0x4002024c, 0x03e0, 0x02c0);
set_reg16_mask(0x40020288, 0x03e0, 0x0300);
set_reg16_mask(0x4002029c, 0x001f, 0x0019);
set_reg16_mask(0x4002003c, 0x6000, 0x0788);
set_reg16_mask(0x40020074, 0x7f00, 0x2007);
set_reg32_mask(0x40020080, 0x00333330, 0x00222224);
set_reg32_mask(0x40020068, 0x00000f0f, 0x00000f0d);
}
static void
ble_rf_rfcu_apply_settings(void)
{
ble_rf_apply_trim(g_cmac_shared_data.trim.rfcu,
g_cmac_shared_data.trim.rfcu_len);
ble_rf_rfcu_apply_recommended_settings();
}
static inline void
ble_rf_synth_enable(void)
{
set_reg8(0x40020005, 3);
}
static inline void
ble_rf_synth_disable(void)
{
set_reg8(0x40020005, 0);
__NOP();
__NOP();
}
static bool
ble_rf_synth_is_enabled(void)
{
return get_reg32_bits(0x40020004, 256);
}
static void
ble_rf_synth_apply_recommended_settings(void)
{
set_reg32_mask(0x40022048, 0x0000000c, 0x000000d5);
set_reg32_mask(0x40022050, 0x00000300, 0x00000300);
set_reg16_mask(0x40022024, 0x0001, 0x0001);
}
static void
ble_rf_synth_apply_settings(void)
{
ble_rf_apply_trim(g_cmac_shared_data.trim.synth,
g_cmac_shared_data.trim.synth_len);
ble_rf_synth_apply_recommended_settings();
}
static void
ble_rf_calibration_0(void)
{
uint32_t bkp[10];
bkp[0] = get_reg32(0x40020208);
bkp[1] = get_reg32(0x40020250);
bkp[2] = get_reg32(0x40020254);
bkp[3] = get_reg32(0x40021028);
bkp[4] = get_reg32(0x40020020);
bkp[5] = get_reg32(0x40020294);
bkp[6] = get_reg32(0x4002103C);
bkp[7] = get_reg32(0x400200A8);
bkp[8] = get_reg32(0x40020000);
bkp[9] = get_reg32(0x40022000);
set_reg32_bits(0x40020000, 0x00000002, 0);
set_reg32_bits(0x40022000, 0x00000001, 0);
set_reg32_mask(0x4002103C, 0x00201c00, 0x00001c00);
set_reg32_bits(0x400200A8, 0x00000001, 1);
set_reg8(0x40020006, 1);
set_reg32(0x40020208, 0);
set_reg32(0x40020250, 0);
set_reg32(0x40020254, 0);
set_reg32(0x40021028, 0x00F8A494);
set_reg32(0x40020020, 8);
set_reg32(0x40020294, 0);
set_reg32(0x40020024, 0);
delay_us(5);
if (get_reg32_bits(0x40020020, 0x00000002)) {
goto done;
}
set_reg32_bits(0x40020020, 0x00000001, 1);
delay_us(15);
if (!get_reg32_bits(0x40020020, 0x00000001)) {
goto done;
}
delay_us(300);
if (get_reg32_bits(0x40020020, 0x00000001)) {
goto done;
}
done:
set_reg32(0x40020024, 0);
set_reg32(0x40020208, bkp[0]);
set_reg32(0x40020250, bkp[1]);
set_reg32(0x40020254, bkp[2]);
set_reg32(0x40021028, bkp[3]);
set_reg32(0x40020020, bkp[4]);
set_reg32(0x40020294, bkp[5]);
set_reg32(0x4002103C, bkp[6]);
set_reg32(0x400200A8, bkp[7]);
set_reg32(0x40020000, bkp[8]);
set_reg32(0x40022000, bkp[9]);
}
static void
ble_rf_calibration_1(void)
{
uint32_t bkp[12];
uint32_t val;
bkp[0] = get_reg32(0x40020020);
bkp[1] = get_reg32(0x40020208);
bkp[2] = get_reg32(0x40020250);
bkp[3] = get_reg32(0x40020254);
bkp[4] = get_reg32(0x40020218);
bkp[5] = get_reg32(0x4002021c);
bkp[6] = get_reg32(0x40020220);
bkp[7] = get_reg32(0x40020270);
bkp[8] = get_reg32(0x4002027c);
bkp[9] = get_reg32(0x4002101c);
bkp[10] = get_reg32(0x40020000);
bkp[11] = get_reg32(0x40022000);
set_reg32(0x4002103c, 0x0124a21f);
set_reg32(0x40020208, 0);
set_reg32(0x40020250, 0);
set_reg32(0x40020254, 0);
set_reg32(0x40020218, 0);
set_reg32(0x4002021c, 0);
set_reg32(0x40020220, 0);
set_reg32(0x40020270, 0);
set_reg32(0x4002027c, 0);
set_reg32(0x40020000, 0x0f168820);
set_reg32_bits(0x40022000, 0x00000001, 0);
set_reg32_bits(0x4002101c, 0x00001e00, 0);
set_reg32_bits(0x4002001c, 0x0000003f, 47);
set_reg8(0x40020006, 1);
set_reg32(0x40020020, 16);
set_reg32_bits(0x4002003c, 0x00000800, 1);
set_reg32(0x40020024, 0);
delay_us(5);
if (get_reg32_bits(0x40020020, 0x00000002)) {
goto done;
}
set_reg32_bits(0x40020020, 0x00000001, 1);
delay_us(15);
if (!get_reg32_bits(0x40020020, 0x00000001)) {
goto done;
}
delay_us(300);
if (get_reg32_bits(0x40020020, 0x00000001)) {
goto done;
}
val = get_reg32(0x40020090);
set_reg32_bits(0x40020094, 0x0000000f, val);
set_reg32_bits(0x40020094, 0x00000f00, val);
set_reg32_bits(0x40020094, 0x000f0000, val);
set_reg32_bits(0x40020094, 0x0f000000, val);
g_ble_phy_rf_data.cal_res_1 = get_reg32(0x40020094);
done:
set_reg32(0x40020024, 0);
set_reg32(0x40020020, bkp[0]);
set_reg32(0x40020208, bkp[1]);
set_reg32(0x40020250, bkp[2]);
set_reg32(0x40020254, bkp[3]);
set_reg32(0x40020218, bkp[4]);
set_reg32(0x4002021c, bkp[5]);
set_reg32(0x40020220, bkp[6]);
set_reg32(0x40020270, bkp[7]);
set_reg32(0x4002027c, bkp[8]);
set_reg32(0x4002101c, bkp[9]);
set_reg32(0x40020000, bkp[10]);
set_reg32(0x40022000, bkp[11]);
set_reg32_bits(0x4002003c, 0x00000800, 0);
}
static void
ble_rf_calibration_2(void)
{
uint32_t bkp[2];
uint32_t k1;
set_reg8(0x40020005, 3);
set_reg32(0x40022000, 0x00000300);
set_reg32_bits(0x40022004, 0x0000007f, 20);
bkp[0] = get_reg32(0x40022040);
set_reg32(0x40022040, 0xffffffff);
set_reg32_bits(0x40022018, 0x0000003f, 0);
set_reg32_bits(0x40022018, 0x00008000, 0);
set_reg32_bits(0x4002201c, 0x00000600, 2);
set_reg32_bits(0x4002201c, 0x00000070, 4);
set_reg32_bits(0x40022030, 0x3f000000, 22);
set_reg32_bits(0x40022030, 0x00000fc0, 24);
set_reg32_bits(0x40022030, 0x0000003f, 24);
set_reg8(0x4002201c, 0x43);
set_reg8(0x40020006, 2);
delay_us(2);
bkp[1] = get_reg32_bits(0x4002024c, 0x000003e0);
set_reg32_bits(0x4002024c, 0x000003e0, 0);
set_reg8(0x40020006, 1);
set_reg32_bits(0x400200ac, 0x00000003, 3);
delay_us(30);
delay_us(100);
set_reg8(0x40020005, 3);
k1 = get_reg32_bits(0x40022088, 0x000001ff);
set_reg32(0x400200ac, 0);
delay_us(20);
set_reg32_bits(0x4002024c, 0x000003e0, bkp[1]);
delay_us(10);
set_reg32_bits(0x40022018, 0xff800000, k1);
set_reg32_bits(0x40022018, 0x00007fc0, k1);
set_reg8(0x4002201c, 0x41);
set_reg32_bits(0x4002201c, 0x00000600, 2);
set_reg8(0x40020006, 2);
delay_us(2);
bkp[1] = get_reg32_bits(0x4002024c, 0x000003e0);
set_reg32_bits(0x4002024c, 0x000003e0, 0);
set_reg8(0x40020006, 1);
set_reg32_bits(0x400200ac, 0x00000003, 3);
delay_us(30);
delay_us(100);
set_reg8(0x40020005, 3);
k1 = get_reg32_bits(0x40022088, 0x1ff);
set_reg32(0x400200ac, 0);
delay_us(20);
set_reg32_bits(0x4002024c, 0x000003e0, bkp[1]);
delay_us(10);
set_reg32_bits(0x40022018, 0xff800000, k1);
set_reg32_bits(0x40022018, 0x00007fc0, k1);
set_reg8(0x4002201c, 0x41);
set_reg32_bits(0x4002201c, 0x00000600, 2);
set_reg8(0x40020006, 2);
delay_us(2);
bkp[1] = get_reg32_bits(0x4002024c, 0x000003e0);
set_reg32_bits(0x4002024c, 0x000003e0, 0);
set_reg8(0x40020006, 1);
set_reg32_bits(0x400200ac, 0x00000003, 3);
delay_us(30);
delay_us(100);
set_reg8(0x40020005, 3);
k1 = get_reg32_bits(0x40022088, 0x000001ff);
set_reg32_bits(0x40022018, 0xff800000, k1);
set_reg32_bits(0x40022018, 0x00007fc0, k1);
set_reg32_bits(0x4002201c, 0x00000001, 0);
set_reg32(0x40022040, bkp[0]);
set_reg32_bits(0x40022018, 0x0000003f, 0x1c);
set_reg32_bits(0x40022018, 0x00008000, 0);
set_reg32_bits(0x40022030, 0x3f000000, 28);
set_reg32_bits(0x40022030, 0x00000fc0, 30);
set_reg32_bits(0x40022030, 0x0000003f, 30);
set_reg32(0x400200ac, 0);
delay_us(20);
set_reg32_bits(0x4002024c, 0x000003e0, bkp[1]);
delay_us(10);
g_ble_phy_rf_data.cal_res_2 = k1;
}
static void
ble_rf_calibrate_int(uint8_t mask)
{
__disable_irq();
ble_rf_enable();
delay_us(20);
ble_rf_synth_disable();
ble_rf_synth_enable();
ble_rf_synth_apply_settings();
set_reg8(0x40020005, 1);
if (mask & RF_CALIBRATION_0) {
ble_rf_calibration_0();
}
if (mask & RF_CALIBRATION_1) {
ble_rf_calibration_1();
}
if (mask & RF_CALIBRATION_2) {
ble_rf_calibration_2();
}
ble_rf_disable();
__enable_irq();
#if MYNEWT_VAL(CMAC_DEBUG_DATA_ENABLE)
g_cmac_shared_data.debug.cal_res_1 = g_ble_phy_rf_data.cal_res_1;
g_cmac_shared_data.debug.cal_res_2 = g_ble_phy_rf_data.cal_res_2;
#endif
}
bool
ble_rf_try_recalibrate(uint32_t idle_time_us)
{
/* Run recalibration if we have at least 1ms of time to spare and RF is
* currently disabled. Calibration is much shorter than 1ms, but that gives
* us good margin to make sure we can finish before next event.
*/
if (!g_ble_phy_rf_data.calibrate_req || (idle_time_us < 1000) ||
ble_rf_is_enabled()) {
return false;
}
ble_rf_calibrate_int(RF_CALIBRATION_2);
g_ble_phy_rf_data.calibrate_req = 0;
return true;
}
static uint32_t
ble_rf_find_trim_reg(volatile uint32_t *tv, unsigned len, uint32_t reg)
{
while (len) {
if (tv[0] == reg) {
return tv[1];
}
len -= 2;
tv += 2;
}
return 0;
}
void
ble_rf_init(void)
{
static bool done = false;
uint32_t val;
ble_rf_disable();
if (done) {
return;
}
val = ble_rf_find_trim_reg(g_cmac_shared_data.trim.rfcu_mode1,
g_cmac_shared_data.trim.rfcu_mode1_len,
0x4002004c);
g_ble_phy_rf_data.trim_val1_tx_1 = val;
val = ble_rf_find_trim_reg(g_cmac_shared_data.trim.rfcu_mode2,
g_cmac_shared_data.trim.rfcu_mode2_len,
0x4002004c);
g_ble_phy_rf_data.trim_val1_tx_2 = val;
if (!g_ble_phy_rf_data.trim_val1_tx_1 || !g_ble_phy_rf_data.trim_val1_tx_2) {
val = ble_rf_find_trim_reg(g_cmac_shared_data.trim.rfcu,
g_cmac_shared_data.trim.rfcu_len,
0x4002004c);
if (!val) {
val = 0x0300;
}
g_ble_phy_rf_data.trim_val1_tx_1 = val;
g_ble_phy_rf_data.trim_val1_tx_2 = val;
}
val = ble_rf_find_trim_reg(g_cmac_shared_data.trim.synth,
g_cmac_shared_data.trim.synth_len,
0x40022038);
if (!val) {
val = 0x0198ff03;
}
g_ble_phy_rf_data.trim_val2_rx = val;
g_ble_phy_rf_data.trim_val2_tx = val;
set_reg32_bits((uint32_t)&g_ble_phy_rf_data.trim_val2_tx, 0x0001ff00, 0x87);
#if MYNEWT_VAL(CMAC_DEBUG_DATA_ENABLE)
g_cmac_shared_data.debug.trim_val1_tx_1 = g_ble_phy_rf_data.trim_val1_tx_1;
g_cmac_shared_data.debug.trim_val1_tx_2 = g_ble_phy_rf_data.trim_val1_tx_2;
g_cmac_shared_data.debug.trim_val2_tx = g_ble_phy_rf_data.trim_val2_tx;
g_cmac_shared_data.debug.trim_val2_rx = g_ble_phy_rf_data.trim_val2_rx;
#endif
ble_rf_rfcu_enable();
ble_rf_rfcu_apply_settings();
g_ble_phy_rf_data.tx_power_cfg1 = get_reg32_bits(0x500000a4, 0xf0);
g_ble_phy_rf_data.tx_power_cfg2 = get_reg32_bits(0x40020238, 0x000003e0);
g_ble_phy_rf_data.tx_power_cfg3 = 0;
ble_rf_rfcu_disable();
ble_rf_calibrate_int(RF_CALIBRATION_0 | RF_CALIBRATION_1 | RF_CALIBRATION_2);
done = true;
}
void
ble_rf_enable(void)
{
if (ble_rf_is_enabled()) {
return;
}
ble_rf_rfcu_enable();
ble_rf_rfcu_apply_settings();
ble_rf_ldo_on();
}
void
ble_rf_configure(void)
{
if (ble_rf_synth_is_enabled()) {
return;
}
ble_rf_synth_enable();
ble_rf_synth_apply_settings();
}
void
ble_rf_stop(void)
{
ble_rf_synth_disable();
set_reg8(0x40020006, 0);
}
void
ble_rf_disable(void)
{
ble_rf_stop();
ble_rf_ldo_off();
ble_rf_rfcu_disable();
}
bool
ble_rf_is_enabled(void)
{
return get_reg32_bits(0x40020008, 5) == 5;
}
void
ble_rf_calibrate_req(void)
{
g_ble_phy_rf_data.calibrate_req = 1;
}
void
ble_rf_setup_tx(uint8_t rf_chan, uint8_t phy_mode)
{
set_reg32_bits(0x40020000, 0x0f000000, g_ble_phy_rf_data.tx_power_cfg0);
set_reg32_bits(0x500000a4, 0x000000f0, g_ble_phy_rf_data.tx_power_cfg1);
set_reg32_bits(0x40020238, 0x000003e0, g_ble_phy_rf_data.tx_power_cfg2);
set_reg32_bits(0x40020234, 0x000003e0, g_ble_phy_rf_data.tx_power_cfg3);
if (g_ble_phy_rf_data.tx_power_cfg0 < 13) {
set_reg32(0x4002004c, g_ble_phy_rf_data.trim_val1_tx_1);
} else {
set_reg32(0x4002004c, g_ble_phy_rf_data.trim_val1_tx_2);
}
set_reg8(0x40020005, 3);
set_reg8(0x40022004, rf_chan);
if (phy_mode == BLE_PHY_MODE_2M) {
#if MYNEWT_VAL(BLE_PHY_RF_HP_MODE)
set_reg32(0x40022000, 0x00000303);
#else
set_reg32(0x40022000, 0x00000003);
#endif
} else {
#if MYNEWT_VAL(BLE_PHY_RF_HP_MODE)
set_reg32(0x40022000, 0x00000300);
#else
set_reg32(0x40022000, 0x00000000);
#endif
}
ble_rf_apply_calibration();
set_reg32_bits(0x40022050, 0x00000200, 1);
set_reg32_bits(0x40022050, 0x00000100, 0);
set_reg32_bits(0x40022048, 0x01ffff00, 0x7700);
set_reg32(0x40022038, g_ble_phy_rf_data.trim_val2_tx);
set_reg8(0x40020006, 3);
}
void
ble_rf_setup_rx(uint8_t rf_chan, uint8_t phy_mode)
{
set_reg32_bits(0x500000a4, 0x000000f0, g_ble_phy_rf_data.tx_power_cfg1);
set_reg8(0x40020005, 3);
set_reg8(0x40022004, rf_chan);
if (phy_mode == BLE_PHY_MODE_2M) {
#if MYNEWT_VAL(BLE_PHY_RF_HP_MODE)
set_reg32(0x40022000, 0x00000303);
set_reg32(0x40020000, 0x0f11b823);
set_reg32(0x4002103c, 0x0125261b);
#else
set_reg32(0x40022000, 0x00000003);
set_reg32(0x40020000, 0x0f0c2803);
set_reg32(0x4002103c, 0x0125a61b);
#endif
set_reg32(0x40021020, 0x000002f5);
set_reg32(0x4002102c, 0x0000d1d5);
} else {
#if MYNEWT_VAL(BLE_PHY_RF_HP_MODE)
set_reg32(0x40022000, 0x00000300);
set_reg32(0x40020000, 0x0f099820);
set_reg32(0x4002103c, 0x0124a21f);
#else
set_reg32(0x40022000, 0x00000000);
set_reg32(0x40020000, 0x0f062800);
set_reg32(0x4002103c, 0x01051e1f);
#endif
set_reg32(0x40021020, 0x000002f5);
set_reg32(0x4002102c, 0x0000dfe7);
}
ble_rf_apply_calibration();
set_reg32_bits(0x40022050, 0x00000200, 1);
set_reg32_bits(0x40022050, 0x00000100, 1);
set_reg32_bits(0x40022048, 0x01ffff00, 0);
set_reg32(0x40022038, g_ble_phy_rf_data.trim_val2_rx);
set_reg8(0x40020006, 3);
}
void
ble_rf_set_tx_power(int dbm)
{
int i;
for (i = 0; i < ARRAY_SIZE(g_ble_rf_power_lvls); i++) {
if (g_ble_rf_power_lvls[i] >= dbm) {
break;
}
}
g_ble_phy_rf_data.tx_power_cfg0 = i + 1;
}
int8_t
ble_rf_get_rssi(void)
{
return (501 * get_reg32_bits(0x40021038, 0x000003ff) - 493000) / 4096;
}

View file

@ -0,0 +1,38 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#ifndef _BLE_RF_PRIV_H_
#define _BLE_RF_PRIV_H_
void ble_rf_init(void);
void ble_rf_enable(void);
void ble_rf_stop(void);
void ble_rf_disable(void);
bool ble_rf_is_enabled(void);
void ble_rf_configure(void);
void ble_rf_calibrate(void);
void ble_rf_setup_tx(uint8_t rf_chan, uint8_t mode);
void ble_rf_setup_rx(uint8_t rf_chan, uint8_t mode);
void ble_rf_set_tx_power(int dbm);
int8_t ble_rf_get_rssi(void);
#endif /* _BLE_RF_PRIV_H_ */

View file

@ -0,0 +1,29 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
syscfg.defs:
BLE_PHY_RF_HP_MODE:
description: Enable high-performance RF mode.
value: 1
BLE_PHY_DEBUG_DSER:
description: Enable DSER output from PHY
value: 0
syscfg.restrictions:
- BLE_LL_RFMGMT_ENABLE_TIME == 0 || BLE_LL_RFMGMT_ENABLE_TIME >= 20

View file

@ -20,6 +20,8 @@
#include <stdint.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include "syscfg/syscfg.h"
#include "os/os.h"
#include "nimble/ble.h"
@ -32,6 +34,9 @@
/* We use this to keep track of which entries are set to valid addresses */
static uint8_t g_ble_hw_whitelist_mask;
static ble_rng_isr_cb_t rng_cb;
static bool rng_started;
/* Returns public device address or -1 if not present */
int
ble_hw_get_public_addr(ble_addr_t *addr)
@ -143,7 +148,8 @@ ble_hw_encrypt_block(struct ble_encryption_block *ecb)
int
ble_hw_rng_init(ble_rng_isr_cb_t cb, int bias)
{
return -1;
rng_cb = cb;
return 0;
}
/**
@ -154,7 +160,15 @@ ble_hw_rng_init(ble_rng_isr_cb_t cb, int bias)
int
ble_hw_rng_start(void)
{
return -1;
rng_started = true;
if (rng_cb) {
while (rng_started) {
rng_cb(rand());
}
}
return 0;
}
/**
@ -165,7 +179,8 @@ ble_hw_rng_start(void)
int
ble_hw_rng_stop(void)
{
return -1;
rng_started = false;
return 0;
}
/**
@ -176,7 +191,7 @@ ble_hw_rng_stop(void)
uint8_t
ble_hw_rng_read(void)
{
return 0;
return rand();
}
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)

View file

@ -0,0 +1,50 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#ifndef H_BLE_XCVR_
#define H_BLE_XCVR_
#ifdef __cplusplus
extern "C" {
#endif
#define XCVR_RX_RADIO_RAMPUP_USECS (40)
#define XCVR_TX_RADIO_RAMPUP_USECS (40)
/*
* NOTE: we have to account for the RTC output compare issue. We want it to be
* 5 ticks.
*/
#define XCVR_PROC_DELAY_USECS (153)
#define XCVR_RX_START_DELAY_USECS (XCVR_RX_RADIO_RAMPUP_USECS)
#define XCVR_TX_START_DELAY_USECS (XCVR_TX_RADIO_RAMPUP_USECS)
#define XCVR_TX_SCHED_DELAY_USECS (XCVR_TX_START_DELAY_USECS + XCVR_PROC_DELAY_USECS)
#define XCVR_RX_SCHED_DELAY_USECS (XCVR_RX_START_DELAY_USECS + XCVR_PROC_DELAY_USECS)
/*
* Define HW whitelist size. This is the total possible whitelist size;
* not necessarily the size that will be used (may be smaller)
*/
#define BLE_HW_WHITE_LIST_SIZE (8)
#ifdef __cplusplus
}
#endif
#endif /* H_BLE_XCVR_ */

View file

@ -0,0 +1,31 @@
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
pkg.name: nimble/drivers/nrf5340
pkg.description: BLE driver for nRF5340 systems.
pkg.author: "Apache Mynewt <dev@mynewt.apache.org>"
pkg.homepage: "http://mynewt.apache.org/"
pkg.keywords:
- ble
- bluetooth
pkg.apis: ble_driver
pkg.deps:
- nimble
- nimble/controller

View file

@ -0,0 +1,475 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#include <stdint.h>
#include <assert.h>
#include <string.h>
#include <syscfg/syscfg.h>
#include <os/os.h>
#include <nimble/ble.h>
#include <nimble/nimble_opt.h>
#include <controller/ble_hw.h>
#include <ble/xcvr.h>
#include <mcu/cmsis_nvic.h>
#include <os/os_trace_api.h>
/* Total number of resolving list elements */
#define BLE_HW_RESOLV_LIST_SIZE (16)
/* We use this to keep track of which entries are set to valid addresses */
static uint8_t g_ble_hw_whitelist_mask;
/* Random number generator isr callback */
static ble_rng_isr_cb_t ble_rng_isr_cb;
/* If LL privacy is enabled, allocate memory for AAR */
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
/* The NRF5340 supports up to 16 IRK entries */
#if (MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE) < 16)
#define NRF_IRK_LIST_ENTRIES (MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE))
#else
#define NRF_IRK_LIST_ENTRIES (16)
#endif
/* NOTE: each entry is 16 bytes long. */
uint32_t g_nrf_irk_list[NRF_IRK_LIST_ENTRIES * 4];
/* Current number of IRK entries */
uint8_t g_nrf_num_irks;
#endif
/* Returns public device address or -1 if not present */
int
ble_hw_get_public_addr(ble_addr_t *addr)
{
uint32_t addr_high;
uint32_t addr_low;
/* Does FICR have a public address */
if ((NRF_FICR_NS->DEVICEADDRTYPE & 1) != 0) {
return -1;
}
/* Copy into device address. We can do this because we know platform */
addr_low = NRF_FICR_NS->DEVICEADDR[0];
addr_high = NRF_FICR_NS->DEVICEADDR[1];
memcpy(addr->val, &addr_low, 4);
memcpy(&addr->val[4], &addr_high, 2);
addr->type = BLE_ADDR_PUBLIC;
return 0;
}
/* Returns random static address or -1 if not present */
int
ble_hw_get_static_addr(ble_addr_t *addr)
{
int rc;
if ((NRF_FICR_NS->DEVICEADDRTYPE & 1) == 1) {
memcpy(addr->val, (void *)&NRF_FICR_NS->DEVICEADDR[0], 4);
memcpy(&addr->val[4], (void *)&NRF_FICR_NS->DEVICEADDR[1], 2);
addr->val[5] |= 0xc0;
addr->type = BLE_ADDR_RANDOM;
rc = 0;
} else {
rc = -1;
}
return rc;
}
/**
* Clear the whitelist
*
* @return int
*/
void
ble_hw_whitelist_clear(void)
{
NRF_RADIO_NS->DACNF = 0;
g_ble_hw_whitelist_mask = 0;
}
/**
* Add a device to the hw whitelist
*
* @param addr
* @param addr_type
*
* @return int 0: success, BLE error code otherwise
*/
int
ble_hw_whitelist_add(const uint8_t *addr, uint8_t addr_type)
{
int i;
uint32_t mask;
/* Find first ununsed device address match element */
mask = 0x01;
for (i = 0; i < BLE_HW_WHITE_LIST_SIZE; ++i) {
if ((mask & g_ble_hw_whitelist_mask) == 0) {
NRF_RADIO_NS->DAB[i] = get_le32(addr);
NRF_RADIO_NS->DAP[i] = get_le16(addr + 4);
if (addr_type == BLE_ADDR_RANDOM) {
NRF_RADIO_NS->DACNF |= (mask << 8);
}
g_ble_hw_whitelist_mask |= mask;
return BLE_ERR_SUCCESS;
}
mask <<= 1;
}
return BLE_ERR_MEM_CAPACITY;
}
/**
* Remove a device from the hw whitelist
*
* @param addr
* @param addr_type
*
*/
void
ble_hw_whitelist_rmv(const uint8_t *addr, uint8_t addr_type)
{
int i;
uint16_t dap;
uint16_t txadd;
uint32_t dab;
uint32_t mask;
/* Find first ununsed device address match element */
dab = get_le32(addr);
dap = get_le16(addr + 4);
txadd = NRF_RADIO_NS->DACNF >> 8;
mask = 0x01;
for (i = 0; i < BLE_HW_WHITE_LIST_SIZE; ++i) {
if (mask & g_ble_hw_whitelist_mask) {
if ((dab == NRF_RADIO_NS->DAB[i]) && (dap == NRF_RADIO_NS->DAP[i])) {
if (addr_type == !!(txadd & mask)) {
break;
}
}
}
mask <<= 1;
}
if (i < BLE_HW_WHITE_LIST_SIZE) {
g_ble_hw_whitelist_mask &= ~mask;
NRF_RADIO_NS->DACNF &= ~mask;
}
}
/**
* Returns the size of the whitelist in HW
*
* @return int Number of devices allowed in whitelist
*/
uint8_t
ble_hw_whitelist_size(void)
{
return BLE_HW_WHITE_LIST_SIZE;
}
/**
* Enable the whitelisted devices
*/
void
ble_hw_whitelist_enable(void)
{
/* Enable the configured device addresses */
NRF_RADIO_NS->DACNF |= g_ble_hw_whitelist_mask;
}
/**
* Disables the whitelisted devices
*/
void
ble_hw_whitelist_disable(void)
{
/* Disable all whitelist devices */
NRF_RADIO_NS->DACNF &= 0x0000ff00;
}
/**
* Boolean function which returns true ('1') if there is a match on the
* whitelist.
*
* @return int
*/
int
ble_hw_whitelist_match(void)
{
return NRF_RADIO_NS->EVENTS_DEVMATCH;
}
/* Encrypt data */
int
ble_hw_encrypt_block(struct ble_encryption_block *ecb)
{
int rc;
uint32_t end;
uint32_t err;
/* Stop ECB */
NRF_ECB_NS->TASKS_STOPECB = 1;
/* XXX: does task stop clear these counters? Anyway to do this quicker? */
NRF_ECB_NS->EVENTS_ENDECB = 0;
NRF_ECB_NS->EVENTS_ERRORECB = 0;
NRF_ECB_NS->ECBDATAPTR = (uint32_t)ecb;
/* Start ECB */
NRF_ECB_NS->TASKS_STARTECB = 1;
/* Wait till error or done */
rc = 0;
while (1) {
end = NRF_ECB_NS->EVENTS_ENDECB;
err = NRF_ECB_NS->EVENTS_ERRORECB;
if (end || err) {
if (err) {
rc = -1;
}
break;
}
}
return rc;
}
/**
* Random number generator ISR.
*/
static void
ble_rng_isr(void)
{
uint8_t rnum;
os_trace_isr_enter();
/* No callback? Clear and disable interrupts */
if (ble_rng_isr_cb == NULL) {
NRF_RNG_NS->INTENCLR = 1;
NRF_RNG_NS->EVENTS_VALRDY = 0;
(void)NRF_RNG_NS->SHORTS;
os_trace_isr_exit();
return;
}
/* If there is a value ready grab it */
if (NRF_RNG_NS->EVENTS_VALRDY) {
NRF_RNG_NS->EVENTS_VALRDY = 0;
rnum = (uint8_t)NRF_RNG_NS->VALUE;
(*ble_rng_isr_cb)(rnum);
}
os_trace_isr_exit();
}
/**
* Initialize the random number generator
*
* @param cb
* @param bias
*
* @return int
*/
int
ble_hw_rng_init(ble_rng_isr_cb_t cb, int bias)
{
/* Set bias */
if (bias) {
NRF_RNG_NS->CONFIG = 1;
} else {
NRF_RNG_NS->CONFIG = 0;
}
/* If we were passed a function pointer we need to enable the interrupt */
if (cb != NULL) {
#ifndef RIOT_VERSION
NVIC_SetPriority(RNG_IRQn, (1 << __NVIC_PRIO_BITS) - 1);
#endif
#if MYNEWT
NVIC_SetVector(RNG_IRQn, (uint32_t)ble_rng_isr);
#else
ble_npl_hw_set_isr(RNG_IRQn, ble_rng_isr);
#endif
NVIC_EnableIRQ(RNG_IRQn);
ble_rng_isr_cb = cb;
}
return 0;
}
/**
* Start the random number generator
*
* @return int
*/
int
ble_hw_rng_start(void)
{
os_sr_t sr;
/* No need for interrupt if there is no callback */
OS_ENTER_CRITICAL(sr);
NRF_RNG_NS->EVENTS_VALRDY = 0;
if (ble_rng_isr_cb) {
NRF_RNG_NS->INTENSET = 1;
}
NRF_RNG_NS->TASKS_START = 1;
OS_EXIT_CRITICAL(sr);
return 0;
}
/**
* Stop the random generator
*
* @return int
*/
int
ble_hw_rng_stop(void)
{
os_sr_t sr;
/* No need for interrupt if there is no callback */
OS_ENTER_CRITICAL(sr);
NRF_RNG_NS->INTENCLR = 1;
NRF_RNG_NS->TASKS_STOP = 1;
NRF_RNG_NS->EVENTS_VALRDY = 0;
OS_EXIT_CRITICAL(sr);
return 0;
}
/**
* Read the random number generator.
*
* @return uint8_t
*/
uint8_t
ble_hw_rng_read(void)
{
uint8_t rnum;
/* Wait for a sample */
while (NRF_RNG_NS->EVENTS_VALRDY == 0) {
}
NRF_RNG_NS->EVENTS_VALRDY = 0;
rnum = (uint8_t)NRF_RNG_NS->VALUE;
return rnum;
}
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
/**
* Clear the resolving list
*
* @return int
*/
void
ble_hw_resolv_list_clear(void)
{
g_nrf_num_irks = 0;
}
/**
* Add a device to the hw resolving list
*
* @param irk Pointer to IRK to add
*
* @return int 0: success, BLE error code otherwise
*/
int
ble_hw_resolv_list_add(uint8_t *irk)
{
uint32_t *nrf_entry;
/* Find first ununsed device address match element */
if (g_nrf_num_irks == NRF_IRK_LIST_ENTRIES) {
return BLE_ERR_MEM_CAPACITY;
}
/* Copy into irk list */
nrf_entry = &g_nrf_irk_list[4 * g_nrf_num_irks];
memcpy(nrf_entry, irk, 16);
/* Add to total */
++g_nrf_num_irks;
return BLE_ERR_SUCCESS;
}
/**
* Remove a device from the hw resolving list
*
* @param index Index of IRK to remove
*/
void
ble_hw_resolv_list_rmv(int index)
{
uint32_t *irk_entry;
if (index < g_nrf_num_irks) {
--g_nrf_num_irks;
irk_entry = &g_nrf_irk_list[index];
if (g_nrf_num_irks > index) {
memmove(irk_entry, irk_entry + 4, 16 * (g_nrf_num_irks - index));
}
}
}
/**
* Returns the size of the resolving list. NOTE: this returns the maximum
* allowable entries in the HW. Configuration options may limit this.
*
* @return int Number of devices allowed in resolving list
*/
uint8_t
ble_hw_resolv_list_size(void)
{
return BLE_HW_RESOLV_LIST_SIZE;
}
/**
* Called to determine if the address received was resolved.
*
* @return int Negative values indicate unresolved address; positive values
* indicate index in resolving list of resolved address.
*/
int
ble_hw_resolv_list_match(void)
{
uint32_t index;
if (NRF_AAR_NS->EVENTS_END) {
if (NRF_AAR_NS->EVENTS_RESOLVED) {
index = NRF_AAR_NS->STATUS;
return (int)index;
}
}
return -1;
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,44 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#include <stdint.h>
#include <syscfg/syscfg.h>
#include <os/os_trace_api.h>
#if MYNEWT_VAL(BLE_PHY_SYSVIEW)
static os_trace_module_t g_ble_phy_trace_mod;
uint32_t ble_phy_trace_off;
static void
ble_phy_trace_module_send_desc(void)
{
os_trace_module_desc(&g_ble_phy_trace_mod, "0 phy_set_tx cputime=%u usecs=%u");
os_trace_module_desc(&g_ble_phy_trace_mod, "1 phy_set_rx cputime=%u usecs=%u");
os_trace_module_desc(&g_ble_phy_trace_mod, "2 phy_disable");
}
void
ble_phy_trace_init(void)
{
ble_phy_trace_off =
os_trace_module_register(&g_ble_phy_trace_mod, "ble_phy", 3,
ble_phy_trace_module_send_desc);
}
#endif

View file

@ -0,0 +1,23 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
syscfg.defs:
BLE_PHY_SYSVIEW:
description: >
Enable SystemView tracing module for radio driver.
value: 0

View file

@ -39,41 +39,47 @@ extern "C" {
struct hci_le_conn_complete;
struct hci_conn_update;
#define BLE_GAP_ADV_ITVL_MS(t) ((t) * 1000 / BLE_HCI_ADV_ITVL)
#define BLE_GAP_SCAN_ITVL_MS(t) ((t) * 1000 / BLE_HCI_SCAN_ITVL)
#define BLE_GAP_SCAN_WIN_MS(t) ((t) * 1000 / BLE_HCI_SCAN_ITVL)
#define BLE_GAP_CONN_ITVL_MS(t) ((t) * 1000 / BLE_HCI_CONN_ITVL)
#define BLE_GAP_SUPERVISION_TIMEOUT_MS(t) ((t) / 10)
/** 30 ms. */
#define BLE_GAP_ADV_FAST_INTERVAL1_MIN (30 * 1000 / BLE_HCI_ADV_ITVL)
#define BLE_GAP_ADV_FAST_INTERVAL1_MIN BLE_GAP_ADV_ITVL_MS(30)
/** 60 ms. */
#define BLE_GAP_ADV_FAST_INTERVAL1_MAX (60 * 1000 / BLE_HCI_ADV_ITVL)
#define BLE_GAP_ADV_FAST_INTERVAL1_MAX BLE_GAP_ADV_ITVL_MS(60)
/** 100 ms. */
#define BLE_GAP_ADV_FAST_INTERVAL2_MIN (100 * 1000 / BLE_HCI_ADV_ITVL)
#define BLE_GAP_ADV_FAST_INTERVAL2_MIN BLE_GAP_ADV_ITVL_MS(100)
/** 150 ms. */
#define BLE_GAP_ADV_FAST_INTERVAL2_MAX (150 * 1000 / BLE_HCI_ADV_ITVL)
#define BLE_GAP_ADV_FAST_INTERVAL2_MAX BLE_GAP_ADV_ITVL_MS(150)
/** 30 ms; active scanning. */
#define BLE_GAP_SCAN_FAST_INTERVAL_MIN (30 * 1000 / BLE_HCI_ADV_ITVL)
#define BLE_GAP_SCAN_FAST_INTERVAL_MIN BLE_GAP_SCAN_ITVL_MS(30)
/** 60 ms; active scanning. */
#define BLE_GAP_SCAN_FAST_INTERVAL_MAX (60 * 1000 / BLE_HCI_ADV_ITVL)
#define BLE_GAP_SCAN_FAST_INTERVAL_MAX BLE_GAP_SCAN_ITVL_MS(60)
/** 11.25 ms; limited discovery interval. */
#define BLE_GAP_LIM_DISC_SCAN_INT (11.25 * 1000 / BLE_HCI_SCAN_ITVL)
#define BLE_GAP_LIM_DISC_SCAN_INT BLE_GAP_SCAN_ITVL_MS(11.25)
/** 11.25 ms; limited discovery window (not from the spec). */
#define BLE_GAP_LIM_DISC_SCAN_WINDOW (11.25 * 1000 / BLE_HCI_SCAN_ITVL)
#define BLE_GAP_LIM_DISC_SCAN_WINDOW BLE_GAP_SCAN_WIN_MS(11.25)
/** 30 ms; active scanning. */
#define BLE_GAP_SCAN_FAST_WINDOW (30 * 1000 / BLE_HCI_SCAN_ITVL)
#define BLE_GAP_SCAN_FAST_WINDOW BLE_GAP_SCAN_WIN_MS(30)
/* 30.72 seconds; active scanning. */
#define BLE_GAP_SCAN_FAST_PERIOD (30.72 * 1000)
#define BLE_GAP_SCAN_FAST_PERIOD BLE_GAP_SCAN_ITVL_MS(30.72)
/** 1.28 seconds; background scanning. */
#define BLE_GAP_SCAN_SLOW_INTERVAL1 (1280 * 1000 / BLE_HCI_SCAN_ITVL)
#define BLE_GAP_SCAN_SLOW_INTERVAL1 BLE_GAP_SCAN_ITVL_MS(1280)
/** 11.25 ms; background scanning. */
#define BLE_GAP_SCAN_SLOW_WINDOW1 (11.25 * 1000 / BLE_HCI_SCAN_ITVL)
#define BLE_GAP_SCAN_SLOW_WINDOW1 BLE_GAP_SCAN_WIN_MS(11.25)
/** 10.24 seconds. */
#define BLE_GAP_DISC_DUR_DFLT (10.24 * 1000)
@ -88,18 +94,18 @@ struct hci_conn_update;
#define BLE_GAP_CONN_PAUSE_PERIPHERAL (5 * 1000)
/* 30 ms. */
#define BLE_GAP_INITIAL_CONN_ITVL_MIN (30 * 1000 / BLE_HCI_CONN_ITVL)
#define BLE_GAP_INITIAL_CONN_ITVL_MIN BLE_GAP_CONN_ITVL_MS(30)
/* 50 ms. */
#define BLE_GAP_INITIAL_CONN_ITVL_MAX (50 * 1000 / BLE_HCI_CONN_ITVL)
#define BLE_GAP_INITIAL_CONN_ITVL_MAX BLE_GAP_CONN_ITVL_MS(50)
/** Default channels mask: all three channels are used. */
#define BLE_GAP_ADV_DFLT_CHANNEL_MAP 0x07
#define BLE_GAP_INITIAL_CONN_LATENCY 0
#define BLE_GAP_INITIAL_SUPERVISION_TIMEOUT 0x0100
#define BLE_GAP_INITIAL_CONN_MIN_CE_LEN 0x0010
#define BLE_GAP_INITIAL_CONN_MAX_CE_LEN 0x0300
#define BLE_GAP_INITIAL_CONN_MIN_CE_LEN 0x0000
#define BLE_GAP_INITIAL_CONN_MAX_CE_LEN 0x0000
#define BLE_GAP_ROLE_MASTER 0
#define BLE_GAP_ROLE_SLAVE 1
@ -1896,6 +1902,20 @@ int ble_gap_unpair(const ble_addr_t *peer_addr);
*/
int ble_gap_unpair_oldest_peer(void);
/**
* Similar to `ble_gap_unpair_oldest_peer()`, except it makes sure that the
* peer received in input parameters is not deleted.
*
* @param peer_addr Address of the peer (not to be deleted)
*
* @return 0 on success;
* A BLE host HCI return code if the controller
* rejected the request;
* A BLE host core return code on unexpected
* error.
*/
int ble_gap_unpair_oldest_except(const ble_addr_t *peer_addr);
#define BLE_GAP_PRIVATE_MODE_NETWORK 0
#define BLE_GAP_PRIVATE_MODE_DEVICE 1

View file

@ -21,6 +21,7 @@
#define H_BLE_HS_LOG_
#include "modlog/modlog.h"
#include "log/log.h"
/* Only include the logcfg header if this version of newt can generate it. */
#if MYNEWT_VAL(NEWT_FEATURE_LOGCFG)

View file

@ -28,14 +28,23 @@ extern "C" {
#define BT_MESH_ADDR_RELAYS 0xfffe
#define BT_MESH_KEY_UNUSED 0xffff
#define BT_MESH_KEY_ANY 0xffff
#define BT_MESH_KEY_DEV 0xfffe
#define BT_MESH_KEY_DEV_LOCAL BT_MESH_KEY_DEV
#define BT_MESH_KEY_DEV_REMOTE 0xfffd
#define BT_MESH_KEY_DEV_ANY 0xfffc
#define BT_MESH_ADDR_IS_UNICAST(addr) ((addr) && (addr) < 0x8000)
#define BT_MESH_ADDR_IS_GROUP(addr) ((addr) >= 0xc000 && (addr) <= 0xff00)
#define BT_MESH_ADDR_IS_VIRTUAL(addr) ((addr) >= 0x8000 && (addr) < 0xc000)
#define BT_MESH_ADDR_IS_RFU(addr) ((addr) >= 0xff00 && (addr) <= 0xfffb)
#define BT_MESH_IS_DEV_KEY(key) (key == BT_MESH_KEY_DEV_LOCAL || \
key == BT_MESH_KEY_DEV_REMOTE)
#define BT_MESH_APP_SEG_SDU_MAX 12
#define BT_MESH_TX_SDU_MAX (CONFIG_BT_MESH_TX_SEG_MAX * BT_MESH_APP_SEG_SDU_MAX)
#define BT_MESH_RX_SDU_MAX (CONFIG_BT_MESH_RX_SEG_MAX * BT_MESH_APP_SEG_SDU_MAX)
/** Helper to define a mesh element within an array.
*
* In case the element has no SIG or Vendor models the helper
@ -57,13 +66,13 @@ extern "C" {
/** Abstraction that describes a Mesh Element */
struct bt_mesh_elem {
/* Unicast Address. Set at runtime during provisioning. */
u16_t addr;
uint16_t addr;
/* Location Descriptor (GATT Bluetooth Namespace Descriptors) */
const u16_t loc;
const uint16_t loc;
const u8_t model_count;
const u8_t vnd_model_count;
const uint8_t model_count;
const uint8_t vnd_model_count;
struct bt_mesh_model * const models;
struct bt_mesh_model * const vnd_models;
@ -132,33 +141,33 @@ struct bt_mesh_elem {
/** Message sending context. */
struct bt_mesh_msg_ctx {
/** NetKey Index of the subnet to send the message on. */
u16_t net_idx;
uint16_t net_idx;
/** AppKey Index to encrypt the message with. */
u16_t app_idx;
uint16_t app_idx;
/** Remote address. */
u16_t addr;
uint16_t addr;
/** Destination address of a received message. Not used for sending. */
u16_t recv_dst;
uint16_t recv_dst;
/** RSSI of received packet. Not used for sending. */
s8_t recv_rssi;
int8_t recv_rssi;
/** Received TTL value. Not used for sending. */
u8_t recv_ttl;
uint8_t recv_ttl;
/** Force sending reliably by using segment acknowledgement */
bool send_rel;
/** TTL, or BT_MESH_TTL_DEFAULT for default TTL. */
u8_t send_ttl;
uint8_t send_ttl;
};
struct bt_mesh_model_op {
/* OpCode encoded using the BT_MESH_MODEL_OP_* macros */
const u32_t opcode;
const uint32_t opcode;
/* Minimum required message length */
const size_t min_len;
@ -324,7 +333,7 @@ struct bt_mesh_model_op {
*
* @return Transmission count (actual transmissions is N + 1).
*/
#define BT_MESH_TRANSMIT_COUNT(transmit) (((transmit) & (u8_t)BIT_MASK(3)))
#define BT_MESH_TRANSMIT_COUNT(transmit) (((transmit) & (uint8_t)BIT_MASK(3)))
/** @def BT_MESH_TRANSMIT_INT
*
@ -375,23 +384,24 @@ struct bt_mesh_model_pub {
/** The model the context belongs to. Initialized by the stack. */
struct bt_mesh_model *mod;
u16_t addr; /**< Publish Address. */
u16_t key; /**< Publish AppKey Index. */
uint16_t addr; /**< Publish Address. */
uint16_t key; /**< Publish AppKey Index. */
u8_t ttl; /**< Publish Time to Live. */
u8_t retransmit; /**< Retransmit Count & Interval Steps. */
u8_t period; /**< Publish Period. */
u8_t period_div:4, /**< Divisor for the Period. */
uint8_t ttl; /**< Publish Time to Live. */
uint8_t retransmit; /**< Retransmit Count & Interval Steps. */
uint8_t period; /**< Publish Period. */
uint8_t period_div:4, /**< Divisor for the Period. */
cred:1, /**< Friendship Credentials Flag. */
send_rel:1,
fast_period:1,/**< Use FastPeriodDivisor */
count:3; /**< Retransmissions left. */
u32_t period_start; /**< Start of the current period. */
uint32_t period_start; /**< Start of the current period. */
/** @brief Publication buffer, containing the publication message.
*
* The application is expected to initialize this with
* a valid net_buf_simple pointer, with the help of e.g.
* a valid os_mbuf pointer, with the help of e.g.
* the NET_BUF_SIMPLE() macro. The publication buffer must
* contain a valid publication message before calling the
* bt_mesh_model_publish() API or after the publication's
@ -415,6 +425,10 @@ struct bt_mesh_model_pub {
* @ref bt_mesh_model_pub.msg with a valid publication
* message.
*
* If the callback returns non-zero, the publication is skipped
* and will resume on the next periodic publishing interval.
*
*
* @param mod The Model the Publication Context belogs to.
*
* @return Zero on success or (negative) error code otherwise.
@ -432,16 +446,18 @@ struct bt_mesh_model_cb {
* @sa settings_handler::h_set
*
* @param model Model to set the persistent data of.
* @param name Name/key of the settings item.
* @param val Data from the backend.
*
* @return 0 on success, error otherwise.
*/
int (*const settings_set)(struct bt_mesh_model *model, char *val);
int (*const settings_set)(struct bt_mesh_model *model,
const char *name, char *val);
/** @brief Callback called when all settings have been loaded.
/** @brief Callback called when the mesh is started.
*
* This handler gets called after the settings have been loaded in
* full.
* This handler gets called after the node has been provisioned, or
* after all mesh data has been loaded from persistent storage.
*
* @sa settings_handler::h_commit
*
@ -449,12 +465,17 @@ struct bt_mesh_model_cb {
*
* @return 0 on success, error otherwise.
*/
int (*const settings_commit)(struct bt_mesh_model *model);
int (*const start)(struct bt_mesh_model *model);
/** @brief Model init callback.
*
* Called on every model instance during mesh initialization.
*
*
* If any of the model init callbacks return an error, the Mesh
* subsystem initialization will be aborted, and the error will be
* returned to the caller of @ref bt_mesh_init.
*
* @param model Model to be initialized.
*
* @return 0 on success, error otherwise.
@ -466,6 +487,9 @@ struct bt_mesh_model_cb {
* Called when the mesh node is reset. All model data is deleted on
* reset, and the model should clear its state.
*
* @note If the model stores any persistent data, this needs to be
* erased manually.
*
* @param model Model this callback belongs to.
*/
void (*const reset)(struct bt_mesh_model *model);
@ -474,26 +498,26 @@ struct bt_mesh_model_cb {
/** Abstraction that describes a Mesh Model instance */
struct bt_mesh_model {
union {
const u16_t id;
const uint16_t id;
struct {
u16_t company;
u16_t id;
uint16_t company;
uint16_t id;
} vnd;
};
/* Internal information, mainly for persistent storage */
u8_t elem_idx; /* Belongs to Nth element */
u8_t mod_idx; /* Is the Nth model in the element */
u16_t flags; /* Model flags for internal bookkeeping */
uint8_t elem_idx; /* Belongs to Nth element */
uint8_t mod_idx; /* Is the Nth model in the element */
uint16_t flags; /* Model flags for internal bookkeeping */
/* Model Publication */
struct bt_mesh_model_pub * const pub;
/* AppKey List */
u16_t keys[CONFIG_BT_MESH_MODEL_KEY_COUNT];
uint16_t keys[CONFIG_BT_MESH_MODEL_KEY_COUNT];
/* Subscription List (group or virtual addresses) */
u16_t groups[CONFIG_BT_MESH_MODEL_GROUP_COUNT];
uint16_t groups[CONFIG_BT_MESH_MODEL_GROUP_COUNT];
const struct bt_mesh_model_op * const op;
@ -511,11 +535,11 @@ struct bt_mesh_model {
};
struct bt_mesh_send_cb {
void (*start)(u16_t duration, int err, void *cb_data);
void (*start)(uint16_t duration, int err, void *cb_data);
void (*end)(int err, void *cb_data);
};
void bt_mesh_model_msg_init(struct os_mbuf *msg, u32_t opcode);
void bt_mesh_model_msg_init(struct os_mbuf *msg, uint32_t opcode);
/** Special TTL value to request using configured default TTL */
#define BT_MESH_TTL_DEFAULT 0xff
@ -574,7 +598,7 @@ struct bt_mesh_elem *bt_mesh_model_elem(struct bt_mesh_model *mod);
* if no SIG model with the given ID exists in the given element.
*/
struct bt_mesh_model *bt_mesh_model_find(const struct bt_mesh_elem *elem,
u16_t id);
uint16_t id);
/** @brief Find a vendor model.
*
@ -586,7 +610,7 @@ struct bt_mesh_model *bt_mesh_model_find(const struct bt_mesh_elem *elem,
* if no vendor model with the given ID exists in the given element.
*/
struct bt_mesh_model *bt_mesh_model_find_vnd(const struct bt_mesh_elem *elem,
u16_t company, u16_t id);
uint16_t company, uint16_t id);
/** @brief Get whether the model is in the primary element of the device.
*
@ -603,13 +627,14 @@ static inline bool bt_mesh_model_in_primary(const struct bt_mesh_model *mod)
*
* @param mod Mesh model.
* @param vnd This is a vendor model.
* @param name Name/key of the settings item.
* @param data Model data to store, or NULL to delete any model data.
* @param data_len Length of the model data.
*
* @return 0 on success, or (negative) error code on failure.
*/
int bt_mesh_model_data_store(struct bt_mesh_model *mod, bool vnd,
const void *data, size_t data_len);
const char *name, const void *data, size_t data_len);
/** @brief Let a model extend another.
*
@ -637,9 +662,9 @@ int bt_mesh_model_extend(struct bt_mesh_model *mod,
/** Node Composition */
struct bt_mesh_comp {
u16_t cid;
u16_t pid;
u16_t vid;
uint16_t cid;
uint16_t pid;
uint16_t vid;
size_t elem_count;
struct bt_mesh_elem *elem;

View file

@ -0,0 +1,409 @@
/* atomic operations */
/*
* Copyright (c) 1997-2015, Wind River Systems, Inc.
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __ATOMIC_H__
#define __ATOMIC_H__
#ifdef __cplusplus
extern "C"
{
#endif
typedef int atomic_t;
typedef atomic_t atomic_val_t;
/**
* @defgroup atomic_apis Atomic Services APIs
* @ingroup kernel_apis
* @{
*/
/**
* @brief Atomic compare-and-set.
*
* This routine performs an atomic compare-and-set on @a target. If the current
* value of @a target equals @a old_value, @a target is set to @a new_value.
* If the current value of @a target does not equal @a old_value, @a target
* is left unchanged.
*
* @param target Address of atomic variable.
* @param old_value Original value to compare against.
* @param new_value New value to store.
* @return 1 if @a new_value is written, 0 otherwise.
*/
static inline int atomic_cas(atomic_t *target, atomic_val_t old_value,
atomic_val_t new_value)
{
return __atomic_compare_exchange_n(target, &old_value, new_value,
0, __ATOMIC_SEQ_CST,
__ATOMIC_SEQ_CST);
}
/**
*
* @brief Atomic addition.
*
* This routine performs an atomic addition on @a target.
*
* @param target Address of atomic variable.
* @param value Value to add.
*
* @return Previous value of @a target.
*/
static inline atomic_val_t atomic_add(atomic_t *target, atomic_val_t value)
{
return __atomic_fetch_add(target, value, __ATOMIC_SEQ_CST);
}
/**
*
* @brief Atomic subtraction.
*
* This routine performs an atomic subtraction on @a target.
*
* @param target Address of atomic variable.
* @param value Value to subtract.
*
* @return Previous value of @a target.
*/
static inline atomic_val_t atomic_sub(atomic_t *target, atomic_val_t value)
{
return __atomic_fetch_sub(target, value, __ATOMIC_SEQ_CST);
}
/**
*
* @brief Atomic increment.
*
* This routine performs an atomic increment by 1 on @a target.
*
* @param target Address of atomic variable.
*
* @return Previous value of @a target.
*/
static inline atomic_val_t atomic_inc(atomic_t *target)
{
return atomic_add(target, 1);
}
/**
*
* @brief Atomic decrement.
*
* This routine performs an atomic decrement by 1 on @a target.
*
* @param target Address of atomic variable.
*
* @return Previous value of @a target.
*/
static inline atomic_val_t atomic_dec(atomic_t *target)
{
return atomic_sub(target, 1);
}
/**
*
* @brief Atomic get.
*
* This routine performs an atomic read on @a target.
*
* @param target Address of atomic variable.
*
* @return Value of @a target.
*/
static inline atomic_val_t atomic_get(const atomic_t *target)
{
return __atomic_load_n(target, __ATOMIC_SEQ_CST);
}
/**
*
* @brief Atomic get-and-set.
*
* This routine atomically sets @a target to @a value and returns
* the previous value of @a target.
*
* @param target Address of atomic variable.
* @param value Value to write to @a target.
*
* @return Previous value of @a target.
*/
static inline atomic_val_t atomic_set(atomic_t *target, atomic_val_t value)
{
/* This builtin, as described by Intel, is not a traditional
* test-and-set operation, but rather an atomic exchange operation. It
* writes value into *ptr, and returns the previous contents of *ptr.
*/
return __atomic_exchange_n(target, value, __ATOMIC_SEQ_CST);
}
/**
*
* @brief Atomic clear.
*
* This routine atomically sets @a target to zero and returns its previous
* value. (Hence, it is equivalent to atomic_set(target, 0).)
*
* @param target Address of atomic variable.
*
* @return Previous value of @a target.
*/
static inline atomic_val_t atomic_clear(atomic_t *target)
{
return atomic_set(target, 0);
}
/**
*
* @brief Atomic bitwise inclusive OR.
*
* This routine atomically sets @a target to the bitwise inclusive OR of
* @a target and @a value.
*
* @param target Address of atomic variable.
* @param value Value to OR.
*
* @return Previous value of @a target.
*/
static inline atomic_val_t atomic_or(atomic_t *target, atomic_val_t value)
{
return __atomic_fetch_or(target, value, __ATOMIC_SEQ_CST);
}
/**
*
* @brief Atomic bitwise exclusive OR (XOR).
*
* This routine atomically sets @a target to the bitwise exclusive OR (XOR) of
* @a target and @a value.
*
* @param target Address of atomic variable.
* @param value Value to XOR
*
* @return Previous value of @a target.
*/
static inline atomic_val_t atomic_xor(atomic_t *target, atomic_val_t value)
{
return __atomic_fetch_xor(target, value, __ATOMIC_SEQ_CST);
}
/**
*
* @brief Atomic bitwise AND.
*
* This routine atomically sets @a target to the bitwise AND of @a target
* and @a value.
*
* @param target Address of atomic variable.
* @param value Value to AND.
*
* @return Previous value of @a target.
*/
static inline atomic_val_t atomic_and(atomic_t *target, atomic_val_t value)
{
return __atomic_fetch_and(target, value, __ATOMIC_SEQ_CST);
}
/**
*
* @brief Atomic bitwise NAND.
*
* This routine atomically sets @a target to the bitwise NAND of @a target
* and @a value. (This operation is equivalent to target = ~(target & value).)
*
* @param target Address of atomic variable.
* @param value Value to NAND.
*
* @return Previous value of @a target.
*/
static inline atomic_val_t atomic_nand(atomic_t *target, atomic_val_t value)
{
return __atomic_fetch_nand(target, value, __ATOMIC_SEQ_CST);
}
/**
* @brief Initialize an atomic variable.
*
* This macro can be used to initialize an atomic variable. For example,
* @code atomic_t my_var = ATOMIC_INIT(75); @endcode
*
* @param i Value to assign to atomic variable.
*/
#define ATOMIC_INIT(i) (i)
/**
* @cond INTERNAL_HIDDEN
*/
#define ATOMIC_BITS (sizeof(atomic_val_t) * 8)
#define ATOMIC_MASK(bit) (1 << ((bit) & (ATOMIC_BITS - 1)))
#define ATOMIC_ELEM(addr, bit) ((addr) + ((bit) / ATOMIC_BITS))
/**
* INTERNAL_HIDDEN @endcond
*/
/**
* @brief Define an array of atomic variables.
*
* This macro defines an array of atomic variables containing at least
* @a num_bits bits.
*
* @note
* If used from file scope, the bits of the array are initialized to zero;
* if used from within a function, the bits are left uninitialized.
*
* @param name Name of array of atomic variables.
* @param num_bits Number of bits needed.
*/
#define ATOMIC_DEFINE(name, num_bits) \
atomic_t name[1 + ((num_bits) - 1) / ATOMIC_BITS]
/**
* @brief Atomically test a bit.
*
* This routine tests whether bit number @a bit of @a target is set or not.
* The target may be a single atomic variable or an array of them.
*
* @param target Address of atomic variable or array.
* @param bit Bit number (starting from 0).
*
* @return 1 if the bit was set, 0 if it wasn't.
*/
static inline int
atomic_test_bit(const atomic_t *target, int bit)
{
atomic_val_t val = atomic_get(ATOMIC_ELEM(target, bit));
return (1 & (val >> (bit & (ATOMIC_BITS - 1))));
}
/**
* @brief Atomically test and clear a bit.
*
* Atomically clear bit number @a bit of @a target and return its old value.
* The target may be a single atomic variable or an array of them.
*
* @param target Address of atomic variable or array.
* @param bit Bit number (starting from 0).
*
* @return 1 if the bit was set, 0 if it wasn't.
*/
static inline int
atomic_test_and_clear_bit(atomic_t *target, int bit)
{
atomic_val_t mask = ATOMIC_MASK(bit);
atomic_val_t old;
old = atomic_and(ATOMIC_ELEM(target, bit), ~mask);
return (old & mask) != 0;
}
/**
* @brief Atomically set a bit.
*
* Atomically set bit number @a bit of @a target and return its old value.
* The target may be a single atomic variable or an array of them.
*
* @param target Address of atomic variable or array.
* @param bit Bit number (starting from 0).
*
* @return 1 if the bit was set, 0 if it wasn't.
*/
static inline int
atomic_test_and_set_bit(atomic_t *target, int bit)
{
atomic_val_t mask = ATOMIC_MASK(bit);
atomic_val_t old;
old = atomic_or(ATOMIC_ELEM(target, bit), mask);
return (old & mask) != 0;
}
/**
* @brief Atomically clear a bit.
*
* Atomically clear bit number @a bit of @a target.
* The target may be a single atomic variable or an array of them.
*
* @param target Address of atomic variable or array.
* @param bit Bit number (starting from 0).
*
* @return N/A
*/
static inline void
atomic_clear_bit(atomic_t *target, int bit)
{
atomic_val_t mask = ATOMIC_MASK(bit);
atomic_and(ATOMIC_ELEM(target, bit), ~mask);
}
/**
* @brief Atomically set a bit.
*
* Atomically set bit number @a bit of @a target.
* The target may be a single atomic variable or an array of them.
*
* @param target Address of atomic variable or array.
* @param bit Bit number (starting from 0).
*
* @return N/A
*/
static inline void
atomic_set_bit(atomic_t *target, int bit)
{
atomic_val_t mask = ATOMIC_MASK(bit);
atomic_or(ATOMIC_ELEM(target, bit), mask);
}
/**
* @brief Atomically set a bit to a given value.
*
* Atomically set bit number @a bit of @a target to value @a val.
* The target may be a single atomic variable or an array of them.
*
* @param target Address of atomic variable or array.
* @param bit Bit number (starting from 0).
* @param val true for 1, false for 0.
*
* @return N/A
*/
static inline void atomic_set_bit_to(atomic_t *target, int bit, bool val)
{
atomic_val_t mask = ATOMIC_MASK(bit);
if (val) {
(void)atomic_or(ATOMIC_ELEM(target, bit), mask);
} else {
(void)atomic_and(ATOMIC_ELEM(target, bit), ~mask);
}
}
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __ATOMIC_H__ */

View file

@ -0,0 +1,267 @@
/*
* Copyright (c) 2019 Tobias Svehagen
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _BLUETOOTH_MESH_CDB_H_
#define _BLUETOOTH_MESH_CDB_H_
#include "syscfg/syscfg.h"
#if MYNEWT_VAL(BLE_MESH_CDB)
#define NODE_COUNT CONFIG_BT_MESH_NODE_COUNT
#define SUBNET_COUNT CONFIG_BT_MESH_SUBNET_COUNT
#define APP_KEY_COUNT CONFIG_BT_MESH_APP_KEY_COUNT
#else
#define NODE_COUNT 0
#define SUBNET_COUNT 0
#define APP_KEY_COUNT 0
#endif
#include "atomic.h"
enum {
BT_MESH_CDB_NODE_CONFIGURED,
BT_MESH_CDB_NODE_BLACKLISTED,
BT_MESH_CDB_NODE_FLAG_COUNT
};
struct bt_mesh_cdb_node {
uint8_t uuid[16];
uint16_t addr;
uint16_t net_idx;
uint8_t num_elem;
uint8_t dev_key[16];
ATOMIC_DEFINE(flags, BT_MESH_CDB_NODE_FLAG_COUNT);
};
struct bt_mesh_cdb_subnet {
uint16_t net_idx;
bool kr_flag;
uint8_t kr_phase;
struct {
uint8_t net_key[16];
} keys[2];
};
struct bt_mesh_cdb_app_key {
uint16_t net_idx;
uint16_t app_idx;
struct {
uint8_t app_key[16];
} keys[2];
};
enum {
BT_MESH_CDB_VALID,
BT_MESH_CDB_SUBNET_PENDING,
BT_MESH_CDB_KEYS_PENDING,
BT_MESH_CDB_NODES_PENDING,
BT_MESH_CDB_IVU_IN_PROGRESS,
BT_MESH_CDB_FLAG_COUNT,
};
struct bt_mesh_cdb {
uint32_t iv_index;
ATOMIC_DEFINE(flags, BT_MESH_CDB_FLAG_COUNT);
struct bt_mesh_cdb_node nodes[NODE_COUNT];
struct bt_mesh_cdb_subnet subnets[SUBNET_COUNT];
struct bt_mesh_cdb_app_key app_keys[APP_KEY_COUNT];
};
extern struct bt_mesh_cdb bt_mesh_cdb;
/** @brief Create the Mesh Configuration Database.
*
* Create and initialize the Mesh Configuration Database. A primary subnet,
* ie one with NetIdx 0, will be added and the provided key will be used as
* NetKey for that subnet.
*
* @param key The NetKey to be used for the primary subnet.
*
* @return 0 on success or negative error code on failure.
*/
int bt_mesh_cdb_create(const uint8_t key[16]);
/** @brief Clear the Mesh Configuration Database.
*
* Remove all nodes, subnets and app-keys stored in the database and mark
* the database as invalid. The data will be cleared from persistent storage
* if CONFIG_BT_SETTINGS is enabled.
*/
void bt_mesh_cdb_clear(void);
/** @brief Set and store the IV Index and IV Update flag.
*
* The IV Index stored in the CDB will be the one used during provisioning
* of new nodes. This function is generally only used from inside the stack.
*
* This function will store the data to persistent storage if
* CONFIG_BT_SETTINGS is enabled.
*
* @param iv_index The new IV Index to use.
* @param iv_update True if there is an ongoing IV Update procedure.
*/
void bt_mesh_cdb_iv_update(uint32_t iv_index, bool iv_update);
/** @brief Allocate a node.
*
* Allocate a new node in the CDB.
*
* @param uuid UUID of the node.
* @param addr Address of the node's primary element. If 0, the lowest
* possible address available will be assigned to the node.
* @param num_elem Number of elements that the node has.
* @param net_idx NetIdx that the node was provisioned to.
*
* @return The new node or NULL if it cannot be allocated.
*/
struct bt_mesh_cdb_node *bt_mesh_cdb_node_alloc(const uint8_t uuid[16], uint16_t addr,
uint8_t num_elem, uint16_t net_idx);
/** @brief Delete a node.
*
* Delete a node from the CDB.
*
* @param node The node to be deleted.
* @param store If true, the node will be cleared from persistent storage.
*/
void bt_mesh_cdb_node_del(struct bt_mesh_cdb_node *node, bool store);
/** @brief Get a node by address.
*
* Try to find the node that has the provided address assigned to one of its
* elements.
*
* @param addr Address of the element to look for.
*
* @return The node that has an element with address addr or NULL if no such
* node exists.
*/
struct bt_mesh_cdb_node *bt_mesh_cdb_node_get(uint16_t addr);
/** @brief Store node to persistent storage.
*
* @param node Node to be stored.
*/
void bt_mesh_cdb_node_store(const struct bt_mesh_cdb_node *node);
enum {
BT_MESH_CDB_ITER_STOP = 0,
BT_MESH_CDB_ITER_CONTINUE,
};
/** @typedef bt_mesh_cdb_node_func_t
* @brief Node iterator callback.
*
* @param node Node found.
* @param user_data Data given.
*
* @return BT_MESH_CDB_ITER_CONTINUE to continue to iterate through the nodes
* or BT_MESH_CDB_ITER_STOP to stop.
*/
typedef uint8_t (*bt_mesh_cdb_node_func_t)(struct bt_mesh_cdb_node *node,
void *user_data);
/** @brief Node iterator.
*
* Iterate nodes in the Mesh Configuration Database. The callback function
* will only be called for valid, ie allocated, nodes.
*
* @param func Callback function.
* @param user_data Data to pass to the callback.
*/
void bt_mesh_cdb_node_foreach(bt_mesh_cdb_node_func_t func, void *user_data);
/** @brief Allocate a subnet.
*
* Allocate a new subnet in the CDB.
*
* @param net_idx NetIdx of the subnet.
*
* @return The new subnet or NULL if it cannot be allocated.
*/
struct bt_mesh_cdb_subnet *bt_mesh_cdb_subnet_alloc(uint16_t net_idx);
/** @brief Delete a subnet.
*
* Delete a subnet from the CDB.
*
* @param sub The subnet to be deleted.
* @param store If true, the subnet will be cleared from persistent storage.
*/
void bt_mesh_cdb_subnet_del(struct bt_mesh_cdb_subnet *sub, bool store);
/** @brief Get a subnet by NetIdx
*
* Try to find the subnet with the specified NetIdx.
*
* @param net_idx NetIdx of the subnet to look for.
*
* @return The subnet with the specified NetIdx or NULL if no such subnet
* exists.
*/
struct bt_mesh_cdb_subnet *bt_mesh_cdb_subnet_get(uint16_t net_idx);
/** @brief Store subnet to persistent storage.
*
* @param sub Subnet to be stored.
*/
void bt_mesh_cdb_subnet_store(const struct bt_mesh_cdb_subnet *sub);
/** @brief Get the flags for a subnet
*
* @param sub The subnet to get flags for.
*
* @return The flags for the subnet.
*/
uint8_t bt_mesh_cdb_subnet_flags(const struct bt_mesh_cdb_subnet *sub);
/** @brief Allocate an application key.
*
* Allocate a new application key in the CDB.
*
* @param net_idx NetIdx of NetKey that the application key is bound to.
* @param app_idx AppIdx of the application key.
*
* @return The new application key or NULL if it cannot be allocated.
*/
struct bt_mesh_cdb_app_key *bt_mesh_cdb_app_key_alloc(uint16_t net_idx,
uint16_t app_idx);
/** @brief Delete an application key.
*
* Delete an application key from the CDB.
*
* @param key The application key to be deleted.
* @param store If true, the key will be cleared from persistent storage.
*/
void bt_mesh_cdb_app_key_del(struct bt_mesh_cdb_app_key *key, bool store);
/** @brief Get an application key by AppIdx
*
* Try to find the application key with the specified AppIdx.
*
* @param app_idx AppIdx of the application key to look for.
*
* @return The application key with the specified AppIdx or NULL if no such key
* exists.
*/
struct bt_mesh_cdb_app_key *bt_mesh_cdb_app_key_get(uint16_t app_idx);
/** @brief Store application key to persistent storage.
*
* @param key Application key to be stored.
*/
void bt_mesh_cdb_app_key_store(const struct bt_mesh_cdb_app_key *key);
#endif /* ZEPHYR_INCLUDE_BLUETOOTH_MESH_CDB_H_ */

View file

@ -0,0 +1,485 @@
/** @file
* @brief Bluetooth Mesh Runtime Configuration APIs.
*/
/*
* Copyright (c) 2020 Nordic Semiconductor
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _BT_MESH_CFG_H_
#define _BT_MESH_CFG_H_
#include <stdbool.h>
#include <stddef.h>
#include <sys/types.h>
/**
* @brief Bluetooth Mesh Runtime Configuration API
* @defgroup bt_mesh_cfg Bluetooth Mesh Runtime Configuration
* @ingroup bt_mesh
* @{
*/
#ifdef __cplusplus
extern "C" {
#endif
/** Bluetooth Mesh Feature states */
enum bt_mesh_feat_state {
/** Feature is supported, but disabled. */
BT_MESH_FEATURE_DISABLED,
/** Feature is supported and enabled. */
BT_MESH_FEATURE_ENABLED,
/** Feature is not supported, and cannot be enabled. */
BT_MESH_FEATURE_NOT_SUPPORTED,
};
/* Legacy feature defines */
#define BT_MESH_RELAY_DISABLED BT_MESH_FEATURE_DISABLED
#define BT_MESH_RELAY_ENABLED BT_MESH_FEATURE_ENABLED
#define BT_MESH_RELAY_NOT_SUPPORTED BT_MESH_FEATURE_NOT_SUPPORTED
#define BT_MESH_BEACON_DISABLED BT_MESH_FEATURE_DISABLED
#define BT_MESH_BEACON_ENABLED BT_MESH_FEATURE_ENABLED
#define BT_MESH_GATT_PROXY_DISABLED BT_MESH_FEATURE_DISABLED
#define BT_MESH_GATT_PROXY_ENABLED BT_MESH_FEATURE_ENABLED
#define BT_MESH_GATT_PROXY_NOT_SUPPORTED BT_MESH_FEATURE_NOT_SUPPORTED
#define BT_MESH_FRIEND_DISABLED BT_MESH_FEATURE_DISABLED
#define BT_MESH_FRIEND_ENABLED BT_MESH_FEATURE_ENABLED
#define BT_MESH_FRIEND_NOT_SUPPORTED BT_MESH_FEATURE_NOT_SUPPORTED
#define BT_MESH_NODE_IDENTITY_STOPPED BT_MESH_FEATURE_DISABLED
#define BT_MESH_NODE_IDENTITY_RUNNING BT_MESH_FEATURE_ENABLED
#define BT_MESH_NODE_IDENTITY_NOT_SUPPORTED BT_MESH_FEATURE_NOT_SUPPORTED
/** @brief Enable or disable sending of the Secure Network Beacon.
*
* @param beacon New Secure Network Beacon state.
*/
void bt_mesh_beacon_set(bool beacon);
/** @brief Get the current Secure Network Beacon state.
*
* @returns Whether the Secure Network Beacon feature is enabled.
*/
bool bt_mesh_beacon_enabled(void);
/** @brief Set the default TTL value.
*
* The default TTL value is used when no explicit TTL value is set. Models will
* use the default TTL value when @ref bt_mesh_msg_ctx::send_ttl is
* @ref BT_MESH_TTL_DEFAULT.
*
* @param default_ttl The new default TTL value. Valid values are 0x00 and 0x02
* to @ref BT_MESH_TTL_MAX.
*
* @retval 0 Successfully set the default TTL value.
* @retval -EINVAL Invalid TTL value.
*/
int bt_mesh_default_ttl_set(uint8_t default_ttl);
/** @brief Get the current default TTL value.
*
* @return The current default TTL value.
*/
uint8_t bt_mesh_default_ttl_get(void);
/** @brief Set the Network Transmit parameters.
*
* The Network Transmit parameters determine the parameters local messages are
* transmitted with.
*
* @see BT_MESH_TRANSMIT
*
* @param xmit New Network Transmit parameters. Use @ref BT_MESH_TRANSMIT for
* encoding.
*/
void bt_mesh_net_transmit_set(uint8_t xmit);
/** @brief Get the current Network Transmit parameters.
*
* The @ref BT_MESH_TRANSMIT_COUNT and @ref BT_MESH_TRANSMIT_INT macros can be
* used to decode the Network Transmit parameters.
*
* @return The current Network Transmit parameters.
*/
uint8_t bt_mesh_net_transmit_get(void);
/** @brief Configure the Relay feature.
*
* Enable or disable the Relay feature, and configure the parameters to
* transmit relayed messages with.
*
* Support for the Relay feature must be enabled through the
* @c CONFIG_BT_MESH_RELAY configuration option.
*
* @see BT_MESH_TRANSMIT
*
* @param relay New Relay feature state. Must be one of
* @ref BT_MESH_FEATURE_ENABLED and
* @ref BT_MESH_FEATURE_DISABLED.
* @param xmit New Relay retransmit parameters. Use @ref BT_MESH_TRANSMIT for
* encoding.
*
* @retval 0 Successfully changed the Relay configuration.
* @retval -ENOTSUP The Relay feature is not supported.
* @retval -EINVAL Invalid parameter.
* @retval -EALREADY Already using the given parameters.
*/
int bt_mesh_relay_set(enum bt_mesh_feat_state relay, uint8_t xmit);
/** @brief Get the current Relay feature state.
*
* @returns The Relay feature state.
*/
enum bt_mesh_feat_state bt_mesh_relay_get(void);
/** @brief Get the current Relay Retransmit parameters.
*
* The @ref BT_MESH_TRANSMIT_COUNT and @ref BT_MESH_TRANSMIT_INT macros can be
* used to decode the Relay Retransmit parameters.
*
* @return The current Relay Retransmit parameters, or 0 if relay is not
* supported.
*/
uint8_t bt_mesh_relay_retransmit_get(void);
/** @brief Enable or disable the GATT Proxy feature.
*
* Support for the GATT Proxy feature must be enabled through the
* @c CONFIG_BT_MESH_GATT_PROXY configuration option.
*
* @note The GATT Proxy feature only controls a Proxy node's ability to relay
* messages to the mesh network. A node that supports GATT Proxy will
* still advertise Connectable Proxy beacons, even if the feature is
* disabled. The Proxy feature can only be fully disabled through compile
* time configuration.
*
* @param gatt_proxy New GATT Proxy state. Must be one of
* @ref BT_MESH_FEATURE_ENABLED and
* @ref BT_MESH_FEATURE_DISABLED.
*
* @retval 0 Successfully changed the GATT Proxy feature state.
* @retval -ENOTSUP The GATT Proxy feature is not supported.
* @retval -EINVAL Invalid parameter.
* @retval -EALREADY Already in the given state.
*/
int bt_mesh_gatt_proxy_set(enum bt_mesh_feat_state gatt_proxy);
/** @brief Get the current GATT Proxy state.
*
* @returns The GATT Proxy feature state.
*/
enum bt_mesh_feat_state bt_mesh_gatt_proxy_get(void);
/** @brief Enable or disable the Friend feature.
*
* Any active friendships will be terminated immediately if the Friend feature
* is disabled.
*
* Support for the Friend feature must be enabled through the
* @c CONFIG_BT_MESH_FRIEND configuration option.
*
* @param friendship New Friend feature state. Must be one of
* @ref BT_MESH_FEATURE_ENABLED and
* @ref BT_MESH_FEATURE_DISABLED.
*
* @retval 0 Successfully changed the Friend feature state.
* @retval -ENOTSUP The Friend feature is not supported.
* @retval -EINVAL Invalid parameter.
* @retval -EALREADY Already in the given state.
*/
int bt_mesh_friend_set(enum bt_mesh_feat_state friendship);
/** @brief Get the current Friend state.
*
* @returns The Friend feature state.
*/
enum bt_mesh_feat_state bt_mesh_friend_get(void);
/**
* @brief Bluetooth Mesh Subnet Configuration
* @defgroup bt_mesh_cfg_subnet Bluetooth Mesh Subnet Configuration
* @{
*/
/** @brief Add a Subnet.
*
* Adds a subnet with the given network index and network key to the list of
* known Subnets. All messages sent on the given Subnet will be processed by
* this node, and the node may send and receive Network Beacons on the given
* Subnet.
*
* @param net_idx Network index.
* @param key Root network key of the Subnet. All other keys are derived
* from this.
*
* @retval STATUS_SUCCESS The Subnet was successfully added.
* @retval STATUS_INSUFF_RESOURCES No room for this Subnet.
* @retval STATUS_UNSPECIFIED The Subnet couldn't be created for some reason.
*/
uint8_t bt_mesh_subnet_add(uint16_t net_idx, const uint8_t key[16]);
/** @brief Update the given Subnet.
*
* Starts the Key Refresh procedure for this Subnet by adding a second set of
* encryption keys. The Subnet will continue sending with the old key (but
* receiving messages using both) until the Subnet enters Key Refresh phase 2.
*
* This allows a network configurator to replace old network and application
* keys for the entire network, effectively removing access for all nodes that
* aren't given the new keys.
*
* @param net_idx Network index.
* @param key New root network key of the Subnet.
*
* @retval STATUS_SUCCESS The Subnet was updated with a second key.
* @retval STATUS_INVALID_NETKEY The NetIdx is unknown.
* @retval STATUS_IDX_ALREADY_STORED The @c key value is the same as the
* current key.
* @retval STATUS_CANNOT_UPDATE The Subnet cannot be updated for some reason.
*/
uint8_t bt_mesh_subnet_update(uint16_t net_idx, const uint8_t key[16]);
/** @brief Delete a Subnet.
*
* Removes the Subnet with the given network index from the node. The node will
* stop sending Network Beacons with the given Subnet, and can no longer
* process messages on this Subnet.
*
* All Applications bound to this Subnet are also deleted.
*
* @param net_idx Network index.
*
* @retval STATUS_SUCCESS The Subnet was deleted.
* @retval STATUS_INVALID_NETKEY The NetIdx is unknown.
*/
uint8_t bt_mesh_subnet_del(uint16_t net_idx);
/** @brief Check whether a Subnet is known.
*
* @param net_idx Network index
*
* @return true if a Subnet with the given index exists, false otherwise.
*/
bool bt_mesh_subnet_exists(uint16_t net_idx);
/** @brief Set the Subnet's Key Refresh phase.
*
* The Key Refresh procedure is started by updating the Subnet keys through
* @ref bt_mesh_subnet_update. This puts the Subnet in Key Refresh Phase 1.
* Once all nodes have received the new Subnet key, Key Refresh Phase 2 can be
* activated through this function to start transmitting with the new network
* key. Finally, to revoke the old key, set the Key Refresh Phase to 3. This
* removes the old keys from the node, and returns the Subnet back to normal
* single-key operation with the new key set.
*
* @param net_idx Network index.
* @param phase Pointer to the new Key Refresh phase. Will return the actual
* Key Refresh phase after updating.
*
* @retval STATUS_SUCCESS The Key Refresh phase of the Subnet was successfully
* changed.
* @retval STATUS_INVALID_NETKEY The NetIdx is unknown.
* @retval STATUS_CANNOT_UPDATE The given phase change is invalid.
*/
uint8_t bt_mesh_subnet_kr_phase_set(uint16_t net_idx, uint8_t *phase);
/** @brief Get the Subnet's Key Refresh phase.
*
* @param net_idx Network index.
* @param phase Pointer to the Key Refresh variable to fill.
*
* @retval STATUS_SUCCESS Successfully populated the @c phase variable.
* @retval STATUS_INVALID_NETKEY The NetIdx is unknown.
*/
uint8_t bt_mesh_subnet_kr_phase_get(uint16_t net_idx, uint8_t *phase);
/** @brief Set the Node Identity state of the Subnet.
*
* The Node Identity state of a Subnet determines whether the Subnet advertises
* connectable Node Identity beacons for Proxy Clients to connect to.
* Once started, the Node Identity beacon runs for 60 seconds, or until it is
* stopped.
*
* This function serves the same purpose as @ref bt_mesh_proxy_identity_enable,
* but only acts on a single Subnet.
*
* GATT Proxy support must be enabled through
* @option{CONFIG_BT_MESH_GATT_PROXY}.
*
* @param net_idx Network index.
* @param node_id New Node Identity state, must be either @ref
* BT_MESH_FEATURE_ENABLED or @ref BT_MESH_FEATURE_DISABLED.
*
* @retval STATUS_SUCCESS Successfully set the Node Identity state of the
* Subnet.
* @retval STATUS_INVALID_NETKEY The NetIdx is unknown.
* @retval STATUS_FEAT_NOT_SUPP The Node Identity feature is not supported.
* @retval STATUS_CANNOT_SET Couldn't set the Node Identity state.
*/
uint8_t bt_mesh_subnet_node_id_set(uint16_t net_idx,
enum bt_mesh_feat_state node_id);
/** @brief Get the Node Identity state of the Subnet.
*
* @param net_idx Network index.
* @param node_id Node Identity variable to fill.
*
* @retval STATUS_SUCCESS Successfully populated the @c node_id variable.
* @retval STATUS_INVALID_NETKEY The NetIdx is unknown.
*/
uint8_t bt_mesh_subnet_node_id_get(uint16_t net_idx,
enum bt_mesh_feat_state *node_id);
/** @brief Get a list of all known Subnet indexes.
*
* Builds a list of all known Subnet indexes in the @c net_idxs array.
* If the @c net_idxs array is smaller than the list of known Subnets, this
* function fills all available entries and returns @c -ENOMEM. In this
* case, the next @c max entries of the list can be read out by calling
* @code
* bt_mesh_subnets_get(list, max, max);
* @endcode
*
* Note that any changes to the Subnet list between calls to this function
* could change the order and number of entries in the list.
*
* @param net_idxs Array to fill.
* @param max Max number of indexes to return.
* @param skip Number of indexes to skip. Enables batched processing of the
* list.
*
* @return The number of indexes added to the @c net_idxs array, or @c -ENOMEM
* if the number of known Subnets exceeds the @c max parameter.
*/
ssize_t bt_mesh_subnets_get(uint16_t net_idxs[], size_t max, off_t skip);
/**
* @}
*/
/**
* @brief Bluetooth Mesh Application Configuration
* @defgroup bt_mesh_cfg_app Bluetooth Mesh Application Configuration
* @{
*/
/** @brief Add an Application key.
*
* Adds the Application with the given index to the list of known applications.
* Allows the node to send and receive model messages encrypted with this
* Application key.
*
* Every Application is bound to a specific Subnet. The node must know the
* Subnet the Application is bound to before it can add the Application.
*
* @param app_idx Application index.
* @param net_idx Network index the Application is bound to.
* @param key Application key value.
*
* @retval STATUS_SUCCESS The Application was successfully added.
* @retval STATUS_INVALID_NETKEY The NetIdx is unknown.
* @retval STATUS_INSUFF_RESOURCES There's no room for storing this
* Application.
* @retval STATUS_INVALID_BINDING This AppIdx is already bound to another
* Subnet.
* @retval STATUS_IDX_ALREADY_STORED This AppIdx is already stored with a
* different key value.
* @retval STATUS_CANNOT_SET Cannot set the Application key for some reason.
*/
uint8_t bt_mesh_app_key_add(uint16_t app_idx, uint16_t net_idx,
const uint8_t key[16]);
/** @brief Update an Application key.
*
* Update an Application with a second Application key, as part of the
* Key Refresh procedure of the bound Subnet. The node will continue
* transmitting with the old application key (but receiving on both) until the
* Subnet enters Key Refresh phase 2. Once the Subnet enters Key Refresh phase
* 3, the old application key will be deleted.
*
* @note The Application key can only be updated if the bound Subnet is in Key
* Refresh phase 1.
*
* @param app_idx Application index.
* @param net_idx Network index the Application is bound to, or
* @ref BT_MESH_KEY_ANY to skip the binding check.
* @param key New key value.
*
* @retval STATUS_SUCCESS The Application key was successfully updated.
* @retval STATUS_INVALID_NETKEY The NetIdx is unknown.
* @retval STATUS_INVALID_BINDING This AppIdx is not bound to the given NetIdx.
* @retval STATUS_CANNOT_UPDATE The Application key cannot be updated for some
* reason.
* @retval STATUS_IDX_ALREADY_STORED This AppIdx is already updated with a
* different key value.
*/
uint8_t bt_mesh_app_key_update(uint16_t app_idx, uint16_t net_idx,
const uint8_t key[16]);
/** @brief Delete an Application key.
*
* All models bound to this application will remove this binding.
* All models publishing with this application will stop publishing.
*
* @param app_idx Application index.
* @param net_idx Network index.
*
* @retval STATUS_SUCCESS The Application key was successfully deleted.
* @retval STATUS_INVALID_NETKEY The NetIdx is unknown.
* @retval STATUS_INVALID_BINDING This AppIdx is not bound to the given NetIdx.
*/
uint8_t bt_mesh_app_key_del(uint16_t app_idx, uint16_t net_idx);
/** @brief Check if an Application key is known.
*
* @param app_idx Application index.
*
* @return true if the Application is known, false otherwise.
*/
bool bt_mesh_app_key_exists(uint16_t app_idx);
/** @brief Get a list of all known Application key indexes.
*
* Builds a list of all Application indexes for the given network index in the
* @c app_idxs array. If the @c app_idxs array cannot fit all bound
* Applications, this function fills all available entries and returns @c
* -ENOMEM. In this case, the next @c max entries of the list can be read out
* by calling
* @code
* bt_mesh_app_keys_get(net_idx, list, max, max);
* @endcode
*
* Note that any changes to the Application key list between calls to this
* function could change the order and number of entries in the list.
*
* @param net_idx Network Index to get the Applications of, or @ref
* BT_MESH_KEY_ANY to get all Applications.
* @param app_idxs Array to fill.
* @param max Max number of indexes to return.
* @param skip Number of indexes to skip. Enables batched processing of the
* list.
*
* @return The number of indexes added to the @c app_idxs array, or @c -ENOMEM
* if the number of known Applications exceeds the @c max parameter.
*/
ssize_t bt_mesh_app_keys_get(uint16_t net_idx, uint16_t app_idxs[], size_t max,
off_t skip);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
/**
* @}
*/
#endif /* _BT_MESH_CFG_H_ */

View file

@ -26,7 +26,7 @@ struct bt_mesh_cfg_cli {
struct bt_mesh_model *model;
struct k_sem op_sync;
u32_t op_pending;
uint32_t op_pending;
void *op_param;
};
@ -37,45 +37,81 @@ extern const struct bt_mesh_model_cb bt_mesh_cfg_cli_cb;
BT_MESH_MODEL_CB(BT_MESH_MODEL_ID_CFG_CLI, bt_mesh_cfg_cli_op, NULL, \
cli_data, &bt_mesh_cfg_cli_cb)
int bt_mesh_cfg_comp_data_get(u16_t net_idx, u16_t addr, u8_t page,
u8_t *status, struct os_mbuf *comp);
int bt_mesh_cfg_node_reset(uint16_t net_idx, uint16_t addr, bool *status);
int bt_mesh_cfg_beacon_get(u16_t net_idx, u16_t addr, u8_t *status);
int bt_mesh_cfg_comp_data_get(uint16_t net_idx, uint16_t addr, uint8_t page,
uint8_t *status, struct os_mbuf *comp);
int bt_mesh_cfg_beacon_set(u16_t net_idx, u16_t addr, u8_t val, u8_t *status);
int bt_mesh_cfg_beacon_get(uint16_t net_idx, uint16_t addr, uint8_t *status);
int bt_mesh_cfg_ttl_get(u16_t net_idx, u16_t addr, u8_t *ttl);
int bt_mesh_cfg_beacon_set(uint16_t net_idx, uint16_t addr, uint8_t val, uint8_t *status);
int bt_mesh_cfg_ttl_set(u16_t net_idx, u16_t addr, u8_t val, u8_t *ttl);
int bt_mesh_cfg_ttl_get(uint16_t net_idx, uint16_t addr, uint8_t *ttl);
int bt_mesh_cfg_friend_get(u16_t net_idx, u16_t addr, u8_t *status);
int bt_mesh_cfg_ttl_set(uint16_t net_idx, uint16_t addr, uint8_t val, uint8_t *ttl);
int bt_mesh_cfg_friend_set(u16_t net_idx, u16_t addr, u8_t val, u8_t *status);
int bt_mesh_cfg_friend_get(uint16_t net_idx, uint16_t addr, uint8_t *status);
int bt_mesh_cfg_gatt_proxy_get(u16_t net_idx, u16_t addr, u8_t *status);
int bt_mesh_cfg_friend_set(uint16_t net_idx, uint16_t addr, uint8_t val, uint8_t *status);
int bt_mesh_cfg_gatt_proxy_set(u16_t net_idx, u16_t addr, u8_t val,
u8_t *status);
int bt_mesh_cfg_gatt_proxy_get(uint16_t net_idx, uint16_t addr, uint8_t *status);
int bt_mesh_cfg_relay_get(u16_t net_idx, u16_t addr, u8_t *status,
u8_t *transmit);
int bt_mesh_cfg_gatt_proxy_set(uint16_t net_idx, uint16_t addr, uint8_t val,
uint8_t *status);
int bt_mesh_cfg_relay_set(u16_t net_idx, u16_t addr, u8_t new_relay,
u8_t new_transmit, u8_t *status, u8_t *transmit);
int bt_mesh_cfg_net_transmit_get(uint16_t net_idx, uint16_t addr,
uint8_t *transmit);
int bt_mesh_cfg_net_key_add(u16_t net_idx, u16_t addr, u16_t key_net_idx,
const u8_t net_key[16], u8_t *status);
int bt_mesh_cfg_net_transmit_set(uint16_t net_idx, uint16_t addr,
uint8_t val, uint8_t *transmit);
int bt_mesh_cfg_app_key_add(u16_t net_idx, u16_t addr, u16_t key_net_idx,
u16_t key_app_idx, const u8_t app_key[16],
u8_t *status);
int bt_mesh_cfg_relay_get(uint16_t net_idx, uint16_t addr, uint8_t *status,
uint8_t *transmit);
int bt_mesh_cfg_mod_app_bind(u16_t net_idx, u16_t addr, u16_t elem_addr,
u16_t mod_app_idx, u16_t mod_id, u8_t *status);
int bt_mesh_cfg_relay_set(uint16_t net_idx, uint16_t addr, uint8_t new_relay,
uint8_t new_transmit, uint8_t *status, uint8_t *transmit);
int bt_mesh_cfg_mod_app_bind_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
u16_t mod_app_idx, u16_t mod_id, u16_t cid,
u8_t *status);
int bt_mesh_cfg_net_key_add(uint16_t net_idx, uint16_t addr, uint16_t key_net_idx,
const uint8_t net_key[16], uint8_t *status);
int bt_mesh_cfg_net_key_get(uint16_t net_idx, uint16_t addr, uint16_t *keys,
size_t *key_cnt);
int bt_mesh_cfg_net_key_del(uint16_t net_idx, uint16_t addr,
uint16_t key_net_idx, uint8_t *status);
int bt_mesh_cfg_app_key_add(uint16_t net_idx, uint16_t addr, uint16_t key_net_idx,
uint16_t key_app_idx, const uint8_t app_key[16],
uint8_t *status);
int bt_mesh_cfg_app_key_get(uint16_t net_idx, uint16_t addr, uint16_t key_net_idx,
uint8_t *status, uint16_t *keys, size_t *key_cnt);
int bt_mesh_cfg_app_key_del(uint16_t net_idx, uint16_t addr,
uint16_t key_net_idx, uint16_t key_app_idx, uint8_t *status);
int bt_mesh_cfg_mod_app_bind(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
uint16_t mod_app_idx, uint16_t mod_id, uint8_t *status);
int bt_mesh_cfg_mod_app_unbind(uint16_t net_idx, uint16_t addr,
uint16_t elem_addr, uint16_t mod_app_idx,
uint16_t mod_id, uint8_t *status);
int bt_mesh_cfg_mod_app_bind_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
uint16_t mod_app_idx, uint16_t mod_id, uint16_t cid,
uint8_t *status);
int bt_mesh_cfg_mod_app_unbind_vnd(uint16_t net_idx, uint16_t addr,
uint16_t elem_addr, uint16_t mod_app_idx, uint16_t mod_id,
uint16_t cid, uint8_t *status);
int bt_mesh_cfg_mod_app_get(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
uint16_t mod_id, uint8_t *status, uint16_t *apps,
size_t *app_cnt);
int bt_mesh_cfg_mod_app_get_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
uint16_t mod_id, uint16_t cid, uint8_t *status,
uint16_t *apps, size_t *app_cnt);
/** @def BT_MESH_PUB_PERIOD_100MS
*
@ -120,109 +156,117 @@ int bt_mesh_cfg_mod_app_bind_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
#define BT_MESH_PUB_PERIOD_10MIN(steps) (((steps) & BIT_MASK(6)) | (3 << 6))
struct bt_mesh_cfg_mod_pub {
u16_t addr;
u16_t app_idx;
uint16_t addr;
uint16_t app_idx;
bool cred_flag;
u8_t ttl;
u8_t period;
u8_t transmit;
uint8_t ttl;
uint8_t period;
uint8_t transmit;
};
int bt_mesh_cfg_mod_pub_get(u16_t net_idx, u16_t addr, u16_t elem_addr,
u16_t mod_id, struct bt_mesh_cfg_mod_pub *pub,
u8_t *status);
int bt_mesh_cfg_mod_pub_get(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
uint16_t mod_id, struct bt_mesh_cfg_mod_pub *pub,
uint8_t *status);
int bt_mesh_cfg_mod_pub_get_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
u16_t mod_id, u16_t cid,
struct bt_mesh_cfg_mod_pub *pub, u8_t *status);
int bt_mesh_cfg_mod_pub_get_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
uint16_t mod_id, uint16_t cid,
struct bt_mesh_cfg_mod_pub *pub, uint8_t *status);
int bt_mesh_cfg_mod_pub_set(u16_t net_idx, u16_t addr, u16_t elem_addr,
u16_t mod_id, struct bt_mesh_cfg_mod_pub *pub,
u8_t *status);
int bt_mesh_cfg_mod_pub_set(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
uint16_t mod_id, struct bt_mesh_cfg_mod_pub *pub,
uint8_t *status);
int bt_mesh_cfg_mod_pub_set_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
u16_t mod_id, u16_t cid,
struct bt_mesh_cfg_mod_pub *pub, u8_t *status);
int bt_mesh_cfg_mod_pub_set_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
uint16_t mod_id, uint16_t cid,
struct bt_mesh_cfg_mod_pub *pub, uint8_t *status);
int bt_mesh_cfg_mod_sub_add(u16_t net_idx, u16_t addr, u16_t elem_addr,
u16_t sub_addr, u16_t mod_id, u8_t *status);
int bt_mesh_cfg_mod_sub_add(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
uint16_t sub_addr, uint16_t mod_id, uint8_t *status);
int bt_mesh_cfg_mod_sub_add_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
u16_t sub_addr, u16_t mod_id, u16_t cid,
u8_t *status);
int bt_mesh_cfg_mod_sub_add_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
uint16_t sub_addr, uint16_t mod_id, uint16_t cid,
uint8_t *status);
int bt_mesh_cfg_mod_sub_del(u16_t net_idx, u16_t addr, u16_t elem_addr,
u16_t sub_addr, u16_t mod_id, u8_t *status);
int bt_mesh_cfg_mod_sub_del(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
uint16_t sub_addr, uint16_t mod_id, uint8_t *status);
int bt_mesh_cfg_mod_sub_del_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
u16_t sub_addr, u16_t mod_id, u16_t cid,
u8_t *status);
int bt_mesh_cfg_mod_sub_del_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
uint16_t sub_addr, uint16_t mod_id, uint16_t cid,
uint8_t *status);
int bt_mesh_cfg_mod_sub_overwrite(u16_t net_idx, u16_t addr, u16_t elem_addr,
u16_t sub_addr, u16_t mod_id, u8_t *status);
int bt_mesh_cfg_mod_sub_overwrite(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
uint16_t sub_addr, uint16_t mod_id, uint8_t *status);
int bt_mesh_cfg_mod_sub_overwrite_vnd(u16_t net_idx, u16_t addr,
u16_t elem_addr, u16_t sub_addr,
u16_t mod_id, u16_t cid, u8_t *status);
int bt_mesh_cfg_mod_sub_overwrite_vnd(uint16_t net_idx, uint16_t addr,
uint16_t elem_addr, uint16_t sub_addr,
uint16_t mod_id, uint16_t cid, uint8_t *status);
int bt_mesh_cfg_mod_sub_va_add(u16_t net_idx, u16_t addr, u16_t elem_addr,
const u8_t label[16], u16_t mod_id,
u16_t *virt_addr, u8_t *status);
int bt_mesh_cfg_mod_sub_va_add(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
const uint8_t label[16], uint16_t mod_id,
uint16_t *virt_addr, uint8_t *status);
int bt_mesh_cfg_mod_sub_va_add_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
const u8_t label[16], u16_t mod_id,
u16_t cid, u16_t *virt_addr, u8_t *status);
int bt_mesh_cfg_mod_sub_va_add_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
const uint8_t label[16], uint16_t mod_id,
uint16_t cid, uint16_t *virt_addr, uint8_t *status);
int bt_mesh_cfg_mod_sub_va_del(u16_t net_idx, u16_t addr, u16_t elem_addr,
const u8_t label[16], u16_t mod_id,
u16_t *virt_addr, u8_t *status);
int bt_mesh_cfg_mod_sub_va_del(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
const uint8_t label[16], uint16_t mod_id,
uint16_t *virt_addr, uint8_t *status);
int bt_mesh_cfg_mod_sub_va_del_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr,
const u8_t label[16], u16_t mod_id,
u16_t cid, u16_t *virt_addr, u8_t *status);
int bt_mesh_cfg_mod_sub_va_del_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
const uint8_t label[16], uint16_t mod_id,
uint16_t cid, uint16_t *virt_addr, uint8_t *status);
int bt_mesh_cfg_mod_sub_va_overwrite(u16_t net_idx, u16_t addr,
u16_t elem_addr, const u8_t label[16],
u16_t mod_id, u16_t *virt_addr,
u8_t *status);
int bt_mesh_cfg_mod_sub_va_overwrite(uint16_t net_idx, uint16_t addr,
uint16_t elem_addr, const uint8_t label[16],
uint16_t mod_id, uint16_t *virt_addr,
uint8_t *status);
int bt_mesh_cfg_mod_sub_va_overwrite_vnd(u16_t net_idx, u16_t addr,
u16_t elem_addr, const u8_t label[16],
u16_t mod_id, u16_t cid,
u16_t *virt_addr, u8_t *status);
int bt_mesh_cfg_mod_sub_va_overwrite_vnd(uint16_t net_idx, uint16_t addr,
uint16_t elem_addr, const uint8_t label[16],
uint16_t mod_id, uint16_t cid,
uint16_t *virt_addr, uint8_t *status);
int bt_mesh_cfg_mod_sub_get(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
uint16_t mod_id, uint8_t *status, uint16_t *subs,
size_t *sub_cnt);
int bt_mesh_cfg_mod_sub_get_vnd(uint16_t net_idx, uint16_t addr, uint16_t elem_addr,
uint16_t mod_id, uint16_t cid, uint8_t *status,
uint16_t *subs, size_t *sub_cnt);
struct bt_mesh_cfg_hb_sub {
u16_t src;
u16_t dst;
u8_t period;
u8_t count;
u8_t min;
u8_t max;
uint16_t src;
uint16_t dst;
uint8_t period;
uint8_t count;
uint8_t min;
uint8_t max;
};
int bt_mesh_cfg_hb_sub_set(u16_t net_idx, u16_t addr,
struct bt_mesh_cfg_hb_sub *sub, u8_t *status);
int bt_mesh_cfg_hb_sub_set(uint16_t net_idx, uint16_t addr,
struct bt_mesh_cfg_hb_sub *sub, uint8_t *status);
int bt_mesh_cfg_hb_sub_get(u16_t net_idx, u16_t addr,
struct bt_mesh_cfg_hb_sub *sub, u8_t *status);
int bt_mesh_cfg_hb_sub_get(uint16_t net_idx, uint16_t addr,
struct bt_mesh_cfg_hb_sub *sub, uint8_t *status);
struct bt_mesh_cfg_hb_pub {
u16_t dst;
u8_t count;
u8_t period;
u8_t ttl;
u16_t feat;
u16_t net_idx;
uint16_t dst;
uint8_t count;
uint8_t period;
uint8_t ttl;
uint16_t feat;
uint16_t net_idx;
};
int bt_mesh_cfg_hb_pub_set(u16_t net_idx, u16_t addr,
const struct bt_mesh_cfg_hb_pub *pub, u8_t *status);
int bt_mesh_cfg_hb_pub_set(uint16_t net_idx, uint16_t addr,
const struct bt_mesh_cfg_hb_pub *pub, uint8_t *status);
int bt_mesh_cfg_hb_pub_get(u16_t net_idx, u16_t addr,
struct bt_mesh_cfg_hb_pub *pub, u8_t *status);
int bt_mesh_cfg_hb_pub_get(uint16_t net_idx, uint16_t addr,
struct bt_mesh_cfg_hb_pub *pub, uint8_t *status);
s32_t bt_mesh_cfg_cli_timeout_get(void);
void bt_mesh_cfg_cli_timeout_set(s32_t timeout);
int32_t bt_mesh_cfg_cli_timeout_get(void);
void bt_mesh_cfg_cli_timeout_set(int32_t timeout);
#ifdef __cplusplus
}

View file

@ -21,51 +21,13 @@
extern "C" {
#endif
/** Mesh Configuration Server Model Context */
struct bt_mesh_cfg_srv {
struct bt_mesh_model *model;
u8_t net_transmit; /* Network Transmit state */
u8_t relay; /* Relay Mode state */
u8_t relay_retransmit; /* Relay Retransmit state */
u8_t beacon; /* Secure Network Beacon state */
u8_t gatt_proxy; /* GATT Proxy state */
u8_t frnd; /* Friend state */
u8_t default_ttl; /* Default TTL */
/* Heartbeat Publication */
struct bt_mesh_hb_pub {
struct k_delayed_work timer;
u16_t dst;
u16_t count;
u8_t period;
u8_t ttl;
u16_t feat;
u16_t net_idx;
} hb_pub;
/* Heartbeat Subscription */
struct bt_mesh_hb_sub {
s64_t expiry;
u16_t src;
u16_t dst;
u16_t count;
u8_t min_hops;
u8_t max_hops;
/* Optional subscription tracking function */
void (*func)(u8_t hops, u16_t feat);
} hb_sub;
};
extern const struct bt_mesh_model_op bt_mesh_cfg_srv_op[];
extern const struct bt_mesh_model_cb bt_mesh_cfg_srv_cb;
#define BT_MESH_MODEL_CFG_SRV(srv_data) \
#define BT_MESH_MODEL_CFG_SRV \
BT_MESH_MODEL_CB(BT_MESH_MODEL_ID_CFG_SRV, bt_mesh_cfg_srv_op, NULL, \
srv_data, &bt_mesh_cfg_srv_cb)
NULL, &bt_mesh_cfg_srv_cb)
#ifdef __cplusplus
}

View file

@ -51,15 +51,6 @@
extern "C" {
#endif
#define u8_t uint8_t
#define s8_t int8_t
#define u16_t uint16_t
#define s16_t int16_t
#define u32_t uint32_t
#define u64_t uint64_t
#define s64_t int64_t
#define s32_t int32_t
/** @brief Helper to declare elements of bt_data arrays
*
* This macro is mainly for creating an array of struct bt_data
@ -73,7 +64,7 @@ extern "C" {
{ \
.type = (_type), \
.data_len = (_data_len), \
.data = (const u8_t *)(_data), \
.data = (const uint8_t *)(_data), \
}
/** @brief Helper to declare elements of bt_data arrays
@ -85,8 +76,8 @@ extern "C" {
* @param _bytes Variable number of single-byte parameters
*/
#define BT_DATA_BYTES(_type, _bytes...) \
BT_DATA(_type, ((u8_t []) { _bytes }), \
sizeof((u8_t []) { _bytes }))
BT_DATA(_type, ((uint8_t []) { _bytes }), \
sizeof((uint8_t []) { _bytes }))
/* EIR/AD data type definitions */
#define BT_DATA_FLAGS 0x01 /* AD flags */
@ -119,9 +110,13 @@ extern "C" {
#define sys_put_be16(a,b) put_be16(b, a)
#define sys_put_le16(a,b) put_le16(b, a)
#define sys_put_le24(a,b) put_le24(b, a)
#define sys_put_be24(a,b) put_be24(b, a)
#define sys_put_be32(a,b) put_be32(b, a)
#define sys_get_be16(a) get_be16(a)
#define sys_get_be24(a) get_be24(a)
#define sys_get_le16(a) get_le16(a)
#define sys_get_le24(a) get_le24(a)
#define sys_get_be32(a) get_be32(a)
#define sys_cpu_to_be16(a) htobe16(a)
#define sys_cpu_to_be32(a) htobe32(a)
@ -196,9 +191,9 @@ typedef ble_addr_t bt_addr_le_t;
struct net_buf_simple_state {
/** Offset of the data pointer from the beginning of the storage */
u16_t offset;
uint16_t offset;
/** Length of data */
u16_t len;
uint16_t len;
};
static inline struct os_mbuf * NET_BUF_SIMPLE(uint16_t size)
@ -238,6 +233,14 @@ static inline void net_buf_simple_init(struct os_mbuf *buf,
buf->om_len = 0;
}
#define net_buf_simple_init_with_data(buf, data, size) \
os_mbuf_copyinto(buf, 0, data, size);
static inline void net_buf_simple_reset(struct os_mbuf *om)
{
net_buf_simple_init(om, 0);
}
void net_buf_put(struct ble_npl_eventq *fifo, struct os_mbuf *buf);
void * net_buf_ref(struct os_mbuf *om);
void net_buf_unref(struct os_mbuf *om);
@ -248,18 +251,20 @@ uint32_t net_buf_simple_pull_le32(struct os_mbuf *om);
uint8_t net_buf_simple_pull_u8(struct os_mbuf *om);
void net_buf_simple_add_le16(struct os_mbuf *om, uint16_t val);
void net_buf_simple_add_be16(struct os_mbuf *om, uint16_t val);
void net_buf_simple_add_le24(struct os_mbuf *om, uint32_t val);
void net_buf_simple_add_u8(struct os_mbuf *om, uint8_t val);
void net_buf_simple_add_be32(struct os_mbuf *om, uint32_t val);
void net_buf_simple_add_le32(struct os_mbuf *om, uint32_t val);
void net_buf_add_zeros(struct os_mbuf *om, uint8_t len);
void net_buf_simple_push_le16(struct os_mbuf *om, uint16_t val);
void net_buf_simple_push_be16(struct os_mbuf *om, uint16_t val);
void net_buf_simple_push_be24(struct os_mbuf *om, uint32_t val);
void net_buf_simple_push_u8(struct os_mbuf *om, uint8_t val);
void *net_buf_simple_pull(struct os_mbuf *om, uint8_t len);
void *net_buf_simple_pull_mem(struct os_mbuf *om, uint8_t len);
void *net_buf_simple_add(struct os_mbuf *om, uint8_t len);
bool k_fifo_is_empty(struct ble_npl_eventq *q);
void *net_buf_get(struct ble_npl_eventq *fifo,s32_t t);
void *net_buf_get(struct ble_npl_eventq *fifo,int32_t t);
uint8_t *net_buf_simple_push(struct os_mbuf *om, uint8_t len);
void net_buf_reserve(struct os_mbuf *om, size_t reserve);
@ -271,7 +276,7 @@ void net_buf_reserve(struct os_mbuf *om, size_t reserve);
#define net_buf_clone(a, b) os_mbuf_dup(a)
#define net_buf_add_be32(a, b) net_buf_simple_add_be32(a, b)
#define net_buf_add_be16(a, b) net_buf_simple_add_be16(a, b)
#define net_buf_pull(a, b) net_buf_simple_pull(a, b)
#define net_buf_pull(a, b) net_buf_simple_pull_mem(a, b)
#define net_buf_pull_mem(a, b) net_buf_simple_pull_mem(a, b)
#define net_buf_pull_u8(a) net_buf_simple_pull_u8(a)
#define net_buf_pull_be16(a) net_buf_simple_pull_be16(a)
@ -279,14 +284,16 @@ void net_buf_reserve(struct os_mbuf *om, size_t reserve);
#define BT_GATT_CCC_NOTIFY BLE_GATT_CHR_PROP_NOTIFY
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
/** Description of different data types that can be encoded into
* advertising data. Used to form arrays that are passed to the
* bt_le_adv_start() function.
*/
struct bt_data {
u8_t type;
u8_t data_len;
const u8_t *data;
uint8_t type;
uint8_t data_len;
const uint8_t *data;
};
struct bt_pub_key_cb {
@ -298,18 +305,24 @@ struct bt_pub_key_cb {
*
* @param key The local public key, or NULL in case of no key.
*/
void (*func)(const u8_t key[64]);
void (*func)(const uint8_t key[64]);
struct bt_pub_key_cb *_next;
};
typedef void (*bt_dh_key_cb_t)(const u8_t key[32]);
int bt_dh_key_gen(const u8_t remote_pk[64], bt_dh_key_cb_t cb);
typedef void (*bt_dh_key_cb_t)(const uint8_t key[32]);
int bt_dh_key_gen(const uint8_t remote_pk[64], bt_dh_key_cb_t cb);
int bt_pub_key_gen(struct bt_pub_key_cb *new_cb);
uint8_t *bt_pub_key_get(void);
int bt_rand(void *buf, size_t len);
const char * bt_hex(const void *buf, size_t len);
int bt_encrypt_be(const uint8_t *key, const uint8_t *plaintext, uint8_t *enc_data);
int bt_ccm_decrypt(const uint8_t key[16], uint8_t nonce[13], const uint8_t *enc_data,
size_t len, const uint8_t *aad, size_t aad_len,
uint8_t *plaintext, size_t mic_size);
int bt_ccm_encrypt(const uint8_t key[16], uint8_t nonce[13], const uint8_t *enc_data,
size_t len, const uint8_t *aad, size_t aad_len,
uint8_t *plaintext, size_t mic_size);
void bt_mesh_register_gatt(void);
int bt_le_adv_start(const struct ble_gap_adv_params *param,
const struct bt_data *ad, size_t ad_len,
@ -323,9 +336,10 @@ struct k_delayed_work {
void k_work_init(struct ble_npl_callout *work, ble_npl_event_fn handler);
void k_delayed_work_init(struct k_delayed_work *w, ble_npl_event_fn *f);
void k_delayed_work_cancel(struct k_delayed_work *w);
bool k_delayed_work_pending(struct k_delayed_work *w);
void k_delayed_work_submit(struct k_delayed_work *w, uint32_t ms);
int64_t k_uptime_get(void);
u32_t k_uptime_get_32(void);
uint32_t k_uptime_get_32(void);
void k_sleep(int32_t duration);
void k_work_submit(struct ble_npl_callout *w);
void k_work_add_arg(struct ble_npl_callout *w, void *arg);
@ -355,18 +369,18 @@ static inline void sys_memcpy_swap(void *dst, const void *src, size_t length)
src += length - 1;
for (; length > 0; length--) {
*((u8_t *)dst++) = *((u8_t *)src--);
*((uint8_t *)dst++) = *((uint8_t *)src--);
}
}
#define popcount(x) __builtin_popcount(x)
static inline unsigned int find_lsb_set(u32_t op)
static inline unsigned int find_lsb_set(uint32_t op)
{
return __builtin_ffs(op);
}
static inline unsigned int find_msb_set(u32_t op)
static inline unsigned int find_msb_set(uint32_t op)
{
if (!op)
return 0;
@ -378,6 +392,7 @@ static inline unsigned int find_msb_set(u32_t op)
#define CONFIG_BT_MESH_GATT_PROXY BLE_MESH_GATT_PROXY
#define CONFIG_BT_MESH_IV_UPDATE_TEST BLE_MESH_IV_UPDATE_TEST
#define CONFIG_BT_MESH_LOW_POWER BLE_MESH_LOW_POWER
#define CONFIG_BT_MESH_LPN_SUB_ALL_NODES_ADDR BLE_MESH_LPN_SUB_ALL_NODES_ADDR
#define CONFIG_BT_MESH_LPN_AUTO BLE_MESH_LPN_AUTO
#define CONFIG_BT_MESH_LPN_ESTABLISHMENT BLE_MESH_LPN_ESTABLISHMENT
#define CONFIG_BT_MESH_PB_ADV BLE_MESH_PB_ADV
@ -388,12 +403,14 @@ static inline unsigned int find_msb_set(u32_t op)
#define CONFIG_BT_SETTINGS BLE_MESH_SETTINGS
#define CONFIG_SETTINGS BLE_MESH_SETTINGS
#define CONFIG_BT_MESH_PROVISIONER BLE_MESH_PROVISIONER
#define CONFIG_BT_MESH_PROV_DEVICE BLE_MESH_PROV_DEVICE
/* Above flags are used with IS_ENABLED macro */
#define IS_ENABLED(config) MYNEWT_VAL(config)
#define CONFIG_BT_MESH_LPN_GROUPS MYNEWT_VAL(BLE_MESH_LPN_GROUPS)
#define CONFIG_BT_MESH_ADV_BUF_COUNT MYNEWT_VAL(BLE_MESH_ADV_BUF_COUNT)
#define CONFIG_BT_MESH_SEG_BUFS MYNEWT_VAL(BLE_MESH_SEG_BUFS )
#define CONFIG_BT_MESH_FRIEND_QUEUE_SIZE MYNEWT_VAL(BLE_MESH_FRIEND_QUEUE_SIZE)
#define CONFIG_BT_MESH_FRIEND_RECV_WIN MYNEWT_VAL(BLE_MESH_FRIEND_RECV_WIN)
#define CONFIG_BT_MESH_LPN_POLL_TIMEOUT MYNEWT_VAL(BLE_MESH_LPN_POLL_TIMEOUT)
@ -408,9 +425,24 @@ static inline unsigned int find_msb_set(u32_t op)
#define CONFIG_BT_MESH_STORE_TIMEOUT MYNEWT_VAL(BLE_MESH_STORE_TIMEOUT)
#define CONFIG_BT_MESH_IVU_DIVIDER MYNEWT_VAL(BLE_MESH_IVU_DIVIDER)
#define CONFIG_BT_DEVICE_NAME MYNEWT_VAL(BLE_MESH_DEVICE_NAME)
#define CONFIG_BT_RX_SEG_MAX MYNEWT_VAL(BLE_MESH_RX_SEG_MAX)
#define CONFIG_BT_MESH_TX_SEG_MAX MYNEWT_VAL(BLE_MESH_TX_SEG_MAX)
#define CONFIG_BT_MESH_RX_SEG_MAX MYNEWT_VAL(BLE_MESH_RX_SEG_MAX)
#define CONFIG_BT_MESH_RX_SEG_MSG_COUNT MYNEWT_VAL(BLE_MESH_RX_SEG_MSG_COUNT)
#define CONFIG_BT_MESH_LABEL_COUNT MYNEWT_VAL(BLE_MESH_LABEL_COUNT)
#define CONFIG_BT_MESH_NODE_COUNT MYNEWT_VAL(BLE_MESH_NODE_COUNT)
#define CONFIG_BT_MESH_NODE_COUNT MYNEWT_VAL(BLE_MESH_CDB_NODE_COUNT)
#define CONFIG_BT_GATT_PROXY_ENABLED MYNEWT_VAL(BLE_MESH_GATT_PROXY_ENABLED)
#define CONFIG_BT_MESH_DEFAULT_TTL MYNEWT_VAL(BLE_MESH_DEFAULT_TTL)
#define CONFIG_BT_MESH_NETWORK_TRANSMIT_COUNT MYNEWT_VAL(BLE_MESH_NETWORK_TRANSMIT_COUNT)
#define CONFIG_BT_MESH_NETWORK_TRANSMIT_INTERVAL MYNEWT_VAL(BLE_MESH_NETWORK_TRANSMIT_INTERVAL)
#define CONFIG_BT_MESH_RELAY_ENABLED MYNEWT_VAL(BLE_MESH_RELAY_ENABLED)
#define CONFIG_BT_MESH_RELAY_RETRANSMIT_INTERVAL MYNEWT_VAL(BLE_MESH_RELAY_RETRANSMIT_INTERVAL)
#define CONFIG_BT_MESH_BEACON_ENABLED MYNEWT_VAL(BLE_MESH_BEACON_ENABLED)
#define CONFIG_BT_MESH_FRIEND_ENABLED MYNEWT_VAL(BLE_MESH_FRIEND_ENABLED)
#define CONFIG_BT_MESH_RELAY MYNEWT_VAL(BLE_MESH_RELAY)
#define CONFIG_BT_MESH_RELAY_RETRANSMIT_COUNT MYNEWT_VAL(BLE_MESH_RELAY_RETRANSMIT_COUNT)
#define CONFIG_BT_MESH_GATT_PROXY_ENABLED MYNEWT_VAL(BLE_MESH_GATT_PROXY_ENABLED)
#define CONFIG_BT_MESH_CDB BLE_MESH_CDB
#define printk console_printf
@ -426,7 +458,7 @@ static inline void k_sem_init(struct k_sem *sem, unsigned int initial_count,
ble_npl_sem_init(sem, initial_count);
}
static inline int k_sem_take(struct k_sem *sem, s32_t timeout)
static inline int k_sem_take(struct k_sem *sem, int32_t timeout)
{
uint32_t ticks;
@ -448,8 +480,8 @@ static inline void k_sem_give(struct k_sem *sem)
static inline int net_buf_id(struct os_mbuf *buf)
{
struct os_mbuf_pool *pool = buf->om_omp;
u8_t *pool_start = (u8_t *)pool->omp_pool->mp_membuf_addr;
u8_t *buf_ptr = (u8_t *)buf;
uint8_t *pool_start = (uint8_t *)pool->omp_pool->mp_membuf_addr;
uint8_t *buf_ptr = (uint8_t *)buf;
return (buf_ptr - pool_start) / BUF_SIZE(pool);
}
@ -495,6 +527,46 @@ settings_load(void)
#define BUILD_ASSERT(cond) _Static_assert(cond, "")
/* Memory slabs/blocks */
/** Memory slab structure */
struct k_mem_slab {
/**
* _wait_q_t is not required now, as we don't implement zephyr timeouts -
* if slab couldn't be allocated, we simply return error
*/
uint32_t num_blocks; /** number of memory blocks available for allocation */
size_t block_size; /** size of single block */
/**
* buffer for blocks - must be alligned to N-byte, where N is a power of 2.
* Minimal size of buffer is num_blocks * block_size
*/
char *buffer;
char *free_list; /** list of free memory blocks */
uint32_t num_used; /** count of used memory blocks */
};
struct k_mem_block_id {
uint32_t pool : 8;
uint32_t level : 4;
uint32_t block : 20;
};
struct k_mem_block {
void *data;
struct k_mem_block_id id;
};
extern void k_mem_slab_free(struct k_mem_slab *slab, void **mem);
extern int k_mem_slab_alloc(struct k_mem_slab *slab, void **mem);
static inline uint32_t k_mem_slab_num_free_get(struct k_mem_slab *slab)
{
return slab->num_blocks - slab->num_used;
}
int create_free_list(struct k_mem_slab *slab);
#ifdef __cplusplus
}
#endif

View file

@ -25,12 +25,12 @@ extern "C" {
struct bt_mesh_health_cli {
struct bt_mesh_model *model;
void (*current_status)(struct bt_mesh_health_cli *cli, u16_t addr,
u8_t test_id, u16_t cid, u8_t *faults,
void (*current_status)(struct bt_mesh_health_cli *cli, uint16_t addr,
uint8_t test_id, uint16_t cid, uint8_t *faults,
size_t fault_count);
struct k_sem op_sync;
u32_t op_pending;
uint32_t op_pending;
void *op_param;
};
@ -43,32 +43,30 @@ extern const struct bt_mesh_model_cb bt_mesh_health_cli_cb;
int bt_mesh_health_cli_set(struct bt_mesh_model *model);
int bt_mesh_health_fault_get(u16_t net_idx, u16_t addr, u16_t app_idx,
u16_t cid, u8_t *test_id, u8_t *faults,
int bt_mesh_health_fault_get(uint16_t addr, uint16_t app_idx, uint16_t cid,
uint8_t *test_id, uint8_t *faults,
size_t *fault_count);
int bt_mesh_health_fault_clear(u16_t net_idx, u16_t addr, u16_t app_idx,
u16_t cid, u8_t *test_id, u8_t *faults,
int bt_mesh_health_fault_clear(uint16_t addr, uint16_t app_idx, uint16_t cid,
uint8_t *test_id, uint8_t *faults,
size_t *fault_count);
int bt_mesh_health_fault_test(u16_t net_idx, u16_t addr, u16_t app_idx,
u16_t cid, u8_t test_id, u8_t *faults,
int bt_mesh_health_fault_test(uint16_t addr, uint16_t app_idx, uint16_t cid,
uint8_t test_id, uint8_t *faults,
size_t *fault_count);
int bt_mesh_health_period_get(u16_t net_idx, u16_t addr, u16_t app_idx,
u8_t *divisor);
int bt_mesh_health_period_get(uint16_t addr, uint16_t app_idx, uint8_t *divisor);
int bt_mesh_health_period_set(u16_t net_idx, u16_t addr, u16_t app_idx,
u8_t divisor, u8_t *updated_divisor);
int bt_mesh_health_period_set(uint16_t addr, uint16_t app_idx, uint8_t divisor,
uint8_t *updated_divisor);
int bt_mesh_health_attention_get(u16_t net_idx, u16_t addr, u16_t app_idx,
u8_t *attention);
int bt_mesh_health_attention_get(uint16_t addr, uint16_t app_idx, uint8_t *attention);
int bt_mesh_health_attention_set(u16_t net_idx, u16_t addr, u16_t app_idx,
u8_t attention, u8_t *updated_attention);
int bt_mesh_health_attention_set(uint16_t addr, uint16_t app_idx, uint8_t attention,
uint8_t *updated_attention);
s32_t bt_mesh_health_cli_timeout_get(void);
void bt_mesh_health_cli_timeout_set(s32_t timeout);
int32_t bt_mesh_health_cli_timeout_get(void);
void bt_mesh_health_cli_timeout_set(int32_t timeout);
#ifdef __cplusplus
}

Some files were not shown because too many files have changed in this diff Show more