diff --git a/src/components/ble/BatteryInformationService.cpp b/src/components/ble/BatteryInformationService.cpp index f7d895c2..bc66ff72 100644 --- a/src/components/ble/BatteryInformationService.cpp +++ b/src/components/ble/BatteryInformationService.cpp @@ -1,3 +1,4 @@ +#include #include "BatteryInformationService.h" #include "components/battery/BatteryController.h" diff --git a/src/components/ble/CurrentTimeClient.cpp b/src/components/ble/CurrentTimeClient.cpp index be50fede..758f636c 100644 --- a/src/components/ble/CurrentTimeClient.cpp +++ b/src/components/ble/CurrentTimeClient.cpp @@ -1,5 +1,6 @@ #include "CurrentTimeClient.h" #include +#include #include "components/datetime/DateTimeController.h" using namespace Pinetime::Controllers; diff --git a/src/components/ble/CurrentTimeService.cpp b/src/components/ble/CurrentTimeService.cpp index 3a6264e2..9f14edc7 100644 --- a/src/components/ble/CurrentTimeService.cpp +++ b/src/components/ble/CurrentTimeService.cpp @@ -1,5 +1,6 @@ #include "CurrentTimeService.h" #include +#include using namespace Pinetime::Controllers; diff --git a/src/heartratetask/HeartRateTask.cpp b/src/heartratetask/HeartRateTask.cpp index 5a6d2a5e..95d7837e 100644 --- a/src/heartratetask/HeartRateTask.cpp +++ b/src/heartratetask/HeartRateTask.cpp @@ -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) { diff --git a/src/libs/mynewt-nimble/apps/README.md b/src/libs/mynewt-nimble/apps/README.md new file mode 100644 index 00000000..f36a836a --- /dev/null +++ b/src/libs/mynewt-nimble/apps/README.md @@ -0,0 +1,54 @@ + + +# 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. \ No newline at end of file diff --git a/src/libs/mynewt-nimble/apps/blemesh/src/main.c b/src/libs/mynewt-nimble/apps/blemesh/src/main.c index 24c9950e..65270554 100644 --- a/src/libs/mynewt-nimble/apps/blemesh/src/main.c +++ b/src/libs/mynewt-nimble/apps/blemesh/src/main.c @@ -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); } diff --git a/src/libs/mynewt-nimble/apps/blemesh_light/src/light_model.c b/src/libs/mynewt-nimble/apps/blemesh_light/src/light_model.c index 8b00e2c0..f666fe26 100644 --- a/src/libs/mynewt-nimble/apps/blemesh_light/src/light_model.c +++ b/src/libs/mynewt-nimble/apps/blemesh_light/src/light_model.c @@ -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); } diff --git a/src/libs/mynewt-nimble/apps/blemesh_light/src/light_model.h b/src/libs/mynewt-nimble/apps/blemesh_light/src/light_model.h index 7fcdd0c3..1f6f3c44 100644 --- a/src/libs/mynewt-nimble/apps/blemesh_light/src/light_model.h +++ b/src/libs/mynewt-nimble/apps/blemesh_light/src/light_model.h @@ -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 diff --git a/src/libs/mynewt-nimble/apps/blemesh_light/src/main.c b/src/libs/mynewt-nimble/apps/blemesh_light/src/main.c index 51d86eb5..70deede1 100644 --- a/src/libs/mynewt-nimble/apps/blemesh_light/src/main.c +++ b/src/libs/mynewt-nimble/apps/blemesh_light/src/main.c @@ -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; diff --git a/src/libs/mynewt-nimble/apps/blemesh_models_example_1/src/main.c b/src/libs/mynewt-nimble/apps/blemesh_models_example_1/src/main.c index ef398c9f..736d4d32 100644 --- a/src/libs/mynewt-nimble/apps/blemesh_models_example_1/src/main.c +++ b/src/libs/mynewt-nimble/apps/blemesh_models_example_1/src/main.c @@ -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); } diff --git a/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/ble_mesh.c b/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/ble_mesh.c index 86d4c515..021d8e08 100644 --- a/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/ble_mesh.c +++ b/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/ble_mesh.c @@ -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, diff --git a/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/device_composition.c b/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/device_composition.c index b638b861..5dfeaf8e 100644 --- a/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/device_composition.c +++ b/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/device_composition.c @@ -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, diff --git a/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/device_composition.h b/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/device_composition.h index 38507195..d0f054ee 100644 --- a/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/device_composition.h +++ b/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/device_composition.h @@ -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; }; diff --git a/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/main.c b/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/main.c index 7c8d65e6..741367b4 100644 --- a/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/main.c +++ b/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/main.c @@ -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); diff --git a/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/publisher.c b/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/publisher.c index 21364b81..f8cf849d 100644 --- a/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/publisher.c +++ b/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/publisher.c @@ -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); } diff --git a/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/state_binding.c b/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/state_binding.c index ae539433..0778f787 100644 --- a/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/state_binding.c +++ b/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/state_binding.c @@ -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; diff --git a/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/state_binding.h b/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/state_binding.h index db1f2a2e..0498e5c6 100644 --- a/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/state_binding.h +++ b/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/state_binding.h @@ -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 diff --git a/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/storage.c b/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/storage.c index 86fec7cc..d0ef980a 100644 --- a/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/storage.c +++ b/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/storage.c @@ -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); diff --git a/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/storage.h b/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/storage.h index e2905048..5e636f62 100644 --- a/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/storage.h +++ b/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/storage.h @@ -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 diff --git a/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/transition.c b/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/transition.c index c9463e10..e31af75d 100644 --- a/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/transition.c +++ b/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/transition.c @@ -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) { diff --git a/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/transition.h b/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/transition.h index 84101395..dc3e8da1 100644 --- a/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/transition.h +++ b/src/libs/mynewt-nimble/apps/blemesh_models_example_2/src/transition.h @@ -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); diff --git a/src/libs/mynewt-nimble/apps/blemesh_shell/src/main.c b/src/libs/mynewt-nimble/apps/blemesh_shell/src/main.c index 4ad23e1d..fcf80127 100644 --- a/src/libs/mynewt-nimble/apps/blemesh_shell/src/main.c +++ b/src/libs/mynewt-nimble/apps/blemesh_shell/src/main.c @@ -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); } diff --git a/src/libs/mynewt-nimble/apps/blestress/src/rx_stress.c b/src/libs/mynewt-nimble/apps/blestress/src/rx_stress.c index a4253ce6..440966ad 100644 --- a/src/libs/mynewt-nimble/apps/blestress/src/rx_stress.c +++ b/src/libs/mynewt-nimble/apps/blestress/src/rx_stress.c @@ -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) { - MODLOG_DFLT(INFO, "L2CAP stalled - waiting\n"); - stalled = true; + 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]); diff --git a/src/libs/mynewt-nimble/apps/blestress/src/stress.c b/src/libs/mynewt-nimble/apps/blestress/src/stress.c index 6f5badf0..1bdbafa9 100644 --- a/src/libs/mynewt-nimble/apps/blestress/src/stress.c +++ b/src/libs/mynewt-nimble/apps/blestress/src/stress.c @@ -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); diff --git a/src/libs/mynewt-nimble/apps/blestress/src/stress.h b/src/libs/mynewt-nimble/apps/blestress/src/stress.h index 91ab4f47..db4fbb36 100644 --- a/src/libs/mynewt-nimble/apps/blestress/src/stress.h +++ b/src/libs/mynewt-nimble/apps/blestress/src/stress.h @@ -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); diff --git a/src/libs/mynewt-nimble/apps/blestress/src/tx_stress.c b/src/libs/mynewt-nimble/apps/blestress/src/tx_stress.c index b73adc8a..4416c568 100644 --- a/src/libs/mynewt-nimble/apps/blestress/src/tx_stress.c +++ b/src/libs/mynewt-nimble/apps/blestress/src/tx_stress.c @@ -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; @@ -1415,7 +1414,7 @@ tx_stress_14_gap_event(struct ble_gap_event *event, void *arg) static int tx_stress_15_write_cb(uint16_t conn_handle, const struct ble_gatt_error *error, - struct ble_gatt_attr *attr, void *arg) + struct ble_gatt_attr *attr, void *arg) { /* Disconnect */ ble_gap_terminate(conn_handle, BLE_ERR_REM_USER_CONN_TERM); @@ -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; } @@ -1473,7 +1472,7 @@ tx_stress_15_gap_event(struct ble_gap_event *event, void *arg) return 0; default: - MODLOG_DFLT(INFO, "Other event occurs=%d\n", event->type); + MODLOG_DFLT(INFO, "Other event occurs=%d\n", event->type); 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; } diff --git a/src/libs/mynewt-nimble/apps/btshell/src/cmd.c b/src/libs/mynewt-nimble/apps/btshell/src/cmd.c index 2713443e..28aa87f2 100644 --- a/src/libs/mynewt-nimble/apps/btshell/src/cmd.c +++ b/src/libs/mynewt-nimble/apps/btshell/src/cmd.c @@ -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} diff --git a/src/libs/mynewt-nimble/apps/bttester/pkg.yml b/src/libs/mynewt-nimble/apps/bttester/pkg.yml index 00e7a760..ba2b7fb1 100644 --- a/src/libs/mynewt-nimble/apps/bttester/pkg.yml +++ b/src/libs/mynewt-nimble/apps/bttester/pkg.yml @@ -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" diff --git a/src/libs/mynewt-nimble/apps/bttester/src/bttester.c b/src/libs/mynewt-nimble/apps/bttester/src/bttester.c index 54b14daa..5ddc2954 100644 --- a/src/libs/mynewt-nimble/apps/bttester/src/bttester.c +++ b/src/libs/mynewt-nimble/apps/bttester/src/bttester.c @@ -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)); } diff --git a/src/libs/mynewt-nimble/apps/bttester/src/bttester.h b/src/libs/mynewt-nimble/apps/bttester/src/bttester.h index f4e66a6f..6761681e 100644 --- a/src/libs/mynewt-nimble/apps/bttester/src/bttester.h +++ b/src/libs/mynewt-nimble/apps/bttester/src/bttester.h @@ -71,37 +71,37 @@ #define sys_cpu_to_le16 htole16 struct btp_hdr { - u8_t service; - u8_t opcode; - u8_t index; - u16_t len; - u8_t data[0]; + uint8_t service; + uint8_t opcode; + uint8_t index; + uint16_t len; + uint8_t data[0]; } __packed; #define BTP_STATUS 0x00 struct btp_status { - u8_t code; + uint8_t code; } __packed; /* Core Service */ #define CORE_READ_SUPPORTED_COMMANDS 0x01 struct core_read_supported_commands_rp { - u8_t data[0]; + uint8_t data[0]; } __packed; #define CORE_READ_SUPPORTED_SERVICES 0x02 struct core_read_supported_services_rp { - u8_t data[0]; + uint8_t data[0]; } __packed; #define CORE_REGISTER_SERVICE 0x03 struct core_register_service_cmd { - u8_t id; + uint8_t id; } __packed; #define CORE_UNREGISTER_SERVICE 0x04 struct core_unregister_service_cmd { - u8_t id; + uint8_t id; } __packed; /* events */ @@ -111,13 +111,13 @@ struct core_unregister_service_cmd { /* commands */ #define GAP_READ_SUPPORTED_COMMANDS 0x01 struct gap_read_supported_commands_rp { - u8_t data[0]; + uint8_t data[0]; } __packed; #define GAP_READ_CONTROLLER_INDEX_LIST 0x02 struct gap_read_controller_index_list_rp { - u8_t num; - u8_t index[0]; + uint8_t num; + uint8_t index[0]; } __packed; #define GAP_SETTINGS_POWERED 0 @@ -139,41 +139,41 @@ struct gap_read_controller_index_list_rp { #define GAP_READ_CONTROLLER_INFO 0x03 struct gap_read_controller_info_rp { - u8_t address[6]; - u32_t supported_settings; - u32_t current_settings; - u8_t cod[3]; - u8_t name[249]; - u8_t short_name[11]; + uint8_t address[6]; + uint32_t supported_settings; + uint32_t current_settings; + uint8_t cod[3]; + uint8_t name[249]; + uint8_t short_name[11]; } __packed; #define GAP_RESET 0x04 struct gap_reset_rp { - u32_t current_settings; + uint32_t current_settings; } __packed; #define GAP_SET_POWERED 0x05 struct gap_set_powered_cmd { - u8_t powered; + uint8_t powered; } __packed; struct gap_set_powered_rp { - u32_t current_settings; + uint32_t current_settings; } __packed; #define GAP_SET_CONNECTABLE 0x06 struct gap_set_connectable_cmd { - u8_t connectable; + uint8_t connectable; } __packed; struct gap_set_connectable_rp { - u32_t current_settings; + uint32_t current_settings; } __packed; #define GAP_SET_FAST_CONNECTABLE 0x07 struct gap_set_fast_connectable_cmd { - u8_t fast_connectable; + uint8_t fast_connectable; } __packed; struct gap_set_fast_connectable_rp { - u32_t current_settings; + uint32_t current_settings; } __packed; #define GAP_NON_DISCOVERABLE 0x00 @@ -182,34 +182,34 @@ struct gap_set_fast_connectable_rp { #define GAP_SET_DISCOVERABLE 0x08 struct gap_set_discoverable_cmd { - u8_t discoverable; + uint8_t discoverable; } __packed; struct gap_set_discoverable_rp { - u32_t current_settings; + uint32_t current_settings; } __packed; #define GAP_SET_BONDABLE 0x09 struct gap_set_bondable_cmd { - u8_t bondable; + uint8_t bondable; } __packed; struct gap_set_bondable_rp { - u32_t current_settings; + uint32_t current_settings; } __packed; #define GAP_START_ADVERTISING 0x0a struct gap_start_advertising_cmd { - u8_t adv_data_len; - u8_t scan_rsp_len; - u8_t adv_data[0]; - u8_t scan_rsp[0]; + uint8_t adv_data_len; + uint8_t scan_rsp_len; + uint8_t adv_data[0]; + uint8_t scan_rsp[0]; } __packed; struct gap_start_advertising_rp { - u32_t current_settings; + uint32_t current_settings; } __packed; #define GAP_STOP_ADVERTISING 0x0b struct gap_stop_advertising_rp { - u32_t current_settings; + uint32_t current_settings; } __packed; #define GAP_DISCOVERY_FLAG_LE 0x01 @@ -220,21 +220,21 @@ struct gap_stop_advertising_rp { #define GAP_START_DISCOVERY 0x0c struct gap_start_discovery_cmd { - u8_t flags; + uint8_t flags; } __packed; #define GAP_STOP_DISCOVERY 0x0d #define GAP_CONNECT 0x0e struct gap_connect_cmd { - u8_t address_type; - u8_t address[6]; + uint8_t address_type; + uint8_t address[6]; } __packed; #define GAP_DISCONNECT 0x0f struct gap_disconnect_cmd { - u8_t address_type; - u8_t address[6]; + uint8_t address_type; + uint8_t address[6]; } __packed; #define GAP_IO_CAP_DISPLAY_ONLY 0 @@ -245,85 +245,85 @@ struct gap_disconnect_cmd { #define GAP_SET_IO_CAP 0x10 struct gap_set_io_cap_cmd { - u8_t io_cap; + uint8_t io_cap; } __packed; #define GAP_PAIR 0x11 struct gap_pair_cmd { - u8_t address_type; - u8_t address[6]; + uint8_t address_type; + uint8_t address[6]; } __packed; #define GAP_UNPAIR 0x12 struct gap_unpair_cmd { - u8_t address_type; - u8_t address[6]; + uint8_t address_type; + uint8_t address[6]; } __packed; #define GAP_PASSKEY_ENTRY 0x13 struct gap_passkey_entry_cmd { - u8_t address_type; - u8_t address[6]; - u32_t passkey; + uint8_t address_type; + uint8_t address[6]; + uint32_t passkey; } __packed; #define GAP_PASSKEY_CONFIRM 0x14 struct gap_passkey_confirm_cmd { - u8_t address_type; - u8_t address[6]; - u8_t match; + uint8_t address_type; + uint8_t address[6]; + uint8_t match; } __packed; #define GAP_START_DIRECT_ADV 0x15 struct gap_start_direct_adv_cmd { - u8_t address_type; - u8_t address[6]; - u8_t high_duty; + uint8_t address_type; + uint8_t address[6]; + uint8_t high_duty; } __packed; #define GAP_CONN_PARAM_UPDATE 0x16 struct gap_conn_param_update_cmd { - u8_t address_type; - u8_t address[6]; - u16_t conn_itvl_min; - u16_t conn_itvl_max; - u16_t conn_latency; - u16_t supervision_timeout; + uint8_t address_type; + uint8_t address[6]; + uint16_t conn_itvl_min; + uint16_t conn_itvl_max; + uint16_t conn_latency; + uint16_t supervision_timeout; } __packed; #define GAP_PAIRING_CONSENT_RSP 0x17 struct gap_pairing_consent_rsp_cmd { - u8_t address_type; - u8_t address[6]; - u8_t consent; + uint8_t address_type; + uint8_t address[6]; + uint8_t consent; } __packed; #define GAP_OOB_LEGACY_SET_DATA 0x18 struct gap_oob_legacy_set_data_cmd { - u8_t oob_data[16]; + uint8_t oob_data[16]; } __packed; #define GAP_OOB_SC_GET_LOCAL_DATA 0x19 struct gap_oob_sc_get_local_data_rp { - u8_t r[16]; - u8_t c[16]; + uint8_t r[16]; + uint8_t c[16]; } __packed; #define GAP_OOB_SC_SET_REMOTE_DATA 0x1a struct gap_oob_sc_set_remote_data_cmd { - u8_t r[16]; - u8_t c[16]; + uint8_t r[16]; + uint8_t c[16]; } __packed; #define GAP_SET_MITM 0x1b struct gap_set_mitm_cmd { - u8_t mitm; + uint8_t mitm; } __packed; /* events */ #define GAP_EV_NEW_SETTINGS 0x80 struct gap_new_settings_ev { - u32_t current_settings; + uint32_t current_settings; } __packed; #define GAP_DEVICE_FOUND_FLAG_RSSI 0x01 @@ -332,84 +332,84 @@ struct gap_new_settings_ev { #define GAP_EV_DEVICE_FOUND 0x81 struct gap_device_found_ev { - u8_t address_type; - u8_t address[6]; - s8_t rssi; - u8_t flags; - u16_t eir_data_len; - u8_t eir_data[0]; + uint8_t address_type; + uint8_t address[6]; + int8_t rssi; + uint8_t flags; + uint16_t eir_data_len; + uint8_t eir_data[0]; } __packed; #define GAP_EV_DEVICE_CONNECTED 0x82 struct gap_device_connected_ev { - u8_t address_type; - u8_t address[6]; - u16_t conn_itvl; - u16_t conn_latency; - u16_t supervision_timeout; + uint8_t address_type; + uint8_t address[6]; + uint16_t conn_itvl; + uint16_t conn_latency; + uint16_t supervision_timeout; } __packed; #define GAP_EV_DEVICE_DISCONNECTED 0x83 struct gap_device_disconnected_ev { - u8_t address_type; - u8_t address[6]; + uint8_t address_type; + uint8_t address[6]; } __packed; #define GAP_EV_PASSKEY_DISPLAY 0x84 struct gap_passkey_display_ev { - u8_t address_type; - u8_t address[6]; - u32_t passkey; + uint8_t address_type; + uint8_t address[6]; + uint32_t passkey; } __packed; #define GAP_EV_PASSKEY_ENTRY_REQ 0x85 struct gap_passkey_entry_req_ev { - u8_t address_type; - u8_t address[6]; + uint8_t address_type; + uint8_t address[6]; } __packed; #define GAP_EV_PASSKEY_CONFIRM_REQ 0x86 struct gap_passkey_confirm_req_ev { - u8_t address_type; - u8_t address[6]; - u32_t passkey; + uint8_t address_type; + uint8_t address[6]; + uint32_t passkey; } __packed; #define GAP_EV_IDENTITY_RESOLVED 0x87 struct gap_identity_resolved_ev { - u8_t address_type; - u8_t address[6]; - u8_t identity_address_type; - u8_t identity_address[6]; + uint8_t address_type; + uint8_t address[6]; + uint8_t identity_address_type; + uint8_t identity_address[6]; } __packed; #define GAP_EV_CONN_PARAM_UPDATE 0x88 struct gap_conn_param_update_ev { - u8_t address_type; - u8_t address[6]; - u16_t conn_itvl; - u16_t conn_latency; - u16_t supervision_timeout; + uint8_t address_type; + uint8_t address[6]; + uint16_t conn_itvl; + uint16_t conn_latency; + uint16_t supervision_timeout; } __packed; #define GAP_EV_SEC_LEVEL_CHANGED 0x89 struct gap_sec_level_changed_ev { - u8_t address_type; - u8_t address[6]; - u8_t level; + uint8_t address_type; + uint8_t address[6]; + uint8_t level; } __packed; #define GAP_EV_PAIRING_CONSENT_REQ 0x8a struct gap_pairing_consent_req_ev { - u8_t address_type; - u8_t address[6]; + uint8_t address_type; + uint8_t address[6]; } __packed; /* GATT Service */ /* commands */ #define GATT_READ_SUPPORTED_COMMANDS 0x01 struct gatt_read_supported_commands_rp { - u8_t data[0]; + uint8_t data[0]; } __packed; #define GATT_SERVICE_PRIMARY 0x00 @@ -417,320 +417,320 @@ struct gatt_read_supported_commands_rp { #define GATT_ADD_SERVICE 0x02 struct gatt_add_service_cmd { - u8_t type; - u8_t uuid_length; - u8_t uuid[0]; + uint8_t type; + uint8_t uuid_length; + uint8_t uuid[0]; } __packed; struct gatt_add_service_rp { - u16_t svc_id; + uint16_t svc_id; } __packed; #define GATT_ADD_CHARACTERISTIC 0x03 struct gatt_add_characteristic_cmd { - u16_t svc_id; - u8_t properties; - u8_t permissions; - u8_t uuid_length; - u8_t uuid[0]; + uint16_t svc_id; + uint8_t properties; + uint8_t permissions; + uint8_t uuid_length; + uint8_t uuid[0]; } __packed; struct gatt_add_characteristic_rp { - u16_t char_id; + uint16_t char_id; } __packed; #define GATT_ADD_DESCRIPTOR 0x04 struct gatt_add_descriptor_cmd { - u16_t char_id; - u8_t permissions; - u8_t uuid_length; - u8_t uuid[0]; + uint16_t char_id; + uint8_t permissions; + uint8_t uuid_length; + uint8_t uuid[0]; } __packed; struct gatt_add_descriptor_rp { - u16_t desc_id; + uint16_t desc_id; } __packed; #define GATT_ADD_INCLUDED_SERVICE 0x05 struct gatt_add_included_service_cmd { - u16_t svc_id; + uint16_t svc_id; } __packed; struct gatt_add_included_service_rp { - u16_t included_service_id; + uint16_t included_service_id; } __packed; #define GATT_SET_VALUE 0x06 struct gatt_set_value_cmd { - u16_t attr_id; - u16_t len; - u8_t value[0]; + uint16_t attr_id; + uint16_t len; + uint8_t value[0]; } __packed; #define GATT_START_SERVER 0x07 struct gatt_start_server_rp { - u16_t db_attr_off; - u8_t db_attr_cnt; + uint16_t db_attr_off; + uint8_t db_attr_cnt; } __packed; #define GATT_SET_ENC_KEY_SIZE 0x09 struct gatt_set_enc_key_size_cmd { - u16_t attr_id; - u8_t key_size; + uint16_t attr_id; + uint8_t key_size; } __packed; /* Gatt Client */ struct gatt_service { - u16_t start_handle; - u16_t end_handle; - u8_t uuid_length; - u8_t uuid[0]; + uint16_t start_handle; + uint16_t end_handle; + uint8_t uuid_length; + uint8_t uuid[0]; } __packed; struct gatt_included { - u16_t included_handle; + uint16_t included_handle; struct gatt_service service; } __packed; struct gatt_characteristic { - u16_t characteristic_handle; - u16_t value_handle; - u8_t properties; - u8_t uuid_length; - u8_t uuid[0]; + uint16_t characteristic_handle; + uint16_t value_handle; + uint8_t properties; + uint8_t uuid_length; + uint8_t uuid[0]; } __packed; struct gatt_descriptor { - u16_t descriptor_handle; - u8_t uuid_length; - u8_t uuid[0]; + uint16_t descriptor_handle; + uint8_t uuid_length; + uint8_t uuid[0]; } __packed; #define GATT_EXCHANGE_MTU 0x0a #define GATT_DISC_ALL_PRIM_SVCS 0x0b struct gatt_disc_all_prim_svcs_cmd { - u8_t address_type; - u8_t address[6]; + uint8_t address_type; + uint8_t address[6]; } __packed; struct gatt_disc_all_prim_svcs_rp { - u8_t services_count; + uint8_t services_count; struct gatt_service services[0]; } __packed; #define GATT_DISC_PRIM_UUID 0x0c struct gatt_disc_prim_uuid_cmd { - u8_t address_type; - u8_t address[6]; - u8_t uuid_length; - u8_t uuid[0]; + uint8_t address_type; + uint8_t address[6]; + uint8_t uuid_length; + uint8_t uuid[0]; } __packed; struct gatt_disc_prim_uuid_rp { - u8_t services_count; + uint8_t services_count; struct gatt_service services[0]; } __packed; #define GATT_FIND_INCLUDED 0x0d struct gatt_find_included_cmd { - u8_t address_type; - u8_t address[6]; - u16_t start_handle; - u16_t end_handle; + uint8_t address_type; + uint8_t address[6]; + uint16_t start_handle; + uint16_t end_handle; } __packed; struct gatt_find_included_rp { - u8_t services_count; + uint8_t services_count; struct gatt_included included[0]; } __packed; #define GATT_DISC_ALL_CHRC 0x0e struct gatt_disc_all_chrc_cmd { - u8_t address_type; - u8_t address[6]; - u16_t start_handle; - u16_t end_handle; + uint8_t address_type; + uint8_t address[6]; + uint16_t start_handle; + uint16_t end_handle; } __packed; struct gatt_disc_chrc_rp { - u8_t characteristics_count; + uint8_t characteristics_count; struct gatt_characteristic characteristics[0]; } __packed; #define GATT_DISC_CHRC_UUID 0x0f struct gatt_disc_chrc_uuid_cmd { - u8_t address_type; - u8_t address[6]; - u16_t start_handle; - u16_t end_handle; - u8_t uuid_length; - u8_t uuid[0]; + uint8_t address_type; + uint8_t address[6]; + uint16_t start_handle; + uint16_t end_handle; + uint8_t uuid_length; + uint8_t uuid[0]; } __packed; #define GATT_DISC_ALL_DESC 0x10 struct gatt_disc_all_desc_cmd { - u8_t address_type; - u8_t address[6]; - u16_t start_handle; - u16_t end_handle; + uint8_t address_type; + uint8_t address[6]; + uint16_t start_handle; + uint16_t end_handle; } __packed; struct gatt_disc_all_desc_rp { - u8_t descriptors_count; + uint8_t descriptors_count; struct gatt_descriptor descriptors[0]; } __packed; #define GATT_READ 0x11 struct gatt_read_cmd { - u8_t address_type; - u8_t address[6]; - u16_t handle; + uint8_t address_type; + uint8_t address[6]; + uint16_t handle; } __packed; struct gatt_read_rp { - u8_t att_response; - u16_t data_length; - u8_t data[0]; + uint8_t att_response; + uint16_t data_length; + uint8_t data[0]; } __packed; #define GATT_READ_UUID 0x12 struct gatt_read_uuid_cmd { - u8_t address_type; - u8_t address[6]; - u16_t start_handle; - u16_t end_handle; - u8_t uuid_length; - u8_t uuid[0]; + uint8_t address_type; + uint8_t address[6]; + uint16_t start_handle; + uint16_t end_handle; + uint8_t uuid_length; + uint8_t uuid[0]; } __packed; #define GATT_READ_LONG 0x13 struct gatt_read_long_cmd { - u8_t address_type; - u8_t address[6]; - u16_t handle; - u16_t offset; + uint8_t address_type; + uint8_t address[6]; + uint16_t handle; + uint16_t offset; } __packed; #define GATT_READ_MULTIPLE 0x14 struct gatt_read_multiple_cmd { - u8_t address_type; - u8_t address[6]; - u8_t handles_count; - u16_t handles[0]; + uint8_t address_type; + uint8_t address[6]; + uint8_t handles_count; + uint16_t handles[0]; } __packed; #define GATT_WRITE_WITHOUT_RSP 0x15 struct gatt_write_without_rsp_cmd { - u8_t address_type; - u8_t address[6]; - u16_t handle; - u16_t data_length; - u8_t data[0]; + uint8_t address_type; + uint8_t address[6]; + uint16_t handle; + uint16_t data_length; + uint8_t data[0]; } __packed; #define GATT_SIGNED_WRITE_WITHOUT_RSP 0x16 struct gatt_signed_write_without_rsp_cmd { - u8_t address_type; - u8_t address[6]; - u16_t handle; - u16_t data_length; - u8_t data[0]; + uint8_t address_type; + uint8_t address[6]; + uint16_t handle; + uint16_t data_length; + uint8_t data[0]; } __packed; #define GATT_WRITE 0x17 struct gatt_write_cmd { - u8_t address_type; - u8_t address[6]; - u16_t handle; - u16_t data_length; - u8_t data[0]; + uint8_t address_type; + uint8_t address[6]; + uint16_t handle; + uint16_t data_length; + uint8_t data[0]; } __packed; #define GATT_WRITE_LONG 0x18 struct gatt_write_long_cmd { - u8_t address_type; - u8_t address[6]; - u16_t handle; - u16_t offset; - u16_t data_length; - u8_t data[0]; + uint8_t address_type; + uint8_t address[6]; + uint16_t handle; + uint16_t offset; + uint16_t data_length; + uint8_t data[0]; } __packed; #define GATT_RELIABLE_WRITE 0x19 struct gatt_reliable_write_cmd { - u8_t address_type; - u8_t address[6]; - u16_t handle; - u16_t offset; - u16_t data_length; - u8_t data[0]; + uint8_t address_type; + uint8_t address[6]; + uint16_t handle; + uint16_t offset; + uint16_t data_length; + uint8_t data[0]; } __packed; #define GATT_CFG_NOTIFY 0x1a #define GATT_CFG_INDICATE 0x1b struct gatt_cfg_notify_cmd { - u8_t address_type; - u8_t address[6]; - u8_t enable; - u16_t ccc_handle; + uint8_t address_type; + uint8_t address[6]; + uint8_t enable; + uint16_t ccc_handle; } __packed; #define GATT_GET_ATTRIBUTES 0x1c struct gatt_get_attributes_cmd { - u16_t start_handle; - u16_t end_handle; - u8_t type_length; - u8_t type[0]; + uint16_t start_handle; + uint16_t end_handle; + uint8_t type_length; + uint8_t type[0]; } __packed; struct gatt_get_attributes_rp { - u8_t attrs_count; - u8_t attrs[0]; + uint8_t attrs_count; + uint8_t attrs[0]; } __packed; struct gatt_attr { - u16_t handle; - u8_t permission; - u8_t type_length; - u8_t type[0]; + uint16_t handle; + uint8_t permission; + uint8_t type_length; + uint8_t type[0]; } __packed; #define GATT_GET_ATTRIBUTE_VALUE 0x1d struct gatt_get_attribute_value_cmd { - u8_t address_type; - u8_t address[6]; - u16_t handle; + uint8_t address_type; + uint8_t address[6]; + uint16_t handle; } __packed; struct gatt_get_attribute_value_rp { - u8_t att_response; - u16_t value_length; - u8_t value[0]; + uint8_t att_response; + uint16_t value_length; + uint8_t value[0]; } __packed; #define GATT_CHANGE_DATABASE 0x1e struct gatt_change_database { - u16_t start_handle; - u16_t end_handle; - u8_t visibility; + uint16_t start_handle; + uint16_t end_handle; + uint8_t visibility; } __packed; /* GATT events */ #define GATT_EV_NOTIFICATION 0x80 struct gatt_notification_ev { - u8_t address_type; - u8_t address[6]; - u8_t type; - u16_t handle; - u16_t data_length; - u8_t data[0]; + uint8_t address_type; + uint8_t address[6]; + uint8_t type; + uint16_t handle; + uint16_t data_length; + uint8_t data[0]; } __packed; #define GATT_EV_ATTR_VALUE_CHANGED 0x81 struct gatt_attr_value_changed_ev { - u16_t handle; - u16_t data_length; - u8_t data[0]; + uint16_t handle; + uint16_t data_length; + uint8_t data[0]; } __packed; -static inline void tester_set_bit(u8_t *addr, unsigned int bit) +static inline void tester_set_bit(uint8_t *addr, unsigned int bit) { - u8_t *p = addr + (bit / 8); + uint8_t *p = addr + (bit / 8); *p |= BIT(bit % 8); } -static inline u8_t tester_test_bit(const u8_t *addr, unsigned int bit) +static inline uint8_t tester_test_bit(const uint8_t *addr, unsigned int bit) { - const u8_t *p = addr + (bit / 8); + const uint8_t *p = addr + (bit / 8); return *p & BIT(bit % 8); } @@ -739,30 +739,33 @@ static inline u8_t tester_test_bit(const u8_t *addr, unsigned int bit) /* commands */ #define L2CAP_READ_SUPPORTED_COMMANDS 0x01 struct l2cap_read_supported_commands_rp { - u8_t data[0]; + uint8_t data[0]; } __packed; #define L2CAP_CONNECT 0x02 struct l2cap_connect_cmd { - u8_t address_type; - u8_t address[6]; - u16_t psm; + uint8_t address_type; + uint8_t address[6]; + uint16_t psm; + uint16_t mtu; + uint8_t num; } __packed; struct l2cap_connect_rp { - u8_t chan_id; + uint8_t num; + uint8_t chan_ids[0]; } __packed; #define L2CAP_DISCONNECT 0x03 struct l2cap_disconnect_cmd { - u8_t chan_id; + uint8_t chan_id; } __packed; #define L2CAP_SEND_DATA 0x04 struct l2cap_send_data_cmd { - u8_t chan_id; - u16_t data_len; - u8_t data[]; + uint8_t chan_id; + uint16_t data_len; + uint8_t data[]; } __packed; #define L2CAP_TRANSPORT_BREDR 0x00 @@ -770,54 +773,78 @@ struct l2cap_send_data_cmd { #define L2CAP_LISTEN 0x05 struct l2cap_listen_cmd { - u16_t psm; - u8_t transport; + uint16_t psm; + uint8_t transport; + uint16_t mtu; + uint16_t response; } __packed; #define L2CAP_ACCEPT_CONNECTION 0x06 struct l2cap_accept_connection_cmd { - u8_t chan_id; - u16_t result; + uint8_t chan_id; + uint16_t result; +} __packed; + +#define L2CAP_RECONFIGURE 0x07 +struct l2cap_reconfigure_cmd { + uint8_t address_type; + uint8_t address[6]; + uint16_t mtu; + uint8_t num; + uint8_t idxs[]; } __packed; /* events */ #define L2CAP_EV_CONNECTION_REQ 0x80 struct l2cap_connection_req_ev { - u8_t chan_id; - u16_t psm; - u8_t address_type; - u8_t address[6]; + uint8_t chan_id; + uint16_t psm; + uint8_t address_type; + uint8_t address[6]; } __packed; #define L2CAP_EV_CONNECTED 0x81 struct l2cap_connected_ev { - u8_t chan_id; - u16_t psm; - u8_t address_type; - u8_t address[6]; + uint8_t chan_id; + uint16_t psm; + uint16_t peer_mtu; + uint16_t peer_mps; + uint16_t our_mtu; + uint16_t our_mps; + uint8_t address_type; + uint8_t address[6]; } __packed; #define L2CAP_EV_DISCONNECTED 0x82 struct l2cap_disconnected_ev { - u16_t result; - u8_t chan_id; - u16_t psm; - u8_t address_type; - u8_t address[6]; + uint16_t result; + uint8_t chan_id; + uint16_t psm; + uint8_t address_type; + uint8_t address[6]; } __packed; #define L2CAP_EV_DATA_RECEIVED 0x83 struct l2cap_data_received_ev { - u8_t chan_id; - u16_t data_length; - u8_t data[0]; + uint8_t chan_id; + uint16_t data_length; + uint8_t data[0]; +} __packed; + +#define L2CAP_EV_RECONFIGURED 0x84 +struct l2cap_reconfigured_ev { + uint8_t chan_id; + uint16_t peer_mtu; + uint16_t peer_mps; + uint16_t our_mtu; + uint16_t our_mps; } __packed; /* MESH Service */ /* commands */ #define MESH_READ_SUPPORTED_COMMANDS 0x01 struct mesh_read_supported_commands_rp { - u8_t data[0]; + uint8_t data[0]; } __packed; #define MESH_OUT_BLINK BIT(0) @@ -833,88 +860,88 @@ struct mesh_read_supported_commands_rp { #define MESH_CONFIG_PROVISIONING 0x02 struct mesh_config_provisioning_cmd { - u8_t uuid[16]; - u8_t static_auth[16]; - u8_t out_size; - u16_t out_actions; - u8_t in_size; - u16_t in_actions; + uint8_t uuid[16]; + uint8_t static_auth[16]; + uint8_t out_size; + uint16_t out_actions; + uint8_t in_size; + uint16_t in_actions; } __packed; #define MESH_PROVISION_NODE 0x03 struct mesh_provision_node_cmd { - u8_t net_key[16]; - u16_t net_key_idx; - u8_t flags; - u32_t iv_index; - u32_t seq_num; - u16_t addr; - u8_t dev_key[16]; + uint8_t net_key[16]; + uint16_t net_key_idx; + uint8_t flags; + uint32_t iv_index; + uint32_t seq_num; + uint16_t addr; + uint8_t dev_key[16]; } __packed; #define MESH_INIT 0x04 #define MESH_RESET 0x05 #define MESH_INPUT_NUMBER 0x06 struct mesh_input_number_cmd { - u32_t number; + uint32_t number; } __packed; #define MESH_INPUT_STRING 0x07 struct mesh_input_string_cmd { - u8_t string_len; - u8_t string[0]; + uint8_t string_len; + uint8_t string[0]; } __packed; #define MESH_IVU_TEST_MODE 0x08 struct mesh_ivu_test_mode_cmd { - u8_t enable; + uint8_t enable; } __packed; #define MESH_IVU_TOGGLE_STATE 0x09 #define MESH_NET_SEND 0x0a struct mesh_net_send_cmd { - u8_t ttl; - u16_t src; - u16_t dst; - u8_t payload_len; - u8_t payload[0]; + uint8_t ttl; + uint16_t src; + uint16_t dst; + uint8_t payload_len; + uint8_t payload[0]; } __packed; #define MESH_HEALTH_GENERATE_FAULTS 0x0b struct mesh_health_generate_faults_rp { - u8_t test_id; - u8_t cur_faults_count; - u8_t reg_faults_count; - u8_t current_faults[0]; - u8_t registered_faults[0]; + uint8_t test_id; + uint8_t cur_faults_count; + uint8_t reg_faults_count; + uint8_t current_faults[0]; + uint8_t registered_faults[0]; } __packed; #define MESH_HEALTH_CLEAR_FAULTS 0x0c #define MESH_LPN 0x0d struct mesh_lpn_set_cmd { - u8_t enable; + uint8_t enable; } __packed; #define MESH_LPN_POLL 0x0e #define MESH_MODEL_SEND 0x0f struct mesh_model_send_cmd { - u16_t src; - u16_t dst; - u8_t payload_len; - u8_t payload[0]; + uint16_t src; + uint16_t dst; + uint8_t payload_len; + uint8_t payload[0]; } __packed; #define MESH_LPN_SUBSCRIBE 0x10 struct mesh_lpn_subscribe_cmd { - u16_t address; + uint16_t address; } __packed; #define MESH_LPN_UNSUBSCRIBE 0x11 struct mesh_lpn_unsubscribe_cmd { - u16_t address; + uint16_t address; } __packed; #define MESH_RPL_CLEAR 0x12 @@ -923,20 +950,20 @@ struct mesh_lpn_unsubscribe_cmd { /* events */ #define MESH_EV_OUT_NUMBER_ACTION 0x80 struct mesh_out_number_action_ev { - u16_t action; - u32_t number; + uint16_t action; + uint32_t number; } __packed; #define MESH_EV_OUT_STRING_ACTION 0x81 struct mesh_out_string_action_ev { - u8_t string_len; - u8_t string[0]; + uint8_t string_len; + uint8_t string[0]; } __packed; #define MESH_EV_IN_ACTION 0x82 struct mesh_in_action_ev { - u16_t action; - u8_t size; + uint16_t action; + uint8_t size; } __packed; #define MESH_EV_PROVISIONED 0x83 @@ -945,63 +972,63 @@ struct mesh_in_action_ev { #define MESH_PROV_BEARER_PB_GATT 0x01 #define MESH_EV_PROV_LINK_OPEN 0x84 struct mesh_prov_link_open_ev { - u8_t bearer; + uint8_t bearer; } __packed; #define MESH_EV_PROV_LINK_CLOSED 0x85 struct mesh_prov_link_closed_ev { - u8_t bearer; + uint8_t bearer; } __packed; #define MESH_EV_NET_RECV 0x86 struct mesh_net_recv_ev { - u8_t ttl; - u8_t ctl; - u16_t src; - u16_t dst; - u8_t payload_len; - u8_t payload[0]; + uint8_t ttl; + uint8_t ctl; + uint16_t src; + uint16_t dst; + uint8_t payload_len; + uint8_t payload[0]; } __packed; #define MESH_EV_INVALID_BEARER 0x87 struct mesh_invalid_bearer_ev { - u8_t opcode; + uint8_t opcode; } __packed; #define MESH_EV_INCOMP_TIMER_EXP 0x88 void tester_init(void); -void tester_rsp(u8_t service, u8_t opcode, u8_t index, u8_t status); -void tester_send(u8_t service, u8_t opcode, u8_t index, u8_t *data, +void tester_rsp(uint8_t service, uint8_t opcode, uint8_t index, uint8_t status); +void tester_send(uint8_t service, uint8_t opcode, uint8_t index, uint8_t *data, size_t len); -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 *buf); -u8_t tester_init_gap(void); -u8_t tester_unregister_gap(void); -void tester_handle_gap(u8_t opcode, u8_t index, u8_t *data, - u16_t len); -u8_t tester_init_gatt(void); -u8_t tester_unregister_gatt(void); -void tester_handle_gatt(u8_t opcode, u8_t index, u8_t *data, - u16_t len); -int tester_gatt_notify_rx_ev(u16_t conn_handle, u16_t attr_handle, - u8_t indication, struct os_mbuf *om); -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); +uint8_t tester_init_gap(void); +uint8_t tester_unregister_gap(void); +void tester_handle_gap(uint8_t opcode, uint8_t index, uint8_t *data, + uint16_t len); +uint8_t tester_init_gatt(void); +uint8_t tester_unregister_gatt(void); +void tester_handle_gatt(uint8_t opcode, uint8_t index, uint8_t *data, + uint16_t len); +int tester_gatt_notify_rx_ev(uint16_t conn_handle, uint16_t attr_handle, + uint8_t indication, struct os_mbuf *om); +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); #if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) -u8_t tester_init_l2cap(void); -u8_t tester_unregister_l2cap(void); -void tester_handle_l2cap(u8_t opcode, u8_t index, u8_t *data, - u16_t len); +uint8_t tester_init_l2cap(void); +uint8_t tester_unregister_l2cap(void); +void tester_handle_l2cap(uint8_t opcode, uint8_t index, uint8_t *data, + uint16_t len); #endif #if MYNEWT_VAL(BLE_MESH) -u8_t tester_init_mesh(void); -u8_t tester_unregister_mesh(void); -void tester_handle_mesh(u8_t opcode, u8_t index, u8_t *data, u16_t len); +uint8_t tester_init_mesh(void); +uint8_t tester_unregister_mesh(void); +void tester_handle_mesh(uint8_t opcode, uint8_t index, uint8_t *data, uint16_t len); #endif /* MYNEWT_VAL(BLE_MESH) */ void gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg); diff --git a/src/libs/mynewt-nimble/apps/bttester/src/bttester_pipe.h b/src/libs/mynewt-nimble/apps/bttester/src/bttester_pipe.h index c54d42de..64b63cd6 100644 --- a/src/libs/mynewt-nimble/apps/bttester/src/bttester_pipe.h +++ b/src/libs/mynewt-nimble/apps/bttester/src/bttester_pipe.h @@ -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); diff --git a/src/libs/mynewt-nimble/apps/bttester/src/gap.c b/src/libs/mynewt-nimble/apps/bttester/src/gap.c index 9d6de043..acac9989 100644 --- a/src/libs/mynewt-nimble/apps/bttester/src/gap.c +++ b/src/libs/mynewt-nimble/apps/bttester/src/gap.c @@ -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; } diff --git a/src/libs/mynewt-nimble/apps/bttester/src/gatt.c b/src/libs/mynewt-nimble/apps/bttester/src/gatt.c index 7e7d1d3b..d40de262 100644 --- a/src/libs/mynewt-nimble/apps/bttester/src/gatt.c +++ b/src/libs/mynewt-nimble/apps/bttester/src/gatt.c @@ -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(¬ify_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; } diff --git a/src/libs/mynewt-nimble/apps/bttester/src/glue.c b/src/libs/mynewt-nimble/apps/bttester/src/glue.c index 6cd7643c..3e606062 100644 --- a/src/libs/mynewt-nimble/apps/bttester/src/glue.c +++ b/src/libs/mynewt-nimble/apps/bttester/src/glue.c @@ -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; diff --git a/src/libs/mynewt-nimble/apps/bttester/src/glue.h b/src/libs/mynewt-nimble/apps/bttester/src/glue.h index e563331e..65085601 100644 --- a/src/libs/mynewt-nimble/apps/bttester/src/glue.h +++ b/src/libs/mynewt-nimble/apps/bttester/src/glue.h @@ -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); diff --git a/src/libs/mynewt-nimble/apps/bttester/src/l2cap.c b/src/libs/mynewt-nimble/apps/bttester/src/l2cap.c index 45b904a1..5c4fc712 100644 --- a/src/libs/mynewt-nimble/apps/bttester/src/l2cap.c +++ b/src/libs/mynewt-nimble/apps/bttester/src/l2cap.c @@ -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; - } - - chan = &channels[i]; - chan->chan_id = i; - - return chan; + if (status != 0) { + return; } - return NULL; + channel = find_channel(chan); + assert(channel != NULL); + + 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; + + 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); - channel = get_free_channel(); - if (!channel) { - assert(0); + if (channel == NULL) { + channel = get_free_channel(); } - 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) { - channel->state = 0; - channel->chan = chan; + assert(channel != NULL); - ev.chan_id = channel->chan_id; - /* TODO: ev.result */ - /* TODO: ev.psm */ - } + channel->state = 0; + channel->chan = chan; + ev.chan_id = channel->chan_id; + 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: + 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; } - chan = get_free_channel(); - if (!chan) { - SYS_LOG_ERR("No free channels"); + 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; + } + + 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), + 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; } - sdu_rx = os_mbuf_get_pkthdr(&sdu_os_mbuf_pool, 0); - if (sdu_rx == NULL) { - SYS_LOG_ERR("Failed to alloc buf"); - goto fail; - } - - rc = ble_l2cap_connect(desc.conn_handle, htole16(cmd->psm), - TESTER_COC_MTU, sdu_rx, - tester_l2cap_event, chan); 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; } diff --git a/src/libs/mynewt-nimble/apps/bttester/src/mesh.c b/src/libs/mynewt-nimble/apps/bttester/src/mesh.c index e18a2a4e..8226fe99 100644 --- a/src/libs/mynewt-nimble/apps/bttester/src/mesh.c +++ b/src/libs/mynewt-nimble/apps/bttester/src/mesh.c @@ -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 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; } diff --git a/src/libs/mynewt-nimble/apps/bttester/src/rtt_pipe.c b/src/libs/mynewt-nimble/apps/bttester/src/rtt_pipe.c index 379345a0..4e667709 100644 --- a/src/libs/mynewt-nimble/apps/bttester/src/rtt_pipe.c +++ b/src/libs/mynewt-nimble/apps/bttester/src/rtt_pipe.c @@ -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; diff --git a/src/libs/mynewt-nimble/apps/bttester/src/uart_pipe.c b/src/libs/mynewt-nimble/apps/bttester/src/uart_pipe.c index ecbefa02..1118d9af 100644 --- a/src/libs/mynewt-nimble/apps/bttester/src/uart_pipe.c +++ b/src/libs/mynewt-nimble/apps/bttester/src/uart_pipe.c @@ -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; diff --git a/src/libs/mynewt-nimble/apps/bttester/syscfg.yml b/src/libs/mynewt-nimble/apps/bttester/syscfg.yml index d0fffe13..db869c34 100644 --- a/src/libs/mynewt-nimble/apps/bttester/syscfg.yml +++ b/src/libs/mynewt-nimble/apps/bttester/syscfg.yml @@ -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 diff --git a/src/libs/mynewt-nimble/apps/central/pkg.yml b/src/libs/mynewt-nimble/apps/central/pkg.yml new file mode 100755 index 00000000..c10ad933 --- /dev/null +++ b/src/libs/mynewt-nimble/apps/central/pkg.yml @@ -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 " + +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" diff --git a/src/libs/mynewt-nimble/apps/central/src/main.c b/src/libs/mynewt-nimble/apps/central/src/main.c new file mode 100755 index 00000000..b2370359 --- /dev/null +++ b/src/libs/mynewt-nimble/apps/central/src/main.c @@ -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; +} diff --git a/src/libs/mynewt-nimble/apps/mesh_badge/README.md b/src/libs/mynewt-nimble/apps/mesh_badge/README.md new file mode 100644 index 00000000..8d2b3fa3 --- /dev/null +++ b/src/libs/mynewt-nimble/apps/mesh_badge/README.md @@ -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 " 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 diff --git a/src/libs/mynewt-nimble/apps/mesh_badge/pkg.yml b/src/libs/mynewt-nimble/apps/mesh_badge/pkg.yml new file mode 100644 index 00000000..0718236f --- /dev/null +++ b/src/libs/mynewt-nimble/apps/mesh_badge/pkg.yml @@ -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 " +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 diff --git a/src/libs/mynewt-nimble/apps/mesh_badge/src/board.h b/src/libs/mynewt-nimble/apps/mesh_badge/src/board.h new file mode 100644 index 00000000..af77e0b4 --- /dev/null +++ b/src/libs/mynewt-nimble/apps/mesh_badge/src/board.h @@ -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); diff --git a/src/libs/mynewt-nimble/apps/mesh_badge/src/gatt_svr.c b/src/libs/mynewt-nimble/apps/mesh_badge/src/gatt_svr.c new file mode 100644 index 00000000..c6005a68 --- /dev/null +++ b/src/libs/mynewt-nimble/apps/mesh_badge/src/gatt_svr.c @@ -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 +#include +#include + +#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; +} diff --git a/src/libs/mynewt-nimble/apps/mesh_badge/src/main.c b/src/libs/mynewt-nimble/apps/mesh_badge/src/main.c new file mode 100644 index 00000000..d856d816 --- /dev/null +++ b/src/libs/mynewt-nimble/apps/mesh_badge/src/main.c @@ -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; +} diff --git a/src/libs/mynewt-nimble/apps/mesh_badge/src/mesh.c b/src/libs/mynewt-nimble/apps/mesh_badge/src/mesh.c new file mode 100644 index 00000000..ee999172 --- /dev/null +++ b/src/libs/mynewt-nimble/apps/mesh_badge/src/mesh.c @@ -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); +} diff --git a/src/libs/mynewt-nimble/apps/mesh_badge/src/mesh.h b/src/libs/mynewt-nimble/apps/mesh_badge/src/mesh.h new file mode 100644 index 00000000..33ee7cd2 --- /dev/null +++ b/src/libs/mynewt-nimble/apps/mesh_badge/src/mesh.h @@ -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); diff --git a/src/libs/mynewt-nimble/apps/mesh_badge/src/mesh_badge.h b/src/libs/mynewt-nimble/apps/mesh_badge/src/mesh_badge.h new file mode 100644 index 00000000..a156f1ce --- /dev/null +++ b/src/libs/mynewt-nimble/apps/mesh_badge/src/mesh_badge.h @@ -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 *); + diff --git a/src/libs/mynewt-nimble/apps/mesh_badge/src/reel_board.c b/src/libs/mynewt-nimble/apps/mesh_badge/src/reel_board.c new file mode 100644 index 00000000..bc822937 --- /dev/null +++ b/src/libs/mynewt-nimble/apps/mesh_badge/src/reel_board.c @@ -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; +} diff --git a/src/libs/mynewt-nimble/apps/mesh_badge/syscfg.yml b/src/libs/mynewt-nimble/apps/mesh_badge/syscfg.yml new file mode 100644 index 00000000..0c60c016 --- /dev/null +++ b/src/libs/mynewt-nimble/apps/mesh_badge/syscfg.yml @@ -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 \ No newline at end of file diff --git a/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll.h b/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll.h index d3340445..1c43e69f 100644 --- a/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll.h +++ b/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll.h @@ -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) diff --git a/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll_conn.h b/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll_conn.h index 26c99265..d7db6878 100644 --- a/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll_conn.h +++ b/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll_conn.h @@ -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; diff --git a/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll_ctrl.h b/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll_ctrl.h index b0da1e73..15a45b2a 100644 --- a/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll_ctrl.h +++ b/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll_ctrl.h @@ -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 diff --git a/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll_hci.h b/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll_hci.h index abef8746..6a9e48e5 100644 --- a/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll_hci.h +++ b/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll_hci.h @@ -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. */ diff --git a/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll_iso.h b/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll_iso.h new file mode 100644 index 00000000..2944b074 --- /dev/null +++ b/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_ll_iso.h @@ -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 + +#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 diff --git a/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_phy.h b/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_phy.h index cabb0adb..cd8350d6 100644 --- a/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_phy.h +++ b/src/libs/mynewt-nimble/nimble/controller/include/controller/ble_phy.h @@ -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; diff --git a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll.c b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll.c index 996ad9c3..a5c48978 100644 --- a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll.c +++ b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll.c @@ -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), diff --git a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_adv.c b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_adv.c index 4ffbe206..72c4e7d6 100644 --- a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_adv.c +++ b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_adv.c @@ -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); } diff --git a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_conn.c b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_conn.c index 1b17a0d2..b8352f4a 100644 --- a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_conn.c +++ b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_conn.c @@ -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,10 +1157,10 @@ 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; } - } + } /* If we send an empty PDU we need to initialize the header */ conn_tx_pdu: @@ -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,129 +3629,142 @@ 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)) { - /* 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) { - /* Check state machine */ - ble_ll_conn_chk_csm_flags(connsm); + /* Packets with invalid CRC are not sent to LL */ + BLE_LL_ASSERT(BLE_MBUF_HDR_CRC_OK(hdr)); - /* Validate rx data pdu */ - rxbuf = rxpdu->om_data; - hdr_byte = rxbuf[0]; - acl_len = rxbuf[1]; - llid = hdr_byte & BLE_LL_DATA_HDR_LLID_MASK; + /* 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) { + STATS_INC(ble_ll_conn_stats, no_conn_sm); + goto conn_rx_data_pdu_end; + } - /* - * 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))) { - STATS_INC(ble_ll_conn_stats, rx_bad_llid); - goto conn_rx_data_pdu_end; - } + /* Check state machine */ + ble_ll_conn_chk_csm_flags(connsm); + + /* Validate rx data pdu */ + rxbuf = rxpdu->om_data; + hdr_byte = rxbuf[0]; + acl_len = rxbuf[1]; + llid = hdr_byte & BLE_LL_DATA_HDR_LLID_MASK; + + /* + * 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))) { + STATS_INC(ble_ll_conn_stats, rx_bad_llid); + goto conn_rx_data_pdu_end; + } #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - /* Check if PDU is allowed when encryption is started. If not, - * terminate connection. - * - * 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)) { - ble_ll_conn_timeout(connsm, BLE_ERR_CONN_TERM_MIC); - goto conn_rx_data_pdu_end; - } + /* Check if PDU is allowed when encryption is started. If not, + * terminate connection. + * + * 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 && + 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) - /* - * Reset authenticated payload timeout if valid MIC. NOTE: we dont - * check the MIC failure bit as that would have terminated the - * connection - */ - if ((connsm->enc_data.enc_state == CONN_ENC_S_ENCRYPTED) && - CONN_F_LE_PING_SUPP(connsm) && (acl_len != 0)) { - ble_ll_conn_auth_pyld_timer_start(connsm); - } + /* + * Reset authenticated payload timeout if valid MIC. NOTE: we dont + * check the MIC failure bit as that would have terminated the + * connection + */ + if ((connsm->enc_data.enc_state == CONN_ENC_S_ENCRYPTED) && + CONN_F_LE_PING_SUPP(connsm) && (acl_len != 0)) { + ble_ll_conn_auth_pyld_timer_start(connsm); + } #endif - /* Update RSSI */ - connsm->conn_rssi = hdr->rxinfo.rssi; + /* Update RSSI */ + connsm->conn_rssi = hdr->rxinfo.rssi; - /* - * If we are a slave, we can only start to use slave latency - * once we have received a NESN of 1 from the master - */ - if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { - if (hdr_byte & BLE_LL_DATA_HDR_NESN_MASK) { - connsm->csmflags.cfbit.allow_slave_latency = 1; - } - } - - /* - * Discard the received PDU if the sequence number is the same - * as the last received sequence number - */ - rxd_sn = hdr_byte & BLE_LL_DATA_HDR_SN_MASK; - if (rxd_sn != connsm->last_rxd_sn) { - /* Update last rxd sn */ - connsm->last_rxd_sn = rxd_sn; - - /* No need to do anything if empty pdu */ - if ((llid == BLE_LL_LLID_DATA_FRAG) && (acl_len == 0)) { - goto conn_rx_data_pdu_end; - } - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - /* - * XXX: should we check to see if we are in a state where we - * might expect to get an encrypted PDU? - */ - if (BLE_MBUF_HDR_MIC_FAILURE(hdr)) { - STATS_INC(ble_ll_conn_stats, mic_failures); - ble_ll_conn_timeout(connsm, BLE_ERR_CONN_TERM_MIC); - goto conn_rx_data_pdu_end; - } -#endif - - if (llid == BLE_LL_LLID_CTRL) { - /* Process control frame */ - STATS_INC(ble_ll_conn_stats, rx_ctrl_pdus); - if (ble_ll_ctrl_rx_pdu(connsm, rxpdu)) { - STATS_INC(ble_ll_conn_stats, rx_malformed_ctrl_pdus); - } - } else { - /* Count # of received l2cap frames and byes */ - STATS_INC(ble_ll_conn_stats, rx_l2cap_pdus); - STATS_INCN(ble_ll_conn_stats, rx_l2cap_bytes, acl_len); - - /* NOTE: there should be at least two bytes available */ - BLE_LL_ASSERT(OS_MBUF_LEADINGSPACE(rxpdu) >= 2); - os_mbuf_prepend(rxpdu, 2); - rxbuf = rxpdu->om_data; - - acl_hdr = (llid << 12) | connsm->conn_handle; - put_le16(rxbuf, acl_hdr); - put_le16(rxbuf + 2, acl_len); - ble_hci_trans_ll_acl_tx(rxpdu); - } - - /* 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); + /* + * If we are a slave, we can only start to use slave latency + * once we have received a NESN of 1 from the master + */ + if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) { + if (hdr_byte & BLE_LL_DATA_HDR_NESN_MASK) { + connsm->csmflags.cfbit.allow_slave_latency = 1; } } + /* + * Discard the received PDU if the sequence number is the same + * as the last received sequence number + */ + rxd_sn = hdr_byte & BLE_LL_DATA_HDR_SN_MASK; + 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; + + /* No need to do anything if empty pdu */ + if ((llid == BLE_LL_LLID_DATA_FRAG) && (acl_len == 0)) { + goto conn_rx_data_pdu_end; + } + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + /* + * XXX: should we check to see if we are in a state where we + * might expect to get an encrypted PDU? + */ + if (BLE_MBUF_HDR_MIC_FAILURE(hdr)) { + STATS_INC(ble_ll_conn_stats, mic_failures); + ble_ll_conn_timeout(connsm, BLE_ERR_CONN_TERM_MIC); + goto conn_rx_data_pdu_end; + } +#endif + + if (llid == BLE_LL_LLID_CTRL) { + /* Process control frame */ + STATS_INC(ble_ll_conn_stats, rx_ctrl_pdus); + if (ble_ll_ctrl_rx_pdu(connsm, rxpdu)) { + STATS_INC(ble_ll_conn_stats, rx_malformed_ctrl_pdus); + } + } else { + /* Count # of received l2cap frames and byes */ + STATS_INC(ble_ll_conn_stats, rx_l2cap_pdus); + STATS_INCN(ble_ll_conn_stats, rx_l2cap_bytes, acl_len); + + /* NOTE: there should be at least two bytes available */ + BLE_LL_ASSERT(OS_MBUF_LEADINGSPACE(rxpdu) >= 2); + os_mbuf_prepend(rxpdu, 2); + rxbuf = rxpdu->om_data; + + acl_hdr = (llid << 12) | connsm->conn_handle; + put_le16(rxbuf, acl_hdr); + put_le16(rxbuf + 2, acl_len); + ble_hci_trans_ll_acl_tx(rxpdu); + } + + /* NOTE: we dont free the mbuf since we handed it off! */ + return; + /* 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! */ - rxpdu = ble_ll_rxpdu_alloc(rx_pyld_len + BLE_LL_PDU_HDR_LEN); + 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(); } diff --git a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_conn_hci.c b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_conn_hci.c index 1350fdc0..9936b9d3 100644 --- a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_conn_hci.c +++ b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_conn_hci.c @@ -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) diff --git a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_conn_priv.h b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_conn_priv.h index f2f72d17..53358c4a 100644 --- a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_conn_priv.h +++ b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_conn_priv.h @@ -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); diff --git a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_ctrl.c b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_ctrl.c index ea2ba834..c4ac6504 100644 --- a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_ctrl.c +++ b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_ctrl.c @@ -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: diff --git a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_hci.c b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_hci.c index b82adc2e..a3da98d9 100644 --- a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_hci.c +++ b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_hci.c @@ -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; diff --git a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_hci_ev.c b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_hci_ev.c index dbc50db9..0d6da9a0 100644 --- a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_hci_ev.c +++ b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_hci_ev.c @@ -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) { diff --git a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_iso.c b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_iso.c new file mode 100644 index 00000000..a6186fe1 --- /dev/null +++ b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_iso.c @@ -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 +#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 diff --git a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_rand.c b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_rand.c index 7b384e9d..8aa71271 100644 --- a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_rand.c +++ b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_rand.c @@ -17,6 +17,9 @@ * under the License. */ +/* for jrand48 */ +#define _XOPEN_SOURCE +#include #include #include #include @@ -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 * diff --git a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_scan.c b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_scan.c index 84747db7..0cbcb376 100644 --- a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_scan.c +++ b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_scan.c @@ -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); diff --git a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_sched.c b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_sched.c index 370faddf..d01f10ed 100644 --- a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_sched.c +++ b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_sched.c @@ -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; diff --git a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_supp_cmd.c b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_supp_cmd.c index 834e0095..cae9eb7d 100644 --- a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_supp_cmd.c +++ b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_supp_cmd.c @@ -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_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, }; diff --git a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_sync.c b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_sync.c index 75f18bf2..df806082 100644 --- a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_sync.c +++ b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_sync.c @@ -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)); diff --git a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_utils.c b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_utils.c index 7fbb18f1..ccdf3775 100644 --- a/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_utils.c +++ b/src/libs/mynewt-nimble/nimble/controller/src/ble_ll_utils.c @@ -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; } diff --git a/src/libs/mynewt-nimble/nimble/controller/syscfg.yml b/src/libs/mynewt-nimble/nimble/controller/syscfg.yml index 85049cb0..2c7c2cb2 100644 --- a/src/libs/mynewt-nimble/nimble/controller/syscfg.yml +++ b/src/libs/mynewt-nimble/nimble/controller/syscfg.yml @@ -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: diff --git a/src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/README.md b/src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/README.md new file mode 100644 index 00000000..2e76e2c1 --- /dev/null +++ b/src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/README.md @@ -0,0 +1,68 @@ + + +## 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) diff --git a/src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/include/ble/xcvr.h b/src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/include/ble/xcvr.h new file mode 100644 index 00000000..e4e741c5 --- /dev/null +++ b/src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/include/ble/xcvr.h @@ -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_ */ diff --git a/src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/pkg.yml b/src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/pkg.yml new file mode 100644 index 00000000..9cf63ffc --- /dev/null +++ b/src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/pkg.yml @@ -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 " +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 diff --git a/src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/src/ble_hw.c b/src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/src/ble_hw.c new file mode 100644 index 00000000..98c8144b --- /dev/null +++ b/src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/src/ble_hw.c @@ -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 +#include +#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(); + } +} diff --git a/src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/src/ble_hw_priv.h b/src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/src/ble_hw_priv.h new file mode 100644 index 00000000..627994ff --- /dev/null +++ b/src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/src/ble_hw_priv.h @@ -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 + +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_ */ diff --git a/src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/src/ble_phy.c b/src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/src/ble_phy.c new file mode 100644 index 00000000..d5767c56 --- /dev/null +++ b/src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/src/ble_phy.c @@ -0,0 +1,1798 @@ +/* + * 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 "syscfg/syscfg.h" +#if !MYNEWT_VAL(BLE_PHY_DEBUG_DSER) +#define MCU_DIAG_SER_DISABLE +#endif + +#include +#include +#include +#include "nimble/ble.h" +#include "mcu/mcu.h" +#include "mcu/cmac_timer.h" +#include "cmac_driver/cmac_shared.h" +#include "controller/ble_phy.h" +#include "controller/ble_ll.h" +#include "stats/stats.h" +#include "CMAC.h" +#include "ble_hw_priv.h" +#include "ble_rf_priv.h" + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) +#error LE Coded PHY cannot be enabled on DA1469x +#endif + +/* Statistics */ +STATS_SECT_START(ble_phy_stats) + STATS_SECT_ENTRY(phy_isrs) + STATS_SECT_ENTRY(tx_good) + STATS_SECT_ENTRY(tx_fail) + STATS_SECT_ENTRY(tx_late) + STATS_SECT_ENTRY(tx_bytes) + STATS_SECT_ENTRY(rx_starts) + STATS_SECT_ENTRY(rx_aborts) + STATS_SECT_ENTRY(rx_valid) + STATS_SECT_ENTRY(rx_crc_err) + STATS_SECT_ENTRY(rx_late) + STATS_SECT_ENTRY(radio_state_errs) + STATS_SECT_ENTRY(rx_hw_err) + STATS_SECT_ENTRY(tx_hw_err) +STATS_SECT_END +STATS_SECT_DECL(ble_phy_stats) ble_phy_stats; + +STATS_NAME_START(ble_phy_stats) + STATS_NAME(ble_phy_stats, phy_isrs) + STATS_NAME(ble_phy_stats, tx_good) + STATS_NAME(ble_phy_stats, tx_fail) + STATS_NAME(ble_phy_stats, tx_late) + STATS_NAME(ble_phy_stats, tx_bytes) + STATS_NAME(ble_phy_stats, rx_starts) + STATS_NAME(ble_phy_stats, rx_aborts) + STATS_NAME(ble_phy_stats, rx_valid) + STATS_NAME(ble_phy_stats, rx_crc_err) + STATS_NAME(ble_phy_stats, rx_late) + STATS_NAME(ble_phy_stats, radio_state_errs) + STATS_NAME(ble_phy_stats, rx_hw_err) + STATS_NAME(ble_phy_stats, tx_hw_err) +STATS_NAME_END(ble_phy_stats) + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) +#error LE Coded PHY is not supported +#endif + +/* An easy way to get and set bit field value in CMAC registers */ +#define CMAC_SETREGF(_reg, _field, _val) \ + CMAC->_reg = (CMAC->_reg & ~(CMAC_ ## _reg ## _ ## _field ## _Msk)) | \ + ((_val) << (CMAC_ ## _reg ## _ ## _field ## _Pos)); +#define CMAC_GETREGF(_reg, _field) \ + (CMAC->_reg & (CMAC_ ## _reg ## _ ## _field ## _Msk)) >> \ + (CMAC_ ## _reg ## _ ## _field ## _Pos) + +/* Definitions for fields queue */ +#define FIELD_DATA_REG_DMA_TX(_offset, _len) \ + ((uint32_t)&g_ble_phy_tx_buf[(_offset)] & 0x3ffff) | ((_len) << 20) +#define FIELD_DATA_REG_DMA_RX(_offset, _len) \ + ((uint32_t)&g_ble_phy_rx_buf[(_offset)] & 0x3ffff) | ((_len) << 20) + +#if MYNEWT_VAL(BLE_LL_DTM) +#define PHY_WHITENING (g_ble_phy_data.phy_whitening) +#else +#define PHY_WHITENING (1) +#endif + +#define FIELD_CTRL_REG_TX_PREAMBLE \ + (0 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_CRC_Pos) | \ + (0 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_WHITENING_Pos) | \ + (0 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_TX_DATA_SRC_Pos) | \ + (g_ble_phy_data.phy_mode_evpsym << \ + CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_EVPSYMBOL_LUT_Pos) | \ + (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_VALID_Pos) | \ + (g_ble_phy_data.phy_mode_pre_len << \ + CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_SIZE_M1_Pos) +#define FIELD_CTRL_REG_TX_ACCESS_ADDR \ + (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_EXC_ON_EXP_Pos) | \ + (0 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_CRC_Pos) | \ + (0 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_WHITENING_Pos) | \ + (0 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_TX_DATA_SRC_Pos) | \ + (g_ble_phy_data.phy_mode_evpsym << \ + CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_EVPSYMBOL_LUT_Pos) | \ + (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_VALID_Pos) | \ + (31 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_SIZE_M1_Pos) +#define FIELD_CTRL_REG_TX_PAYLOAD \ + (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_CRC_Pos) | \ + (PHY_WHITENING << \ + CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_WHITENING_Pos) | \ + (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_DMA_MEM_Pos) | \ + (g_ble_phy_data.phy_mode_evpsym << \ + CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_EVPSYMBOL_LUT_Pos) | \ + (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_VALID_Pos); +#define FIELD_CTRL_REG_TX_ENC_PAYLOAD \ + (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_CRC_Pos) | \ + (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_WHITENING_Pos) | \ + (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_DMA_CRYPTO_Pos) | \ + (g_ble_phy_data.phy_mode_evpsym << \ + CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_EVPSYMBOL_LUT_Pos) | \ + (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_VALID_Pos) +#define FIELD_CTRL_REG_TX_MIC \ + (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_CRC_Pos) | \ + (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_WHITENING_Pos) | \ + (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_DMA_CRYPTO_Pos) | \ + (g_ble_phy_data.phy_mode_evpsym << \ + CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_EVPSYMBOL_LUT_Pos) | \ + (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_VALID_Pos) +#define FIELD_CTRL_REG_TX_CRC \ + (0 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_CRC_Pos) | \ + (PHY_WHITENING << \ + CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_WHITENING_Pos) | \ + (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_TX_DATA_SRC_Pos) | \ + (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_LAST_Pos) | \ + (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_MSB_FIRST_Pos) | \ + (g_ble_phy_data.phy_mode_evpsym << \ + CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_EVPSYMBOL_LUT_Pos) | \ + (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_VALID_Pos) | \ + (23 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_SIZE_M1_Pos) +#define FIELD_CTRL_REG_RX_ACCESS_ADDR \ + (0 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_CRC_Pos) | \ + (0 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_WHITENING_Pos) | \ + (0 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_TX_DATA_SRC_Pos) | \ + (g_ble_phy_data.phy_mode_evpsym << \ + CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_EVPSYMBOL_LUT_Pos) | \ + (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_CORR_Pos) | \ + (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_VALID_Pos) | \ + (31 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_SIZE_M1_Pos) +#define FIELD_CTRL_REG_RX_HEADER \ + (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_EXC_ON_EXP_Pos) | \ + (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_CRC_Pos) | \ + (PHY_WHITENING << \ + CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_WHITENING_Pos) | \ + (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_DMA_MEM_Pos) | \ + (g_ble_phy_data.phy_mode_evpsym << \ + CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_EVPSYMBOL_LUT_Pos) | \ + (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_VALID_Pos) +#define FIELD_CTRL_REG_RX_CRC \ + (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_CRC_Pos) | \ + (PHY_WHITENING << \ + CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_WHITENING_Pos) | \ + (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_LAST_Pos) | \ + (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_MSB_FIRST_Pos) | \ + (g_ble_phy_data.phy_mode_evpsym << \ + CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_EVPSYMBOL_LUT_Pos) | \ + (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_VALID_Pos) | \ + (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_DMA_MEM_Pos) +#define FIELD_CTRL_REG_RX_PAYLOAD \ + (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_CRC_Pos) | \ + (PHY_WHITENING << \ + CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_WHITENING_Pos) | \ + (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_DMA_MEM_Pos) | \ + (g_ble_phy_data.phy_mode_evpsym << \ + CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_EVPSYMBOL_LUT_Pos) | \ + (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_VALID_Pos) +#define FIELD_CTRL_REG_RX_PAYLOAD_WITH_EXC \ + FIELD_CTRL_REG_RX_PAYLOAD | \ + (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_EXC_ON_EXP_Pos) +#define FIELD_CTRL_REG_RX_ENC_PAYLOAD \ + (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_CRC_Pos) | \ + (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_WHITENING_Pos) | \ + (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_XL_DMA_CRYPTO_Pos) | \ + (g_ble_phy_data.phy_mode_evpsym << \ + CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_EVPSYMBOL_LUT_Pos) | \ + (1 << CMAC_CM_FIELD_PUSH_CTRL_REG_FIELD_VALID_Pos) + +/* RF power up/down delays */ +#define PHY_DELAY_POWER_DN_RX (23) +#define PHY_DELAY_POWER_DN_TX (23) +#define PHY_DELAY_POWER_UP_RX (90) +#define PHY_DELAY_POWER_UP_TX (75) +#define PHY_DELAY_TX_RX ((PHY_DELAY_POWER_DN_TX) + (PHY_DELAY_POWER_UP_RX)) +#define PHY_DELAY_RX_TX ((PHY_DELAY_POWER_DN_RX) + (PHY_DELAY_POWER_UP_TX)) + +/* RF TX/RX path delays */ +static const uint8_t g_ble_phy_path_delay_tx[2] = { + 4, /* 1M = 3.8us */ + 0, /* 2M = 0.2us */ +}; +static const uint8_t g_ble_phy_path_delay_rx[2] = { + 2, /* 1M = 2.2us */ + 1, /* 2M = 0.8us */ +}; + +/* Measured and pre-calculated offsets for transitions */ +static const uint8_t g_ble_phy_frame_offset_txrx[4] = { + ((BLE_LL_IFS) - (PHY_DELAY_TX_RX) + (4)), /* 2M/1M */ + ((BLE_LL_IFS) - (PHY_DELAY_TX_RX) + (5)), /* 1M/1M */ + ((BLE_LL_IFS) - (PHY_DELAY_TX_RX) + (4)), /* 2M/2M */ + ((BLE_LL_IFS) - (PHY_DELAY_TX_RX) + (5)), /* 1M/2M */ +}; +static const uint8_t g_ble_phy_frame_offset_rxtx[4] = { + ((BLE_LL_IFS) - (PHY_DELAY_RX_TX) - (5)), /* 2M/1M */ + ((BLE_LL_IFS) - (PHY_DELAY_RX_TX) - (6)), /* 1M/1M */ + ((BLE_LL_IFS) - (PHY_DELAY_RX_TX) - (3)), /* 2M/2M */ + ((BLE_LL_IFS) - (PHY_DELAY_RX_TX) - (5)), /* 1M/2M */ +}; + +/* packet start offsets (in usecs) */ +static const uint16_t g_ble_phy_mode_pkt_start_off[BLE_PHY_NUM_MODE] = { 376, 40, 24, 376 }; + +struct ble_phy_data { + uint8_t phy_state; /* Current state */ + uint8_t channel; /* Current PHY channel */ + uint8_t phy_mode_cur; /* Current PHY mode */ + uint8_t phy_mode_tx; /* TX PHY mode */ + uint8_t phy_mode_rx; /* RX PHY mode */ + uint8_t phy_mode_pre_len; /* Preamble length - 1 */ + uint8_t phy_mode_evpsym; /* EVPSYMBOL_LUT value for fields */ + uint8_t end_transition; /* Scheduled transition */ + uint8_t path_delay_tx; + uint8_t path_delay_rx; + uint8_t frame_offset_txrx; + uint8_t frame_offset_rxtx; + uint8_t phy_rx_started; + uint8_t phy_encrypted; + uint8_t phy_privacy; +#if MYNEWT_VAL(BLE_LL_DTM) + uint8_t phy_whitening; /* Whitening state (disabled for DTM) */ +#endif + uint32_t access_addr; /* Current access address */ + uint32_t crc_init; + uint32_t llt_at_cputime; + uint32_t cputime_at_llt; + uint64_t start_llt; + struct ble_mbuf_hdr rxhdr; + ble_phy_tx_end_func txend_cb; + void *txend_arg; +}; + +static struct ble_phy_data g_ble_phy_data; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) +/* Encryption related variables */ +struct ble_phy_encrypt_obj { + uint8_t key[16]; + uint8_t b0[16]; + uint8_t b1[16]; + uint8_t ai[16]; +}; + +struct ble_phy_encrypt_obj g_ble_phy_encrypt_data; + +static void ble_phy_tx_enc_start(void); +static void ble_phy_rx_enc_start(uint8_t len); +#endif + +#define SW_MAC_EXC_NONE (0) +#define SW_MAC_EXC_LL_RX_END (1) +#define SW_MAC_EXC_TXEND_CB (2) +#define SW_MAC_EXC_LL_RX_START (3) +#define SW_MAC_EXC_WFR_TIMER_EXP (4) + +static volatile uint8_t g_sw_mac_exc; + +/* Channel index to RF channel mapping */ +static const uint8_t g_ble_phy_chan_to_rf[BLE_PHY_NUM_CHANS] = { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, /* 0-9 */ + 11, 13, 14, 15, 16, 17, 18, 19, 20, 21, /* 10-19 */ + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, /* 20-29 */ + 32, 33, 34, 35, 36, 37, 38, 0, 12, 39, /* 30-39 */ +}; + +__attribute__((aligned(4))) +static uint8_t g_ble_phy_tx_buf[BLE_PHY_MAX_PDU_LEN + 3]; +__attribute__((aligned(4))) +static uint8_t g_ble_phy_rx_buf[BLE_PHY_MAX_PDU_LEN + 3]; + +static void ble_phy_irq_field_tx(void); +static void ble_phy_irq_field_rx(void); +static void ble_phy_irq_frame_tx(void); +static void ble_phy_irq_frame_rx(void); +static bool ble_phy_rx_start_isr(void); +static void ble_phy_rx_setup_fields(void); +static void ble_phy_rx_setup_xcvr(void); +static void ble_phy_mode_apply(uint8_t phy_mode); + +void +FIELD_IRQHandler(void) +{ + MCU_DIAG_SER('E'); + + switch (g_ble_phy_data.phy_state) { + case BLE_PHY_STATE_TX: + ble_phy_irq_field_tx(); + break; + case BLE_PHY_STATE_RX: + ble_phy_irq_field_rx(); + break; + default: + STATS_INC(ble_phy_stats, radio_state_errs); + CMAC->CM_EXC_STAT_REG = 0xfffffffe; + break; + } + + MCU_DIAG_SER('e'); +} + +void +CALLBACK_IRQHandler(void) +{ + MCU_DIAG_SER('C'); + + /* XXX: clear these for now. */ + (void)CMAC->CM_BS_SMPL_D_REG; + + /* Clear IRQ*/ + CMAC->CM_EV_SET_REG = CMAC_CM_EV_SET_REG_EV1C_CALLBACK_VALID_CLR_Msk; + CMAC->CM_EXC_STAT_REG = CMAC_CM_EXC_STAT_REG_EXC_FIELD_ON_THR_EXP_Msk; + + /* + * Program next frame for transition to TX. CM_EV_LINKUP_REG register to + * enable actual transition can be set later, we just need to make sure 2nd + * frame is already set before current frame is finished - this guarantees + * that frame for transition will be moved to 1st frame once current frame + * is popped off the queue. + */ + CMAC->CM_FRAME_2_REG = CMAC_CM_FRAME_2_REG_FRAME_VALID_Msk | + CMAC_CM_FRAME_2_REG_FRAME_TX_Msk | + CMAC_CM_FRAME_2_REG_FRAME_EXC_ON_BS_START_Msk | + ((g_ble_phy_data.frame_offset_rxtx) << + CMAC_CM_FRAME_2_REG_FRAME_START_OFFSET_Pos); + + /* + * We just got an access address match so do this as early as possible + * to save time in the field rx isr. + */ + ble_phy_rx_start_isr(); + + MCU_DIAG_SER('c'); +} + +void +FRAME_IRQHandler(void) +{ + MCU_DIAG_SER('F'); + + switch (g_ble_phy_data.phy_state) { + case BLE_PHY_STATE_TX: + ble_phy_irq_frame_tx(); + break; + case BLE_PHY_STATE_RX: + ble_phy_irq_frame_rx(); + break; + default: + STATS_INC(ble_phy_stats, radio_state_errs); + CMAC->CM_EXC_STAT_REG = 0xfffffffe; + break; + } + + MCU_DIAG_SER('f'); +} + +void +SW_MAC_IRQHandler(void) +{ + uint8_t exc; + int rc; + + MCU_DIAG_SER('S'); + + CMAC->CM_EXC_STAT_REG = CMAC_CM_EXC_STAT_REG_EXC_SW_MAC_Msk; + assert(g_sw_mac_exc); + + exc = g_sw_mac_exc; + g_sw_mac_exc = 0; + + MCU_DIAG_SER('0' + exc); + + /* Next SW_MAC handover can now be queued */ + os_arch_cmac_bs_ctrl_irq_unblock(); + + switch (exc) { + case SW_MAC_EXC_TXEND_CB: + assert(g_ble_phy_data.txend_cb); + g_ble_phy_data.txend_cb(g_ble_phy_data.txend_arg); + break; + case SW_MAC_EXC_WFR_TIMER_EXP: + ble_ll_wfr_timer_exp(NULL); + break; + case SW_MAC_EXC_LL_RX_START: + /* Call Link Layer receive start function */ + rc = ble_ll_rx_start(&g_ble_phy_rx_buf[0], g_ble_phy_data.channel, + &g_ble_phy_data.rxhdr); + if (rc == 0) { + /* Set rx started flag and enable rx end ISR */ + g_ble_phy_data.phy_rx_started = 1; + + /* No transition */ + CMAC->CM_EV_LINKUP_REG = CMAC_CM_EV_LINKUP_REG_LU_PHY_TO_IDLE_2_NONE_Msk | + CMAC_CM_EV_LINKUP_REG_LU_FRAME_START_2_NONE_Msk; + } else if (rc > 0) { + g_ble_phy_data.phy_rx_started = 1; + + /* Setup transition */ + CMAC->CM_EV_LINKUP_REG = CMAC_CM_EV_LINKUP_REG_LU_PHY_TO_IDLE_2_EXC_Msk | + CMAC_CM_EV_LINKUP_REG_LU_FRAME_START_2_PHY_TO_IDLE_Msk; + } else { + /* Disable PHY */ + ble_phy_disable(); + STATS_INC(ble_phy_stats, rx_aborts); + } + break; + case SW_MAC_EXC_LL_RX_END: + /* Call LL end processing */ + rc = ble_ll_rx_end(&g_ble_phy_rx_buf[0], &g_ble_phy_data.rxhdr); + if (rc < 0) { + ble_phy_disable(); + } + break; + default: + assert(0); + break; + } + + MCU_DIAG_SER('s'); +} + +static inline uint32_t +ble_phy_convert_and_record_start_time(uint32_t cputime, uint8_t rem_usecs) +{ + uint64_t ll_val; + + ll_val = cmac_timer_convert_hal2llt(cputime); + + /* + * Since we just converted cputime to the LL timer, record both these + * values as they will be used to calculate packet reception start time. + */ + g_ble_phy_data.cputime_at_llt = cputime; + g_ble_phy_data.llt_at_cputime = ll_val; + g_ble_phy_data.start_llt = ll_val + rem_usecs; + + return ll_val; +} + +static inline void +ble_phy_sw_mac_handover(uint8_t exc) +{ + assert(!g_sw_mac_exc); + + g_sw_mac_exc = exc; + + CMAC->CM_EV_SET_REG = CMAC_CM_EV_SET_REG_EV1C_SW_MAC_Msk; + + /* + * We want SW_MAC to be fired just after BS_CTRL interrupt so we block + * BS_CTRL temporarily and SW_MAC is next in order of interrupts priority. + */ + os_arch_cmac_bs_ctrl_irq_block(); +} + +static void +ble_phy_rx_end_isr(void) +{ + struct ble_mbuf_hdr *ble_hdr; + + /* XXX just clear captured timer for now. Handle rx end time */ + (void)CMAC->CM_TS1_REG; + + /* Set RSSI and CRC status flag in header */ + ble_hdr = &g_ble_phy_data.rxhdr; + + /* Count PHY crc errors and valid packets */ + if (CMAC->CM_CRC_REG != 0) { + STATS_INC(ble_phy_stats, rx_crc_err); + } else { + STATS_INC(ble_phy_stats, rx_valid); + ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_CRC_OK; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + if (g_ble_phy_data.phy_encrypted) { + /* Only set MIC failure flag if frame is not zero length */ + if (g_ble_phy_rx_buf[1] != 0) { + if (CMAC->CM_CRYPTO_STAT_REG != 0) { + ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_MIC_FAILURE; + } else { + g_ble_phy_rx_buf[1] = g_ble_phy_rx_buf[1] - 4; + } + } + } +#endif + } + + ble_phy_sw_mac_handover(SW_MAC_EXC_LL_RX_END); +} + +static bool +ble_phy_rx_start_isr(void) +{ + uint32_t llt32; + uint32_t llt_10_0; + uint32_t llt_10_0_mask; + uint32_t timestamp; + uint32_t ticks; + uint32_t usecs; + struct ble_mbuf_hdr *ble_hdr; + + /* Initialize the ble mbuf header */ + ble_hdr = &g_ble_phy_data.rxhdr; + ble_hdr->rxinfo.flags = ble_ll_state_get(); + ble_hdr->rxinfo.channel = g_ble_phy_data.channel; + ble_hdr->rxinfo.handle = 0; + ble_hdr->rxinfo.phy = ble_phy_get_cur_phy(); + ble_hdr->rxinfo.phy_mode = g_ble_phy_data.phy_mode_rx; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + ble_hdr->rxinfo.user_data = NULL; +#endif + + /* Read the latched RSSI value */ + ble_hdr->rxinfo.rssi = ble_rf_get_rssi(); +#if MYNEWT_VAL(CMAC_DEBUG_DATA_ENABLE) + g_cmac_shared_data.debug.last_rx_rssi = ble_hdr->rxinfo.rssi; +#endif + + /* Count rx starts */ + STATS_INC(ble_phy_stats, rx_starts); + + /* + * Calculate packet start time. Note that we have only received the + * access address at this point but we should have the 1st symbol and + * thus the timestamp should be set (this is based on looking at the diag + * signals). For now, lets make sure that the dirty bit is set. The + * dirty bit means that the timestamp was set since the last time cleared. + * Note that we need to read the timestamp first to guarantee it was set + * before reading the LL timer. + */ + timestamp = CMAC->CM_TS1_REG; + assert((timestamp & CMAC_CM_TS1_REG_TS1_DIRTY_Msk) != 0); + + /* Get the LL timer (only need 32 bits) */ + llt32 = cmac_timer_read32(); + + /* + * We assume that the timestamp was set within 11 bits, or 2047 usecs, of + * when we read the ll timer. We assume this because we need to calculate + * the LL timer value at the timestamp. If the low 11 bits of the LL timer + * are greater than the timestamp, it means that the upper bits of the + * timestamp are correct. If the timestamp value is greater, it means the + * timer wrapped the 11 bits and we need to adjust the LL timer value. + */ + llt_10_0_mask = (CMAC_CM_TS1_REG_TS1_TIMER1_9_0_Msk | + CMAC_CM_TS1_REG_TS1_TIMER1_10_Msk); + timestamp &= llt_10_0_mask; + llt_10_0 = llt32 & llt_10_0_mask; + llt32 &= ~llt_10_0_mask; + if (timestamp > llt_10_0) { + llt32 -= 2048; + } + llt32 |= timestamp; + + /* Actual RX start time needs to account for preamble and access address */ + llt32 -= g_ble_phy_mode_pkt_start_off[g_ble_phy_data.phy_mode_rx] + + g_ble_phy_data.path_delay_rx; + + if (llt32 < g_ble_phy_data.llt_at_cputime) { + g_ble_phy_data.llt_at_cputime -= 31; + g_ble_phy_data.cputime_at_llt--; + } + + /* + * We now have the LL timer when the packet was received. Get the cputime + * and the leftover usecs. + */ + usecs = llt32 - g_ble_phy_data.llt_at_cputime; + ticks = os_cputime_usecs_to_ticks(usecs); + ble_hdr->beg_cputime = g_ble_phy_data.cputime_at_llt + ticks; + ble_hdr->rem_usecs = usecs - os_cputime_ticks_to_usecs(ticks); + + return true; +} + +static void +ble_phy_irq_field_tx_exc_bs_start_4this(void) +{ + CMAC->CM_EXC_STAT_REG = CMAC_CM_EXC_STAT_REG_EXC_BS_START_4THIS_Msk; + + if (g_ble_phy_data.end_transition == BLE_PHY_TRANSITION_TX_RX) { + /* + * Setup 2nd frame that will start after current one. + * -2us offset to adjust for allowed active clock accuracy. + */ + CMAC->CM_FRAME_2_REG = CMAC_CM_FRAME_2_REG_FRAME_VALID_Msk | + (((g_ble_phy_data.frame_offset_txrx) - 2) << + CMAC_CM_FRAME_2_REG_FRAME_START_OFFSET_Pos); + + /* Next frame starts automatically on phy2idle */ + CMAC->CM_EV_LINKUP_REG = CMAC_CM_EV_LINKUP_REG_LU_PHY_TO_IDLE_2_EXC_Msk | + CMAC_CM_EV_LINKUP_REG_LU_FRAME_START_2_PHY_TO_IDLE_Msk; + + ble_phy_wfr_enable(BLE_PHY_WFR_ENABLE_TXRX, g_ble_phy_data.phy_mode_rx, 0); + } else { + CMAC->CM_EV_LINKUP_REG = CMAC_CM_EV_LINKUP_REG_LU_PHY_TO_IDLE_2_EXC_Msk | + CMAC_CM_EV_LINKUP_REG_LU_FRAME_START_2_NONE_Msk; + } + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + if (g_ble_phy_data.phy_encrypted && (g_ble_phy_tx_buf[1] != 0)) { + ble_phy_tx_enc_start(); + } +#endif +} + +static void +ble_phy_irq_field_tx_exc_field_on_thr_exp(void) +{ + CMAC->CM_EXC_STAT_REG = CMAC_CM_EXC_STAT_REG_EXC_FIELD_ON_THR_EXP_Msk; + (void)CMAC->CM_TS1_REG; + + /* Set up remaining field (CRC) */ + CMAC->CM_FIELD_PUSH_CTRL_REG = FIELD_CTRL_REG_TX_CRC; +} + +static void +ble_phy_irq_field_tx(void) +{ + uint32_t stat; + + stat = CMAC->CM_EXC_STAT_REG; + + if (stat & CMAC_CM_EXC_STAT_REG_EXC_BS_START_4THIS_Msk) { + MCU_DIAG_SER('6'); + ble_phy_irq_field_tx_exc_bs_start_4this(); + } + + if (stat & CMAC_CM_EXC_STAT_REG_EXC_FIELD_ON_THR_EXP_Msk) { + MCU_DIAG_SER('7'); + ble_phy_irq_field_tx_exc_field_on_thr_exp(); + } +} + +static void +ble_phy_irq_frame_tx_exc_bs_stop(void) +{ + CMAC->CM_EXC_STAT_REG = CMAC_CM_EXC_STAT_REG_EXC_BS_STOP_Msk; + + /* Clear latched timestamp so we do not have error on next frame */ + (void)CMAC->CM_TS1_REG; + + if (g_ble_phy_data.end_transition == BLE_PHY_TRANSITION_TX_RX) { +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) + ble_phy_mode_apply(g_ble_phy_data.phy_mode_rx); +#endif + ble_phy_rx_setup_fields(); + } else { + CMAC->CM_EV_LINKUP_REG = CMAC_CM_EV_LINKUP_REG_LU_PHY_TO_IDLE_2_EXC_Msk | + CMAC_CM_EV_LINKUP_REG_LU_FRAME_START_2_NONE_Msk; + } + + if (g_ble_phy_data.txend_cb) { + ble_phy_sw_mac_handover(SW_MAC_EXC_TXEND_CB); + return; + } +} + +static void +ble_phy_irq_frame_tx_exc_phy_to_idle_4this(void) +{ + CMAC->CM_EXC_STAT_REG = CMAC_CM_EXC_STAT_REG_EXC_PHY_TO_IDLE_4THIS_Msk; + + if (g_ble_phy_data.end_transition == BLE_PHY_TRANSITION_TX_RX) { + ble_phy_rx_setup_xcvr(); + + g_ble_phy_data.phy_state = BLE_PHY_STATE_RX; + } else { + /* + * Disable explicitly in case RX-TX was done (we cannot setup for auto + * disable in such case) */ + ble_rf_stop(); + + g_ble_phy_data.phy_state = BLE_PHY_STATE_IDLE; + } + + g_ble_phy_data.end_transition = BLE_PHY_TRANSITION_NONE; +} + +static void +ble_phy_irq_frame_tx(void) +{ + uint32_t stat; + + stat = CMAC->CM_EXC_STAT_REG; + + /* + * In case of phy2idle this should be first and only exception we handle + * here. This is because in case of TX-RX transition frame_start will occur + * at the same as phy2idle so we will have 2 exceptions here. To handle this + * properly we first need to handle phy2idle in TX state and keep frame_start + * pending so it will be called again in RX state. + */ + if (stat & CMAC_CM_EXC_STAT_REG_EXC_PHY_TO_IDLE_4THIS_Msk) { + MCU_DIAG_SER('6'); + ble_phy_irq_frame_tx_exc_phy_to_idle_4this(); + return; + } + + if (stat & CMAC_CM_EXC_STAT_REG_EXC_FRAME_START_Msk) { + MCU_DIAG_SER('7'); + CMAC->CM_EXC_STAT_REG = CMAC_CM_EXC_STAT_REG_EXC_FRAME_START_Msk; + } + + if (stat & CMAC_CM_EXC_STAT_REG_EXC_BS_STOP_Msk) { + MCU_DIAG_SER('8'); + ble_phy_irq_frame_tx_exc_bs_stop(); + } +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) +static void +ble_phy_field_rx_encrypted(uint32_t len) +{ + if (len) { + /* + * An encrypted frame should have a minimum length of 5 + * bytes (at least one for payload and 4 for MIC). If the + * length is less than 5 this frame is bogus and will most + * likely fail CRC. We still need to process this frame + * though as we need to call the handover function with + * the frame. If this happens we will not bother to + * run the remaining bytes through the accelerator; just + * process them like normal and generate (a hopefully + * incorrect) CRC. + */ + if (len >= 5) { + /* Start the crypto accelerator */ + ble_phy_rx_enc_start(len); + + /* + * We have already processed one byte; process remaining + * payload and MIC. Note: length contains MIC. + */ + len -= 2; + CMAC->CM_FIELD_PUSH_DATA_REG = FIELD_DATA_REG_DMA_RX(4, len); + CMAC->CM_FIELD_PUSH_CTRL_REG = FIELD_CTRL_REG_RX_ENC_PAYLOAD; + + /* CRC */ + CMAC->CM_FIELD_PUSH_DATA_REG = FIELD_DATA_REG_DMA_RX(4 + len, 3); + CMAC->CM_FIELD_PUSH_CTRL_REG = FIELD_CTRL_REG_RX_CRC; + } else { + /* We have processed one byte so far. Send remaining + payload bytes to normal rx payload processing */ + len -= 2; + if (len) { + CMAC->CM_FIELD_PUSH_DATA_REG = FIELD_DATA_REG_DMA_RX(4, len); + CMAC->CM_FIELD_PUSH_CTRL_REG = FIELD_CTRL_REG_RX_PAYLOAD; + } + + CMAC->CM_FIELD_PUSH_DATA_REG = FIELD_DATA_REG_DMA_RX(4 + len, 3); + CMAC->CM_FIELD_PUSH_CTRL_REG = FIELD_CTRL_REG_RX_CRC; + + /* Clear crypto pre-buffer */ + CMAC->CM_CRYPTO_CTRL_REG = CMAC_CM_CRYPTO_CTRL_REG_CM_CRYPTO_SW_REQ_PBUF_CLR_Msk; + } + } else { + /* We programmed one byte, so get next two bytes for CRC */ + CMAC->CM_FIELD_PUSH_DATA_REG = FIELD_DATA_REG_DMA_RX(4, 1); + CMAC->CM_FIELD_PUSH_CTRL_REG = FIELD_CTRL_REG_RX_CRC; + } +} +#endif + +static void +ble_phy_field_rx_unencrypted(uint32_t len) +{ + uint8_t pduhdr; + uint8_t adva_thr; + + if (len) { + pduhdr = g_ble_phy_rx_buf[0]; + adva_thr = 0; + + /* + * Setup interrupt after AdvA to start address resolving if + * privacy is enabled and TxAdd bit is set. + */ + if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) && + g_ble_phy_data.phy_privacy && (pduhdr & 0x40)) { + + /* + * For legacy advertising AdvA ends at 6th byte. + * For extended advertising AdvA ends at 8th byte. + * We already programmed 2 bytes of payload so need + * to adjust threshold accordingly or just reset it + * in case there is not enough bytes in PDU to fit AdvA. + */ + adva_thr = (pduhdr & 0x0f) == 0x07 ? 6 : 4; + if (len >= adva_thr + 2) { + CMAC->CM_FIELD_PUSH_DATA_REG = FIELD_DATA_REG_DMA_RX(4, adva_thr); + CMAC->CM_FIELD_PUSH_CTRL_REG = FIELD_CTRL_REG_RX_PAYLOAD_WITH_EXC; + } else { + adva_thr = 0; + } + } + + CMAC->CM_FIELD_PUSH_DATA_REG = FIELD_DATA_REG_DMA_RX(4 + adva_thr, + len - adva_thr); + CMAC->CM_FIELD_PUSH_CTRL_REG = FIELD_CTRL_REG_RX_PAYLOAD; + } + + CMAC->CM_FIELD_PUSH_DATA_REG = FIELD_DATA_REG_DMA_RX(4 + len, 1); + CMAC->CM_FIELD_PUSH_CTRL_REG = FIELD_CTRL_REG_RX_CRC; +} + +static void +ble_phy_irq_field_rx_exc_field_on_thr_exp(void) +{ + uint32_t len; + uint32_t smpl; + + CMAC->CM_EXC_STAT_REG = CMAC_CM_EXC_STAT_REG_EXC_FIELD_ON_THR_EXP_Msk; + + smpl = CMAC->CM_BS_SMPL_ST_REG; + + if ((smpl & CMAC_CM_BS_SMPL_ST_REG_FIELD_CNT_LATCHED_Msk) == 1) { + assert(g_ble_phy_data.phy_rx_started == 0); + + /* Clear this */ + (void)CMAC->CM_TS1_REG; + + /* Read length of frame */ + len = CMAC->CM_BS_SMPL_D_REG; + len = len & 0xFF; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + if (g_ble_phy_data.phy_encrypted) { + ble_phy_field_rx_encrypted(len); + } else { + ble_phy_field_rx_unencrypted(len); + } +#else + ble_phy_field_rx_unencrypted(len); +#endif + + ble_phy_sw_mac_handover(SW_MAC_EXC_LL_RX_START); + } else if ((smpl & CMAC_CM_BS_SMPL_ST_REG_FIELD_CNT_LATCHED_Msk) == 3) { + (void)CMAC->CM_BS_SMPL_D_REG; + + assert(g_ble_phy_data.phy_privacy); + + /* + * Resolve only if RPA is received. AdvA is at different offset + * in ExtAdv PDU. TxAdd was already checked before programming + * field threshold. + */ + if ((g_ble_phy_rx_buf[0] & 0x0f) == 0x07) { + if ((g_ble_phy_rx_buf[9] & 0xc0) == 0x40) { + ble_hw_resolv_proc_start(&g_ble_phy_rx_buf[4]); + } + } else { + if ((g_ble_phy_rx_buf[7] & 0xc0) == 0x40) { + ble_hw_resolv_proc_start(&g_ble_phy_rx_buf[2]); + } + } + } else { + assert(0); + } +} + +static void +ble_phy_irq_field_rx_exc_stat_reg_exc_corr_timeout(void) +{ + CMAC->CM_EXC_STAT_REG = CMAC_CM_EXC_STAT_REG_EXC_CORR_TIMEOUT_Msk; + CMAC->CM_EXC_STAT_REG = CMAC_CM_EXC_STAT_REG_EXC_BS_STOP_Msk; + CMAC->CM_EV_LINKUP_REG = CMAC_CM_EV_LINKUP_REG_LU_FRAME_START_2_NONE_Msk; + + ble_phy_sw_mac_handover(SW_MAC_EXC_WFR_TIMER_EXP); +} + +static void +ble_phy_irq_field_rx(void) +{ + uint32_t stat; + + stat = CMAC->CM_EXC_STAT_REG; + + if (stat & CMAC_CM_EXC_STAT_REG_EXC_FIELD_ON_THR_EXP_Msk) { + MCU_DIAG_SER('1'); + ble_phy_irq_field_rx_exc_field_on_thr_exp(); + } + + if (stat & CMAC_CM_EXC_STAT_REG_EXC_CORR_TIMEOUT_Msk) { + MCU_DIAG_SER('2'); + ble_phy_irq_field_rx_exc_stat_reg_exc_corr_timeout(); + } +} + +static void +ble_phy_irq_frame_rx_exc_phy_to_idle_4this(void) +{ + uint8_t rf_chan; + + CMAC->CM_EXC_STAT_REG = CMAC_CM_EXC_STAT_REG_EXC_PHY_TO_IDLE_4THIS_Msk; + + /* We are here only on transition, so switch to TX */ +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) + ble_phy_mode_apply(g_ble_phy_data.phy_mode_tx); +#endif + rf_chan = g_ble_phy_chan_to_rf[g_ble_phy_data.channel]; + ble_rf_setup_tx(rf_chan, g_ble_phy_data.phy_mode_tx); + g_ble_phy_data.phy_state = BLE_PHY_STATE_TX; +} + +static void +ble_phy_irq_frame_rx_exc_frame_start(void) +{ + CMAC->CM_EXC_STAT_REG = CMAC_CM_EXC_STAT_REG_EXC_FRAME_START_Msk; +} + +static void +ble_phy_irq_frame_rx_exc_bs_stop(void) +{ + CMAC->CM_EXC_STAT_REG = CMAC_CM_EXC_STAT_REG_EXC_BS_STOP_Msk; + ble_phy_rx_end_isr(); +} + +static void +ble_phy_irq_frame_rx(void) +{ + uint32_t stat; + + stat = CMAC->CM_EXC_STAT_REG; + + if (stat & CMAC_CM_EXC_STAT_REG_EXC_PHY_TO_IDLE_4THIS_Msk) { + MCU_DIAG_SER('3'); + ble_phy_irq_frame_rx_exc_phy_to_idle_4this(); + return; + } + + if (stat & CMAC_CM_EXC_STAT_REG_EXC_FRAME_START_Msk) { + MCU_DIAG_SER('1'); + ble_phy_irq_frame_rx_exc_frame_start(); + } + + if (stat & CMAC_CM_EXC_STAT_REG_EXC_BS_STOP_Msk) { + MCU_DIAG_SER('2'); + ble_phy_irq_frame_rx_exc_bs_stop(); + } +} + +static void +ble_phy_mode_apply(uint8_t phy_mode) +{ + if (phy_mode == g_ble_phy_data.phy_mode_cur) { + return; + } + + switch (phy_mode) { + case BLE_PHY_MODE_1M: +#if MYNEWT_VAL(BLE_PHY_RF_HP_MODE) + CMAC_SETREGF(CM_PHY_CTRL2_REG, CORR_CLK_MODE, 3); +#endif + CMAC_SETREGF(CM_PHY_CTRL2_REG, PHY_MODE, 1); + g_ble_phy_data.phy_mode_evpsym = 1; /* 1000 ns per symbol */ + g_ble_phy_data.phy_mode_pre_len = 7; + break; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) + case BLE_PHY_MODE_2M: +#if MYNEWT_VAL(BLE_PHY_RF_HP_MODE) + CMAC_SETREGF(CM_PHY_CTRL2_REG, CORR_CLK_MODE, 2); +#endif + CMAC_SETREGF(CM_PHY_CTRL2_REG, PHY_MODE, 0); + g_ble_phy_data.phy_mode_evpsym = 0; /* 500 ns per symbol */ + g_ble_phy_data.phy_mode_pre_len = 15; + break; +#endif + default: + assert(0); + return; + } + + g_ble_phy_data.phy_mode_cur = phy_mode; +} + +void +ble_phy_mode_set(uint8_t tx_phy_mode, uint8_t rx_phy_mode) +{ + uint8_t txrx; + uint8_t rxtx; + + g_ble_phy_data.phy_mode_tx = tx_phy_mode; + g_ble_phy_data.phy_mode_rx = rx_phy_mode; + + g_ble_phy_data.path_delay_tx = g_ble_phy_path_delay_tx[tx_phy_mode - 1]; + g_ble_phy_data.path_delay_rx = g_ble_phy_path_delay_rx[rx_phy_mode - 1]; + + /* + * Calculate index of transition in frame offset array without tons of + * branches. Note that transitions have to be in specific order in array. + * + * phy_mode 1M = 01b + * phy_mode 2M = 10b + * + * 1M/1M = 01b | 00b = 01b + * 1M/2M = 01b | 10b = 11b + * 2M/1M = 00b | 00b = 00b + * 2M/2M = 00b | 10b = 10b + */ + txrx = (tx_phy_mode & 0x01) | (rx_phy_mode & 0x02); + rxtx = (rx_phy_mode & 0x01) | (tx_phy_mode & 0x02); + g_ble_phy_data.frame_offset_txrx = g_ble_phy_frame_offset_txrx[txrx]; + g_ble_phy_data.frame_offset_rxtx = g_ble_phy_frame_offset_rxtx[rxtx]; +} + +int +ble_phy_get_cur_phy(void) +{ +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) + switch (g_ble_phy_data.phy_mode_cur) { + case BLE_PHY_MODE_1M: + return BLE_PHY_1M; + case BLE_PHY_MODE_2M: + return BLE_PHY_2M; + default: + assert(0); + return -1; + } +#else + return BLE_PHY_1M; +#endif +} + +/** + * Copies the data from the phy receive buffer into a mbuf chain. + * + * @param dptr Pointer to receive buffer + * @param rxpdu Pointer to already allocated mbuf chain + * + * NOTE: the packet header already has the total mbuf length in it. The + * lengths of the individual mbufs are not set prior to calling. + * + */ +void +ble_phy_rxpdu_copy(uint8_t *dptr, struct os_mbuf *rxpdu) +{ + uint32_t rem_len; + uint32_t copy_len; + uint32_t block_len; + uint32_t block_rem_len; + void *dst; + void *src; + struct os_mbuf * om; + + /* Better be aligned */ + assert(((uint32_t)dptr & 3) == 0); + + block_len = rxpdu->om_omp->omp_databuf_len; + rem_len = OS_MBUF_PKTHDR(rxpdu)->omp_len; + src = dptr; + + /* + * Setup for copying from first mbuf which is shorter due to packet header + * and extra leading space + */ + copy_len = block_len - rxpdu->om_pkthdr_len - 4; + om = rxpdu; + dst = om->om_data; + + while (om) { + /* + * Always copy blocks of length aligned to word size, only last mbuf + * will have remaining non-word size bytes appended. + */ + block_rem_len = copy_len; + copy_len = min(copy_len, rem_len); + copy_len &= ~3; + + dst = om->om_data; + om->om_len = copy_len; + rem_len -= copy_len; + block_rem_len -= copy_len; + + __asm__ volatile (".syntax unified \n" + " mov r4, %[len] \n" + " b 2f \n" + "1: ldr r3, [%[src], %[len]] \n" + " str r3, [%[dst], %[len]] \n" + "2: subs %[len], #4 \n" + " bpl 1b \n" + " adds %[src], %[src], r4 \n" + " adds %[dst], %[dst], r4 \n" + : [dst] "+l" (dst), [src] "+l" (src), + [len] "+l" (copy_len) + : + : "r3", "r4", "memory"); + + if ((rem_len < 4) && (block_rem_len >= rem_len)) { + break; + } + + /* Move to next mbuf */ + om = SLIST_NEXT(om, om_next); + copy_len = block_len; + } + + /* Copy remaining bytes, if any, to last mbuf */ + om->om_len += rem_len; + __asm__ volatile (".syntax unified \n" + " b 2f \n" + "1: ldrb r3, [%[src], %[len]] \n" + " strb r3, [%[dst], %[len]] \n" + "2: subs %[len], #1 \n" + " bpl 1b \n" + : [len] "+l" (rem_len) + : [dst] "l" (dst), [src] "l" (src) + : "r3", "memory"); + + /* Copy header */ + memcpy(BLE_MBUF_HDR_PTR(rxpdu), &g_ble_phy_data.rxhdr, + sizeof(struct ble_mbuf_hdr)); +} + +void +ble_phy_wfr_enable(int txrx, uint8_t tx_phy_mode, uint32_t wfr_usecs) +{ + uint64_t llt; + uint32_t corr_window; + uint32_t llt_z_ticks; + uint32_t aa_time; + + /* + * RX is started 2us earlier due to allowed clock accuracy and it should end + * 2us later for the same reason. Preamble is always 8us (8 symbols on 1M, + * 16 symbols on 2M) and Access Address is 32us on 1M and 16us on 2M. Add + * 1us just in case... + */ +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) + aa_time = 2 + (g_ble_phy_data.phy_mode_rx == BLE_PHY_MODE_1M ? 40 : 24) + 2 + 1; +#else + aa_time = 45; +#endif + + if (txrx == BLE_PHY_WFR_ENABLE_TXRX) { + CMAC_SETREGF(CM_PHY_CTRL2_REG, CORR_WINDOW, aa_time); + CMAC->CM_EV_LINKUP_REG = CMAC_CM_EV_LINKUP_REG_LU_CORR_TMR_LD_2_CORR_START_Msk; + } else if (wfr_usecs < 16384) { + CMAC_SETREGF(CM_PHY_CTRL2_REG, CORR_WINDOW, wfr_usecs + aa_time); + CMAC->CM_EV_LINKUP_REG = CMAC_CM_EV_LINKUP_REG_LU_CORR_TMR_LD_2_CORR_START_Msk; + } else { + wfr_usecs += aa_time; + llt = g_ble_phy_data.start_llt; + + /* + * wfr is outside range of CORR_WINDOW so we need to use LLT to start + * correlator timeout with some delay. Let's use ~10ms as new CORR_WINDOW + * value (does not really matter, just had to pick something) so need to + * calculate how many hi-Z ticks of delay we need. + */ + llt_z_ticks = (wfr_usecs - 10000) / 1024; + + /* New CORR_WINDOW is wfr adjusted by hi-Z ticks and remainder of 1st tick. */ + corr_window = wfr_usecs; + corr_window -= llt_z_ticks * 1024; + corr_window -= 1024 - (llt & 0x3ff); + + CMAC->CM_LL_TIMER1_36_10_EQ_Z_REG = (llt >> 10) + llt_z_ticks; + CMAC_SETREGF(CM_PHY_CTRL2_REG, CORR_WINDOW, corr_window); + CMAC->CM_EV_LINKUP_REG = CMAC_CM_EV_LINKUP_REG_LU_CORR_TMR_LD_2_TMR1_36_10_EQ_Z_Msk; + } +} + +int +ble_phy_init(void) +{ + g_ble_phy_data.phy_state = BLE_PHY_STATE_IDLE; +#if MYNEWT_VAL(BLE_LL_DTM) + g_ble_phy_data.phy_whitening = 1; +#endif + + ble_rf_init(); + + /* + * 9_0_EQ_X can be linked to start RX/TX so we'll use this one for + * scheduling TX/RX start - make sure it's not linked to LL_TIMER2LLC + */ + CMAC->CM_LL_INT_SEL_REG &= ~CMAC_CM_LL_INT_SEL_REG_LL_TIMER1_9_0_EQ_X_SEL_Msk; + + CMAC->CM_PHY_CTRL_REG = ((PHY_DELAY_POWER_DN_RX - 1) << 24) | + ((PHY_DELAY_POWER_DN_TX - 1) << 16) | + ((PHY_DELAY_POWER_UP_RX - 1) << 8) | + ((PHY_DELAY_POWER_UP_TX - 1)); + +#if MYNEWT_VAL(BLE_PHY_RF_HP_MODE) + CMAC->CM_PHY_CTRL2_REG = CMAC_CM_PHY_CTRL2_REG_PHY_MODE_Msk | + (3 << CMAC_CM_PHY_CTRL2_REG_CORR_CLK_MODE_Pos); +#else + CMAC->CM_PHY_CTRL2_REG = CMAC_CM_PHY_CTRL2_REG_PHY_MODE_Msk | + (2 << CMAC_CM_PHY_CTRL2_REG_CORR_CLK_MODE_Pos); +#endif + + CMAC_SETREGF(CM_CTRL2_REG, WHITENING_MODE, 0); + CMAC_SETREGF(CM_CTRL2_REG, CRC_MODE, 0); + + /* Setup for 1M by default */ + ble_phy_mode_set(BLE_PHY_MODE_1M, BLE_PHY_MODE_1M); + ble_phy_mode_apply(BLE_PHY_MODE_1M); + + NVIC_SetPriority(FIELD_IRQn, 0); + NVIC_SetPriority(CALLBACK_IRQn, 0); + NVIC_SetPriority(FRAME_IRQn, 0); + NVIC_SetPriority(CRYPTO_IRQn, 1); + NVIC_SetPriority(SW_MAC_IRQn, 1); + NVIC_EnableIRQ(FIELD_IRQn); + NVIC_EnableIRQ(CALLBACK_IRQn); + NVIC_EnableIRQ(FRAME_IRQn); + NVIC_EnableIRQ(SW_MAC_IRQn); + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + /* Initialize non-zero fixed values in CCM blocks */ + g_ble_phy_encrypt_data.b0[0] = 0x49; + g_ble_phy_encrypt_data.b1[1] = 0x01; + g_ble_phy_encrypt_data.ai[0] = 0x01; +#endif + + return 0; +} + +void +ble_phy_disable(void) +{ + MCU_DIAG_SER('D'); + + __disable_irq(); + + CMAC->CM_EV_SET_REG = CMAC_CM_EV_SET_REG_EV1C_BS_CLEAR_Msk; + + __NOP(); + __NOP(); + __NOP(); + __NOP(); + __NOP(); + + CMAC->CM_EXC_STAT_REG = CMAC_CM_EXC_STAT_REG_EXC_FIELD_ON_THR_EXP_Msk | + CMAC_CM_EXC_STAT_REG_EXC_BS_START_4THIS_Msk | + CMAC_CM_EXC_STAT_REG_EXC_CORR_TIMEOUT_Msk | + CMAC_CM_EXC_STAT_REG_EXC_BS_STOP_Msk | + CMAC_CM_EXC_STAT_REG_EXC_FRAME_START_Msk | + CMAC_CM_EXC_STAT_REG_EXC_PHY_TO_IDLE_4THIS_Msk | + CMAC_CM_EXC_STAT_REG_EXC_SW_MAC_Msk; + + NVIC->ICPR[0] = (1 << FIELD_IRQn) | (1 << CALLBACK_IRQn) | + (1 << FRAME_IRQn) | (1 << SW_MAC_IRQn); + + os_arch_cmac_bs_ctrl_irq_unblock(); + g_sw_mac_exc = 0; + + CMAC->CM_ERROR_DIS_REG = 0; + + ble_rf_stop(); + + /* + * If ble_phy_disable is called precisely when access address was matched, + * ts1_dirty may not be cleared properly. This is because bs_clear will + * cause bitstream controller to be stopped and we won't get callback_irq, + * but seems like demodulator is still active for a while and will trigger + * ev1c_ts1_trigger on 1st symbol which will set ts1_dirty. We do not expect + * ts1_dirty to be set after bs_clear so we won't clear it. To workaround + * his, we can just clear it explicitly here after everything is already + * disabled. + */ + (void)CMAC->CM_TS1_REG; + + __enable_irq(); + + g_ble_phy_data.phy_state = BLE_PHY_STATE_IDLE; +} + +static void +ble_phy_rx_setup_fields(void) +{ + /* Make sure CRC LFSR initial value is set */ + CMAC_SETREGF(CM_CRC_REG, CRC_INIT_VAL, g_ble_phy_data.crc_init); + + CMAC->CM_FIELD_PUSH_DATA_REG = g_ble_phy_data.access_addr; + CMAC->CM_FIELD_PUSH_CTRL_REG = FIELD_CTRL_REG_RX_ACCESS_ADDR; + CMAC->CM_FIELD_PUSH_DATA_REG = FIELD_DATA_REG_DMA_RX(0, 2); + CMAC->CM_FIELD_PUSH_CTRL_REG = FIELD_CTRL_REG_RX_HEADER; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + if (g_ble_phy_data.phy_encrypted) { + /* Only program one byte for encrypted payloads */ + CMAC->CM_FIELD_PUSH_DATA_REG = FIELD_DATA_REG_DMA_RX(2, 2); + CMAC->CM_FIELD_PUSH_CTRL_REG = FIELD_CTRL_REG_RX_ENC_PAYLOAD; + } else { + CMAC->CM_FIELD_PUSH_DATA_REG = FIELD_DATA_REG_DMA_RX(2, 2); + CMAC->CM_FIELD_PUSH_CTRL_REG = FIELD_CTRL_REG_RX_PAYLOAD; + } +#else + CMAC->CM_FIELD_PUSH_DATA_REG = FIELD_DATA_REG_DMA_RX(2, 2); + CMAC->CM_FIELD_PUSH_CTRL_REG = FIELD_CTRL_REG_RX_PAYLOAD; +#endif +} + +static void +ble_phy_rx_setup_xcvr(void) +{ + uint8_t rf_chan = g_ble_phy_chan_to_rf[g_ble_phy_data.channel]; + + CMAC->CM_EV_SET_REG = CMAC_CM_EV_SET_REG_EV1C_CALLBACK_VALID_SET_Msk; + + ble_rf_setup_rx(rf_chan, g_ble_phy_data.phy_mode_rx); + + g_ble_phy_data.phy_rx_started = 0; +} + +int +ble_phy_rx(void) +{ + MCU_DIAG_SER('R'); + + ble_rf_configure(); + ble_phy_rx_setup_xcvr(); + + CMAC->CM_FRAME_1_REG = CMAC_CM_FRAME_1_REG_FRAME_VALID_Msk; + + CMAC_SETREGF(CM_PHY_CTRL2_REG, CORR_WINDOW, 0); + + ble_phy_rx_setup_fields(); + + g_ble_phy_data.phy_state = BLE_PHY_STATE_RX; + + return 0; +} + +int +ble_phy_rx_set_start_time(uint32_t cputime, uint8_t rem_usecs) +{ + uint32_t ll_val32; + int32_t time_till_start; + + MCU_DIAG_SER('r'); + +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) + ble_phy_mode_apply(g_ble_phy_data.phy_mode_rx); +#endif + + assert(ble_rf_is_enabled()); + + ble_phy_rx(); + + /* Get LL timer at cputime */ + ll_val32 = ble_phy_convert_and_record_start_time(cputime, rem_usecs); + + /* Add remaining usecs to get exact receive start time */ + ll_val32 += rem_usecs; + + /* Adjust start time for rx delays */ + ll_val32 -= PHY_DELAY_POWER_UP_RX - g_ble_phy_data.path_delay_rx; + + __disable_irq(); + CMAC->CM_LL_TIMER1_9_0_EQ_X_REG = ll_val32; + CMAC->CM_EV_LINKUP_REG = + CMAC_CM_EV_LINKUP_REG_LU_FRAME_START_2_TMR1_9_0_EQ_X_Msk; + + time_till_start = (int32_t)(ll_val32 - cmac_timer_read32()); + if (time_till_start <= 0) { + /* + * Possible we missed the frame start! If we have, we need to start + * ASAP. + */ + if ((CMAC->CM_EXC_STAT_REG & CMAC_CM_EXC_STAT_REG_EXC_FRAME_START_Msk) == 0) { + /* We missed start. Start now */ + CMAC->CM_EV_LINKUP_REG = + CMAC_CM_EV_LINKUP_REG_LU_FRAME_START_2_ASAP_Msk; + } + } + __enable_irq(); + + return 0; +} + +int +ble_phy_tx(ble_phy_tx_pducb_t pducb, void *pducb_arg, uint8_t end_trans) +{ + uint8_t *txbuf = g_ble_phy_tx_buf; + int rc; + + MCU_DIAG_SER('T'); + + assert(CMAC->CM_FRAME_1_REG & CMAC_CM_FRAME_1_REG_FRAME_TX_Msk); + + g_ble_phy_data.end_transition = end_trans; + + /* + * Program required fields now so in worst case TX can continue while we + * are still preparing header and payload. + */ + CMAC->CM_FIELD_PUSH_DATA_REG = g_ble_phy_data.access_addr & 1 ? 0x5555 : 0xaaaa; + CMAC->CM_FIELD_PUSH_CTRL_REG = FIELD_CTRL_REG_TX_PREAMBLE; + CMAC->CM_FIELD_PUSH_DATA_REG = g_ble_phy_data.access_addr; + CMAC->CM_FIELD_PUSH_CTRL_REG = FIELD_CTRL_REG_TX_ACCESS_ADDR; + + /* Make sure CRC LFSR initial value is set */ + CMAC_SETREGF(CM_CRC_REG, CRC_INIT_VAL, g_ble_phy_data.crc_init); + + /* txbuf[0] is hdr_byte, txbuf[1] is pkt_len */ + txbuf[1] = pducb(&txbuf[2], pducb_arg, &txbuf[0]); + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + if (g_ble_phy_data.phy_encrypted && (txbuf[1] != 0)) { + /* We have to add the MIC to the length */ + txbuf[1] += BLE_LL_DATA_MIC_LEN; + + /* Program header field */ + CMAC->CM_FIELD_PUSH_DATA_REG = FIELD_DATA_REG_DMA_TX(0, 2); + CMAC->CM_FIELD_PUSH_CTRL_REG = FIELD_CTRL_REG_TX_PAYLOAD; + + /* Program payload (and MIC) */ + CMAC->CM_FIELD_PUSH_DATA_REG = FIELD_DATA_REG_DMA_TX(2, txbuf[1]); + CMAC->CM_FIELD_PUSH_CTRL_REG = FIELD_CTRL_REG_TX_ENC_PAYLOAD; + } else { + /* Program header and payload fields */ + CMAC->CM_FIELD_PUSH_DATA_REG = FIELD_DATA_REG_DMA_TX(0, txbuf[1] + 2); + CMAC->CM_FIELD_PUSH_CTRL_REG = FIELD_CTRL_REG_TX_PAYLOAD; + } +#else + /* Program header and payload fields */ + CMAC->CM_FIELD_PUSH_DATA_REG = FIELD_DATA_REG_DMA_TX(0, txbuf[1] + 2); + CMAC->CM_FIELD_PUSH_CTRL_REG = FIELD_CTRL_REG_TX_PAYLOAD; +#endif + + /* + * If there was FIELD_ON_THR exception it means access address was already + * sent and we are likely too late here - abort. + */ + if (CMAC->CM_EXC_STAT_REG & CMAC_CM_EXC_STAT_REG_EXC_FIELD_ON_THR_EXP_Msk) { + ble_phy_disable(); + g_ble_phy_data.end_transition = BLE_PHY_TRANSITION_NONE; + STATS_INC(ble_phy_stats, tx_late); + rc = BLE_PHY_ERR_RADIO_STATE; + } else { + if (g_ble_phy_data.phy_state == BLE_PHY_STATE_IDLE) { + g_ble_phy_data.phy_state = BLE_PHY_STATE_TX; + } + STATS_INC(ble_phy_stats, tx_good); + STATS_INCN(ble_phy_stats, tx_bytes, txbuf[1] + 2); + rc = BLE_ERR_SUCCESS; + } + + /* Now we can handle BS_CTRL */ + CMAC->CM_ERROR_DIS_REG &= ~CMAC_CM_ERROR_DIS_REG_CM_FIELD1_ERR_Msk; + NVIC_EnableIRQ(FRAME_IRQn); + NVIC_EnableIRQ(FIELD_IRQn); + + return rc; +} + +int +ble_phy_tx_set_start_time(uint32_t cputime, uint8_t rem_usecs) +{ + uint8_t rf_chan = g_ble_phy_chan_to_rf[g_ble_phy_data.channel]; + uint32_t ll_val32; + int rc; + + MCU_DIAG_SER('t'); + +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) + ble_phy_mode_apply(g_ble_phy_data.phy_mode_tx); +#endif + + assert(ble_rf_is_enabled()); + + ble_rf_configure(); + ble_rf_setup_tx(rf_chan, g_ble_phy_data.phy_mode_tx); + + ll_val32 = ble_phy_convert_and_record_start_time(cputime, rem_usecs); + ll_val32 += rem_usecs; + ll_val32 -= PHY_DELAY_POWER_UP_TX + g_ble_phy_data.path_delay_tx; + /* we can schedule TX only up to 1023us in advance */ + assert((int32_t)(ll_val32 - cmac_timer_read32()) < 1024); + + /* + * We do not want FIELD/FRAME interrupts or FIELD1_ERR until ble_phy_tx() + * has finished pushing all the fields. Also we do not want premature + * FRAME_ERR so disable it until we program FRAME1 properly. If we won't + * make configuration on time, assume tx_late and abort TX. + */ + NVIC_DisableIRQ(FRAME_IRQn); + NVIC_DisableIRQ(FIELD_IRQn); + CMAC->CM_ERROR_DIS_REG |= CMAC_CM_ERROR_DIS_REG_CM_FIELD1_ERR_Msk | + CMAC_CM_ERROR_DIS_REG_CM_FRAME_ERR_Msk; + + CMAC->CM_LL_TIMER1_9_0_EQ_X_REG = ll_val32; + CMAC->CM_EV_LINKUP_REG = CMAC_CM_EV_LINKUP_REG_LU_FRAME_START_2_TMR1_9_0_EQ_X_Msk; + + if ((int32_t)(ll_val32 - cmac_timer_read32()) < 0) { + goto tx_late; + } + + /* + * Program frame now since it needs to be ready for FRAME_START, we can + * push fields later + */ + CMAC->CM_FRAME_1_REG = CMAC_CM_FRAME_1_REG_FRAME_VALID_Msk | + CMAC_CM_FRAME_1_REG_FRAME_TX_Msk | + CMAC_CM_FRAME_1_REG_FRAME_EXC_ON_BS_START_Msk; + + /* + * There should be no EXC_FRAME_START here so if it already happened we + * need to assume tx_late and abort. + */ + if (CMAC->CM_EXC_STAT_REG & CMAC_CM_EXC_STAT_REG_EXC_FRAME_START_Msk) { + goto tx_late; + } + + CMAC->CM_ERROR_DIS_REG &= ~CMAC_CM_ERROR_DIS_REG_CM_FRAME_ERR_Msk; + rc = 0; + + goto done; + +tx_late: + STATS_INC(ble_phy_stats, tx_late); + ble_phy_disable(); + NVIC_EnableIRQ(FRAME_IRQn); + NVIC_EnableIRQ(FIELD_IRQn); + rc = BLE_PHY_ERR_TX_LATE; + +done: + return rc; +} + +void +ble_phy_set_txend_cb(ble_phy_tx_end_func txend_cb, void *arg) +{ + g_ble_phy_data.txend_cb = txend_cb; + g_ble_phy_data.txend_arg = arg; +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) +void +ble_phy_tx_enc_start(void) +{ + struct ble_phy_encrypt_obj *enc; + + enc = &g_ble_phy_encrypt_data; + enc->b0[15] = g_ble_phy_tx_buf[1] - 4; + enc->b1[2] = g_ble_phy_tx_buf[0] & BLE_LL_DATA_HDR_LLID_MASK; + + /* XXX: should we check for busy? */ + /* XXX: might not be needed, but for now terminate any crypto operations. */ + 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_IN_SEL_Msk | + CMAC_CM_CRYPTO_CTRL_REG_CM_CRYPTO_CTR_MAC_EN_Msk | + CMAC_CM_CRYPTO_CTRL_REG_CM_CRYPTO_CTR_PLD_EN_Msk | + CMAC_CM_CRYPTO_CTRL_REG_CM_CRYPTO_AUTH_EN_Msk | + CMAC_CM_CRYPTO_CTRL_REG_CM_CRYPTO_ENC_DECN_Msk; + + /* Start crypto */ + CMAC->CM_EV_SET_REG = CMAC_CM_EV_SET_REG_EV_CRYPTO_START_Msk; +} + +void +ble_phy_rx_enc_start(uint8_t len) +{ + struct ble_phy_encrypt_obj *enc; + + enc = &g_ble_phy_encrypt_data; + enc->b0[15] = len - 4; /* length without MIC as length includes MIC */ + enc->b1[2] = g_ble_phy_rx_buf[0] & BLE_LL_DATA_HDR_LLID_MASK; + + /* XXX: should we check for busy? */ + /* XXX: might not be needed, but for now terminate any crypto operations. */ + //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_OUT_SEL_Msk | + CMAC_CM_CRYPTO_CTRL_REG_CM_CRYPTO_CTR_MAC_EN_Msk | + CMAC_CM_CRYPTO_CTRL_REG_CM_CRYPTO_CTR_PLD_EN_Msk | + CMAC_CM_CRYPTO_CTRL_REG_CM_CRYPTO_AUTH_EN_Msk; + + /* Start crypto */ + CMAC->CM_EV_SET_REG = CMAC_CM_EV_SET_REG_EV_CRYPTO_START_Msk; +} + +void +ble_phy_encrypt_enable(uint64_t pkt_counter, uint8_t *iv, uint8_t *key, + uint8_t is_master) +{ + struct ble_phy_encrypt_obj *enc; + + enc = &g_ble_phy_encrypt_data; + memcpy(enc->key, key, 16); + memcpy(&enc->b0[6], iv, 8); + put_le32(&enc->b0[1], pkt_counter); + enc->b0[5] = is_master ? 0x80 : 0; + memcpy(&enc->ai[6], iv, 8); + put_le32(&enc->ai[1], pkt_counter); + enc->ai[5] = enc->b0[5]; + + g_ble_phy_data.phy_encrypted = 1; + + /* Program key registers */ + CMAC->CM_CRYPTO_KEY_31_0_REG = get_le32(&enc->key[0]); + CMAC->CM_CRYPTO_KEY_63_32_REG = get_le32(&enc->key[4]); + CMAC->CM_CRYPTO_KEY_95_64_REG = get_le32(&enc->key[8]); + CMAC->CM_CRYPTO_KEY_127_96_REG = get_le32(&enc->key[12]); + + /* Program ADRx registers */ + CMAC->CM_CRYPTO_IN_ADR0_REG = (uint32_t)enc->b1; + CMAC->CM_CRYPTO_IN_ADR1_REG = (uint32_t)enc->b0; + CMAC->CM_CRYPTO_IN_ADR2_REG = (uint32_t)&g_ble_phy_tx_buf[2]; + CMAC->CM_CRYPTO_IN_ADR3_REG = (uint32_t)enc->ai; + CMAC->CM_CRYPTO_OUT_ADR_REG = (uint32_t)&g_ble_phy_rx_buf[2]; + + CMAC->CM_CRYPTO_CTRL_REG = CMAC_CM_CRYPTO_CTRL_REG_CM_CRYPTO_SW_REQ_PBUF_CLR_Msk; +} + +void +ble_phy_encrypt_set_pkt_cntr(uint64_t pkt_counter, int dir) +{ + struct ble_phy_encrypt_obj *enc; + + enc = &g_ble_phy_encrypt_data; + put_le32(&enc->b0[1], pkt_counter); + enc->b0[5] = dir ? 0x80 : 0; + put_le32(&enc->ai[1], pkt_counter); + enc->ai[5] = enc->b0[5]; + + CMAC->CM_CRYPTO_CTRL_REG = CMAC_CM_CRYPTO_CTRL_REG_CM_CRYPTO_SW_REQ_PBUF_CLR_Msk; +} + +void +ble_phy_encrypt_disable(void) +{ + g_ble_phy_data.phy_encrypted = 0; +} +#endif + +int +ble_phy_txpwr_set(int dbm) +{ +#if MYNEWT_VAL(CMAC_DEBUG_DATA_ENABLE) + if (g_cmac_shared_data.debug.tx_power_override != INT8_MAX) { + ble_rf_set_tx_power(g_cmac_shared_data.debug.tx_power_override); + } else { + ble_rf_set_tx_power(dbm); + } +#else + ble_rf_set_tx_power(dbm); +#endif + + return 0; +} + +int +ble_phy_txpower_round(int dbm) +{ + return 0; +} + +void +ble_phy_set_rx_pwr_compensation(int8_t compensation) +{ +} + +int +ble_phy_setchan(uint8_t chan, uint32_t access_addr, uint32_t crc_init) +{ + uint8_t rf_chan = g_ble_phy_chan_to_rf[chan]; + + assert(chan < BLE_PHY_NUM_CHANS); + + if (chan >= BLE_PHY_NUM_CHANS) { + return BLE_PHY_ERR_INV_PARAM; + } + + g_ble_phy_data.channel = chan; + g_ble_phy_data.access_addr = access_addr; + g_ble_phy_data.crc_init = crc_init; + + CMAC_SETREGF(CM_PHY_CTRL2_REG, PHY_RF_CHANNEL, rf_chan); + + return 0; +} + +void +ble_phy_restart_rx(void) +{ + /* XXX: for now, we will disable the phy using ble_phy_disable and then + re-enable it + */ + ble_phy_disable(); + + /* Apply mode before starting RX */ +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) + ble_phy_mode_apply(g_ble_phy_data.phy_mode_rx); +#endif + + /* Setup phy to rx again */ + ble_phy_rx(); + + /* Start reception now */ + CMAC->CM_EV_LINKUP_REG = CMAC_CM_EV_LINKUP_REG_LU_FRAME_START_2_ASAP_Msk; +} + +uint32_t +ble_phy_access_addr_get(void) +{ + return g_ble_phy_data.access_addr; +} + +int +ble_phy_state_get(void) +{ + return g_ble_phy_data.phy_state; +} + +int +ble_phy_rx_started(void) +{ + return g_ble_phy_data.phy_rx_started; +} + +uint8_t +ble_phy_xcvr_state_get(void) +{ + return ble_rf_is_enabled(); +} + +uint8_t +ble_phy_max_data_pdu_pyld(void) +{ + return BLE_LL_DATA_PDU_MAX_PYLD; +} + +void +ble_phy_resolv_list_enable(void) +{ + g_ble_phy_data.phy_privacy = 1; + + ble_hw_resolv_proc_enable(); +} + +void +ble_phy_resolv_list_disable(void) +{ + ble_hw_resolv_proc_disable(); + + g_ble_phy_data.phy_privacy = 0; +} + +void +ble_phy_rfclk_enable(void) +{ + ble_rf_enable(); +} + +void +ble_phy_rfclk_disable(void) +{ + /* XXX We can't disable RF while PHY_BUSY is asserted so let's wait a bit */ + while (CMAC->CM_DIAG_WORD2_REG & CMAC_CM_DIAG_WORD2_REG_DIAG2_PHY_BUSY_BUF_Msk); + + ble_rf_disable(); +} + +#if MYNEWT_VAL(BLE_LL_DTM) +void +ble_phy_enable_dtm(void) +{ + g_ble_phy_data.phy_whitening = 0; +} + +void +ble_phy_disable_dtm(void) +{ + g_ble_phy_data.phy_whitening = 1; +} +#endif diff --git a/src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/src/ble_rf.c b/src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/src/ble_rf.c new file mode 100644 index 00000000..806f4ea8 --- /dev/null +++ b/src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/src/ble_rf.c @@ -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 +#include +#include +#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; +} diff --git a/src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/src/ble_rf_priv.h b/src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/src/ble_rf_priv.h new file mode 100644 index 00000000..50c2e4a7 --- /dev/null +++ b/src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/src/ble_rf_priv.h @@ -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_ */ diff --git a/src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/syscfg.yml b/src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/syscfg.yml new file mode 100644 index 00000000..a82b62e5 --- /dev/null +++ b/src/libs/mynewt-nimble/nimble/drivers/dialog_cmac/syscfg.yml @@ -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 diff --git a/src/libs/mynewt-nimble/nimble/drivers/native/src/ble_hw.c b/src/libs/mynewt-nimble/nimble/drivers/native/src/ble_hw.c index 5eb1eb95..8aa29d32 100644 --- a/src/libs/mynewt-nimble/nimble/drivers/native/src/ble_hw.c +++ b/src/libs/mynewt-nimble/nimble/drivers/native/src/ble_hw.c @@ -20,6 +20,8 @@ #include #include #include +#include +#include #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) diff --git a/src/libs/mynewt-nimble/nimble/drivers/nrf5340/include/ble/xcvr.h b/src/libs/mynewt-nimble/nimble/drivers/nrf5340/include/ble/xcvr.h new file mode 100644 index 00000000..df6ef700 --- /dev/null +++ b/src/libs/mynewt-nimble/nimble/drivers/nrf5340/include/ble/xcvr.h @@ -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_ */ diff --git a/src/libs/mynewt-nimble/nimble/drivers/nrf5340/pkg.yml b/src/libs/mynewt-nimble/nimble/drivers/nrf5340/pkg.yml new file mode 100644 index 00000000..3ff44212 --- /dev/null +++ b/src/libs/mynewt-nimble/nimble/drivers/nrf5340/pkg.yml @@ -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 " +pkg.homepage: "http://mynewt.apache.org/" +pkg.keywords: + - ble + - bluetooth + +pkg.apis: ble_driver +pkg.deps: + - nimble + - nimble/controller diff --git a/src/libs/mynewt-nimble/nimble/drivers/nrf5340/src/ble_hw.c b/src/libs/mynewt-nimble/nimble/drivers/nrf5340/src/ble_hw.c new file mode 100644 index 00000000..bbe61697 --- /dev/null +++ b/src/libs/mynewt-nimble/nimble/drivers/nrf5340/src/ble_hw.c @@ -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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* 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 diff --git a/src/libs/mynewt-nimble/nimble/drivers/nrf5340/src/ble_phy.c b/src/libs/mynewt-nimble/nimble/drivers/nrf5340/src/ble_phy.c new file mode 100644 index 00000000..e07bbaa1 --- /dev/null +++ b/src/libs/mynewt-nimble/nimble/drivers/nrf5340/src/ble_phy.c @@ -0,0 +1,1820 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/* + * NOTE: This code uses 0-5 DPPI channels so care should be taken when using + * DPPI somewhere else. + * TODO maybe we could reduce number of used channels if we reuse same channel + * for mutually exclusive events but for now make it simpler to debug. + */ + +#define DPPI_CH_TIMER0_EVENTS_COMPARE_0 0 +#define DPPI_CH_TIMER0_EVENTS_COMPARE_3 1 +#define DPPI_CH_RADIO_EVENTS_END 2 +#define DPPI_CH_RADIO_EVENTS_BCMATCH 3 +#define DPPI_CH_RADIO_EVENTS_ADDRESS 4 +#define DPPI_CH_RTC0_EVENTS_COMPARE_0 5 + +#define DPPI_CH_ENABLE_ALL (DPPIC_CHEN_CH0_Msk | DPPIC_CHEN_CH1_Msk | DPPIC_CHEN_CH2_Msk | \ + DPPIC_CHEN_CH3_Msk | DPPIC_CHEN_CH4_Msk | DPPIC_CHEN_CH5_Msk) + +#define DPPI_PUBLISH_TIMER0_EVENTS_COMPARE_0 ((DPPI_CH_TIMER0_EVENTS_COMPARE_0 << TIMER_PUBLISH_COMPARE_CHIDX_Pos) | \ + (TIMER_PUBLISH_COMPARE_EN_Enabled << TIMER_PUBLISH_COMPARE_EN_Pos)) +#define DPPI_PUBLISH_TIMER0_EVENTS_COMPARE_3 ((DPPI_CH_TIMER0_EVENTS_COMPARE_3 << TIMER_PUBLISH_COMPARE_CHIDX_Pos) | \ + (TIMER_PUBLISH_COMPARE_EN_Enabled << TIMER_PUBLISH_COMPARE_EN_Pos)) +#define DPPI_PUBLISH_RADIO_EVENTS_END ((DPPI_CH_RADIO_EVENTS_END << RADIO_PUBLISH_END_CHIDX_Pos) | \ + (RADIO_PUBLISH_END_EN_Enabled << RADIO_PUBLISH_END_EN_Pos)) +#define DPPI_PUBLISH_RADIO_EVENTS_BCMATCH ((DPPI_CH_RADIO_EVENTS_BCMATCH << RADIO_PUBLISH_BCMATCH_CHIDX_Pos) | \ + (RADIO_PUBLISH_BCMATCH_EN_Enabled << RADIO_PUBLISH_BCMATCH_EN_Pos)) +#define DPPI_PUBLISH_RADIO_EVENTS_ADDRESS ((DPPI_CH_RADIO_EVENTS_ADDRESS << RADIO_PUBLISH_ADDRESS_CHIDX_Pos) | \ + (RADIO_PUBLISH_ADDRESS_EN_Enabled << RADIO_PUBLISH_ADDRESS_EN_Pos)) +#define DPPI_PUBLISH_RTC0_EVENTS_COMPARE_0 ((DPPI_CH_RTC0_EVENTS_COMPARE_0 << RTC_PUBLISH_COMPARE_CHIDX_Pos) | \ + (RTC_PUBLISH_COMPARE_EN_Enabled << RTC_PUBLISH_COMPARE_EN_Pos)) + +#define DPPI_SUBSCRIBE_TIMER0_TASKS_START(_enable) ((DPPI_CH_RTC0_EVENTS_COMPARE_0 << TIMER_SUBSCRIBE_START_CHIDX_Pos) | \ + ((_enable) << TIMER_SUBSCRIBE_START_EN_Pos)) +#define DPPI_SUBSCRIBE_TIMER0_TASKS_CAPTURE1(_enable) ((DPPI_CH_RADIO_EVENTS_ADDRESS << TIMER_SUBSCRIBE_CAPTURE_CHIDX_Pos) | \ + ((_enable) << TIMER_SUBSCRIBE_CAPTURE_EN_Pos)) +#define DPPI_SUBSCRIBE_TIMER0_TASKS_CAPTURE2(_enable) ((DPPI_CH_RADIO_EVENTS_END << TIMER_SUBSCRIBE_CAPTURE_CHIDX_Pos) | \ + ((_enable) << TIMER_SUBSCRIBE_CAPTURE_EN_Pos)) +#define DPPI_SUBSCRIBE_TIMER0_TASKS_CAPTURE3(_enable) ((DPPI_CH_RADIO_EVENTS_ADDRESS << TIMER_SUBSCRIBE_CAPTURE_CHIDX_Pos) | \ + ((_enable) << TIMER_SUBSCRIBE_CAPTURE_EN_Pos)) +#define DPPI_SUBSCRIBE_RADIO_TASKS_DISABLE(_enable) ((DPPI_CH_TIMER0_EVENTS_COMPARE_3 << RADIO_SUBSCRIBE_DISABLE_CHIDX_Pos) | \ + ((_enable) << RADIO_SUBSCRIBE_DISABLE_EN_Pos)) +#define DPPI_SUBSCRIBE_RADIO_TASKS_RXEN(_enable) ((DPPI_CH_TIMER0_EVENTS_COMPARE_0 << RADIO_SUBSCRIBE_RXEN_CHIDX_Pos) | \ + ((_enable) << RADIO_SUBSCRIBE_RXEN_EN_Pos)) +#define DPPI_SUBSCRIBE_RADIO_TASKS_TXEN(_enable) ((DPPI_CH_TIMER0_EVENTS_COMPARE_0 << RADIO_SUBSCRIBE_TXEN_CHIDX_Pos) | \ + ((_enable) << RADIO_SUBSCRIBE_TXEN_EN_Pos)) +#define DPPI_SUBSCRIBE_AAR_TASKS_START(_enable) ((DPPI_CH_RADIO_EVENTS_BCMATCH << AAR_SUBSCRIBE_START_CHIDX_Pos) | \ + ((_enable) << AAR_SUBSCRIBE_START_EN_Pos)) +#define DPPI_SUBSCRIBE_CCM_TASKS_CRYPT(_enable) ((DPPI_CH_RADIO_EVENTS_ADDRESS << CCM_SUBSCRIBE_CRYPT_CHIDX_Pos) | \ + ((_enable) << CCM_SUBSCRIBE_CRYPT_EN_Pos)) + +extern uint8_t g_nrf_num_irks; +extern uint32_t g_nrf_irk_list[]; + +/* To disable all radio interrupts */ +#define NRF_RADIO_IRQ_MASK_ALL (0x34FF) + +/* + * We configure the nrf with a 1 byte S0 field, 8 bit length field, and + * zero bit S1 field. The preamble is 8 bits long. + */ +#define NRF_LFLEN_BITS (8) +#define NRF_S0LEN (1) +#define NRF_S1LEN_BITS (0) +#define NRF_CILEN_BITS (2) +#define NRF_TERMLEN_BITS (3) + +/* Maximum length of frames */ +#define NRF_MAXLEN (255) +#define NRF_BALEN (3) /* For base address of 3 bytes */ + +/* NRF_RADIO_NS->PCNF0 configuration values */ +#define NRF_PCNF0 (NRF_LFLEN_BITS << RADIO_PCNF0_LFLEN_Pos) | \ + (RADIO_PCNF0_S1INCL_Msk) | \ + (NRF_S0LEN << RADIO_PCNF0_S0LEN_Pos) | \ + (NRF_S1LEN_BITS << RADIO_PCNF0_S1LEN_Pos) +#define NRF_PCNF0_1M (NRF_PCNF0) | \ + (RADIO_PCNF0_PLEN_8bit << RADIO_PCNF0_PLEN_Pos) +#define NRF_PCNF0_2M (NRF_PCNF0) | \ + (RADIO_PCNF0_PLEN_16bit << RADIO_PCNF0_PLEN_Pos) +#define NRF_PCNF0_CODED (NRF_PCNF0) | \ + (RADIO_PCNF0_PLEN_LongRange << RADIO_PCNF0_PLEN_Pos) | \ + (NRF_CILEN_BITS << RADIO_PCNF0_CILEN_Pos) | \ + (NRF_TERMLEN_BITS << RADIO_PCNF0_TERMLEN_Pos) + +/* BLE PHY data structure */ +struct ble_phy_obj { + uint8_t phy_stats_initialized; + int8_t phy_txpwr_dbm; + uint8_t phy_chan; + uint8_t phy_state; + uint8_t phy_transition; + uint8_t phy_transition_late; + uint8_t phy_rx_started; + uint8_t phy_encrypted; + uint8_t phy_privacy; + uint8_t phy_tx_pyld_len; + uint8_t phy_cur_phy_mode; + uint8_t phy_tx_phy_mode; + uint8_t phy_rx_phy_mode; + uint8_t phy_bcc_offset; + int8_t rx_pwr_compensation; + uint32_t phy_aar_scratch; + uint32_t phy_access_address; + struct ble_mbuf_hdr rxhdr; + void *txend_arg; + ble_phy_tx_end_func txend_cb; + uint32_t phy_start_cputime; +}; +struct ble_phy_obj g_ble_phy_data; + +/* XXX: if 27 byte packets desired we can make this smaller */ +/* Global transmit/receive buffer */ +static uint32_t g_ble_phy_tx_buf[(BLE_PHY_MAX_PDU_LEN + 3) / 4]; +static uint32_t g_ble_phy_rx_buf[(BLE_PHY_MAX_PDU_LEN + 3) / 4]; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) +/* Make sure word-aligned for faster copies */ +static uint32_t g_ble_phy_enc_buf[(BLE_PHY_MAX_PDU_LEN + 3) / 4]; +#endif + +/* RF center frequency for each channel index (offset from 2400 MHz) */ +static const uint8_t g_ble_phy_chan_freq[BLE_PHY_NUM_CHANS] = { + 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, /* 0-9 */ + 24, 28, 30, 32, 34, 36, 38, 40, 42, 44, /* 10-19 */ + 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, /* 20-29 */ + 66, 68, 70, 72, 74, 76, 78, 2, 26, 80, /* 30-39 */ +}; + +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) +/* packet start offsets (in usecs) */ +static const uint16_t g_ble_phy_mode_pkt_start_off[BLE_PHY_NUM_MODE] = { + [BLE_PHY_MODE_1M] = 40, + [BLE_PHY_MODE_2M] = 24, + [BLE_PHY_MODE_CODED_125KBPS] = 376, + [BLE_PHY_MODE_CODED_500KBPS] = 376 +}; +#endif + +/* Various radio timings */ +/* Radio ramp-up times in usecs (fast mode) */ +#define BLE_PHY_T_TXENFAST (XCVR_TX_RADIO_RAMPUP_USECS) +#define BLE_PHY_T_RXENFAST (XCVR_RX_RADIO_RAMPUP_USECS) + +/* delay between EVENTS_READY and start of tx */ +static const uint8_t g_ble_phy_t_txdelay[BLE_PHY_NUM_MODE] = { + [BLE_PHY_MODE_1M] = 4, + [BLE_PHY_MODE_2M] = 3, + [BLE_PHY_MODE_CODED_125KBPS] = 5, + [BLE_PHY_MODE_CODED_500KBPS] = 5 +}; +/* delay between EVENTS_END and end of txd packet */ +static const uint8_t g_ble_phy_t_txenddelay[BLE_PHY_NUM_MODE] = { + [BLE_PHY_MODE_1M] = 4, + [BLE_PHY_MODE_2M] = 3, + [BLE_PHY_MODE_CODED_125KBPS] = 9, + [BLE_PHY_MODE_CODED_500KBPS] = 3 +}; +/* delay between rxd access address (w/ TERM1 for coded) and EVENTS_ADDRESS */ +static const uint8_t g_ble_phy_t_rxaddrdelay[BLE_PHY_NUM_MODE] = { + [BLE_PHY_MODE_1M] = 6, + [BLE_PHY_MODE_2M] = 2, + [BLE_PHY_MODE_CODED_125KBPS] = 17, + [BLE_PHY_MODE_CODED_500KBPS] = 17 +}; +/* delay between end of rxd packet and EVENTS_END */ +static const uint8_t g_ble_phy_t_rxenddelay[BLE_PHY_NUM_MODE] = { + [BLE_PHY_MODE_1M] = 6, + [BLE_PHY_MODE_2M] = 2, + [BLE_PHY_MODE_CODED_125KBPS] = 27, + [BLE_PHY_MODE_CODED_500KBPS] = 22 +}; + +/* Statistics */ +STATS_SECT_START(ble_phy_stats) +STATS_SECT_ENTRY(phy_isrs) +STATS_SECT_ENTRY(tx_good) +STATS_SECT_ENTRY(tx_fail) +STATS_SECT_ENTRY(tx_late) +STATS_SECT_ENTRY(tx_bytes) +STATS_SECT_ENTRY(rx_starts) +STATS_SECT_ENTRY(rx_aborts) +STATS_SECT_ENTRY(rx_valid) +STATS_SECT_ENTRY(rx_crc_err) +STATS_SECT_ENTRY(rx_late) +STATS_SECT_ENTRY(radio_state_errs) +STATS_SECT_ENTRY(rx_hw_err) +STATS_SECT_ENTRY(tx_hw_err) +STATS_SECT_END +STATS_SECT_DECL(ble_phy_stats) ble_phy_stats; + +STATS_NAME_START(ble_phy_stats) +STATS_NAME(ble_phy_stats, phy_isrs) +STATS_NAME(ble_phy_stats, tx_good) +STATS_NAME(ble_phy_stats, tx_fail) +STATS_NAME(ble_phy_stats, tx_late) +STATS_NAME(ble_phy_stats, tx_bytes) +STATS_NAME(ble_phy_stats, rx_starts) +STATS_NAME(ble_phy_stats, rx_aborts) +STATS_NAME(ble_phy_stats, rx_valid) +STATS_NAME(ble_phy_stats, rx_crc_err) +STATS_NAME(ble_phy_stats, rx_late) +STATS_NAME(ble_phy_stats, radio_state_errs) +STATS_NAME(ble_phy_stats, rx_hw_err) +STATS_NAME(ble_phy_stats, tx_hw_err) +STATS_NAME_END(ble_phy_stats) + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) +/* + * Per nordic, the number of bytes needed for scratch is 16 + MAX_PKT_SIZE. + * However, when I used a smaller size it still overwrote the scratchpad. Until + * I figure this out I am just going to allocate 67 words so we have enough + * space for 267 bytes of scratch. I used 268 bytes since not sure if this + * needs to be aligned and burning a byte is no big deal. + * + *#define NRF_ENC_SCRATCH_WORDS (((MYNEWT_VAL(BLE_LL_MAX_PKT_SIZE) + 16) + 3) / 4) + */ +#define NRF_ENC_SCRATCH_WORDS (67) + +static uint32_t nrf_encrypt_scratchpad[NRF_ENC_SCRATCH_WORDS]; + +struct nrf_ccm_data { + uint8_t key[16]; + uint64_t pkt_counter; + uint8_t dir_bit; + uint8_t iv[8]; +} __attribute__((packed)); + +static struct nrf_ccm_data nrf_ccm_data; +#endif + +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) + +uint32_t +ble_phy_mode_pdu_start_off(int phy_mode) +{ + return g_ble_phy_mode_pkt_start_off[phy_mode]; +} + +static void +ble_phy_mode_apply(uint8_t phy_mode) +{ + if (phy_mode == g_ble_phy_data.phy_cur_phy_mode) { + return; + } + + switch (phy_mode) { + case BLE_PHY_MODE_1M: + NRF_RADIO_NS->MODE = RADIO_MODE_MODE_Ble_1Mbit; + NRF_RADIO_NS->PCNF0 = NRF_PCNF0_1M; + break; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) + case BLE_PHY_MODE_2M: + NRF_RADIO_NS->MODE = RADIO_MODE_MODE_Ble_2Mbit; + NRF_RADIO_NS->PCNF0 = NRF_PCNF0_2M; + break; +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) + case BLE_PHY_MODE_CODED_125KBPS: + NRF_RADIO_NS->MODE = RADIO_MODE_MODE_Ble_LR125Kbit; + NRF_RADIO_NS->PCNF0 = NRF_PCNF0_CODED; + break; + case BLE_PHY_MODE_CODED_500KBPS: + NRF_RADIO_NS->MODE = RADIO_MODE_MODE_Ble_LR500Kbit; + NRF_RADIO_NS->PCNF0 = NRF_PCNF0_CODED; + break; +#endif + default: + assert(0); + } + + g_ble_phy_data.phy_cur_phy_mode = phy_mode; +} +#endif + +void +ble_phy_mode_set(uint8_t tx_phy_mode, uint8_t rx_phy_mode) +{ + g_ble_phy_data.phy_tx_phy_mode = tx_phy_mode; + g_ble_phy_data.phy_rx_phy_mode = rx_phy_mode; +} + +int +ble_phy_get_cur_phy(void) +{ +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) + switch (g_ble_phy_data.phy_cur_phy_mode) { + case BLE_PHY_MODE_1M: + return BLE_PHY_1M; + case BLE_PHY_MODE_2M: + return BLE_PHY_2M; + case BLE_PHY_MODE_CODED_125KBPS: + case BLE_PHY_MODE_CODED_500KBPS: + return BLE_PHY_CODED; + default: + assert(0); + return -1; + } +#else + return BLE_PHY_1M; +#endif +} + +void +ble_phy_rxpdu_copy(uint8_t *dptr, struct os_mbuf *rxpdu) +{ + uint32_t rem_len; + uint32_t copy_len; + uint32_t block_len; + uint32_t block_rem_len; + void *dst; + void *src; + struct os_mbuf * om; + + /* Better be aligned */ + assert(((uint32_t)dptr & 3) == 0); + + block_len = rxpdu->om_omp->omp_databuf_len; + rem_len = OS_MBUF_PKTHDR(rxpdu)->omp_len; + src = dptr; + + /* + * Setup for copying from first mbuf which is shorter due to packet header + * and extra leading space + */ + copy_len = block_len - rxpdu->om_pkthdr_len - 4; + om = rxpdu; + dst = om->om_data; + + while (true) { + /* + * Always copy blocks of length aligned to word size, only last mbuf + * will have remaining non-word size bytes appended. + */ + block_rem_len = copy_len; + copy_len = min(copy_len, rem_len); + copy_len &= ~3; + + dst = om->om_data; + om->om_len = copy_len; + rem_len -= copy_len; + block_rem_len -= copy_len; + + __asm__ volatile (".syntax unified \n" + " mov r4, %[len] \n" + " b 2f \n" + "1: ldr r3, [%[src], %[len]] \n" + " str r3, [%[dst], %[len]] \n" + "2: subs %[len], #4 \n" + " bpl 1b \n" + " adds %[src], %[src], r4 \n" + " adds %[dst], %[dst], r4 \n" + : [dst] "+r" (dst), [src] "+r" (src), + [len] "+r" (copy_len) + : + : "r3", "r4", "memory" + ); + + if ((rem_len < 4) && (block_rem_len >= rem_len)) { + break; + } + + /* Move to next mbuf */ + om = SLIST_NEXT(om, om_next); + copy_len = block_len; + } + + /* Copy remaining bytes, if any, to last mbuf */ + om->om_len += rem_len; + __asm__ volatile (".syntax unified \n" + " b 2f \n" + "1: ldrb r3, [%[src], %[len]] \n" + " strb r3, [%[dst], %[len]] \n" + "2: subs %[len], #1 \n" + " bpl 1b \n" + : [len] "+r" (rem_len) + : [dst] "r" (dst), [src] "r" (src) + : "r3", "memory" + ); + + /* Copy header */ + memcpy(BLE_MBUF_HDR_PTR(rxpdu), &g_ble_phy_data.rxhdr, + sizeof(struct ble_mbuf_hdr)); +} + +/** + * Called when we want to wait if the radio is in either the rx or tx + * disable states. We want to wait until that state is over before doing + * anything to the radio + */ +static void +nrf_wait_disabled(void) +{ + uint32_t state; + + state = NRF_RADIO_NS->STATE; + if (state != RADIO_STATE_STATE_Disabled) { + if ((state == RADIO_STATE_STATE_RxDisable) || + (state == RADIO_STATE_STATE_TxDisable)) { + /* This will end within a short time (6 usecs). Just poll */ + while (NRF_RADIO_NS->STATE == state) { + /* If this fails, something is really wrong. Should last + * no more than 6 usecs + */ + } + } + } +} + +static int +ble_phy_set_start_time(uint32_t cputime, uint8_t rem_usecs, bool tx) +{ + uint32_t next_cc; + uint32_t cur_cc; + uint32_t cntr; + uint32_t delta; + + /* + * We need to adjust start time to include radio ramp-up and TX pipeline + * delay (the latter only if applicable, so only for TX). + * + * Radio ramp-up time is 40 usecs and TX delay is 3 or 5 usecs depending on + * phy, thus we'll offset RTC by 2 full ticks (61 usecs) and then compensate + * using TIMER0 with 1 usec precision. + */ + + cputime -= 2; + rem_usecs += 61; + if (tx) { + rem_usecs -= BLE_PHY_T_TXENFAST; + rem_usecs -= g_ble_phy_t_txdelay[g_ble_phy_data.phy_cur_phy_mode]; + } else { + rem_usecs -= BLE_PHY_T_RXENFAST; + } + + /* + * rem_usecs will be no more than 2 ticks, but if it is more than single + * tick then we should better count one more low-power tick rather than + * 30 high-power usecs. Also make sure we don't set TIMER0 CC to 0 as the + * compare won't occur. + */ + + if (rem_usecs > 30) { + cputime++; + rem_usecs -= 30; + } + + /* + * Can we set the RTC compare to start TIMER0? We can do it if: + * a) Current compare value is not N+1 or N+2 ticks from current + * counter. + * b) The value we want to set is not at least N+2 from current + * counter. + * + * NOTE: since the counter can tick 1 while we do these calculations we + * need to account for it. + */ + next_cc = cputime & 0xffffff; + cur_cc = NRF_RTC0_NS->CC[0]; + cntr = NRF_RTC0_NS->COUNTER; + + delta = (cur_cc - cntr) & 0xffffff; + if ((delta <= 3) && (delta != 0)) { + return -1; + } + delta = (next_cc - cntr) & 0xffffff; + if ((delta & 0x800000) || (delta < 3)) { + return -1; + } + + /* Clear and set TIMER0 to fire off at proper time */ + NRF_TIMER0_NS->TASKS_CLEAR = 1; + NRF_TIMER0_NS->CC[0] = rem_usecs; + NRF_TIMER0_NS->EVENTS_COMPARE[0] = 0; + + /* Set RTC compare to start TIMER0 */ + NRF_RTC0_NS->EVENTS_COMPARE[0] = 0; + NRF_RTC0_NS->CC[0] = next_cc; + NRF_RTC0_NS->EVTENSET = RTC_EVTENSET_COMPARE0_Msk; + + /* Enable PPI */ + NRF_TIMER0_NS->SUBSCRIBE_START = DPPI_SUBSCRIBE_TIMER0_TASKS_START(1); + + /* Store the cputime at which we set the RTC */ + g_ble_phy_data.phy_start_cputime = cputime; + + return 0; +} + +static int +ble_phy_set_start_now(void) +{ + os_sr_t sr; + uint32_t now; + + OS_ENTER_CRITICAL(sr); + + /* + * Set TIMER0 to fire immediately. We can't set CC to 0 as compare will not + * occur in such case. + */ + NRF_TIMER0_NS->TASKS_CLEAR = 1; + NRF_TIMER0_NS->CC[0] = 1; + NRF_TIMER0_NS->EVENTS_COMPARE[0] = 0; + + /* + * Set RTC compare to start TIMER0. We need to set it to at least N+2 ticks + * from current value to guarantee triggering compare event, but let's set + * it to N+3 to account for possible extra tick on RTC0 during these + * operations. + */ + now = os_cputime_get32(); + NRF_RTC0_NS->EVENTS_COMPARE[0] = 0; + NRF_RTC0_NS->CC[0] = now + 3; + NRF_RTC0_NS->EVTENSET = RTC_EVTENSET_COMPARE0_Msk; + + /* Enable PPI */ + NRF_TIMER0_NS->SUBSCRIBE_START = DPPI_SUBSCRIBE_TIMER0_TASKS_START(1); + + /* + * Store the cputime at which we set the RTC + * + * XXX Compare event may be triggered on previous CC value (if it was set to + * less than N+2) so in rare cases actual start time may be 2 ticks earlier + * than what we expect. Since this is only used on RX, it may cause AUX scan + * to be scheduled 1 or 2 ticks too late so we'll miss it - it's acceptable + * for now. + */ + g_ble_phy_data.phy_start_cputime = now + 3; + + OS_EXIT_CRITICAL(sr); + + return 0; +} + +void +ble_phy_wfr_enable(int txrx, uint8_t tx_phy_mode, uint32_t wfr_usecs) +{ + uint32_t end_time; + uint8_t phy; + + phy = g_ble_phy_data.phy_cur_phy_mode; + + if (txrx == BLE_PHY_WFR_ENABLE_TXRX) { + /* RX shall start exactly T_IFS after TX end captured in CC[2] */ + end_time = NRF_TIMER0_NS->CC[2] + BLE_LL_IFS; + /* Adjust for delay between EVENT_END and actual TX end time */ + end_time += g_ble_phy_t_txenddelay[tx_phy_mode]; + /* Wait a bit longer due to allowed active clock accuracy */ + end_time += 2; + /* + * It's possible that we'll capture PDU start time at the end of timer + * cycle and since wfr expires at the beginning of calculated timer + * cycle it can be almost 1 usec too early. Let's compensate for this + * by waiting 1 usec more. + */ + end_time += 1; + } else { + /* + * RX shall start no later than wfr_usecs after RX enabled. + * CC[0] is the time of RXEN so adjust for radio ram-up. + * Do not add jitter since this is already covered by LL. + */ + end_time = NRF_TIMER0_NS->CC[0] + BLE_PHY_T_RXENFAST + wfr_usecs; + } + + /* + * Note: on LE Coded EVENT_ADDRESS is fired after TERM1 is received, so + * we are actually calculating relative to start of packet payload + * which is fine. + */ + + /* Adjust for receiving access address since this triggers EVENT_ADDRESS */ + end_time += ble_phy_mode_pdu_start_off(phy); + /* Adjust for delay between actual access address RX and EVENT_ADDRESS */ + end_time += g_ble_phy_t_rxaddrdelay[phy]; + + /* wfr_secs is the time from rxen until timeout */ + NRF_TIMER0_NS->CC[3] = end_time; + NRF_TIMER0_NS->EVENTS_COMPARE[3] = 0; + + /* Subscribe for wait for response events */ + NRF_TIMER0_NS->SUBSCRIBE_CAPTURE[3] = DPPI_SUBSCRIBE_TIMER0_TASKS_CAPTURE3(1); + NRF_RADIO_NS->SUBSCRIBE_DISABLE = DPPI_SUBSCRIBE_RADIO_TASKS_DISABLE(1); + + /* Enable the disabled interrupt so we time out on events compare */ + NRF_RADIO_NS->INTENSET = RADIO_INTENSET_DISABLED_Msk; + + /* + * It may happen that if CPU is halted for a brief moment (e.g. during flash + * erase or write), TIMER0 already counted past CC[3] and thus wfr will not + * fire as expected. In case this happened, let's just disable PPIs for wfr + * and trigger wfr manually (i.e. disable radio). + * + * Note that the same applies to RX start time set in CC[0] but since it + * should fire earlier than wfr, fixing wfr is enough. + * + * CC[1] is only used as a reference on RX start, we do not need it here so + * it can be used to read TIMER0 counter. + */ + NRF_TIMER0_NS->TASKS_CAPTURE[1] = 1; + if (NRF_TIMER0_NS->CC[1] > NRF_TIMER0_NS->CC[3]) { + /* Unsubscribe from wfr events */ + NRF_TIMER0_NS->SUBSCRIBE_CAPTURE[3] = DPPI_SUBSCRIBE_TIMER0_TASKS_CAPTURE3(0); + NRF_RADIO_NS->SUBSCRIBE_DISABLE = DPPI_SUBSCRIBE_RADIO_TASKS_DISABLE(0); + + NRF_RADIO_NS->TASKS_DISABLE = 1; + } +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) +static uint32_t +ble_phy_get_ccm_datarate(void) +{ +#if BLE_LL_BT5_PHY_SUPPORTED + switch (g_ble_phy_data.phy_cur_phy_mode) { + case BLE_PHY_MODE_1M: + return CCM_MODE_DATARATE_1Mbit << CCM_MODE_DATARATE_Pos; + case BLE_PHY_MODE_2M: + return CCM_MODE_DATARATE_2Mbit << CCM_MODE_DATARATE_Pos; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) + case BLE_PHY_MODE_CODED_125KBPS: + return CCM_MODE_DATARATE_125Kbps << CCM_MODE_DATARATE_Pos; + case BLE_PHY_MODE_CODED_500KBPS: + return CCM_MODE_DATARATE_500Kbps << CCM_MODE_DATARATE_Pos; +#endif + } + + assert(0); + return 0; +#else + return CCM_MODE_DATARATE_1Mbit << CCM_MODE_DATARATE_Pos; +#endif +} +#endif + +/** + * Setup transceiver for receive. + */ +static void +ble_phy_rx_xcvr_setup(void) +{ + uint8_t *dptr; + + dptr = (uint8_t *)&g_ble_phy_rx_buf[0]; + dptr += 3; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + if (g_ble_phy_data.phy_encrypted) { + NRF_RADIO_NS->PACKETPTR = (uint32_t)&g_ble_phy_enc_buf[0]; + NRF_CCM_NS->INPTR = (uint32_t)&g_ble_phy_enc_buf[0]; + NRF_CCM_NS->OUTPTR = (uint32_t)dptr; + NRF_CCM_NS->SCRATCHPTR = (uint32_t)&nrf_encrypt_scratchpad[0]; + NRF_CCM_NS->MODE = CCM_MODE_LENGTH_Msk | CCM_MODE_MODE_Decryption | + ble_phy_get_ccm_datarate(); + NRF_CCM_NS->CNFPTR = (uint32_t)&nrf_ccm_data; + NRF_CCM_NS->SHORTS = 0; + NRF_CCM_NS->EVENTS_ERROR = 0; + NRF_CCM_NS->EVENTS_ENDCRYPT = 0; + NRF_CCM_NS->TASKS_KSGEN = 1; + + /* Subscribe to radio address event */ + NRF_CCM_NS->SUBSCRIBE_CRYPT = DPPI_SUBSCRIBE_CCM_TASKS_CRYPT(1); + } else { + NRF_RADIO_NS->PACKETPTR = (uint32_t)dptr; + } +#else + NRF_RADIO_NS->PACKETPTR = (uint32_t)dptr; +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + if (g_ble_phy_data.phy_privacy) { + NRF_AAR_NS->ENABLE = AAR_ENABLE_ENABLE_Enabled; + NRF_AAR_NS->IRKPTR = (uint32_t)&g_nrf_irk_list[0]; + NRF_AAR_NS->SCRATCHPTR = (uint32_t)&g_ble_phy_data.phy_aar_scratch; + NRF_AAR_NS->EVENTS_END = 0; + NRF_AAR_NS->EVENTS_RESOLVED = 0; + NRF_AAR_NS->EVENTS_NOTRESOLVED = 0; + } else { + if (g_ble_phy_data.phy_encrypted == 0) { + NRF_AAR_NS->ENABLE = AAR_ENABLE_ENABLE_Disabled; + } + } +#endif + + /* Turn off trigger TXEN on output compare match and AAR on bcmatch */ + NRF_RADIO_NS->SUBSCRIBE_TXEN = DPPI_SUBSCRIBE_RADIO_TASKS_TXEN(0); + NRF_AAR_NS->SUBSCRIBE_START = DPPI_SUBSCRIBE_AAR_TASKS_START(0); + + /* Reset the rx started flag. Used for the wait for response */ + g_ble_phy_data.phy_rx_started = 0; + g_ble_phy_data.phy_state = BLE_PHY_STATE_RX; + +#if BLE_LL_BT5_PHY_SUPPORTED + /* + * On Coded PHY there are CI and TERM1 fields before PDU starts so we need + * to take this into account when setting up BCC. + */ + if (g_ble_phy_data.phy_cur_phy_mode == BLE_PHY_MODE_CODED_125KBPS || + g_ble_phy_data.phy_cur_phy_mode == BLE_PHY_MODE_CODED_500KBPS) { + g_ble_phy_data.phy_bcc_offset = 5; + } else { + g_ble_phy_data.phy_bcc_offset = 0; + } +#else + g_ble_phy_data.phy_bcc_offset = 0; +#endif + + /* I want to know when 1st byte received (after address) */ + NRF_RADIO_NS->BCC = 8 + g_ble_phy_data.phy_bcc_offset; /* in bits */ + NRF_RADIO_NS->EVENTS_ADDRESS = 0; + NRF_RADIO_NS->EVENTS_DEVMATCH = 0; + NRF_RADIO_NS->EVENTS_BCMATCH = 0; + NRF_RADIO_NS->EVENTS_RSSIEND = 0; + NRF_RADIO_NS->EVENTS_CRCOK = 0; + NRF_RADIO_NS->SHORTS = RADIO_SHORTS_END_DISABLE_Msk | + RADIO_SHORTS_READY_START_Msk | + RADIO_SHORTS_ADDRESS_BCSTART_Msk | + RADIO_SHORTS_ADDRESS_RSSISTART_Msk | + RADIO_SHORTS_DISABLED_RSSISTOP_Msk; + + NRF_RADIO_NS->INTENSET = RADIO_INTENSET_ADDRESS_Msk; +} + +/** + * Called from interrupt context when the transmit ends + * + */ +static void +ble_phy_tx_end_isr(void) +{ + uint8_t tx_phy_mode; + uint8_t was_encrypted; + uint8_t transition; + uint32_t rx_time; + uint32_t wfr_time; + + /* Store PHY on which we've just transmitted smth */ + tx_phy_mode = g_ble_phy_data.phy_cur_phy_mode; + + /* If this transmission was encrypted we need to remember it */ + was_encrypted = g_ble_phy_data.phy_encrypted; + (void)was_encrypted; + + /* Better be in TX state! */ + assert(g_ble_phy_data.phy_state == BLE_PHY_STATE_TX); + + /* Clear events and clear interrupt on disabled event */ + NRF_RADIO_NS->EVENTS_DISABLED = 0; + NRF_RADIO_NS->INTENCLR = RADIO_INTENCLR_DISABLED_Msk; + NRF_RADIO_NS->EVENTS_END = 0; + wfr_time = NRF_RADIO_NS->SHORTS; + (void)wfr_time; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + /* + * XXX: not sure what to do. We had a HW error during transmission. + * For now I just count a stat but continue on like all is good. + */ + if (was_encrypted) { + if (NRF_CCM_NS->EVENTS_ERROR) { + STATS_INC(ble_phy_stats, tx_hw_err); + NRF_CCM_NS->EVENTS_ERROR = 0; + } + } +#endif + + /* Call transmit end callback */ + if (g_ble_phy_data.txend_cb) { + g_ble_phy_data.txend_cb(g_ble_phy_data.txend_arg); + } + + transition = g_ble_phy_data.phy_transition; + if (transition == BLE_PHY_TRANSITION_TX_RX) { + +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) + ble_phy_mode_apply(g_ble_phy_data.phy_rx_phy_mode); +#endif + + /* Packet pointer needs to be reset. */ + ble_phy_rx_xcvr_setup(); + + ble_phy_wfr_enable(BLE_PHY_WFR_ENABLE_TXRX, tx_phy_mode, 0); + + /* Schedule RX exactly T_IFS after TX end captured in CC[2] */ + rx_time = NRF_TIMER0_NS->CC[2] + BLE_LL_IFS; + /* Adjust for delay between EVENT_END and actual TX end time */ + rx_time += g_ble_phy_t_txenddelay[tx_phy_mode]; + /* Adjust for radio ramp-up */ + rx_time -= BLE_PHY_T_RXENFAST; + /* Start listening a bit earlier due to allowed active clock accuracy */ + rx_time -= 2; + + NRF_TIMER0_NS->CC[0] = rx_time; + NRF_TIMER0_NS->EVENTS_COMPARE[0] = 0; + + /* Start radio on timer */ + NRF_RADIO_NS->SUBSCRIBE_RXEN = DPPI_SUBSCRIBE_RADIO_TASKS_RXEN(1); + + } else { + NRF_TIMER0_NS->TASKS_STOP = 1; + NRF_TIMER0_NS->TASKS_SHUTDOWN = 1; + + NRF_TIMER0_NS->SUBSCRIBE_CAPTURE[3] = DPPI_SUBSCRIBE_TIMER0_TASKS_CAPTURE3(0); + NRF_RADIO_NS->SUBSCRIBE_DISABLE = DPPI_SUBSCRIBE_RADIO_TASKS_DISABLE(0); + NRF_RADIO_NS->SUBSCRIBE_TXEN = DPPI_SUBSCRIBE_RADIO_TASKS_TXEN(0); + NRF_TIMER0_NS->SUBSCRIBE_START = DPPI_SUBSCRIBE_TIMER0_TASKS_START(0); + + assert(transition == BLE_PHY_TRANSITION_NONE); + } +} + +static inline uint8_t +ble_phy_get_cur_rx_phy_mode(void) +{ + uint8_t phy; + + phy = g_ble_phy_data.phy_cur_phy_mode; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) + /* + * For Coded PHY mode can be set to either codings since actual coding is + * set in packet header. However, here we need actual coding of received + * packet as this determines pipeline delays so need to figure this out + * using CI field. + */ + if ((phy == BLE_PHY_MODE_CODED_125KBPS) || + (phy == BLE_PHY_MODE_CODED_500KBPS)) { + phy = NRF_RADIO_NS->PDUSTAT & RADIO_PDUSTAT_CISTAT_Msk ? + BLE_PHY_MODE_CODED_500KBPS : BLE_PHY_MODE_CODED_125KBPS; + } +#endif + + return phy; +} + +static void +ble_phy_rx_end_isr(void) +{ + int rc; + uint8_t *dptr; + uint8_t crcok; + uint32_t tx_time; + struct ble_mbuf_hdr *ble_hdr; + + /* Clear events and clear interrupt */ + NRF_RADIO_NS->EVENTS_END = 0; + NRF_RADIO_NS->INTENCLR = RADIO_INTENCLR_END_Msk; + + /* Disable automatic RXEN */ + NRF_RADIO_NS->SUBSCRIBE_RXEN = DPPI_SUBSCRIBE_RADIO_TASKS_RXEN(0); + + /* Set RSSI and CRC status flag in header */ + ble_hdr = &g_ble_phy_data.rxhdr; + assert(NRF_RADIO_NS->EVENTS_RSSIEND != 0); + ble_hdr->rxinfo.rssi = (-1 * NRF_RADIO_NS->RSSISAMPLE) + + g_ble_phy_data.rx_pwr_compensation; + + dptr = (uint8_t *)&g_ble_phy_rx_buf[0]; + dptr += 3; + + /* Count PHY crc errors and valid packets */ + crcok = NRF_RADIO_NS->EVENTS_CRCOK; + if (!crcok) { + STATS_INC(ble_phy_stats, rx_crc_err); + } else { + STATS_INC(ble_phy_stats, rx_valid); + ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_CRC_OK; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + if (g_ble_phy_data.phy_encrypted) { + /* Only set MIC failure flag if frame is not zero length */ + if ((dptr[1] != 0) && (NRF_CCM_NS->MICSTATUS == 0)) { + ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_MIC_FAILURE; + } + + /* + * XXX: not sure how to deal with this. This should not + * be a MIC failure but we should not hand it up. I guess + * this is just some form of rx error and that is how we + * handle it? For now, just set CRC error flags + */ + if (NRF_CCM_NS->EVENTS_ERROR) { + STATS_INC(ble_phy_stats, rx_hw_err); + ble_hdr->rxinfo.flags &= ~BLE_MBUF_HDR_F_CRC_OK; + } + + /* + * XXX: This is a total hack work-around for now but I dont + * know what else to do. If ENDCRYPT is not set and we are + * encrypted we need to not trust this frame and drop it. + */ + if (NRF_CCM_NS->EVENTS_ENDCRYPT == 0) { + STATS_INC(ble_phy_stats, rx_hw_err); + ble_hdr->rxinfo.flags &= ~BLE_MBUF_HDR_F_CRC_OK; + } + } +#endif + } + +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) + ble_phy_mode_apply(g_ble_phy_data.phy_tx_phy_mode); +#endif + + /* + * Let's schedule TX now and we will just cancel it after processing RXed + * packet if we don't need TX. + * + * We need this to initiate connection in case AUX_CONNECT_REQ was sent on + * LE Coded S8. In this case the time we process RXed packet is roughly the + * same as the limit when we need to have TX scheduled (i.e. TIMER0 and PPI + * armed) so we may simply miss the slot and set the timer in the past. + * + * When TX is scheduled in advance, we may event process packet a bit longer + * during radio ramp-up - this gives us extra 40 usecs which is more than + * enough. + */ + + /* Schedule TX exactly T_IFS after RX end captured in CC[2] */ + tx_time = NRF_TIMER0_NS->CC[2] + BLE_LL_IFS; + /* Adjust for delay between actual RX end time and EVENT_END */ + tx_time -= g_ble_phy_t_rxenddelay[ble_hdr->rxinfo.phy_mode]; + /* Adjust for radio ramp-up */ + tx_time -= BLE_PHY_T_TXENFAST; + /* Adjust for delay between EVENT_READY and actual TX start time */ + tx_time -= g_ble_phy_t_txdelay[g_ble_phy_data.phy_cur_phy_mode]; + + NRF_TIMER0_NS->CC[0] = tx_time; + NRF_TIMER0_NS->EVENTS_COMPARE[0] = 0; + + /* Enable automatic TX */ + NRF_RADIO_NS->SUBSCRIBE_TXEN = DPPI_SUBSCRIBE_RADIO_TASKS_TXEN(1); + + /* + * XXX: Hack warning! + * + * It may happen (during flash erase) that CPU is stopped for a moment and + * TIMER0 already counted past CC[0]. In such case we will be stuck waiting + * for TX to start since EVENTS_COMPARE[0] will not happen any time soon. + * For now let's set a flag denoting that we are late in RX-TX transition so + * ble_phy_tx() will fail - this allows everything to cleanup nicely without + * the need for extra handling in many places. + * + * Note: CC[3] is used only for wfr which we do not need here. + */ + NRF_TIMER0_NS->TASKS_CAPTURE[3] = 1; + if (NRF_TIMER0_NS->CC[3] > NRF_TIMER0_NS->CC[0]) { + NRF_RADIO_NS->SUBSCRIBE_TXEN = DPPI_SUBSCRIBE_RADIO_TASKS_TXEN(0); + + g_ble_phy_data.phy_transition_late = 1; + } + + /* + * XXX: This is a horrible ugly hack to deal with the RAM S1 byte + * that is not sent over the air but is present here. Simply move the + * data pointer to deal with it. Fix this later. + */ + dptr[2] = dptr[1]; + dptr[1] = dptr[0]; + rc = ble_ll_rx_end(dptr + 1, ble_hdr); + if (rc < 0) { + ble_phy_disable(); + } +} + +static bool +ble_phy_rx_start_isr(void) +{ + int rc; + uint32_t state; + uint32_t usecs; + uint32_t pdu_usecs; + uint32_t ticks; + struct ble_mbuf_hdr *ble_hdr; + uint8_t *dptr; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + int adva_offset; +#endif + + dptr = (uint8_t *)&g_ble_phy_rx_buf[0]; + + /* Clear events and clear interrupt */ + NRF_RADIO_NS->EVENTS_ADDRESS = 0; + + /* Clear wfr timer channels and DISABLED interrupt */ + NRF_RADIO_NS->INTENCLR = RADIO_INTENCLR_DISABLED_Msk | RADIO_INTENCLR_ADDRESS_Msk; + NRF_TIMER0_NS->SUBSCRIBE_CAPTURE[3] = DPPI_SUBSCRIBE_TIMER0_TASKS_CAPTURE3(0); + NRF_RADIO_NS->SUBSCRIBE_DISABLE = DPPI_SUBSCRIBE_RADIO_TASKS_DISABLE(0); + + /* Initialize the ble mbuf header */ + ble_hdr = &g_ble_phy_data.rxhdr; + ble_hdr->rxinfo.flags = ble_ll_state_get(); + ble_hdr->rxinfo.channel = g_ble_phy_data.phy_chan; + ble_hdr->rxinfo.handle = 0; + ble_hdr->rxinfo.phy = ble_phy_get_cur_phy(); + ble_hdr->rxinfo.phy_mode = ble_phy_get_cur_rx_phy_mode(); +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + ble_hdr->rxinfo.user_data = NULL; +#endif + + /* + * Calculate accurate packets start time (with remainder) + * + * We may start receiving packet somewhere during preamble in which case + * it is possible that actual transmission started before TIMER0 was + * running - need to take this into account. + */ + ble_hdr->beg_cputime = g_ble_phy_data.phy_start_cputime; + + usecs = NRF_TIMER0_NS->CC[1]; + pdu_usecs = ble_phy_mode_pdu_start_off(ble_hdr->rxinfo.phy_mode) + + g_ble_phy_t_rxaddrdelay[ble_hdr->rxinfo.phy_mode]; + if (usecs < pdu_usecs) { + g_ble_phy_data.phy_start_cputime--; + usecs += 30; + } + usecs -= pdu_usecs; + + ticks = os_cputime_usecs_to_ticks(usecs); + usecs -= os_cputime_ticks_to_usecs(ticks); + if (usecs == 31) { + usecs = 0; + ++ticks; + } + + ble_hdr->beg_cputime += ticks; + ble_hdr->rem_usecs = usecs; + + /* Wait to get 1st byte of frame */ + while (1) { + state = NRF_RADIO_NS->STATE; + if (NRF_RADIO_NS->EVENTS_BCMATCH != 0) { + break; + } + + /* + * If state is disabled, we should have the BCMATCH. If not, + * something is wrong! + */ + if (state == RADIO_STATE_STATE_Disabled) { + NRF_RADIO_NS->INTENCLR = NRF_RADIO_IRQ_MASK_ALL; + NRF_RADIO_NS->SHORTS = 0; + return false; + } + } + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + /* + * If privacy is enabled and received PDU has TxAdd bit set (i.e. random + * address) we try to resolve address using AAR. + */ + if (g_ble_phy_data.phy_privacy && (dptr[3] & 0x40)) { + /* + * AdvA is located at 4th octet in RX buffer (after S0, length an S1 + * fields). In case of extended advertising PDU we need to add 2 more + * octets for extended header. + */ + adva_offset = (dptr[3] & 0x0f) == 0x07 ? 2 : 0; + NRF_AAR_NS->ADDRPTR = (uint32_t)(dptr + 3 + adva_offset); + + /* Trigger AAR after last bit of AdvA is received */ + NRF_RADIO_NS->EVENTS_BCMATCH = 0; + NRF_AAR_NS->SUBSCRIBE_START = DPPI_SUBSCRIBE_AAR_TASKS_START(1); + NRF_RADIO_NS->BCC = (BLE_LL_PDU_HDR_LEN + adva_offset + BLE_DEV_ADDR_LEN) * 8 + + g_ble_phy_data.phy_bcc_offset; + } +#endif + + /* Call Link Layer receive start function */ + rc = ble_ll_rx_start(dptr + 3, + g_ble_phy_data.phy_chan, + &g_ble_phy_data.rxhdr); + if (rc >= 0) { + /* Set rx started flag and enable rx end ISR */ + g_ble_phy_data.phy_rx_started = 1; + NRF_RADIO_NS->INTENSET = RADIO_INTENSET_END_Msk; + } else { + /* Disable PHY */ + ble_phy_disable(); + STATS_INC(ble_phy_stats, rx_aborts); + } + + /* Count rx starts */ + STATS_INC(ble_phy_stats, rx_starts); + + return true; +} + +static void +ble_phy_isr(void) +{ + uint32_t irq_en; + + os_trace_isr_enter(); + + /* Read irq register to determine which interrupts are enabled */ + irq_en = NRF_RADIO_NS->INTENCLR; + + /* + * NOTE: order of checking is important! Possible, if things get delayed, + * we have both an ADDRESS and DISABLED interrupt in rx state. If we get + * an address, we disable the DISABLED interrupt. + */ + + /* We get this if we have started to receive a frame */ + if ((irq_en & RADIO_INTENCLR_ADDRESS_Msk) && NRF_RADIO_NS->EVENTS_ADDRESS) { + /* + * wfr timer is calculated to expire at the exact time we should start + * receiving a packet (with 1 usec precision) so it is possible it will + * fire at the same time as EVENT_ADDRESS. If this happens, radio will + * be disabled while we are waiting for EVENT_BCCMATCH after 1st byte + * of payload is received and ble_phy_rx_start_isr() will fail. In this + * case we should not clear DISABLED irq mask so it will be handled as + * regular radio disabled event below. In other case radio was disabled + * on purpose and there's nothing more to handle so we can clear mask. + */ + if (ble_phy_rx_start_isr()) { + irq_en &= ~RADIO_INTENCLR_DISABLED_Msk; + } + } + + /* Check for disabled event. This only happens for transmits now */ + if ((irq_en & RADIO_INTENCLR_DISABLED_Msk) && NRF_RADIO_NS->EVENTS_DISABLED) { + if (g_ble_phy_data.phy_state == BLE_PHY_STATE_RX) { + NRF_RADIO_NS->EVENTS_DISABLED = 0; + ble_ll_wfr_timer_exp(NULL); + } else if (g_ble_phy_data.phy_state == BLE_PHY_STATE_IDLE) { + assert(0); + } else { + ble_phy_tx_end_isr(); + } + } + + /* Receive packet end (we dont enable this for transmit) */ + if ((irq_en & RADIO_INTENCLR_END_Msk) && NRF_RADIO_NS->EVENTS_END) { + ble_phy_rx_end_isr(); + } + + g_ble_phy_data.phy_transition_late = 0; + + /* Ensures IRQ is cleared */ + irq_en = NRF_RADIO_NS->SHORTS; + + /* Count # of interrupts */ + STATS_INC(ble_phy_stats, phy_isrs); + + os_trace_isr_exit(); +} + +int +ble_phy_init(void) +{ + int rc; + + /* Default phy to use is 1M */ + g_ble_phy_data.phy_cur_phy_mode = BLE_PHY_MODE_1M; + g_ble_phy_data.phy_tx_phy_mode = BLE_PHY_MODE_1M; + g_ble_phy_data.phy_rx_phy_mode = BLE_PHY_MODE_1M; + + g_ble_phy_data.rx_pwr_compensation = 0; + + /* Set phy channel to an invalid channel so first set channel works */ + g_ble_phy_data.phy_chan = BLE_PHY_NUM_CHANS; + + /* Toggle peripheral power to reset (just in case) */ + NRF_RADIO_NS->POWER = 0; + NRF_RADIO_NS->POWER = 1; + + /* Errata 16 - RADIO: POWER register is not functional + * Workaround: Reset all RADIO registers in firmware. + */ + NRF_RADIO_NS->SUBSCRIBE_TXEN = 0; + NRF_RADIO_NS->SUBSCRIBE_RXEN = 0; + NRF_RADIO_NS->SUBSCRIBE_DISABLE = 0; + + /* Disable all interrupts */ + NRF_RADIO_NS->INTENCLR = NRF_RADIO_IRQ_MASK_ALL; + + /* Set configuration registers */ + NRF_RADIO_NS->MODE = RADIO_MODE_MODE_Ble_1Mbit; + NRF_RADIO_NS->PCNF0 = NRF_PCNF0; + + /* XXX: should maxlen be 251 for encryption? */ + NRF_RADIO_NS->PCNF1 = NRF_MAXLEN | + (RADIO_PCNF1_ENDIAN_Little << RADIO_PCNF1_ENDIAN_Pos) | + (NRF_BALEN << RADIO_PCNF1_BALEN_Pos) | + RADIO_PCNF1_WHITEEN_Msk; + + /* Enable radio fast ramp-up */ + NRF_RADIO_NS->MODECNF0 |= (RADIO_MODECNF0_RU_Fast << RADIO_MODECNF0_RU_Pos) & RADIO_MODECNF0_RU_Msk; + + /* Set logical address 1 for TX and RX */ + NRF_RADIO_NS->TXADDRESS = 0; + NRF_RADIO_NS->RXADDRESSES = (1 << 0); + + /* Configure the CRC registers */ + NRF_RADIO_NS->CRCCNF = (RADIO_CRCCNF_SKIPADDR_Skip << RADIO_CRCCNF_SKIPADDR_Pos) | RADIO_CRCCNF_LEN_Three; + + /* Configure BLE poly */ + NRF_RADIO_NS->CRCPOLY = 0x0000065B; + + /* Configure IFS */ + NRF_RADIO_NS->TIFS = BLE_LL_IFS; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + NRF_CCM_NS->INTENCLR = 0xffffffff; + NRF_CCM_NS->SHORTS = CCM_SHORTS_ENDKSGEN_CRYPT_Msk; + NRF_CCM_NS->EVENTS_ERROR = 0; + memset(nrf_encrypt_scratchpad, 0, sizeof(nrf_encrypt_scratchpad)); +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + g_ble_phy_data.phy_aar_scratch = 0; + NRF_AAR_NS->IRKPTR = (uint32_t)&g_nrf_irk_list[0]; + NRF_AAR_NS->INTENCLR = 0xffffffff; + NRF_AAR_NS->EVENTS_END = 0; + NRF_AAR_NS->EVENTS_RESOLVED = 0; + NRF_AAR_NS->EVENTS_NOTRESOLVED = 0; + NRF_AAR_NS->NIRK = 0; +#endif + + /* TIMER0 setup for PHY when using RTC */ + NRF_TIMER0_NS->TASKS_STOP = 1; + NRF_TIMER0_NS->TASKS_SHUTDOWN = 1; + NRF_TIMER0_NS->BITMODE = 3; /* 32-bit timer */ + NRF_TIMER0_NS->MODE = 0; /* Timer mode */ + NRF_TIMER0_NS->PRESCALER = 4; /* gives us 1 MHz */ + + /* Publish events */ + NRF_TIMER0_NS->PUBLISH_COMPARE[0] = DPPI_PUBLISH_TIMER0_EVENTS_COMPARE_0; + NRF_TIMER0_NS->PUBLISH_COMPARE[3] = DPPI_PUBLISH_TIMER0_EVENTS_COMPARE_3; + NRF_RADIO_NS->PUBLISH_END = DPPI_PUBLISH_RADIO_EVENTS_END; + NRF_RADIO_NS->PUBLISH_BCMATCH = DPPI_PUBLISH_RADIO_EVENTS_BCMATCH; + NRF_RADIO_NS->PUBLISH_ADDRESS = DPPI_PUBLISH_RADIO_EVENTS_ADDRESS; + NRF_RTC0_NS->PUBLISH_COMPARE[0] = DPPI_PUBLISH_RTC0_EVENTS_COMPARE_0; + + /* Enable channels we publish on */ + NRF_DPPIC_NS->CHENSET = DPPI_CH_ENABLE_ALL; + + /* Captures tx/rx start in timer0 cc 1 and tx/rx end in timer0 cc 2 */ + NRF_TIMER0_NS->SUBSCRIBE_CAPTURE[1] = DPPI_SUBSCRIBE_TIMER0_TASKS_CAPTURE1(1); + NRF_TIMER0_NS->SUBSCRIBE_CAPTURE[2] = DPPI_SUBSCRIBE_TIMER0_TASKS_CAPTURE2(1); + + /* Set isr in vector table and enable interrupt */ +#ifndef RIOT_VERSION + NVIC_SetPriority(RADIO_IRQn, 0); +#endif +#if MYNEWT + NVIC_SetVector(RADIO_IRQn, (uint32_t)ble_phy_isr); +#else + ble_npl_hw_set_isr(RADIO_IRQn, ble_phy_isr); +#endif + NVIC_EnableIRQ(RADIO_IRQn); + + /* Register phy statistics */ + if (!g_ble_phy_data.phy_stats_initialized) { + rc = stats_init_and_reg(STATS_HDR(ble_phy_stats), + STATS_SIZE_INIT_PARMS(ble_phy_stats, + STATS_SIZE_32), + STATS_NAME_INIT_PARMS(ble_phy_stats), + "ble_phy"); + assert(rc == 0); + + g_ble_phy_data.phy_stats_initialized = 1; + } + + return 0; +} + +int +ble_phy_rx(void) +{ + /* + * Check radio state. + * + * In case radio is now disabling we'll wait for it to finish, but if for + * any reason it's just in idle state we proceed with RX as usual since + * nRF52 radio can ramp-up from idle state as well. + * + * Note that TX and RX states values are the same except for 3rd bit so we + * can make a shortcut here when checking for idle state. + */ + nrf_wait_disabled(); + if ((NRF_RADIO_NS->STATE != RADIO_STATE_STATE_Disabled) && + ((NRF_RADIO_NS->STATE & 0x07) != RADIO_STATE_STATE_RxIdle)) { + ble_phy_disable(); + STATS_INC(ble_phy_stats, radio_state_errs); + return BLE_PHY_ERR_RADIO_STATE; + } + + /* Make sure all interrupts are disabled */ + NRF_RADIO_NS->INTENCLR = NRF_RADIO_IRQ_MASK_ALL; + + /* Clear events prior to enabling receive */ + NRF_RADIO_NS->EVENTS_END = 0; + NRF_RADIO_NS->EVENTS_DISABLED = 0; + + /* Setup for rx */ + ble_phy_rx_xcvr_setup(); + + /* task to start RX should be subscribed here */ + assert(NRF_RADIO_NS->SUBSCRIBE_RXEN & DPPI_SUBSCRIBE_RADIO_TASKS_RXEN(1)); + + return 0; +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) +void +ble_phy_encrypt_enable(uint64_t pkt_counter, uint8_t *iv, uint8_t *key, + uint8_t is_master) +{ + memcpy(nrf_ccm_data.key, key, 16); + nrf_ccm_data.pkt_counter = pkt_counter; + memcpy(nrf_ccm_data.iv, iv, 8); + nrf_ccm_data.dir_bit = is_master; + g_ble_phy_data.phy_encrypted = 1; + /* Enable the module (AAR cannot be on while CCM on) */ + NRF_AAR_NS->ENABLE = AAR_ENABLE_ENABLE_Disabled; + NRF_CCM_NS->ENABLE = CCM_ENABLE_ENABLE_Enabled; +} + +void +ble_phy_encrypt_set_pkt_cntr(uint64_t pkt_counter, int dir) +{ + nrf_ccm_data.pkt_counter = pkt_counter; + nrf_ccm_data.dir_bit = dir; +} + +void +ble_phy_encrypt_disable(void) +{ + NRF_CCM_NS->SUBSCRIBE_CRYPT = DPPI_SUBSCRIBE_CCM_TASKS_CRYPT(0); + NRF_CCM_NS->TASKS_STOP = 1; + NRF_CCM_NS->EVENTS_ERROR = 0; + NRF_CCM_NS->ENABLE = CCM_ENABLE_ENABLE_Disabled; + + g_ble_phy_data.phy_encrypted = 0; +} +#endif + +void +ble_phy_set_txend_cb(ble_phy_tx_end_func txend_cb, void *arg) +{ + /* Set transmit end callback and arg */ + g_ble_phy_data.txend_cb = txend_cb; + g_ble_phy_data.txend_arg = arg; +} + +int +ble_phy_tx_set_start_time(uint32_t cputime, uint8_t rem_usecs) +{ + int rc; + + ble_phy_trace_u32x2(BLE_PHY_TRACE_ID_START_TX, cputime, rem_usecs); + +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) + ble_phy_mode_apply(g_ble_phy_data.phy_tx_phy_mode); +#endif + + /* XXX: This should not be necessary, but paranoia is good! */ + /* Clear timer0 compare to RXEN since we are transmitting */ + NRF_RADIO_NS->SUBSCRIBE_RXEN = DPPI_SUBSCRIBE_RADIO_TASKS_RXEN(0); + + if (ble_phy_set_start_time(cputime, rem_usecs, true) != 0) { + STATS_INC(ble_phy_stats, tx_late); + ble_phy_disable(); + rc = BLE_PHY_ERR_TX_LATE; + } else { + /* Enable PPI to automatically start TXEN */ + NRF_RADIO_NS->SUBSCRIBE_TXEN = DPPI_SUBSCRIBE_RADIO_TASKS_TXEN(1); + rc = 0; + } + return rc; +} + +int +ble_phy_rx_set_start_time(uint32_t cputime, uint8_t rem_usecs) +{ + bool late = false; + int rc = 0; + + ble_phy_trace_u32x2(BLE_PHY_TRACE_ID_START_RX, cputime, rem_usecs); + +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) + ble_phy_mode_apply(g_ble_phy_data.phy_rx_phy_mode); +#endif + + /* XXX: This should not be necessary, but paranoia is good! */ + /* Clear timer0 compare to TXEN since we are transmitting */ + NRF_RADIO_NS->SUBSCRIBE_TXEN = DPPI_SUBSCRIBE_RADIO_TASKS_TXEN(0); + + if (ble_phy_set_start_time(cputime, rem_usecs, false) != 0) { + STATS_INC(ble_phy_stats, rx_late); + + /* We're late so let's just try to start RX as soon as possible */ + ble_phy_set_start_now(); + + late = true; + } + + /* Enable PPI to automatically start RXEN */ + NRF_RADIO_NS->SUBSCRIBE_RXEN = DPPI_SUBSCRIBE_RADIO_TASKS_RXEN(1); + + /* Start rx */ + rc = ble_phy_rx(); + + /* + * If we enabled receiver but were late, let's return proper error code so + * caller can handle this. + */ + if (!rc && late) { + rc = BLE_PHY_ERR_RX_LATE; + } + + return rc; +} + +int +ble_phy_tx(ble_phy_tx_pducb_t pducb, void *pducb_arg, uint8_t end_trans) +{ + int rc; + uint8_t *dptr; + uint8_t *pktptr; + uint8_t payload_len; + uint8_t hdr_byte; + uint32_t state; + uint32_t shortcuts; + + if (g_ble_phy_data.phy_transition_late) { + ble_phy_disable(); + STATS_INC(ble_phy_stats, tx_late); + return BLE_PHY_ERR_TX_LATE; + } + + /* + * This check is to make sure that the radio is not in a state where + * it is moving to disabled state. If so, let it get there. + */ + nrf_wait_disabled(); + + /* + * XXX: Although we may not have to do this here, I clear all the PPI + * that should not be used when transmitting. Some of them are only enabled + * if encryption and/or privacy is on, but I dont care. Better to be + * paranoid, and if you are going to clear one, might as well clear them + * all. + */ + NRF_TIMER0_NS->SUBSCRIBE_CAPTURE[3] = DPPI_SUBSCRIBE_TIMER0_TASKS_CAPTURE3(0); + NRF_RADIO_NS->SUBSCRIBE_DISABLE = DPPI_SUBSCRIBE_RADIO_TASKS_DISABLE(0); + NRF_AAR_NS->SUBSCRIBE_START = DPPI_SUBSCRIBE_AAR_TASKS_START(0); + NRF_CCM_NS->SUBSCRIBE_CRYPT = DPPI_SUBSCRIBE_CCM_TASKS_CRYPT(0); + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + if (g_ble_phy_data.phy_encrypted) { + dptr = (uint8_t *)&g_ble_phy_enc_buf[0]; + pktptr = (uint8_t *)&g_ble_phy_tx_buf[0]; + NRF_CCM_NS->SHORTS = CCM_SHORTS_ENDKSGEN_CRYPT_Msk; + NRF_CCM_NS->INPTR = (uint32_t)dptr; + NRF_CCM_NS->OUTPTR = (uint32_t)pktptr; + NRF_CCM_NS->SCRATCHPTR = (uint32_t)&nrf_encrypt_scratchpad[0]; + NRF_CCM_NS->EVENTS_ERROR = 0; + NRF_CCM_NS->MODE = CCM_MODE_LENGTH_Msk | ble_phy_get_ccm_datarate(); + NRF_CCM_NS->CNFPTR = (uint32_t)&nrf_ccm_data; + } else { +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + NRF_AAR_NS->IRKPTR = (uint32_t)&g_nrf_irk_list[0]; +#endif + dptr = (uint8_t *)&g_ble_phy_tx_buf[0]; + pktptr = dptr; + } +#else + dptr = (uint8_t *)&g_ble_phy_tx_buf[0]; + pktptr = dptr; +#endif + + /* Set PDU payload */ + payload_len = pducb(&dptr[3], pducb_arg, &hdr_byte); + + /* RAM representation has S0, LENGTH and S1 fields. (3 bytes) */ + dptr[0] = hdr_byte; + dptr[1] = payload_len; + dptr[2] = 0; + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + /* Start key-stream generation and encryption (via short) */ + if (g_ble_phy_data.phy_encrypted) { + NRF_CCM_NS->TASKS_KSGEN = 1; + } +#endif + + NRF_RADIO_NS->PACKETPTR = (uint32_t)pktptr; + + /* Clear the ready, end and disabled events */ + NRF_RADIO_NS->EVENTS_READY = 0; + NRF_RADIO_NS->EVENTS_END = 0; + NRF_RADIO_NS->EVENTS_DISABLED = 0; + + /* Enable shortcuts for transmit start/end. */ + shortcuts = RADIO_SHORTS_END_DISABLE_Msk | RADIO_SHORTS_READY_START_Msk; + NRF_RADIO_NS->SHORTS = shortcuts; + NRF_RADIO_NS->INTENSET = RADIO_INTENSET_DISABLED_Msk; + + /* Set the PHY transition */ + g_ble_phy_data.phy_transition = end_trans; + + /* Set transmitted payload length */ + g_ble_phy_data.phy_tx_pyld_len = payload_len; + + /* If we already started transmitting, abort it! */ + state = NRF_RADIO_NS->STATE; + if (state != RADIO_STATE_STATE_Tx) { + /* Set phy state to transmitting and count packet statistics */ + g_ble_phy_data.phy_state = BLE_PHY_STATE_TX; + STATS_INC(ble_phy_stats, tx_good); + STATS_INCN(ble_phy_stats, tx_bytes, payload_len + BLE_LL_PDU_HDR_LEN); + rc = BLE_ERR_SUCCESS; + } else { + ble_phy_disable(); + STATS_INC(ble_phy_stats, tx_late); + rc = BLE_PHY_ERR_RADIO_STATE; + } + + return rc; +} + +int +ble_phy_txpwr_set(int dbm) +{ + /* "Rail" power level if outside supported range */ + dbm = ble_phy_txpower_round(dbm); + + NRF_RADIO_NS->TXPOWER = dbm; + g_ble_phy_data.phy_txpwr_dbm = dbm; + + return 0; +} + +int +ble_phy_txpower_round(int dbm) +{ + /* "Rail" power level if outside supported range */ + + if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_0dBm) { + return (int8_t)RADIO_TXPOWER_TXPOWER_0dBm; + } + + if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg1dBm) { + return (int8_t)RADIO_TXPOWER_TXPOWER_Neg1dBm; + } + + if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg2dBm) { + return (int8_t)RADIO_TXPOWER_TXPOWER_Neg2dBm; + } + + if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg3dBm) { + return (int8_t)RADIO_TXPOWER_TXPOWER_Neg4dBm; + } + + if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg4dBm) { + return (int8_t)RADIO_TXPOWER_TXPOWER_Neg4dBm; + } + + if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg5dBm) { + return (int8_t)RADIO_TXPOWER_TXPOWER_Neg5dBm; + } + + if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg6dBm) { + return (int8_t)RADIO_TXPOWER_TXPOWER_Neg6dBm; + } + + if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg7dBm) { + return (int8_t)RADIO_TXPOWER_TXPOWER_Neg7dBm; + } + + if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg8dBm) { + return (int8_t)RADIO_TXPOWER_TXPOWER_Neg8dBm; + } + + if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg12dBm) { + return (int8_t)RADIO_TXPOWER_TXPOWER_Neg12dBm; + } + + if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg16dBm) { + return (int8_t)RADIO_TXPOWER_TXPOWER_Neg16dBm; + } + + if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg20dBm) { + return (int8_t)RADIO_TXPOWER_TXPOWER_Neg20dBm; + } + + if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg40dBm) { + return (int8_t)RADIO_TXPOWER_TXPOWER_Neg40dBm; + } + + return (int8_t)RADIO_TXPOWER_TXPOWER_Neg40dBm; +} + +static int +ble_phy_set_access_addr(uint32_t access_addr) +{ + NRF_RADIO_NS->BASE0 = (access_addr << 8); + NRF_RADIO_NS->PREFIX0 = (NRF_RADIO_NS->PREFIX0 & 0xFFFFFF00) | (access_addr >> 24); + + g_ble_phy_data.phy_access_address = access_addr; + + return 0; +} + +int +ble_phy_txpwr_get(void) +{ + return g_ble_phy_data.phy_txpwr_dbm; +} + +void +ble_phy_set_rx_pwr_compensation(int8_t compensation) +{ + g_ble_phy_data.rx_pwr_compensation = compensation; +} + +int +ble_phy_setchan(uint8_t chan, uint32_t access_addr, uint32_t crcinit) +{ + assert(chan < BLE_PHY_NUM_CHANS); + + /* Check for valid channel range */ + if (chan >= BLE_PHY_NUM_CHANS) { + return BLE_PHY_ERR_INV_PARAM; + } + + /* Set current access address */ + ble_phy_set_access_addr(access_addr); + + /* Configure crcinit */ + NRF_RADIO_NS->CRCINIT = crcinit; + + /* Set the frequency and the data whitening initial value */ + g_ble_phy_data.phy_chan = chan; + NRF_RADIO_NS->FREQUENCY = g_ble_phy_chan_freq[chan]; + NRF_RADIO_NS->DATAWHITEIV = chan; + + return 0; +} + +/** + * Stop the timer used to count microseconds when using RTC for cputime + */ +static void +ble_phy_stop_usec_timer(void) +{ + NRF_TIMER0_NS->TASKS_STOP = 1; + NRF_TIMER0_NS->TASKS_SHUTDOWN = 1; + NRF_RTC0_NS->EVTENCLR = RTC_EVTENSET_COMPARE0_Msk; +} + +/** + * ble phy disable irq and ppi + * + * This routine is to be called when reception was stopped due to either a + * wait for response timeout or a packet being received and the phy is to be + * restarted in receive mode. Generally, the disable routine is called to stop + * the phy. + */ +static void +ble_phy_disable_irq_and_ppi(void) +{ + NRF_RADIO_NS->INTENCLR = NRF_RADIO_IRQ_MASK_ALL; + NRF_RADIO_NS->SHORTS = 0; + NRF_RADIO_NS->TASKS_DISABLE = 1; + + NRF_TIMER0_NS->SUBSCRIBE_START = DPPI_SUBSCRIBE_TIMER0_TASKS_START(0); + NRF_TIMER0_NS->SUBSCRIBE_CAPTURE[3] = DPPI_SUBSCRIBE_TIMER0_TASKS_CAPTURE3(0); + NRF_RADIO_NS->SUBSCRIBE_DISABLE = DPPI_SUBSCRIBE_RADIO_TASKS_DISABLE(0); + NRF_RADIO_NS->SUBSCRIBE_TXEN = DPPI_SUBSCRIBE_RADIO_TASKS_TXEN(0); + NRF_RADIO_NS->SUBSCRIBE_RXEN = DPPI_SUBSCRIBE_RADIO_TASKS_RXEN(0); + NRF_AAR_NS->SUBSCRIBE_START = DPPI_SUBSCRIBE_AAR_TASKS_START(0); + NRF_CCM_NS->SUBSCRIBE_CRYPT = DPPI_SUBSCRIBE_CCM_TASKS_CRYPT(0); + + NVIC_ClearPendingIRQ(RADIO_IRQn); + g_ble_phy_data.phy_state = BLE_PHY_STATE_IDLE; +} + +void +ble_phy_restart_rx(void) +{ + ble_phy_stop_usec_timer(); + ble_phy_disable_irq_and_ppi(); + + ble_phy_set_start_now(); + /* Enable PPI to automatically start RXEN */ + NRF_RADIO_NS->SUBSCRIBE_RXEN = DPPI_SUBSCRIBE_RADIO_TASKS_RXEN(1); + + ble_phy_rx(); +} + +void +ble_phy_disable(void) +{ + ble_phy_trace_void(BLE_PHY_TRACE_ID_DISABLE); + + ble_phy_stop_usec_timer(); + ble_phy_disable_irq_and_ppi(); +} + +uint32_t +ble_phy_access_addr_get(void) +{ + return g_ble_phy_data.phy_access_address; +} + +int +ble_phy_state_get(void) +{ + return g_ble_phy_data.phy_state; +} + +int +ble_phy_rx_started(void) +{ + return g_ble_phy_data.phy_rx_started; +} + +uint8_t +ble_phy_xcvr_state_get(void) +{ + uint32_t state; + state = NRF_RADIO_NS->STATE; + return (uint8_t)state; +} + +uint8_t +ble_phy_max_data_pdu_pyld(void) +{ + return BLE_LL_DATA_PDU_MAX_PYLD; +} + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) +void +ble_phy_resolv_list_enable(void) +{ + NRF_AAR_NS->NIRK = (uint32_t)g_nrf_num_irks; + g_ble_phy_data.phy_privacy = 1; +} + +void +ble_phy_resolv_list_disable(void) +{ + g_ble_phy_data.phy_privacy = 0; +} +#endif + +#if MYNEWT_VAL(BLE_LL_DTM) +void +ble_phy_enable_dtm(void) +{ + /* When DTM is enabled we need to disable whitening as per + * Bluetooth v5.0 Vol 6. Part F. 4.1.1 + */ + NRF_RADIO_NS->PCNF1 &= ~RADIO_PCNF1_WHITEEN_Msk; +} + +void +ble_phy_disable_dtm(void) +{ + /* Enable whitening */ + NRF_RADIO_NS->PCNF1 |= RADIO_PCNF1_WHITEEN_Msk; +} +#endif + +void +ble_phy_rfclk_enable(void) +{ +#if MYNEWT + nrf5340_net_clock_hfxo_request(); +#else + NRF_CLOCK_NS->TASKS_HFCLKSTART = 1; +#endif +} + +void +ble_phy_rfclk_disable(void) +{ +#if MYNEWT + nrf5340_net_clock_hfxo_release(); +#else + NRF_CLOCK_NS->TASKS_HFCLKSTOP = 1; +#endif +} diff --git a/src/libs/mynewt-nimble/nimble/drivers/nrf5340/src/ble_phy_trace.c b/src/libs/mynewt-nimble/nimble/drivers/nrf5340/src/ble_phy_trace.c new file mode 100644 index 00000000..6967c3f7 --- /dev/null +++ b/src/libs/mynewt-nimble/nimble/drivers/nrf5340/src/ble_phy_trace.c @@ -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 +#include +#include + +#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 diff --git a/src/libs/mynewt-nimble/nimble/drivers/nrf5340/syscfg.yml b/src/libs/mynewt-nimble/nimble/drivers/nrf5340/syscfg.yml new file mode 100644 index 00000000..dd8b9304 --- /dev/null +++ b/src/libs/mynewt-nimble/nimble/drivers/nrf5340/syscfg.yml @@ -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 diff --git a/src/libs/mynewt-nimble/nimble/host/include/host/ble_gap.h b/src/libs/mynewt-nimble/nimble/host/include/host/ble_gap.h index 20e7dab7..20f9e30d 100644 --- a/src/libs/mynewt-nimble/nimble/host/include/host/ble_gap.h +++ b/src/libs/mynewt-nimble/nimble/host/include/host/ble_gap.h @@ -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 diff --git a/src/libs/mynewt-nimble/nimble/host/include/host/ble_hs_log.h b/src/libs/mynewt-nimble/nimble/host/include/host/ble_hs_log.h index 8d0a4596..7b90eaf9 100644 --- a/src/libs/mynewt-nimble/nimble/host/include/host/ble_hs_log.h +++ b/src/libs/mynewt-nimble/nimble/host/include/host/ble_hs_log.h @@ -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) diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/access.h b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/access.h index 1f99f412..9f923cb9 100644 --- a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/access.h +++ b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/access.h @@ -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 @@ -414,6 +424,10 @@ struct bt_mesh_model_pub { * will be called periodically and is expected to update * @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. * @@ -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; diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/atomic.h b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/atomic.h new file mode 100644 index 00000000..2c731794 --- /dev/null +++ b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/atomic.h @@ -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__ */ diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/cdb.h b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/cdb.h new file mode 100644 index 00000000..8f9a6bc9 --- /dev/null +++ b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/cdb.h @@ -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_ */ \ No newline at end of file diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/cfg.h b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/cfg.h new file mode 100644 index 00000000..378f0a0a --- /dev/null +++ b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/cfg.h @@ -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 +#include +#include + +/** + * @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_ */ \ No newline at end of file diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/cfg_cli.h b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/cfg_cli.h index 7dc237be..bd2f9fe5 100644 --- a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/cfg_cli.h +++ b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/cfg_cli.h @@ -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 } diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/cfg_srv.h b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/cfg_srv.h index 14d8a295..5bf3f439 100644 --- a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/cfg_srv.h +++ b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/cfg_srv.h @@ -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 } diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/glue.h b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/glue.h index e37fcfbc..abe3dd53 100644 --- a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/glue.h +++ b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/glue.h @@ -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; @@ -374,43 +388,61 @@ static inline unsigned int find_msb_set(u32_t op) return 32 - __builtin_clz(op); } -#define CONFIG_BT_MESH_FRIEND BLE_MESH_FRIEND -#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_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 -#define CONFIG_BT_MESH_PB_GATT BLE_MESH_PB_GATT -#define CONFIG_BT_MESH_PROV BLE_MESH_PROV -#define CONFIG_BT_MESH_PROXY BLE_MESH_PROXY -#define CONFIG_BT_TESTING BLE_MESH_TESTING -#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_FRIEND BLE_MESH_FRIEND +#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 +#define CONFIG_BT_MESH_PB_GATT BLE_MESH_PB_GATT +#define CONFIG_BT_MESH_PROV BLE_MESH_PROV +#define CONFIG_BT_MESH_PROXY BLE_MESH_PROXY +#define CONFIG_BT_TESTING BLE_MESH_TESTING +#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_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) -#define CONFIG_BT_MESH_MODEL_GROUP_COUNT MYNEWT_VAL(BLE_MESH_MODEL_GROUP_COUNT) -#define CONFIG_BT_MESH_MODEL_KEY_COUNT MYNEWT_VAL(BLE_MESH_MODEL_KEY_COUNT) -#define CONFIG_BT_MESH_NODE_ID_TIMEOUT MYNEWT_VAL(BLE_MESH_NODE_ID_TIMEOUT) -#define CONFIG_BT_MAX_CONN MYNEWT_VAL(BLE_MAX_CONNECTIONS) -#define CONFIG_BT_MESH_SEQ_STORE_RATE MYNEWT_VAL(BLE_MESH_SEQ_STORE_RATE) -#define CONFIG_BT_MESH_RPL_STORE_TIMEOUT MYNEWT_VAL(BLE_MESH_RPL_STORE_TIMEOUT) -#define CONFIG_BT_MESH_APP_KEY_COUNT MYNEWT_VAL(BLE_MESH_APP_KEY_COUNT) -#define CONFIG_BT_MESH_SUBNET_COUNT MYNEWT_VAL(BLE_MESH_SUBNET_COUNT) -#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_MESH_TX_SEG_MAX MYNEWT_VAL(BLE_MESH_TX_SEG_MAX) -#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_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) +#define CONFIG_BT_MESH_MODEL_GROUP_COUNT MYNEWT_VAL(BLE_MESH_MODEL_GROUP_COUNT) +#define CONFIG_BT_MESH_MODEL_KEY_COUNT MYNEWT_VAL(BLE_MESH_MODEL_KEY_COUNT) +#define CONFIG_BT_MESH_NODE_ID_TIMEOUT MYNEWT_VAL(BLE_MESH_NODE_ID_TIMEOUT) +#define CONFIG_BT_MAX_CONN MYNEWT_VAL(BLE_MAX_CONNECTIONS) +#define CONFIG_BT_MESH_SEQ_STORE_RATE MYNEWT_VAL(BLE_MESH_SEQ_STORE_RATE) +#define CONFIG_BT_MESH_RPL_STORE_TIMEOUT MYNEWT_VAL(BLE_MESH_RPL_STORE_TIMEOUT) +#define CONFIG_BT_MESH_APP_KEY_COUNT MYNEWT_VAL(BLE_MESH_APP_KEY_COUNT) +#define CONFIG_BT_MESH_SUBNET_COUNT MYNEWT_VAL(BLE_MESH_SUBNET_COUNT) +#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_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 diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/health_cli.h b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/health_cli.h index 8ab8d6d5..e9efe4b1 100644 --- a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/health_cli.h +++ b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/health_cli.h @@ -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, - size_t *fault_count); +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, - size_t *fault_count); +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, - size_t *fault_count); +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 } diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/health_srv.h b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/health_srv.h index 83982376..ad79e368 100644 --- a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/health_srv.h +++ b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/health_srv.h @@ -23,21 +23,21 @@ extern "C" { struct bt_mesh_health_srv_cb { /* Fetch current faults */ - int (*fault_get_cur)(struct bt_mesh_model *model, u8_t *test_id, - u16_t *company_id, u8_t *faults, - u8_t *fault_count); + int (*fault_get_cur)(struct bt_mesh_model *model, uint8_t *test_id, + uint16_t *company_id, uint8_t *faults, + uint8_t *fault_count); /* Fetch registered faults */ - int (*fault_get_reg)(struct bt_mesh_model *model, u16_t company_id, - u8_t *test_id, u8_t *faults, - u8_t *fault_count); + int (*fault_get_reg)(struct bt_mesh_model *model, uint16_t company_id, + uint8_t *test_id, uint8_t *faults, + uint8_t *fault_count); /* Clear registered faults */ - int (*fault_clear)(struct bt_mesh_model *model, u16_t company_id); + int (*fault_clear)(struct bt_mesh_model *model, uint16_t company_id); /* Run a specific test */ - int (*fault_test)(struct bt_mesh_model *model, u8_t test_id, - u16_t company_id); + int (*fault_test)(struct bt_mesh_model *model, uint8_t test_id, + uint16_t company_id); /* Attention on */ void (*attn_on)(struct bt_mesh_model *model); @@ -52,7 +52,7 @@ struct bt_mesh_health_srv_cb { * * @param max_faults Maximum number of faults the element can have. * - * @return a New net_buf_simple of the needed size. + * @return a New os_mbuf of the needed size. */ #define BT_MESH_HEALTH_FAULT_MSG(max_faults) \ NET_BUF_SIMPLE(1 + 3 + (max_faults)) diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/heartbeat.h b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/heartbeat.h new file mode 100644 index 00000000..b9990f6f --- /dev/null +++ b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/heartbeat.h @@ -0,0 +1,123 @@ +/** @file + * @brief Bluetooth Mesh Heartbeat API. + */ + +/* + * Copyright (c) 2020 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef _BLUETOOTH_MESH_HEARTBEAT_H_ +#define _BLUETOOTH_MESH_HEARTBEAT_H_ + +/** + * @brief Bluetooth Mesh + * @defgroup bt_mesh_heartbeat Bluetooth Mesh Heartbeat + * @ingroup bt_mesh + * @{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** Heartbeat Publication parameters */ +struct bt_mesh_hb_pub { + /** Destination address. */ + uint16_t dst; + /** Remaining publish count. */ + uint16_t count; + /** Time To Live value. */ + uint8_t ttl; + /** + * Bitmap of features that trigger a Heartbeat publication if + * they change. Legal values are @ref BT_MESH_FEAT_RELAY, + * @ref BT_MESH_FEAT_PROXY, @ref BT_MESH_FEAT_FRIEND and + * @ref BT_MESH_FEAT_LOW_POWER. + */ + uint16_t feat; + /** Network index used for publishing. */ + uint16_t net_idx; + /** Publication period in seconds. */ + uint32_t period; +}; + +/** Heartbeat Subscription parameters. */ +struct bt_mesh_hb_sub { + /** Subscription period in seconds. */ + uint32_t period; + /** Remaining subscription time in seconds. */ + uint32_t remaining; + /** Source address to receive Heartbeats from. */ + uint16_t src; + /** Destination address to received Heartbeats on. */ + uint16_t dst; + /** The number of received Heartbeat messages so far. */ + uint16_t count; + /** + * Minimum hops in received messages, ie the shortest registered + * path from the publishing node to the subscribing node. A + * Heartbeat received from an immediate neighbor has hop + * count = 1. + */ + uint8_t min_hops; + /** + * Maximum hops in received messages, ie the longest registered + * path from the publishing node to the subscribing node. A + * Heartbeat received from an immediate neighbor has hop + * count = 1. + */ + uint8_t max_hops; +}; + +/** Heartbeat callback structure */ +struct bt_mesh_hb_cb { + /** @brief Receive callback for heartbeats. + * + * Gets called on every received Heartbeat that matches the current + * Heartbeat subscription parameters. + * + * @param sub Current Heartbeat subscription parameters. + * @param hops The number of hops the Heartbeat was received + * with. + * @param feat The feature set of the publishing node. The + * value is a bitmap of @ref BT_MESH_FEAT_RELAY, + * @ref BT_MESH_FEAT_PROXY, + * @ref BT_MESH_FEAT_FRIEND and + * @ref BT_MESH_FEAT_LOW_POWER. + */ + void (*recv)(const struct bt_mesh_hb_sub *sub, uint8_t hops, + uint16_t feat); + + /** @brief Subscription end callback for heartbeats. + * + * Gets called when the subscription period ends, providing a summary + * of the received heartbeat messages. + * + * @param sub Current Heartbeat subscription parameters. + */ + void (*sub_end)(const struct bt_mesh_hb_sub *sub); +}; + +/** @brief Get the current Heartbeat publication parameters. + * + * @param get Heartbeat publication parameters return buffer. + */ +void bt_mesh_hb_pub_get(struct bt_mesh_hb_pub *get); + +/** @brief Get the current Heartbeat subscription parameters. + * + * @param get Heartbeat subscription parameters return buffer. + */ +void bt_mesh_hb_sub_get(struct bt_mesh_hb_sub *get); + +extern struct bt_mesh_hb_cb hb_cb; + +#ifdef __cplusplus +} +#endif +/** + * @} + */ + +#endif /* _BLUETOOTH_MESH_HEARTBEAT_H_ */ \ No newline at end of file diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/main.h b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/main.h index 4a5bedba..2bcb05c8 100644 --- a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/main.h +++ b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/main.h @@ -59,10 +59,37 @@ typedef enum { BT_MESH_PROV_OOB_ON_DEV = BIT(15), } bt_mesh_prov_oob_info_t; +/** Device Capabilities. */ +struct bt_mesh_dev_capabilities { + /** Number of elements supported by the device */ + uint8_t elem_count; + + /** Supported algorithms and other capabilities */ + uint16_t algorithms; + + /** Supported public key types */ + uint8_t pub_key_type; + + /** Supported static OOB Types */ + uint8_t static_oob; + + /** Supported Output OOB Actions */ + bt_mesh_output_action_t output_actions; + + /** Supported Input OOB Actions */ + bt_mesh_input_action_t input_actions; + + /** Maximum size of Output OOB supported */ + uint8_t output_size; + + /** Maximum size in octets of Input OOB supported */ + uint8_t input_size; +}; + /** Provisioning properties & capabilities. */ struct bt_mesh_prov { /** The UUID that's used when advertising as unprovisioned */ - const u8_t *uuid; + const uint8_t *uuid; /** Optional URI. This will be advertised separately from the * unprovisioned beacon, however the unprovisioned beacon will @@ -75,19 +102,34 @@ struct bt_mesh_prov { bt_mesh_prov_oob_info_t oob_info; /** Static OOB value */ - const u8_t *static_val; + const uint8_t *static_val; /** Static OOB value length */ - u8_t static_val_len; + uint8_t static_val_len; /** Maximum size of Output OOB supported */ - u8_t output_size; + uint8_t output_size; /** Supported Output OOB Actions */ - u16_t output_actions; + uint16_t output_actions; /* Maximum size of Input OOB supported */ - u8_t input_size; + uint8_t input_size; /** Supported Input OOB Actions */ - u16_t input_actions; + uint16_t input_actions; + + /** @brief Provisioning Capabilities. + * + * This callback notifies the application that the provisioning capabilities + * of the unprovisioned device has been received. + * + * The application can consequently call bt_mesh_auth_method_set_<*> to + * select suitable provisioning oob authentication method. + * + * When this callback returns, the provisioner will start authentication with + * the chosen method. + * + * @param cap capabilities supported by device. + */ + void (*capabilities)(const struct bt_mesh_dev_capabilities *cap); /** @brief Output of a number is requested. * @@ -99,7 +141,7 @@ struct bt_mesh_prov { * * @return Zero on success or negative error code otherwise */ - int (*output_number)(bt_mesh_output_action_t act, u32_t num); + int (*output_number)(bt_mesh_output_action_t act, uint32_t num); /** @brief Output of a string is requested. * @@ -126,7 +168,7 @@ struct bt_mesh_prov { * * @return Zero on success or negative error code otherwise */ - int (*input)(bt_mesh_input_action_t act, u8_t size); + int (*input)(bt_mesh_input_action_t act, uint8_t size); /** @brief The other device finished their OOB input. * @@ -146,9 +188,9 @@ struct bt_mesh_prov { * @param uri_hash Pointer to URI Hash value. NULL if no hash was * present in the beacon. */ - void (*unprovisioned_beacon)(u8_t uuid[16], + void (*unprovisioned_beacon)(uint8_t uuid[16], bt_mesh_prov_oob_info_t oob_info, - u32_t *uri_hash); + uint32_t *uri_hash); /** @brief Provisioning link has been opened. * @@ -177,7 +219,7 @@ struct bt_mesh_prov { * @param net_idx NetKeyIndex given during provisioning. * @param addr Primary element address. */ - void (*complete)(u16_t net_idx, u16_t addr); + void (*complete)(uint16_t net_idx, uint16_t addr); /** @brief A new node has been added to the provisioning database. * @@ -186,10 +228,12 @@ struct bt_mesh_prov { * the specified NetKeyIndex and primary element address. * * @param net_idx NetKeyIndex given during provisioning. + * @param uuid UUID of the added node * @param addr Primary element address. * @param num_elem Number of elements that this node has. */ - void (*node_added)(u16_t net_idx, u16_t addr, u8_t num_elem); + void (*node_added)(uint16_t net_idx, uint8_t uuid[16], uint16_t addr, + uint8_t num_elem); /** @brief Node has been reset. * @@ -222,7 +266,90 @@ int bt_mesh_input_string(const char *str); * * @return Zero on success or (negative) error code otherwise. */ -int bt_mesh_input_number(u32_t num); +int bt_mesh_input_number(uint32_t num); + +/** @brief Provide Device public key. + * + * @param public_key Device public key. + * + * @return Zero on success or (negative) error code otherwise. + */ +int bt_mesh_prov_remote_pub_key_set(const uint8_t public_key[64]); + +/** @brief Use Input OOB authentication. + * + * Provisioner only. + * + * Instruct the unprovisioned device to use the specified Input OOB + * authentication action. When using @ref BT_MESH_PUSH, @ref BT_MESH_TWIST or + * @ref BT_MESH_ENTER_NUMBER, the @ref bt_mesh_prov::output_number callback is + * called with a random number that has to be entered on the unprovisioned + * device. + * + * When using @ref BT_MESH_ENTER_STRING, the @ref bt_mesh_prov::output_string + * callback is called with a random string that has to be entered on the + * unprovisioned device. + * + * @param action Authentication action used by the unprovisioned device. + * @param size Authentication size. + * + * @return Zero on success or (negative) error code otherwise. + */ +int bt_mesh_auth_method_set_input(bt_mesh_input_action_t action, uint8_t size); + +/** @brief Use Output OOB authentication. + * + * Provisioner only. + * + * Instruct the unprovisioned device to use the specified Output OOB + * authentication action. The @ref bt_mesh_prov::input callback will + * be called. + * + * When using @ref BT_MESH_BLINK, @ref BT_MESH_BEEP, @ref BT_MESH_VIBRATE + * or @ref BT_MESH_DISPLAY_NUMBER, and the application has to call + * @ref bt_mesh_input_number with the random number indicated by + * the unprovisioned device. + * + * When using @ref BT_MESH_DISPLAY_STRING, the application has to call + * @ref bt_mesh_input_string with the random string displayed by the + * unprovisioned device. + * + * @param action Authentication action used by the unprovisioned device. + * @param size Authentication size. + * + * @return Zero on success or (negative) error code otherwise. + */ +int bt_mesh_auth_method_set_output(bt_mesh_output_action_t action, uint8_t size); + +/** @brief Use static OOB authentication. + * + * Provisioner only. + * + * Instruct the unprovisioned device to use static OOB authentication, and use + * the given static authentication value when provisioning. + * + * @param static_val Static OOB value. + * @param size Static OOB value size. + * + * @return Zero on success or (negative) error code otherwise. + */ +int bt_mesh_auth_method_set_static(const uint8_t *static_val, uint8_t size); + +/** @brief Don't use OOB authentication. + * + * Provisioner only. + * + * Don't use any authentication when provisioning new devices. This is the + * default behavior. + * + * @warning Not using any authentication exposes the mesh network to + * impersonation attacks, where attackers can pretend to be the + * unprovisioned device to gain access to the network. Authentication + * is strongly encouraged. + * + * @return Zero on success or (negative) error code otherwise. + */ +int bt_mesh_auth_method_set_none(void); /** @brief Enable specific provisioning bearers * @@ -258,25 +385,6 @@ int bt_mesh_prov_disable(bt_mesh_prov_bearer_t bearers); /* Primary Network Key index */ #define BT_MESH_NET_PRIMARY 0x000 -#define BT_MESH_RELAY_DISABLED 0x00 -#define BT_MESH_RELAY_ENABLED 0x01 -#define BT_MESH_RELAY_NOT_SUPPORTED 0x02 - -#define BT_MESH_BEACON_DISABLED 0x00 -#define BT_MESH_BEACON_ENABLED 0x01 - -#define BT_MESH_GATT_PROXY_DISABLED 0x00 -#define BT_MESH_GATT_PROXY_ENABLED 0x01 -#define BT_MESH_GATT_PROXY_NOT_SUPPORTED 0x02 - -#define BT_MESH_FRIEND_DISABLED 0x00 -#define BT_MESH_FRIEND_ENABLED 0x01 -#define BT_MESH_FRIEND_NOT_SUPPORTED 0x02 - -#define BT_MESH_NODE_IDENTITY_STOPPED 0x00 -#define BT_MESH_NODE_IDENTITY_RUNNING 0x01 -#define BT_MESH_NODE_IDENTITY_NOT_SUPPORTED 0x02 - /* Features */ #define BT_MESH_FEAT_RELAY BIT(0) #define BT_MESH_FEAT_PROXY BIT(1) @@ -299,7 +407,7 @@ int bt_mesh_prov_disable(bt_mesh_prov_bearer_t bearers); * * @return Zero on success or (negative) error code otherwise. */ -int bt_mesh_init(u8_t own_addr_type, +int bt_mesh_init(uint8_t own_addr_type, const struct bt_mesh_prov *prov, const struct bt_mesh_comp *comp); @@ -351,9 +459,9 @@ int bt_mesh_resume(void); * * @return Zero on success or (negative) error code otherwise. */ -int bt_mesh_provision(const u8_t net_key[16], u16_t net_idx, - u8_t flags, u32_t iv_index, u16_t addr, - const u8_t dev_key[16]); +int bt_mesh_provision(const uint8_t net_key[16], uint16_t net_idx, + uint8_t flags, uint32_t iv_index, uint16_t addr, + const uint8_t dev_key[16]); /** @brief Provision a Mesh Node using PB-ADV * @@ -365,8 +473,8 @@ int bt_mesh_provision(const u8_t net_key[16], u16_t net_idx, * * @return Zero on success or (negative) error code otherwise. */ -int bt_mesh_provision_adv(const u8_t uuid[16], u16_t net_idx, u16_t addr, - u8_t attention_duration); +int bt_mesh_provision_adv(const uint8_t uuid[16], uint16_t net_idx, uint16_t addr, + uint8_t attention_duration); /** @brief Check if the local node has been provisioned. * @@ -428,7 +536,17 @@ int bt_mesh_lpn_poll(void); * * @param cb Function to call when the Friendship status changes. */ -void bt_mesh_lpn_set_cb(void (*cb)(u16_t friend_addr, bool established)); +void bt_mesh_lpn_set_cb(void (*cb)(uint16_t friend_addr, bool established)); + +/** @brief Terminate Friendship. + * + * Terminated Friendship for given LPN. + * + * @param lpn_addr Low Power Node address. + * + * @return Zero on success or (negative) error code otherwise. + */ +int bt_mesh_friend_terminate(uint16_t lpn_addr); #ifdef __cplusplus } diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/mesh.h b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/mesh.h index 9ba63ef0..b9bc24fb 100644 --- a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/mesh.h +++ b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/mesh.h @@ -17,10 +17,15 @@ #include "glue.h" #include "access.h" #include "main.h" +#include "cfg.h" #include "cfg_srv.h" #include "health_srv.h" #include "cfg_cli.h" #include "health_cli.h" #include "proxy.h" +#include "cdb.h" +#include "cfg.h" +#include "heartbeat.h" +#include "../src/app_keys.h" #endif /* __BT_MESH_H */ diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/model_cli.h b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/model_cli.h index f2e77a47..87e2dd2b 100644 --- a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/model_cli.h +++ b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/model_cli.h @@ -15,7 +15,7 @@ struct bt_mesh_gen_model_cli { struct bt_mesh_model *model; struct k_sem op_sync; - u32_t op_pending; + uint32_t op_pending; void *op_param; }; @@ -33,14 +33,14 @@ extern const struct bt_mesh_model_cb bt_mesh_gen_level_cli_cb; BT_MESH_MODEL_CB(BT_MESH_MODEL_ID_GEN_LEVEL_CLI, gen_level_cli_op, pub,\ cli_data, &bt_mesh_gen_level_cli_cb) -int bt_mesh_gen_onoff_get(u16_t net_idx, u16_t addr, u16_t app_idx, - u8_t *state); -int bt_mesh_gen_onoff_set(u16_t net_idx, u16_t addr, u16_t app_idx, - u8_t val, u8_t *state); -int bt_mesh_gen_level_get(u16_t net_idx, u16_t addr, u16_t app_idx, - s16_t *level); -int bt_mesh_gen_level_set(u16_t net_idx, u16_t addr, u16_t app_idx, - s16_t val, s16_t *state); +int bt_mesh_gen_onoff_get(uint16_t net_idx, uint16_t addr, uint16_t app_idx, + uint8_t *state); +int bt_mesh_gen_onoff_set(uint16_t net_idx, uint16_t addr, uint16_t app_idx, + uint8_t val, uint8_t *state); +int bt_mesh_gen_level_get(uint16_t net_idx, uint16_t addr, uint16_t app_idx, + int16_t *level); +int bt_mesh_gen_level_set(uint16_t net_idx, uint16_t addr, uint16_t app_idx, + int16_t val, int16_t *state); #ifdef __cplusplus } diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/model_srv.h b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/model_srv.h index e498ad34..a23296b8 100644 --- a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/model_srv.h +++ b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/model_srv.h @@ -14,8 +14,8 @@ extern "C" { struct bt_mesh_gen_onoff_srv { struct bt_mesh_model *model; - int (*get)(struct bt_mesh_model *model, u8_t *state); - int (*set)(struct bt_mesh_model *model, u8_t state); + int (*get)(struct bt_mesh_model *model, uint8_t *state); + int (*set)(struct bt_mesh_model *model, uint8_t state); }; extern const struct bt_mesh_model_op gen_onoff_srv_op[]; @@ -28,8 +28,8 @@ extern const struct bt_mesh_model_cb gen_onoff_srv_cb; struct bt_mesh_gen_level_srv { struct bt_mesh_model *model; - int (*get)(struct bt_mesh_model *model, s16_t *level); - int (*set)(struct bt_mesh_model *model, s16_t level); + int (*get)(struct bt_mesh_model *model, int16_t *level); + int (*set)(struct bt_mesh_model *model, int16_t level); }; extern const struct bt_mesh_model_op gen_level_srv_op[]; @@ -42,8 +42,8 @@ extern const struct bt_mesh_model_cb gen_level_srv_cb; struct bt_mesh_light_lightness_srv { struct bt_mesh_model *model; - int (*get)(struct bt_mesh_model *model, s16_t *level); - int (*set)(struct bt_mesh_model *model, s16_t level); + int (*get)(struct bt_mesh_model *model, int16_t *level); + int (*set)(struct bt_mesh_model *model, int16_t level); }; extern const struct bt_mesh_model_op light_lightness_srv_op[]; @@ -53,12 +53,12 @@ extern const struct bt_mesh_model_cb light_lightness_srv_cb; BT_MESH_MODEL_CB(BT_MESH_MODEL_ID_LIGHT_LIGHTNESS_SRV, \ light_lightness_srv_op, pub, srv, &light_lightness_srv_cb) -void bt_mesh_set_gen_onoff_srv_cb(int (*get)(struct bt_mesh_model *model, u8_t *state), - int (*set)(struct bt_mesh_model *model, u8_t state)); -void bt_mesh_set_gen_level_srv_cb(int (*get)(struct bt_mesh_model *model, s16_t *level), - int (*set)(struct bt_mesh_model *model, s16_t level)); -void bt_mesh_set_light_lightness_srv_cb(int (*get)(struct bt_mesh_model *model, s16_t *level), - int (*set)(struct bt_mesh_model *model, s16_t level)); +void bt_mesh_set_gen_onoff_srv_cb(int (*get)(struct bt_mesh_model *model, uint8_t *state), + int (*set)(struct bt_mesh_model *model, uint8_t state)); +void bt_mesh_set_gen_level_srv_cb(int (*get)(struct bt_mesh_model *model, int16_t *level), + int (*set)(struct bt_mesh_model *model, int16_t level)); +void bt_mesh_set_light_lightness_srv_cb(int (*get)(struct bt_mesh_model *model, int16_t *level), + int (*set)(struct bt_mesh_model *model, int16_t level)); #ifdef __cplusplus } diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/testing.h b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/testing.h index 4c2b2a61..580aafe4 100644 --- a/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/testing.h +++ b/src/libs/mynewt-nimble/nimble/host/mesh/include/mesh/testing.h @@ -33,13 +33,13 @@ extern "C" { * Allows access to Bluetooth stack internals, not exposed by public API. */ struct bt_test_cb { - void (*mesh_net_recv)(u8_t ttl, u8_t ctl, u16_t src, u16_t dst, + void (*mesh_net_recv)(uint8_t ttl, uint8_t ctl, uint16_t src, uint16_t dst, const void *payload, size_t payload_len); - void (*mesh_model_bound)(u16_t addr, struct bt_mesh_model *model, - u16_t key_idx); - void (*mesh_model_unbound)(u16_t addr, struct bt_mesh_model *model, - u16_t key_idx); - void (*mesh_prov_invalid_bearer)(u8_t opcode); + void (*mesh_model_bound)(uint16_t addr, struct bt_mesh_model *model, + uint16_t key_idx); + void (*mesh_model_unbound)(uint16_t addr, struct bt_mesh_model *model, + uint16_t key_idx); + void (*mesh_prov_invalid_bearer)(uint8_t opcode); void (*mesh_trans_incomp_timer_exp)(void); sys_snode_t node; @@ -66,7 +66,7 @@ void bt_test_cb_unregister(struct bt_test_cb *cb); * * @return Zero on success or (negative) error code otherwise. */ -int bt_test_mesh_lpn_group_add(u16_t group); +int bt_test_mesh_lpn_group_add(uint16_t group); /** Send Friend Subscription List Remove message. * @@ -79,7 +79,7 @@ int bt_test_mesh_lpn_group_add(u16_t group); * * @return Zero on success or (negative) error code otherwise. */ -int bt_test_mesh_lpn_group_remove(u16_t *groups, size_t groups_count); +int bt_test_mesh_lpn_group_remove(uint16_t *groups, size_t groups_count); /** Clear replay protection list cache. * @@ -87,12 +87,12 @@ int bt_test_mesh_lpn_group_remove(u16_t *groups, size_t groups_count); */ int bt_test_mesh_rpl_clear(void); -u8_t mod_bind(struct bt_mesh_model *model, u16_t key_idx); -u8_t mod_unbind(struct bt_mesh_model *model, u16_t key_idx, bool store); +uint8_t mod_bind(struct bt_mesh_model *model, uint16_t key_idx); +uint8_t mod_unbind(struct bt_mesh_model *model, uint16_t key_idx, bool store); int cmd_mesh_init(int argc, char *argv[]); int bt_test_shell_init(void); -int bt_test_bind_app_key_to_model(struct bt_mesh_model *model, u16_t key_idx, u16_t id); +int bt_test_bind_app_key_to_model(struct bt_mesh_model *model, uint16_t key_idx, uint16_t id); /** * @} diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/access.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/access.c index ff8e9999..da077182 100644 --- a/src/libs/mynewt-nimble/nimble/host/mesh/src/access.c +++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/access.c @@ -26,7 +26,7 @@ #endif static const struct bt_mesh_comp *dev_comp; -static u16_t dev_primary_addr; +static uint16_t dev_primary_addr; void bt_mesh_model_foreach(void (*func)(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, @@ -53,7 +53,7 @@ void bt_mesh_model_foreach(void (*func)(struct bt_mesh_model *mod, } } -s32_t bt_mesh_model_pub_period_get(struct bt_mesh_model *mod) +int32_t bt_mesh_model_pub_period_get(struct bt_mesh_model *mod) { int period; @@ -89,10 +89,10 @@ s32_t bt_mesh_model_pub_period_get(struct bt_mesh_model *mod) } } -static s32_t next_period(struct bt_mesh_model *mod) +static int32_t next_period(struct bt_mesh_model *mod) { struct bt_mesh_model_pub *pub = mod->pub; - u32_t elapsed, period; + uint32_t elapsed, period; period = bt_mesh_model_pub_period_get(mod); if (!period) { @@ -115,7 +115,7 @@ static s32_t next_period(struct bt_mesh_model *mod) static void publish_sent(int err, void *user_data) { struct bt_mesh_model *mod = user_data; - s32_t delay; + int32_t delay; BT_DBG("err %d", err); @@ -131,7 +131,7 @@ static void publish_sent(int err, void *user_data) } } -static void publish_start(u16_t duration, int err, void *user_data) +static void publish_start(uint16_t duration, int err, void *user_data) { struct bt_mesh_model *mod = user_data; struct bt_mesh_model_pub *pub = mod->pub; @@ -156,30 +156,18 @@ static int publish_retransmit(struct bt_mesh_model *mod) { struct os_mbuf *sdu = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX); struct bt_mesh_model_pub *pub = mod->pub; - struct bt_mesh_app_key *key; struct bt_mesh_msg_ctx ctx = { .addr = pub->addr, .send_ttl = pub->ttl, + .app_idx = pub->key, }; struct bt_mesh_net_tx tx = { .ctx = &ctx, .src = bt_mesh_model_elem(mod)->addr, - .xmit = bt_mesh_net_transmit_get(), .friend_cred = pub->cred, }; int err; - key = bt_mesh_app_key_find(pub->key); - if (!key) { - err = -EADDRNOTAVAIL; - goto done; - } - - tx.sub = bt_mesh_subnet_get(key->net_idx); - - ctx.net_idx = key->net_idx; - ctx.app_idx = key->app_idx; - net_buf_simple_init(sdu, 0); net_buf_simple_add_mem(sdu, pub->msg->om_data, pub->msg->om_len); @@ -187,15 +175,22 @@ static int publish_retransmit(struct bt_mesh_model *mod) err = bt_mesh_trans_send(&tx, sdu, &pub_sent_cb, mod); -done: os_mbuf_free_chain(sdu); return err; } +static void publish_retransmit_end(int err, struct bt_mesh_model_pub *pub) +{ + /* Cancel all retransmits for this publish attempt */ + pub->count = 0U; + /* Make sure the publish timer gets reset */ + publish_sent(err, pub->mod); +} + static void mod_publish(struct ble_npl_event *work) { struct bt_mesh_model_pub *pub = ble_npl_event_get_arg(work); - s32_t period_ms; + int32_t period_ms; int err; BT_DBG(""); @@ -227,7 +222,10 @@ static void mod_publish(struct ble_npl_event *work) err = pub->update(pub->mod); if (err) { - BT_ERR("Failed to update publication message"); + /* Cancel this publish attempt. */ + BT_DBG("Update failed, skipping publish (err: %d)", err); + pub->period_start = k_uptime_get_32(); + publish_retransmit_end(err, pub); return; } @@ -242,7 +240,7 @@ struct bt_mesh_elem *bt_mesh_model_elem(struct bt_mesh_model *mod) return &dev_comp->elem[mod->elem_idx]; } -struct bt_mesh_model *bt_mesh_model_get(bool vnd, u8_t elem_idx, u8_t mod_idx) +struct bt_mesh_model *bt_mesh_model_get(bool vnd, uint8_t elem_idx, uint8_t mod_idx) { struct bt_mesh_elem *elem; @@ -274,6 +272,11 @@ static void mod_init(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, bool vnd, bool primary, void *user_data) { int i; + int *err = user_data; + + if (*err) { + return; + } if (mod->pub) { mod->pub->mod = mod; @@ -293,12 +296,14 @@ static void mod_init(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, } if (mod->cb && mod->cb->init) { - mod->cb->init(mod); + *err = mod->cb->init(mod); } } int bt_mesh_comp_register(const struct bt_mesh_comp *comp) { + int err; + /* There must be at least one element */ if (!comp->elem_count) { return -EINVAL; @@ -306,12 +311,13 @@ int bt_mesh_comp_register(const struct bt_mesh_comp *comp) dev_comp = comp; - bt_mesh_model_foreach(mod_init, NULL); + err = 0; + bt_mesh_model_foreach(mod_init, &err); - return 0; + return err; } -void bt_mesh_comp_provision(u16_t addr) +void bt_mesh_comp_provision(uint16_t addr) { int i; @@ -334,16 +340,14 @@ void bt_mesh_comp_unprovision(void) BT_DBG(""); dev_primary_addr = BT_MESH_ADDR_UNASSIGNED; - - bt_mesh_model_foreach(mod_init, NULL); } -u16_t bt_mesh_primary_addr(void) +uint16_t bt_mesh_primary_addr(void) { return dev_primary_addr; } -static u16_t *model_group_get(struct bt_mesh_model *mod, u16_t addr) +static uint16_t *model_group_get(struct bt_mesh_model *mod, uint16_t addr) { int i; @@ -357,13 +361,13 @@ static u16_t *model_group_get(struct bt_mesh_model *mod, u16_t addr) } struct find_group_visitor_ctx { - u16_t *entry; + uint16_t *entry; struct bt_mesh_model *mod; - u16_t addr; + uint16_t addr; }; static enum bt_mesh_walk find_group_mod_visitor(struct bt_mesh_model *mod, - u32_t depth, void *user_data) + uint32_t depth, void *user_data) { struct find_group_visitor_ctx *ctx = user_data; @@ -380,7 +384,7 @@ static enum bt_mesh_walk find_group_mod_visitor(struct bt_mesh_model *mod, return BT_MESH_WALK_CONTINUE; } -u16_t *bt_mesh_model_find_group(struct bt_mesh_model **mod, u16_t addr) +uint16_t *bt_mesh_model_find_group(struct bt_mesh_model **mod, uint16_t addr) { struct find_group_visitor_ctx ctx = { .mod = *mod, @@ -396,10 +400,10 @@ u16_t *bt_mesh_model_find_group(struct bt_mesh_model **mod, u16_t addr) } static struct bt_mesh_model *bt_mesh_elem_find_group(struct bt_mesh_elem *elem, - u16_t group_addr) + uint16_t group_addr) { struct bt_mesh_model *model; - u16_t *match; + uint16_t *match; int i; for (i = 0; i < elem->model_count; i++) { @@ -423,9 +427,9 @@ static struct bt_mesh_model *bt_mesh_elem_find_group(struct bt_mesh_elem *elem, return NULL; } -struct bt_mesh_elem *bt_mesh_elem_find(u16_t addr) +struct bt_mesh_elem *bt_mesh_elem_find(uint16_t addr) { - u16_t index; + uint16_t index; if (BT_MESH_ADDR_IS_UNICAST(addr)) { index = (addr - dev_comp->elem[0].addr); @@ -447,12 +451,12 @@ struct bt_mesh_elem *bt_mesh_elem_find(u16_t addr) return NULL; } -u8_t bt_mesh_elem_count(void) +uint8_t bt_mesh_elem_count(void) { return dev_comp->elem_count; } -static bool model_has_key(struct bt_mesh_model *mod, u16_t key) +static bool model_has_key(struct bt_mesh_model *mod, uint16_t key) { int i; @@ -467,22 +471,26 @@ static bool model_has_key(struct bt_mesh_model *mod, u16_t key) return false; } -static bool model_has_dst(struct bt_mesh_model *mod, u16_t dst) +static bool model_has_dst(struct bt_mesh_model *mod, uint16_t dst) { if (BT_MESH_ADDR_IS_UNICAST(dst)) { return (dev_comp->elem[mod->elem_idx].addr == dst); } else if (BT_MESH_ADDR_IS_GROUP(dst) || BT_MESH_ADDR_IS_VIRTUAL(dst)) { - return bt_mesh_model_find_group(&mod, dst); + return !!bt_mesh_model_find_group(&mod, dst); } - return (mod->elem_idx == 0 && bt_mesh_fixed_group_match(dst)); + /* If a message with a fixed group address is sent to the access layer, + * the lower layers have already confirmed that we are subscribing to + * it. All models on the primary element should receive the message. + */ + return mod->elem_idx == 0; } static const struct bt_mesh_model_op *find_op(struct bt_mesh_model *models, - u8_t model_count, u32_t opcode, + uint8_t model_count, uint32_t opcode, struct bt_mesh_model **model) { - u8_t i; + uint8_t i; for (i = 0; i < model_count; i++) { const struct bt_mesh_model_op *op; @@ -500,7 +508,7 @@ static const struct bt_mesh_model_op *find_op(struct bt_mesh_model *models, return NULL; } -static int get_opcode(struct os_mbuf *buf, u32_t *opcode) +static int get_opcode(struct os_mbuf *buf, uint32_t *opcode) { switch (buf->om_data[0] >> 6) { case 0x00: @@ -527,6 +535,10 @@ static int get_opcode(struct os_mbuf *buf, u32_t *opcode) } *opcode = net_buf_simple_pull_u8(buf) << 16; + /* Using LE for the CID since the model layer is defined as + * little-endian in the mesh spec and using BT_MESH_MODEL_OP_3 + * will declare the opcode in this way. + */ *opcode |= net_buf_simple_pull_le16(buf); return 0; } @@ -534,29 +546,12 @@ static int get_opcode(struct os_mbuf *buf, u32_t *opcode) CODE_UNREACHABLE; } -bool bt_mesh_fixed_group_match(u16_t addr) -{ - /* Check for fixed group addresses */ - switch (addr) { - case BT_MESH_ADDR_ALL_NODES: - return true; - case BT_MESH_ADDR_PROXIES: - return (bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED); - case BT_MESH_ADDR_FRIENDS: - return (bt_mesh_friend_get() == BT_MESH_FRIEND_ENABLED); - case BT_MESH_ADDR_RELAYS: - return (bt_mesh_relay_get() == BT_MESH_RELAY_ENABLED); - default: - return false; - } -} - void bt_mesh_model_recv(struct bt_mesh_net_rx *rx, struct os_mbuf *buf) { struct bt_mesh_model *models, *model; const struct bt_mesh_model_op *op; - u32_t opcode; - u8_t count; + uint32_t opcode; + uint8_t count; int i; BT_DBG("app_idx 0x%04x src 0x%04x dst 0x%04x", rx->ctx.app_idx, @@ -615,7 +610,7 @@ void bt_mesh_model_recv(struct bt_mesh_net_rx *rx, struct os_mbuf *buf) } } -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) { net_buf_simple_init(msg, 0); @@ -628,6 +623,10 @@ void bt_mesh_model_msg_init(struct os_mbuf *msg, u32_t opcode) break; case 3: net_buf_simple_add_u8(msg, ((opcode >> 16) & 0xff)); + /* Using LE for the CID since the model layer is defined as + * little-endian in the mesh spec and using BT_MESH_MODEL_OP_3 + * will declare the opcode in this way. + */ net_buf_simple_add_le16(msg, opcode & 0xffff); break; default: @@ -674,11 +673,8 @@ int bt_mesh_model_send(struct bt_mesh_model *model, const struct bt_mesh_send_cb *cb, void *cb_data) { struct bt_mesh_net_tx tx = { - .sub = bt_mesh_subnet_get(ctx->net_idx), .ctx = ctx, .src = bt_mesh_model_elem(model)->addr, - .xmit = bt_mesh_net_transmit_get(), - .friend_cred = 0, }; return model_send(model, &tx, false, msg, cb, cb_data); @@ -688,13 +684,15 @@ int bt_mesh_model_publish(struct bt_mesh_model *model) { struct os_mbuf *sdu = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX); struct bt_mesh_model_pub *pub = model->pub; - struct bt_mesh_app_key *key; struct bt_mesh_msg_ctx ctx = { + .addr = pub->addr, + .send_ttl = pub->ttl, + .send_rel = pub->send_rel, + .app_idx = pub->key, }; struct bt_mesh_net_tx tx = { .ctx = &ctx, .src = bt_mesh_model_elem(model)->addr, - .xmit = bt_mesh_net_transmit_get(), }; int err; @@ -710,12 +708,6 @@ int bt_mesh_model_publish(struct bt_mesh_model *model) goto done; } - key = bt_mesh_app_key_find(pub->key); - if (!key) { - err = -EADDRNOTAVAIL; - goto done; - } - if (pub->msg->om_len + 4 > BT_MESH_TX_SDU_MAX) { BT_ERR("Message does not fit maximum SDU size"); err = -EMSGSIZE; @@ -730,13 +722,7 @@ int bt_mesh_model_publish(struct bt_mesh_model *model) net_buf_simple_init(sdu, 0); net_buf_simple_add_mem(sdu, pub->msg->om_data, pub->msg->om_len); - ctx.addr = pub->addr; - ctx.send_ttl = pub->ttl; - ctx.net_idx = key->net_idx; - ctx.app_idx = key->app_idx; - tx.friend_cred = pub->cred; - tx.sub = bt_mesh_subnet_get(ctx.net_idx), pub->count = BT_MESH_PUB_TRANSMIT_COUNT(pub->retransmit); @@ -745,10 +731,7 @@ int bt_mesh_model_publish(struct bt_mesh_model *model) err = model_send(model, &tx, true, sdu, &pub_sent_cb, model); if (err) { - /* Don't try retransmissions for this publish attempt */ - pub->count = 0; - /* Make sure the publish timer gets reset */ - publish_sent(err, model); + publish_retransmit_end(err, pub); } done: @@ -757,9 +740,9 @@ done: } 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) { - u8_t i; + uint8_t i; for (i = 0; i < elem->vnd_model_count; i++) { if (elem->vnd_models[i].vnd.company == company && @@ -772,9 +755,9 @@ struct bt_mesh_model *bt_mesh_model_find_vnd(const struct bt_mesh_elem *elem, } struct bt_mesh_model *bt_mesh_model_find(const struct bt_mesh_elem *elem, - u16_t id) + uint16_t id) { - u8_t i; + uint8_t i; for (i = 0; i < elem->model_count; i++) { if (elem->models[i].id == id) { @@ -802,29 +785,38 @@ struct bt_mesh_model *bt_mesh_model_root(struct bt_mesh_model *mod) void bt_mesh_model_tree_walk(struct bt_mesh_model *root, enum bt_mesh_walk (*cb)(struct bt_mesh_model *mod, - u32_t depth, + uint32_t depth, void *user_data), void *user_data) { struct bt_mesh_model *m = root; - u32_t depth = 0; + int depth = 0; + /* 'skip' is set to true when we ascend from child to parent node. + * In that case, we want to skip calling the callback on the parent + * node and we don't want to descend onto a child node as those + * nodes have already been visited. + */ + bool skip = false; do { - if (cb(m, depth, user_data) == BT_MESH_WALK_STOP) { + if (!skip && + cb(m, (uint32_t)depth, user_data) == BT_MESH_WALK_STOP) { return; } #if MYNEWT_VAL(BLE_MESH_MODEL_EXTENSIONS) - if (m->extends) { + if (!skip && m->extends) { m = m->extends; depth++; } else if (m->flags & BT_MESH_MOD_NEXT_IS_PARENT) { - m = m->next->next; + m = m->next; depth--; + skip = true; } else { m = m->next; + skip = false; } #endif - } while (m && m != root); + } while (m && depth > 0); } #if MYNEWT_VAL(BLE_MESH_MODEL_EXTENSIONS) diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/access.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/access.h index 48514983..affba538 100644 --- a/src/libs/mynewt-nimble/nimble/host/mesh/src/access.h +++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/access.h @@ -16,8 +16,7 @@ enum { BT_MESH_MOD_BIND_PENDING = BIT(0), BT_MESH_MOD_SUB_PENDING = BIT(1), BT_MESH_MOD_PUB_PENDING = BIT(2), - BT_MESH_MOD_DATA_PRESENT = BIT(3), - BT_MESH_MOD_NEXT_IS_PARENT = BIT(4), + BT_MESH_MOD_NEXT_IS_PARENT = BIT(3), }; /* Tree walk return codes */ @@ -26,23 +25,21 @@ enum bt_mesh_walk { BT_MESH_WALK_CONTINUE, }; -void bt_mesh_elem_register(struct bt_mesh_elem *elem, u8_t count); +void bt_mesh_elem_register(struct bt_mesh_elem *elem, uint8_t count); -u8_t bt_mesh_elem_count(void); +uint8_t bt_mesh_elem_count(void); /* Find local element based on unicast or group address */ -struct bt_mesh_elem *bt_mesh_elem_find(u16_t addr); +struct bt_mesh_elem *bt_mesh_elem_find(uint16_t addr); struct bt_mesh_model *bt_mesh_model_root(struct bt_mesh_model *mod); void bt_mesh_model_tree_walk(struct bt_mesh_model *root, enum bt_mesh_walk (*cb)(struct bt_mesh_model *mod, - u32_t depth, + uint32_t depth, void *user_data), void *user_data); -u16_t *bt_mesh_model_find_group(struct bt_mesh_model **mod, u16_t addr); - -bool bt_mesh_fixed_group_match(u16_t addr); +uint16_t *bt_mesh_model_find_group(struct bt_mesh_model **mod, uint16_t addr); void bt_mesh_model_foreach(void (*func)(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, @@ -50,16 +47,16 @@ void bt_mesh_model_foreach(void (*func)(struct bt_mesh_model *mod, void *user_data), void *user_data); -s32_t bt_mesh_model_pub_period_get(struct bt_mesh_model *mod); +int32_t bt_mesh_model_pub_period_get(struct bt_mesh_model *mod); -void bt_mesh_comp_provision(u16_t addr); +void bt_mesh_comp_provision(uint16_t addr); void bt_mesh_comp_unprovision(void); -u16_t bt_mesh_primary_addr(void); +uint16_t bt_mesh_primary_addr(void); const struct bt_mesh_comp *bt_mesh_comp_get(void); -struct bt_mesh_model *bt_mesh_model_get(bool vnd, u8_t elem_idx, u8_t mod_idx); +struct bt_mesh_model *bt_mesh_model_get(bool vnd, uint8_t elem_idx, uint8_t mod_idx); void bt_mesh_model_recv(struct bt_mesh_net_rx *rx, struct os_mbuf *buf); diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/adv.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/adv.c index 4bd51cc1..4b372991 100644 --- a/src/libs/mynewt-nimble/nimble/host/mesh/src/adv.c +++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/adv.c @@ -38,19 +38,18 @@ #define ADV_INT_DEFAULT_MS 100 #define ADV_INT_FAST_MS 20 -static s32_t adv_int_min = ADV_INT_DEFAULT_MS; +static int32_t adv_int_min = ADV_INT_DEFAULT_MS; /* TinyCrypt PRNG consumes a lot of stack space, so we need to have * an increased call stack whenever it's used. */ #if MYNEWT -#define ADV_STACK_SIZE 768 -OS_TASK_STACK_DEFINE(g_blemesh_stack, ADV_STACK_SIZE); +OS_TASK_STACK_DEFINE(g_blemesh_stack, MYNEWT_VAL(BLE_MESH_ADV_STACK_SIZE)); struct os_task adv_task; #endif static struct ble_npl_eventq adv_queue; -extern u8_t g_mesh_addr_type; +extern uint8_t g_mesh_addr_type; static int adv_initialized = false; static os_membuf_t adv_buf_mem[OS_MEMPOOL_SIZE( @@ -60,14 +59,6 @@ static os_membuf_t adv_buf_mem[OS_MEMPOOL_SIZE( struct os_mbuf_pool adv_os_mbuf_pool; static struct os_mempool adv_buf_mempool; -static const u8_t adv_type[] = { - [BT_MESH_ADV_PROV] = BLE_HS_ADV_TYPE_MESH_PROV, - [BT_MESH_ADV_DATA] = BLE_HS_ADV_TYPE_MESH_MESSAGE, - [BT_MESH_ADV_BEACON] = BLE_HS_ADV_TYPE_MESH_BEACON, - [BT_MESH_ADV_URI] = BLE_HS_ADV_TYPE_URI, -}; - - static struct bt_mesh_adv adv_pool[CONFIG_BT_MESH_ADV_BUF_COUNT]; static struct bt_mesh_adv *adv_alloc(int id) @@ -75,7 +66,7 @@ static struct bt_mesh_adv *adv_alloc(int id) return &adv_pool[id]; } -static inline void adv_send_start(u16_t duration, int err, +static inline void adv_send_start(uint16_t duration, int err, const struct bt_mesh_send_cb *cb, void *cb_data) { @@ -94,10 +85,17 @@ static inline void adv_send_end(int err, const struct bt_mesh_send_cb *cb, static inline void adv_send(struct os_mbuf *buf) { + static const uint8_t adv_type[] = { + [BT_MESH_ADV_PROV] = BLE_HS_ADV_TYPE_MESH_PROV, + [BT_MESH_ADV_DATA] = BLE_HS_ADV_TYPE_MESH_MESSAGE, + [BT_MESH_ADV_BEACON] = BLE_HS_ADV_TYPE_MESH_BEACON, + [BT_MESH_ADV_URI] = BLE_HS_ADV_TYPE_URI, +} ; + const struct bt_mesh_send_cb *cb = BT_MESH_ADV(buf)->cb; void *cb_data = BT_MESH_ADV(buf)->cb_data; struct ble_gap_adv_params param = { 0 }; - u16_t duration, adv_int; + uint16_t duration, adv_int; struct bt_data ad; int err; @@ -154,7 +152,7 @@ mesh_adv_thread(void *args) static struct ble_npl_event *ev; struct os_mbuf *buf; #if (MYNEWT_VAL(BLE_MESH_PROXY)) - s32_t timeout; + int32_t timeout; #endif BT_DBG("started"); @@ -208,7 +206,7 @@ void bt_mesh_adv_update(void) struct os_mbuf *bt_mesh_adv_create_from_pool(struct os_mbuf_pool *pool, bt_mesh_adv_alloc_t get_id, enum bt_mesh_adv_type type, - u8_t xmit, s32_t timeout) + uint8_t xmit, int32_t timeout) { struct bt_mesh_adv *adv; struct os_mbuf *buf; @@ -235,10 +233,11 @@ struct os_mbuf *bt_mesh_adv_create_from_pool(struct os_mbuf_pool *pool, ble_npl_event_set_arg(&adv->ev, buf); return buf; + os_mbuf_free_chain(buf); } -struct os_mbuf *bt_mesh_adv_create(enum bt_mesh_adv_type type, u8_t xmit, - s32_t timeout) +struct os_mbuf *bt_mesh_adv_create(enum bt_mesh_adv_type type, uint8_t xmit, + int32_t timeout) { return bt_mesh_adv_create_from_pool(&adv_os_mbuf_pool, adv_alloc, type, xmit, timeout); @@ -257,8 +256,8 @@ void bt_mesh_adv_send(struct os_mbuf *buf, const struct bt_mesh_send_cb *cb, net_buf_put(&adv_queue, net_buf_ref(buf)); } -static void bt_mesh_scan_cb(const bt_addr_le_t *addr, s8_t rssi, - u8_t adv_type, struct os_mbuf *buf) +static void bt_mesh_scan_cb(const bt_addr_le_t *addr, int8_t rssi, + uint8_t adv_type, struct os_mbuf *buf) { if (adv_type != BLE_HCI_ADV_TYPE_ADV_NONCONN_IND) { return; @@ -270,7 +269,7 @@ static void bt_mesh_scan_cb(const bt_addr_le_t *addr, s8_t rssi, while (buf->om_len > 1) { struct net_buf_simple_state state; - u8_t len, type; + uint8_t len, type; len = net_buf_simple_pull_u8(buf); /* Check for early termination */ @@ -304,7 +303,7 @@ static void bt_mesh_scan_cb(const bt_addr_le_t *addr, s8_t rssi, } net_buf_simple_restore(buf, &state); - net_buf_simple_pull(buf, len); + net_buf_simple_pull_mem(buf, len); } } @@ -333,7 +332,7 @@ void bt_mesh_adv_init(void) #if MYNEWT os_task_init(&adv_task, "mesh_adv", mesh_adv_thread, NULL, MYNEWT_VAL(BLE_MESH_ADV_TASK_PRIO), OS_WAIT_FOREVER, - g_blemesh_stack, ADV_STACK_SIZE); + g_blemesh_stack, MYNEWT_VAL(BLE_MESH_ADV_STACK_SIZE)); #endif /* For BT5 controllers we can have fast advertising interval */ @@ -362,7 +361,7 @@ ble_adv_gap_mesh_cb(struct ble_gap_event *event, void *arg) case BLE_GAP_EVENT_EXT_DISC: ext_desc = &event->ext_disc; buf = os_mbuf_get_pkthdr(&adv_os_mbuf_pool, 0); - if (!buf || os_mbuf_append(buf, ext_desc->data, ext_desc->length_data)) { + if (!buf || os_mbuf_append(buf, ext_desc->om_data, ext_desc->length_data)) { BT_ERR("Could not append data"); goto done; } diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/adv.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/adv.h index 4d0f7d8b..779ee58e 100644 --- a/src/libs/mynewt-nimble/nimble/host/mesh/src/adv.h +++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/adv.h @@ -31,23 +31,18 @@ enum bt_mesh_adv_type BT_MESH_ADV_URI, }; -typedef void (*bt_mesh_adv_func_t)(struct os_mbuf *buf, u16_t duration, +typedef void (*bt_mesh_adv_func_t)(struct os_mbuf *buf, uint16_t duration, int err, void *user_data); struct bt_mesh_adv { const struct bt_mesh_send_cb *cb; void *cb_data; - u8_t type:2, + uint8_t type:2, busy:1; - u8_t xmit; + uint8_t xmit; - /* For transport layer segment sending */ - struct { - u8_t attempts; - } seg; - - u8_t flags; + uint8_t flags; int ref_cnt; struct ble_npl_event ev; @@ -56,13 +51,13 @@ struct bt_mesh_adv { typedef struct bt_mesh_adv *(*bt_mesh_adv_alloc_t)(int id); /* xmit_count: Number of retransmissions, i.e. 0 == 1 transmission */ -struct os_mbuf *bt_mesh_adv_create(enum bt_mesh_adv_type type, u8_t xmit, - s32_t timeout); +struct os_mbuf *bt_mesh_adv_create(enum bt_mesh_adv_type type, uint8_t xmit, + int32_t timeout); struct os_mbuf *bt_mesh_adv_create_from_pool(struct os_mbuf_pool *pool, bt_mesh_adv_alloc_t get_id, enum bt_mesh_adv_type type, - u8_t xmit, s32_t timeout); + uint8_t xmit, int32_t timeout); void bt_mesh_adv_send(struct os_mbuf *buf, const struct bt_mesh_send_cb *cb, void *cb_data); diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/aes-ccm.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/aes-ccm.c new file mode 100644 index 00000000..ab23c264 --- /dev/null +++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/aes-ccm.c @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2020 Nordic Semiconductor ASA + * Copyright (c) 2017 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "crypto.h" +#define MESH_LOG_MODULE BLE_MESH_LOG + +static inline void xor16(uint8_t *dst, const uint8_t *a, const uint8_t *b) +{ + dst[0] = a[0] ^ b[0]; + dst[1] = a[1] ^ b[1]; + dst[2] = a[2] ^ b[2]; + dst[3] = a[3] ^ b[3]; + dst[4] = a[4] ^ b[4]; + dst[5] = a[5] ^ b[5]; + dst[6] = a[6] ^ b[6]; + dst[7] = a[7] ^ b[7]; + dst[8] = a[8] ^ b[8]; + dst[9] = a[9] ^ b[9]; + dst[10] = a[10] ^ b[10]; + dst[11] = a[11] ^ b[11]; + dst[12] = a[12] ^ b[12]; + dst[13] = a[13] ^ b[13]; + dst[14] = a[14] ^ b[14]; + dst[15] = a[15] ^ b[15]; +} + +/* pmsg is assumed to have the nonce already present in bytes 1-13 */ +static int ccm_calculate_X0(const uint8_t key[16], const uint8_t *aad, uint8_t aad_len, + size_t mic_size, uint8_t msg_len, uint8_t b[16], + uint8_t X0[16]) +{ + int i, j, err; + + /* X_0 = e(AppKey, flags || nonce || length) */ + b[0] = (((mic_size - 2) / 2) << 3) | ((!!aad_len) << 6) | 0x01; + + sys_put_be16(msg_len, b + 14); + + err = bt_encrypt_be(key, b, X0); + if (err) { + return err; + } + + /* If AAD is being used to authenticate, include it here */ + if (aad_len) { + sys_put_be16(aad_len, b); + + for (i = 0; i < sizeof(uint16_t); i++) { + b[i] = X0[i] ^ b[i]; + } + + j = 0; + aad_len += sizeof(uint16_t); + while (aad_len > 16) { + do { + b[i] = X0[i] ^ aad[j]; + i++, j++; + } while (i < 16); + + aad_len -= 16; + i = 0; + + err = bt_encrypt_be(key, b, X0); + if (err) { + return err; + } + } + + for (; i < aad_len; i++, j++) { + b[i] = X0[i] ^ aad[j]; + } + + for (i = aad_len; i < 16; i++) { + b[i] = X0[i]; + } + + err = bt_encrypt_be(key, b, X0); + if (err) { + return err; + } + } + + return 0; +} + +static int ccm_auth(const uint8_t key[16], uint8_t nonce[13], + const uint8_t *cleartext_msg, size_t msg_len, const uint8_t *aad, + size_t aad_len, uint8_t *mic, size_t mic_size) +{ + uint8_t b[16], Xn[16], s0[16]; + uint16_t blk_cnt, last_blk; + int err, j, i; + + last_blk = msg_len % 16; + blk_cnt = (msg_len + 15) / 16; + if (!last_blk) { + last_blk = 16U; + } + + b[0] = 0x01; + memcpy(b + 1, nonce, 13); + + /* S[0] = e(AppKey, 0x01 || nonce || 0x0000) */ + sys_put_be16(0x0000, &b[14]); + + err = bt_encrypt_be(key, b, s0); + if (err) { + return err; + } + + ccm_calculate_X0(key, aad, aad_len, mic_size, msg_len, b, Xn); + + for (j = 0; j < blk_cnt; j++) { + /* X_1 = e(AppKey, X_0 ^ Payload[0-15]) */ + if (j + 1 == blk_cnt) { + for (i = 0; i < last_blk; i++) { + b[i] = Xn[i] ^ cleartext_msg[(j * 16) + i]; + } + + memcpy(&b[i], &Xn[i], 16 - i); + } else { + xor16(b, Xn, &cleartext_msg[j * 16]); + } + + err = bt_encrypt_be(key, b, Xn); + if (err) { + return err; + } + } + + /* MIC = C_mic ^ X_1 */ + for (i = 0; i < mic_size; i++) { + mic[i] = s0[i] ^ Xn[i]; + } + + return 0; +} + +static int ccm_crypt(const uint8_t key[16], const uint8_t nonce[13], + const uint8_t *in_msg, uint8_t *out_msg, size_t msg_len) +{ + uint8_t a_i[16], s_i[16]; + uint16_t last_blk, blk_cnt; + size_t i, j; + int err; + + last_blk = msg_len % 16; + blk_cnt = (msg_len + 15) / 16; + if (!last_blk) { + last_blk = 16U; + } + + a_i[0] = 0x01; + memcpy(&a_i[1], nonce, 13); + + for (j = 0; j < blk_cnt; j++) { + /* S_1 = e(AppKey, 0x01 || nonce || 0x0001) */ + sys_put_be16(j + 1, &a_i[14]); + + err = bt_encrypt_be(key, a_i, s_i); + if (err) { + return err; + } + + /* Encrypted = Payload[0-15] ^ C_1 */ + if (j < blk_cnt - 1) { + xor16(&out_msg[j * 16], s_i, &in_msg[j * 16]); + } else { + for (i = 0; i < last_blk; i++) { + out_msg[(j * 16) + i] = + in_msg[(j * 16) + i] ^ s_i[i]; + } + } + } + return 0; +} + +int bt_ccm_decrypt(const uint8_t key[16], uint8_t nonce[13], const uint8_t *enc_msg, + size_t msg_len, const uint8_t *aad, size_t aad_len, + uint8_t *out_msg, size_t mic_size) +{ + uint8_t mic[16]; + + if (aad_len >= 0xff00 || mic_size > sizeof(mic)) { + return -EINVAL; + } + + ccm_crypt(key, nonce, enc_msg, out_msg, msg_len); + + ccm_auth(key, nonce, out_msg, msg_len, aad, aad_len, mic, mic_size); + + if (memcmp(mic, enc_msg + msg_len, mic_size)) { + return -EBADMSG; + } + + return 0; +} + +int bt_ccm_encrypt(const uint8_t key[16], uint8_t nonce[13], const uint8_t *msg, + size_t msg_len, const uint8_t *aad, size_t aad_len, + uint8_t *out_msg, size_t mic_size) +{ + uint8_t *mic = out_msg + msg_len; + + BT_DBG("key %s", bt_hex(key, 16)); + BT_DBG("nonce %s", bt_hex(nonce, 13)); + BT_DBG("msg (len %zu) %s", msg_len, bt_hex(msg, msg_len)); + BT_DBG("aad_len %zu mic_size %zu", aad_len, mic_size); + + /* Unsupported AAD size */ + if (aad_len >= 0xff00 || mic_size > 16) { + return -EINVAL; + } + + ccm_auth(key, nonce, out_msg, msg_len, aad, aad_len, mic, mic_size); + + ccm_crypt(key, nonce, msg, out_msg, msg_len); + + return 0; +} diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/app_keys.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/app_keys.c new file mode 100644 index 00000000..a6c32bf3 --- /dev/null +++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/app_keys.c @@ -0,0 +1,507 @@ +/* + * Copyright (c) 2017 Intel Corporation + * Copyright (c) 2020 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "mesh/mesh.h" +#include "mesh_priv.h" +#include "net.h" +#include "app_keys.h" +#include "rpl.h" +#include "settings.h" +#include "crypto.h" +#include "adv.h" +#include "proxy.h" +#include "friend.h" +#include "foundation.h" +#include "access.h" +#include "subnet.h" + +#define MESH_LOG_MODULE BLE_MESH_LOG +#include "log/log.h" + +static struct bt_mesh_app_key apps[CONFIG_BT_MESH_APP_KEY_COUNT] = { + [0 ... (CONFIG_BT_MESH_APP_KEY_COUNT - 1)] = { + .app_idx = BT_MESH_KEY_UNUSED, + .net_idx = BT_MESH_KEY_UNUSED, + } +}; + +static void app_key_evt(struct bt_mesh_app_key *app, enum bt_mesh_key_evt evt) +{ + int i; + + for (i = 0; i < (sizeof(bt_mesh_app_key_cb_list)/sizeof(void *)); i++) { + if (bt_mesh_app_key_cb_list[i]) { + BT_DBG("app_key_evt %d", i); + bt_mesh_app_key_cb_list[i] (app->app_idx, app->net_idx, evt); + } + } +} + +struct bt_mesh_app_key *app_get(uint16_t app_idx) +{ + for (int i = 0; i < ARRAY_SIZE(apps); i++) { + if (apps[i].app_idx == app_idx) { + return &apps[i]; + } + } + + return NULL; +} + +static struct bt_mesh_app_key *app_key_alloc(uint16_t app_idx) +{ + struct bt_mesh_app_key *app = NULL; + + for (int i = 0; i < ARRAY_SIZE(apps); i++) { + /* Check for already existing app_key */ + if (apps[i].app_idx == app_idx) { + return &apps[i]; + } + + if (!app && apps[i].app_idx == BT_MESH_KEY_UNUSED) { + app = &apps[i]; + } + } + + return app; +} + +static void app_key_del(struct bt_mesh_app_key *app) +{ + BT_DBG("AppIdx 0x%03x", app->app_idx); + + if (IS_ENABLED(CONFIG_BT_SETTINGS)) { + bt_mesh_clear_app_key(app->app_idx); + } + + app_key_evt(app, BT_MESH_KEY_DELETED); + + app->net_idx = BT_MESH_KEY_UNUSED; + app->app_idx = BT_MESH_KEY_UNUSED; + (void)memset(app->keys, 0, sizeof(app->keys)); +} + +static void app_key_revoke(struct bt_mesh_app_key *app) +{ + if (!app->updated) { + return; + } + + memcpy(&app->keys[0], &app->keys[1], sizeof(app->keys[0])); + memset(&app->keys[1], 0, sizeof(app->keys[1])); + app->updated = false; + + if (IS_ENABLED(CONFIG_BT_SETTINGS)) { + bt_mesh_store_app_key(app->app_idx); + } + + app_key_evt(app, BT_MESH_KEY_REVOKED); +} + + +static void subnet_evt(struct bt_mesh_subnet *sub, enum bt_mesh_key_evt evt) +{ + if (evt == BT_MESH_KEY_UPDATED || evt == BT_MESH_KEY_ADDED) { + return; + } + + for (int i = 0; i < ARRAY_SIZE(apps); i++) { + struct bt_mesh_app_key *app = &apps[i]; + + if (app->app_idx == BT_MESH_KEY_UNUSED) { + continue; + } + + if (app->net_idx != sub->net_idx) { + continue; + } + + if (evt == BT_MESH_KEY_DELETED) { + app_key_del(app); + } else if (evt == BT_MESH_KEY_REVOKED) { + app_key_revoke(app); + } else if (evt == BT_MESH_KEY_SWAPPED && app->updated) { + app_key_evt(app, BT_MESH_KEY_SWAPPED); + } + } +} + + +uint8_t bt_mesh_app_key_add(uint16_t app_idx, uint16_t net_idx, + const uint8_t key[16]) +{ + if (!bt_mesh_subnet_cb_list[0]) { + bt_mesh_subnet_cb_list[0] = subnet_evt; + } + + struct bt_mesh_app_key *app; + + BT_DBG("net_idx 0x%04x app_idx %04x val %s", net_idx, app_idx, + bt_hex(key, 16)); + + if (!bt_mesh_subnet_get(net_idx)) { + return STATUS_INVALID_NETKEY; + } + + app = app_key_alloc(app_idx); + if (!app) { + return STATUS_INSUFF_RESOURCES; + } + + if (app->app_idx == app_idx) { + if (app->net_idx != net_idx) { + return STATUS_INVALID_BINDING; + } + + if (memcmp(key, app->keys[0].val, 16)) { + return STATUS_IDX_ALREADY_STORED; + } + + return STATUS_SUCCESS; + } + + if (bt_mesh_app_id(key, &app->keys[0].id)) { + return STATUS_CANNOT_SET; + } + + BT_DBG("AppIdx 0x%04x AID 0x%02x", app_idx, app->keys[0].id); + + app->net_idx = net_idx; + app->app_idx = app_idx; + app->updated = false; + memcpy(app->keys[0].val, key, 16); + + if (IS_ENABLED(CONFIG_BT_SETTINGS)) { + BT_DBG("Storing AppKey persistently"); + bt_mesh_store_app_key(app->app_idx); + } + + app_key_evt(app, BT_MESH_KEY_ADDED); + + return STATUS_SUCCESS; +} + +struct bt_mesh_app_key *bt_mesh_app_key_get(uint16_t app_idx) +{ + struct bt_mesh_app_key *app; + + app = app_get(app_idx); + if (app) { + return app; + } + + return NULL; +} + +uint8_t bt_mesh_app_key_update(uint16_t app_idx, uint16_t net_idx, + const uint8_t key[16]) +{ + struct bt_mesh_app_key *app; + struct bt_mesh_subnet *sub; + + BT_DBG("net_idx 0x%04x app_idx %04x val %s", net_idx, app_idx, + bt_hex(key, 16)); + + app = app_get(app_idx); + if (!app) { + return STATUS_INVALID_APPKEY; + } + + if (net_idx != BT_MESH_KEY_UNUSED && app->net_idx != net_idx) { + return STATUS_INVALID_BINDING; + } + + sub = bt_mesh_subnet_get(app->net_idx); + if (!sub) { + return STATUS_INVALID_NETKEY; + } + + /* The AppKey Update message shall generate an error when node + * is in normal operation, Phase 2, or Phase 3 or in Phase 1 + * when the AppKey Update message on a valid AppKeyIndex when + * the AppKey value is different. + */ + if (sub->kr_phase != BT_MESH_KR_PHASE_1) { + return STATUS_CANNOT_UPDATE; + } + + if (app->updated) { + if (memcmp(app->keys[1].val, key, 16)) { + return STATUS_IDX_ALREADY_STORED; + } + + return STATUS_SUCCESS; + } + + if (bt_mesh_app_id(key, &app->keys[1].id)) { + return STATUS_CANNOT_UPDATE; + } + + BT_DBG("app_idx 0x%04x AID 0x%02x", app_idx, app->keys[1].id); + + app->updated = true; + memcpy(app->keys[1].val, key, 16); + + if (IS_ENABLED(CONFIG_BT_SETTINGS)) { + BT_DBG("Storing AppKey persistently"); + bt_mesh_store_app_key(app->app_idx); + } + + app_key_evt(app, BT_MESH_KEY_UPDATED); + + return STATUS_SUCCESS; +} + +uint8_t bt_mesh_app_key_del(uint16_t app_idx, uint16_t net_idx) +{ + struct bt_mesh_app_key *app; + + BT_DBG("AppIdx 0x%03x", app_idx); + + if (net_idx != BT_MESH_KEY_UNUSED && !bt_mesh_subnet_get(net_idx)) { + return STATUS_INVALID_NETKEY; + } + + app = app_get(app_idx); + if (!app) { + /* This could be a retry of a previous attempt that had its + * response lost, so pretend that it was a success. + */ + return STATUS_SUCCESS; + } + + if (net_idx != BT_MESH_KEY_UNUSED && net_idx != app->net_idx) { + return STATUS_INVALID_BINDING; + } + + app_key_del(app); + + return STATUS_SUCCESS; +} + +int bt_mesh_app_key_set(uint16_t app_idx, uint16_t net_idx, + const uint8_t old_key[16], const uint8_t new_key[16]) +{ + struct bt_mesh_app_key *app; + + app = app_key_alloc(app_idx); + if (!app) { + return -ENOMEM; + } + + if (app->app_idx == app_idx) { + return 0; + } + + BT_DBG("AppIdx 0x%04x AID 0x%02x", app_idx, app->keys[0].id); + + memcpy(app->keys[0].val, old_key, 16); + if (bt_mesh_app_id(old_key, &app->keys[0].id)) { + return -EIO; + } + + if (new_key) { + memcpy(app->keys[1].val, new_key, 16); + if (bt_mesh_app_id(new_key, &app->keys[1].id)) { + return -EIO; + } + } + + app->net_idx = net_idx; + app->app_idx = app_idx; + app->updated = !!new_key; + + return 0; +} + +bool bt_mesh_app_key_exists(uint16_t app_idx) +{ + for (int i = 0; i < ARRAY_SIZE(apps); i++) { + if (apps[i].app_idx == app_idx) { + return true; + } + } + + return false; +} + +ssize_t bt_mesh_app_keys_get(uint16_t net_idx, uint16_t app_idxs[], size_t max, + off_t skip) +{ + size_t count = 0; + + for (int i = 0; i < ARRAY_SIZE(apps); i++) { + struct bt_mesh_app_key *app = &apps[i]; + + if (app->app_idx == BT_MESH_KEY_UNUSED) { + continue; + } + + if (net_idx != BT_MESH_KEY_ANY && app->net_idx != net_idx) { + continue; + } + + if (skip) { + skip--; + continue; + } + + if (count >= max) { + return -ENOMEM; + } + + app_idxs[count++] = app->app_idx; + } + + return count; +} + +int bt_mesh_keys_resolve(struct bt_mesh_msg_ctx *ctx, + struct bt_mesh_subnet **sub, + const uint8_t *app_key[16], uint8_t *aid) +{ + struct bt_mesh_app_key *app = NULL; + + if (BT_MESH_IS_DEV_KEY(ctx->app_idx)) { + /* With device keys, the application has to decide which subnet + * to send on. + */ + *sub = bt_mesh_subnet_get(ctx->net_idx); + if (!*sub) { + BT_WARN("Unknown NetKey 0x%03x", ctx->net_idx); + return -EINVAL; + } + + if (ctx->app_idx == BT_MESH_KEY_DEV_REMOTE && + !bt_mesh_elem_find(ctx->addr)) { + struct bt_mesh_cdb_node *node; + + if (!IS_ENABLED(CONFIG_BT_MESH_CDB)) { + BT_WARN("No DevKey for 0x%04x", ctx->addr); + return -EINVAL; + } + + node = bt_mesh_cdb_node_get(ctx->addr); + if (!node) { + BT_WARN("No DevKey for 0x%04x", ctx->addr); + return -EINVAL; + } + + *app_key = node->dev_key; + } else { + *app_key = bt_mesh.dev_key; + } + + *aid = 0; + return 0; + } + + app = app_get(ctx->app_idx); + if (!app) { + BT_WARN("Unknown AppKey 0x%03x", ctx->app_idx); + return -EINVAL; + } + + *sub = bt_mesh_subnet_get(app->net_idx); + if (!*sub) { + BT_WARN("Unknown NetKey 0x%03x", app->net_idx); + return -EINVAL; + } + + if ((*sub)->kr_phase == BT_MESH_KR_PHASE_2 && app->updated) { + *aid = app->keys[1].id; + *app_key = app->keys[1].val; + } else { + *aid = app->keys[0].id; + *app_key = app->keys[0].val; + } + + return 0; +} + +uint16_t bt_mesh_app_key_find(bool dev_key, uint8_t aid, + struct bt_mesh_net_rx *rx, + int (*cb)(struct bt_mesh_net_rx *rx, + const uint8_t key[16], void *cb_data), + void *cb_data) +{ + int err, i; + + if (dev_key) { + /* Attempt remote dev key first, as that is only available for + * provisioner devices, which normally don't interact with nodes + * that know their local dev key. + */ + if (IS_ENABLED(CONFIG_BT_MESH_CDB) && + rx->net_if != BT_MESH_NET_IF_LOCAL) { + struct bt_mesh_cdb_node *node; + + node = bt_mesh_cdb_node_get(rx->ctx.addr); + if (node && !cb(rx, node->dev_key, cb_data)) { + return BT_MESH_KEY_DEV_REMOTE; + } + } + + /** Bluetooth Mesh Specification v1.0.1, section 3.4.3: + * The Device key is only valid for unicast addresses. + */ + if (BT_MESH_ADDR_IS_UNICAST(rx->ctx.recv_dst)) { + err = cb(rx, bt_mesh.dev_key, cb_data); + if (!err) { + return BT_MESH_KEY_DEV_LOCAL; + } + } + + return BT_MESH_KEY_UNUSED; + } + + for (i = 0; i < ARRAY_SIZE(apps); i++) { + const struct bt_mesh_app_key *app = &apps[i]; + const struct bt_mesh_app_cred *cred; + + if (app->app_idx == BT_MESH_KEY_UNUSED) { + continue; + } + + if (app->net_idx != rx->sub->net_idx) { + continue; + } + + if (rx->new_key && app->updated) { + cred = &app->keys[1]; + } else { + cred = &app->keys[0]; + } + + if (cred->id != aid) { + continue; + } + + err = cb(rx, cred->val, cb_data); + if (err) { + continue; + } + + return app->app_idx; + } + + return BT_MESH_KEY_UNUSED; +} + + +void bt_mesh_app_keys_reset(void) +{ + for (int i = 0; i < ARRAY_SIZE(apps); i++) { + struct bt_mesh_app_key *app = &apps[i]; + + if (app->app_idx != BT_MESH_KEY_UNUSED) { + app_key_del(app); + } + } +} \ No newline at end of file diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/app_keys.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/app_keys.h new file mode 100644 index 00000000..d007b785 --- /dev/null +++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/app_keys.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2020 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _BT_MESH_APP_KEYS_H_ +#define _BT_MESH_APP_KEYS_H_ + +#include "mesh/mesh.h" +#include "subnet.h" + +/** Mesh Application. */ +struct bt_mesh_app_key { + uint16_t net_idx; + uint16_t app_idx; + bool updated; + struct bt_mesh_app_cred { + uint8_t id; + uint8_t val[16]; + } keys[2]; +}; + +/** @brief Reset the app keys module. */ +void bt_mesh_app_keys_reset(void); + +/** @brief Get the application key with the given AppIdx. + * + * @param app_idx App index. + * + * @return The matching application, or NULL if the application isn't known. + */ +struct bt_mesh_app_key *bt_mesh_app_key_get(uint16_t app_idx); + +/** @brief Initialize a new application key with the given parameters. + * + * @param app_idx AppIndex. + * @param net_idx NetIndex the application is bound to. + * @param old_key Current application key. + * @param new_key Updated application key, or NULL if not known. + * + * @return 0 on success, or (negative) error code on failure. + */ +int bt_mesh_app_key_set(uint16_t app_idx, uint16_t net_idx, + const uint8_t old_key[16], const uint8_t new_key[16]); + +/** @brief Resolve the message encryption keys, given a message context. + * + * Will use the @c ctx::app_idx and @c ctx::net_idx fields to find a pair of + * message encryption keys. If @c ctx::app_idx represents a device key, the + * @c ctx::net_idx will be used to determine the net key. Otherwise, the + * @c ctx::net_idx parameter will be ignored. + * + * @param ctx Message context. + * @param sub Subnet return parameter. + * @param app_key Application return parameter. + * @param aid Application ID return parameter. + * + * @return 0 on success, or (negative) error code on failure. + */ +int bt_mesh_keys_resolve(struct bt_mesh_msg_ctx *ctx, + struct bt_mesh_subnet **sub, + const uint8_t *app_key[16], uint8_t *aid); + +/** @brief Iterate through all matching application keys and call @c cb on each. + * + * @param dev_key Whether to return device keys. + * @param aid 7 bit application ID to match. + * @param rx RX structure to match against. + * @param cb Callback to call for every valid app key. + * @param cb_data Callback data to pass to the callback. + * + * @return The AppIdx that yielded a 0-return from the callback. + */ +uint16_t bt_mesh_app_key_find(bool dev_key, uint8_t aid, + struct bt_mesh_net_rx *rx, + int (*cb)(struct bt_mesh_net_rx *rx, + const uint8_t key[16], void *cb_data), + void *cb_data); + +struct bt_mesh_app_key *app_get(uint16_t app_idx); + +extern void (*bt_mesh_app_key_cb_list[1]) (uint16_t app_idx, uint16_t net_idx, + enum bt_mesh_key_evt evt); + +#endif /* _BT_MESH_APP_KEYS_H_ */ \ No newline at end of file diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/beacon.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/beacon.c index cd540aa8..6a5fc5a1 100644 --- a/src/libs/mynewt-nimble/nimble/host/mesh/src/beacon.c +++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/beacon.c @@ -21,8 +21,8 @@ #include "crypto.h" #include "beacon.h" #include "foundation.h" +#include "atomic.h" -#define UNPROVISIONED_INTERVAL (K_SECONDS(5)) #define PROVISIONED_INTERVAL (K_SECONDS(10)) #define BEACON_TYPE_UNPROVISIONED 0x00 @@ -36,26 +36,12 @@ static struct k_delayed_work beacon_timer; -static struct bt_mesh_subnet *cache_check(u8_t data[21]) +static int cache_check(struct bt_mesh_subnet *sub, void *beacon_data) { - int i; - - for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) { - struct bt_mesh_subnet *sub = &bt_mesh.sub[i]; - - if (sub->net_idx == BT_MESH_KEY_UNUSED) { - continue; - } - - if (!memcmp(sub->beacon_cache, data, 21)) { - return sub; - } - } - - return NULL; + return !memcmp(sub->beacon_cache, beacon_data, 21); } -static void cache_add(u8_t data[21], struct bt_mesh_subnet *sub) +static void cache_add(uint8_t data[21], struct bt_mesh_subnet *sub) { memcpy(sub->beacon_cache, data, 21); } @@ -72,16 +58,12 @@ static void beacon_complete(int err, void *user_data) void bt_mesh_beacon_create(struct bt_mesh_subnet *sub, struct os_mbuf *buf) { - u8_t flags = bt_mesh_net_flags(sub); + uint8_t flags = bt_mesh_net_flags(sub); struct bt_mesh_subnet_keys *keys; net_buf_simple_add_u8(buf, BEACON_TYPE_SECURE); - if (sub->kr_flag) { - keys = &sub->keys[1]; - } else { - keys = &sub->keys[0]; - } + keys = &sub->keys[SUBNET_KEY_TX_IDX(sub)]; net_buf_simple_add_u8(buf, flags); @@ -103,53 +85,43 @@ void bt_mesh_beacon_create(struct bt_mesh_subnet *sub, #define BEACON_THRESHOLD(sub) (K_SECONDS(10 * ((sub)->beacons_last + 1)) - \ K_SECONDS(5)) -static int secure_beacon_send(void) +static int secure_beacon_send(struct bt_mesh_subnet *sub, void *cb_data) { static const struct bt_mesh_send_cb send_cb = { .end = beacon_complete, }; - u32_t now = k_uptime_get_32(); - int i; + uint32_t now = k_uptime_get_32(); + struct os_mbuf *buf; + uint32_t time_diff; BT_DBG(""); - for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) { - struct bt_mesh_subnet *sub = &bt_mesh.sub[i]; - struct os_mbuf *buf; - u32_t time_diff; - - if (sub->net_idx == BT_MESH_KEY_UNUSED) { - continue; - } - - time_diff = now - sub->beacon_sent; - if (time_diff < K_SECONDS(600) && - time_diff < BEACON_THRESHOLD(sub)) { - continue; - } - - buf = bt_mesh_adv_create(BT_MESH_ADV_BEACON, PROV_XMIT, - K_NO_WAIT); - if (!buf) { - BT_ERR("Unable to allocate beacon buffer"); - return -ENOBUFS; - } - - bt_mesh_beacon_create(sub, buf); - - bt_mesh_adv_send(buf, &send_cb, sub); - net_buf_unref(buf); + time_diff = now - sub->beacon_sent; + if (time_diff < (600 * MSEC_PER_SEC) && + time_diff < BEACON_THRESHOLD(sub)) { + return 0; } + buf = bt_mesh_adv_create(BT_MESH_ADV_BEACON, PROV_XMIT, K_NO_WAIT); + if (!buf) { + BT_ERR("Unable to allocate beacon buffer"); + return -ENOMEM; + } + + bt_mesh_beacon_create(sub, buf); + + bt_mesh_adv_send(buf, &send_cb, sub); + net_buf_unref(buf); + return 0; } static int unprovisioned_beacon_send(void) { const struct bt_mesh_prov *prov; - u8_t uri_hash[16] = { 0 }; + uint8_t uri_hash[16] = { 0 }; struct os_mbuf *buf; - u16_t oob_info; + uint16_t oob_info; BT_DBG("unprovisioned_beacon_send"); @@ -202,12 +174,11 @@ static int unprovisioned_beacon_send(void) static void unprovisioned_beacon_recv(struct os_mbuf *buf) { -#if MYNEWT_VAL(BLE_MESH_PB_ADV) const struct bt_mesh_prov *prov; - u8_t *uuid; - u16_t oob_info; - u32_t uri_hash_val; - u32_t *uri_hash = NULL; + uint8_t *uuid; + uint16_t oob_info; + uint32_t uri_hash_val; + uint32_t *uri_hash = NULL; if (buf->om_len != 18 && buf->om_len != 22) { BT_ERR("Invalid unprovisioned beacon length (%u)", buf->om_len); @@ -231,13 +202,17 @@ static void unprovisioned_beacon_recv(struct os_mbuf *buf) (bt_mesh_prov_oob_info_t)oob_info, uri_hash); } -#endif +} + +static void sub_update_beacon_observation(struct bt_mesh_subnet *sub) +{ + sub->beacons_last = sub->beacons_cur; + sub->beacons_cur = 0U; } static void update_beacon_observation(void) { static bool first_half; - int i; /* Observation period is 20 seconds, whereas the beacon timer * runs every 10 seconds. We process what's happened during the @@ -248,23 +223,15 @@ static void update_beacon_observation(void) return; } - for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) { - struct bt_mesh_subnet *sub = &bt_mesh.sub[i]; - - if (sub->net_idx == BT_MESH_KEY_UNUSED) { - continue; - } - - sub->beacons_last = sub->beacons_cur; - sub->beacons_cur = 0; - } + bt_mesh_subnet_foreach(sub_update_beacon_observation); } static void beacon_send(struct ble_npl_event *work) { /* Don't send anything if we have an active provisioning link */ - if ((MYNEWT_VAL(BLE_MESH_PROV)) && bt_prov_active()) { - k_delayed_work_submit(&beacon_timer, UNPROVISIONED_INTERVAL); + if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV) && bt_mesh_prov_active()) { + k_delayed_work_submit(&beacon_timer, + K_SECONDS(MYNEWT_VAL(BLE_MESH_UNPROV_BEACON_INT))); return; } @@ -272,34 +239,81 @@ static void beacon_send(struct ble_npl_event *work) if (bt_mesh_is_provisioned()) { update_beacon_observation(); - secure_beacon_send(); + (void)bt_mesh_subnet_find(secure_beacon_send, NULL); /* Only resubmit if beaconing is still enabled */ - if (bt_mesh_beacon_get() == BT_MESH_BEACON_ENABLED || + if (bt_mesh_beacon_enabled() || atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_INITIATOR)) { k_delayed_work_submit(&beacon_timer, PROVISIONED_INTERVAL); } - } else if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV)) { - unprovisioned_beacon_send(); - k_delayed_work_submit(&beacon_timer, UNPROVISIONED_INTERVAL); + + return; } + + if (IS_ENABLED(BLE_MESH_PB_ADV)) { + unprovisioned_beacon_send(); + k_delayed_work_submit(&beacon_timer, + K_SECONDS(MYNEWT_VAL(BLE_MESH_UNPROV_BEACON_INT))); + } +} + +struct beacon_params { + const uint8_t *net_id; + const uint8_t *auth; + uint32_t iv_index; + uint8_t flags; + + bool new_key; +}; + +static bool auth_match(struct bt_mesh_subnet_keys *keys, + const struct beacon_params *params) +{ + uint8_t net_auth[8]; + + if (memcmp(params->net_id, keys->net_id, 8)) { + return false; + } + + bt_mesh_beacon_auth(keys->beacon, params->flags, keys->net_id, + params->iv_index, net_auth); + + if (memcmp(params->auth, net_auth, 8)) { + BT_WARN("Authentication Value %s != %s", + bt_hex(params->auth, 8), bt_hex(net_auth, 8)); + return false; + } + + return true; +} + +static int subnet_by_id(struct bt_mesh_subnet *sub, void *cb_data) +{ + struct beacon_params *params = cb_data; + + for (int i = 0; i < ARRAY_SIZE(sub->keys); i++) { + if (sub->keys[i].valid && auth_match(&sub->keys[i], params)) { + params->new_key = (i > 0); + return true; + } + } + + return false; } static void secure_beacon_recv(struct os_mbuf *buf) { - u8_t *data, *net_id, *auth; + struct beacon_params params; struct bt_mesh_subnet *sub; - u32_t iv_index; - bool new_key, kr_change, iv_change; - u8_t flags; + uint8_t *data; if (buf->om_len < 21) { BT_ERR("Too short secure beacon (len %u)", buf->om_len); return; } - sub = cache_check(buf->om_data); + sub = bt_mesh_subnet_find(cache_check, buf->om_data); if (sub) { /* We've seen this beacon before - just update the stats */ goto update_stats; @@ -308,27 +322,30 @@ static void secure_beacon_recv(struct os_mbuf *buf) /* So we can add to the cache if auth matches */ data = buf->om_data; - flags = net_buf_simple_pull_u8(buf); - net_id = net_buf_simple_pull_mem(buf, 8); - iv_index = net_buf_simple_pull_be32(buf); - auth = buf->om_data; + params.flags = net_buf_simple_pull_u8(buf); + params.net_id = net_buf_simple_pull_mem(buf, 8); + params.iv_index = net_buf_simple_pull_be32(buf); + params.auth = buf->om_data; BT_DBG("flags 0x%02x id %s iv_index 0x%08x", - flags, bt_hex(net_id, 8), (unsigned) iv_index); + params.flags, bt_hex(params.net_id, 8), params.iv_index); - sub = bt_mesh_subnet_find(net_id, flags, iv_index, auth, &new_key); + sub = bt_mesh_subnet_find(subnet_by_id, ¶ms); if (!sub) { BT_DBG("No subnet that matched beacon"); return; } - if (sub->kr_phase == BT_MESH_KR_PHASE_2 && !new_key) { + if (sub->kr_phase == BT_MESH_KR_PHASE_2 && !params.new_key) { BT_WARN("Ignoring Phase 2 KR Update secured using old key"); return; } cache_add(data, sub); + bt_mesh_kr_update(sub, BT_MESH_KEY_REFRESH(params.flags), + params.new_key); + /* If we have NetKey0 accept initiation only from it */ if (bt_mesh_subnet_get(BT_MESH_KEY_PRIMARY) && sub->net_idx != BT_MESH_KEY_PRIMARY) { @@ -337,31 +354,18 @@ static void secure_beacon_recv(struct os_mbuf *buf) } BT_DBG("net_idx 0x%04x iv_index 0x%08x, current iv_index 0x%08x", - sub->net_idx, (unsigned) iv_index, (unsigned) bt_mesh.iv_index); + sub->net_idx, params.iv_index, bt_mesh.iv_index); if (atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_INITIATOR) && (atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS) == - BT_MESH_IV_UPDATE(flags))) { + BT_MESH_IV_UPDATE(params.flags))) { bt_mesh_beacon_ivu_initiator(false); } - iv_change = bt_mesh_net_iv_update(iv_index, BT_MESH_IV_UPDATE(flags)); - - kr_change = bt_mesh_kr_update(sub, BT_MESH_KEY_REFRESH(flags), new_key); - if (kr_change) { - bt_mesh_net_beacon_update(sub); - } - - if (iv_change) { - /* Update all subnets */ - bt_mesh_net_sec_update(NULL); - } else if (kr_change) { - /* Key Refresh without IV Update only impacts one subnet */ - bt_mesh_net_sec_update(sub); - } + bt_mesh_net_iv_update(params.iv_index, BT_MESH_IV_UPDATE(params.flags)); update_stats: - if (bt_mesh_beacon_get() == BT_MESH_BEACON_ENABLED && + if (bt_mesh_beacon_enabled() && sub->beacons_cur < 0xff) { sub->beacons_cur++; } @@ -369,7 +373,7 @@ update_stats: void bt_mesh_beacon_recv(struct os_mbuf *buf) { - u8_t type; + uint8_t type; BT_DBG("%u bytes: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len)); @@ -381,7 +385,9 @@ void bt_mesh_beacon_recv(struct os_mbuf *buf) type = net_buf_simple_pull_u8(buf); switch (type) { case BEACON_TYPE_UNPROVISIONED: - unprovisioned_beacon_recv(buf); + if (IS_ENABLED(BLE_MESH_PB_ADV)) { + unprovisioned_beacon_recv(buf); + } break; case BEACON_TYPE_SECURE: secure_beacon_recv(buf); @@ -392,8 +398,38 @@ void bt_mesh_beacon_recv(struct os_mbuf *buf) } } +void bt_mesh_beacon_update(struct bt_mesh_subnet *sub) +{ + uint8_t flags = bt_mesh_net_flags(sub); + struct bt_mesh_subnet_keys *keys; + int err; + + keys = &sub->keys[SUBNET_KEY_TX_IDX(sub)]; + + BT_DBG("NetIndex 0x%03x Using %s key", sub->net_idx, + SUBNET_KEY_TX_IDX(sub) ? "new" : "current"); + BT_DBG("flags 0x%02x, IVI 0x%08x", flags, bt_mesh.iv_index); + + err = bt_mesh_beacon_auth(keys->beacon, flags, keys->net_id, + bt_mesh.iv_index, sub->auth); + if (err) { + BT_ERR("Failed updating net beacon for 0x%03x", sub->net_idx); + } +} + +static void subnet_evt(struct bt_mesh_subnet *sub, enum bt_mesh_key_evt evt) +{ + if (evt != BT_MESH_KEY_DELETED) { + bt_mesh_beacon_update(sub); + } +} + void bt_mesh_beacon_init(void) { + if (!bt_mesh_subnet_cb_list[1]) { + bt_mesh_subnet_cb_list[1] = subnet_evt; + } + k_delayed_work_init(&beacon_timer, beacon_send); } @@ -402,35 +438,30 @@ void bt_mesh_beacon_ivu_initiator(bool enable) atomic_set_bit_to(bt_mesh.flags, BT_MESH_IVU_INITIATOR, enable); if (enable) { - k_work_submit(&beacon_timer.work); - } else if (bt_mesh_beacon_get() == BT_MESH_BEACON_DISABLED) { + k_delayed_work_submit(&beacon_timer, K_NO_WAIT); + } else if (!bt_mesh_beacon_enabled()) { k_delayed_work_cancel(&beacon_timer); } } +static void subnet_beacon_enable(struct bt_mesh_subnet *sub) +{ + sub->beacons_last = 0U; + sub->beacons_cur = 0U; + + bt_mesh_beacon_update(sub); +} + void bt_mesh_beacon_enable(void) { - int i; - if (!bt_mesh_is_provisioned()) { - k_work_submit(&beacon_timer.work); + k_delayed_work_submit(&beacon_timer, K_NO_WAIT); return; } - for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) { - struct bt_mesh_subnet *sub = &bt_mesh.sub[i]; + bt_mesh_subnet_foreach(subnet_beacon_enable); - if (sub->net_idx == BT_MESH_KEY_UNUSED) { - continue; - } - - sub->beacons_last = 0; - sub->beacons_cur = 0; - - bt_mesh_net_beacon_update(sub); - } - - k_work_submit(&beacon_timer.work); + k_delayed_work_submit(&beacon_timer, K_NO_WAIT); } void bt_mesh_beacon_disable(void) diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/beacon.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/beacon.h index ac4bfed8..a6aa8cbb 100644 --- a/src/libs/mynewt-nimble/nimble/host/mesh/src/beacon.h +++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/beacon.h @@ -22,5 +22,6 @@ void bt_mesh_beacon_create(struct bt_mesh_subnet *sub, struct os_mbuf *buf); void bt_mesh_beacon_init(void); +void bt_mesh_beacon_update(struct bt_mesh_subnet *sub); #endif diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/cdb.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/cdb.c new file mode 100644 index 00000000..bcca3b90 --- /dev/null +++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/cdb.c @@ -0,0 +1,389 @@ +/* + * Copyright (c) 2019 Tobias Svehagen + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#if BLE_MESH_CDB +#define BT_DBG_ENABLED MYNEWT_VAL(BLE_MESH_DEBUG_CDB) +#define LOG_MODULE_NAME bt_mesh_cdb +#include "log/log.h" + +#include "mesh/mesh.h" +#include "net.h" +#include "rpl.h" +#include "settings.h" +#include "mesh_priv.h" +#include "mesh/glue.h" + + +struct bt_mesh_cdb bt_mesh_cdb = { + .nodes = { + [0 ... (CONFIG_BT_MESH_NODE_COUNT - 1)] = { + .addr = BT_MESH_ADDR_UNASSIGNED, + } + }, + .subnets = { + [0 ... (CONFIG_BT_MESH_SUBNET_COUNT - 1)] = { + .net_idx = BT_MESH_KEY_UNUSED, + } + }, + .app_keys = { + [0 ... (CONFIG_BT_MESH_APP_KEY_COUNT - 1)] = { + .net_idx = BT_MESH_KEY_UNUSED, + } + }, +}; + +/* + * Check if an address range from addr_start for addr_start + num_elem - 1 is + * free for use. When a conflict is found, next will be set to the next address + * available after the conflicting range and -EAGAIN will be returned. + */ +static int addr_is_free(uint16_t addr_start, uint8_t num_elem, uint16_t *next) +{ + uint16_t addr_end = addr_start + num_elem - 1; + uint16_t other_start, other_end; + int i; + + if (!BT_MESH_ADDR_IS_UNICAST(addr_start) || + !BT_MESH_ADDR_IS_UNICAST(addr_end) || + num_elem == 0) { + return -EINVAL; + } + + for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes); i++) { + struct bt_mesh_cdb_node *node = &bt_mesh_cdb.nodes[i]; + + if (node->addr == BT_MESH_ADDR_UNASSIGNED) { + continue; + } + + other_start = node->addr; + other_end = other_start + node->num_elem - 1; + + if (!(addr_end < other_start || addr_start > other_end)) { + if (next) { + *next = other_end + 1; + } + + return -EAGAIN; + } + } + + return 0; +} + +/* + * Find the lowest possible starting address that can fit num_elem elements. If + * a free address range cannot be found, BT_MESH_ADDR_UNASSIGNED will be + * returned. Otherwise the first address in the range is returned. + * + * NOTE: This is quite an ineffective algorithm as it might need to look + * through the array of nodes N+2 times. A more effective algorithm + * could be used if the nodes were stored in a sorted list. + */ +static uint16_t find_lowest_free_addr(uint8_t num_elem) +{ + uint16_t addr = 1, next = 0; + int err, i; + + /* + * It takes a maximum of node count + 2 to find a free address if there + * is any. +1 for our own address and +1 for making sure that the + * address range is valid. + */ + for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes) + 2; ++i) { + err = addr_is_free(addr, num_elem, &next); + if (err == 0) { + break; + } else if (err != -EAGAIN) { + addr = BT_MESH_ADDR_UNASSIGNED; + break; + } + + addr = next; + } + + return addr; +} + +int bt_mesh_cdb_create(const uint8_t key[16]) +{ + struct bt_mesh_cdb_subnet *sub; + + if (atomic_test_and_set_bit(bt_mesh_cdb.flags, + BT_MESH_CDB_VALID)) { + return -EALREADY; + } + + sub = bt_mesh_cdb_subnet_alloc(BT_MESH_KEY_PRIMARY); + if (sub == NULL) { + return -ENOMEM; + } + + memcpy(sub->keys[0].net_key, key, 16); + bt_mesh_cdb.iv_index = 0; + + if (IS_ENABLED(CONFIG_BT_SETTINGS)) { + bt_mesh_store_cdb(); + bt_mesh_store_cdb_subnet(sub); + } + + return 0; +} + +void bt_mesh_cdb_clear(void) +{ + int i; + + atomic_clear_bit(bt_mesh_cdb.flags, BT_MESH_CDB_VALID); + + for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes); ++i) { + if (bt_mesh_cdb.nodes[i].addr != BT_MESH_ADDR_UNASSIGNED) { + bt_mesh_cdb_node_del(&bt_mesh_cdb.nodes[i], true); + } + } + + for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.subnets); ++i) { + if (bt_mesh_cdb.subnets[i].net_idx != BT_MESH_KEY_UNUSED) { + bt_mesh_cdb_subnet_del(&bt_mesh_cdb.subnets[i], true); + } + } + + for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.app_keys); ++i) { + if (bt_mesh_cdb.app_keys[i].net_idx != BT_MESH_KEY_UNUSED) { + bt_mesh_cdb_app_key_del(&bt_mesh_cdb.app_keys[i], true); + } + } + + if (IS_ENABLED(CONFIG_BT_SETTINGS)) { + bt_mesh_store_cdb(); + } +} + +void bt_mesh_cdb_iv_update(uint32_t iv_index, bool iv_update) +{ + BT_DBG("Updating IV index to %d\n", iv_index); + + bt_mesh_cdb.iv_index = iv_index; + + atomic_set_bit_to(bt_mesh_cdb.flags, BT_MESH_CDB_IVU_IN_PROGRESS, + iv_update); + + if (IS_ENABLED(CONFIG_BT_SETTINGS)) { + bt_mesh_store_cdb(); + } +} + +struct bt_mesh_cdb_subnet *bt_mesh_cdb_subnet_alloc(uint16_t net_idx) +{ + struct bt_mesh_cdb_subnet *sub; + int i; + + if (bt_mesh_cdb_subnet_get(net_idx) != NULL) { + return NULL; + } + + for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.subnets); ++i) { + sub = &bt_mesh_cdb.subnets[i]; + + if (sub->net_idx != BT_MESH_KEY_UNUSED) { + continue; + } + + sub->net_idx = net_idx; + + return sub; + } + + return NULL; +} + +void bt_mesh_cdb_subnet_del(struct bt_mesh_cdb_subnet *sub, bool store) +{ + BT_DBG("NetIdx 0x%03x store %u", sub->net_idx, store); + + if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) { + bt_mesh_clear_cdb_subnet(sub); + } + + sub->net_idx = BT_MESH_KEY_UNUSED; + memset(sub->keys, 0, sizeof(sub->keys)); +} + +struct bt_mesh_cdb_subnet *bt_mesh_cdb_subnet_get(uint16_t net_idx) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.subnets); ++i) { + if (bt_mesh_cdb.subnets[i].net_idx == net_idx) { + return &bt_mesh_cdb.subnets[i]; + } + } + + return NULL; +} + +void bt_mesh_cdb_subnet_store(const struct bt_mesh_cdb_subnet *sub) +{ + if (MYNEWT_VAL(BLE_MESH_SETTINGS)) { + bt_mesh_store_cdb_subnet(sub); + } +} + +uint8_t bt_mesh_cdb_subnet_flags(const struct bt_mesh_cdb_subnet *sub) +{ + uint8_t flags = 0x00; + + if (sub && sub->kr_flag) { + flags |= BT_MESH_NET_FLAG_KR; + } + + if (atomic_test_bit(bt_mesh_cdb.flags, BT_MESH_CDB_IVU_IN_PROGRESS)) { + flags |= BT_MESH_NET_FLAG_IVU; + } + + return flags; +} + +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) +{ + int i; + + if (addr == BT_MESH_ADDR_UNASSIGNED) { + addr = find_lowest_free_addr(num_elem); + if (addr == BT_MESH_ADDR_UNASSIGNED) { + return NULL; + } + } else if (addr_is_free(addr, num_elem, NULL) < 0) { + BT_DBG("Address range 0x%04x-0x%04x is not free", addr, + addr + num_elem - 1); + return NULL; + } + + for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes); i++) { + struct bt_mesh_cdb_node *node = &bt_mesh_cdb.nodes[i]; + + if (node->addr == BT_MESH_ADDR_UNASSIGNED) { + memcpy(node->uuid, uuid, 16); + node->addr = addr; + node->num_elem = num_elem; + node->net_idx = net_idx; + atomic_set(node->flags, 0); + return node; + } + } + + return NULL; +} + +void bt_mesh_cdb_node_del(struct bt_mesh_cdb_node *node, bool store) +{ + BT_DBG("Node addr 0x%04x store %u", node->addr, store); + + if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) { + bt_mesh_clear_cdb_node(node); + } + + node->addr = BT_MESH_ADDR_UNASSIGNED; + memset(node->dev_key, 0, sizeof(node->dev_key)); +} + +struct bt_mesh_cdb_node *bt_mesh_cdb_node_get(uint16_t addr) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes); i++) { + struct bt_mesh_cdb_node *node = &bt_mesh_cdb.nodes[i]; + + if (addr >= node->addr && + addr <= node->addr + node->num_elem - 1) { + return node; + } + } + + return NULL; +} + +void bt_mesh_cdb_node_store(const struct bt_mesh_cdb_node *node) +{ + if (MYNEWT_VAL(BLE_MESH_SETTINGS)) { + bt_mesh_store_cdb_node(node); + } +} + +void bt_mesh_cdb_node_foreach(bt_mesh_cdb_node_func_t func, void *user_data) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes); ++i) { + if (bt_mesh_cdb.nodes[i].addr == BT_MESH_ADDR_UNASSIGNED) { + continue; + } + + if (func(&bt_mesh_cdb.nodes[i], user_data) == + BT_MESH_CDB_ITER_STOP) { + break; + } + } +} + +struct bt_mesh_cdb_app_key *bt_mesh_cdb_app_key_alloc(uint16_t net_idx, + uint16_t app_idx) +{ + struct bt_mesh_cdb_app_key *key; + int i; + + for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.app_keys); ++i) { + key = &bt_mesh_cdb.app_keys[i]; + + if (key->net_idx != BT_MESH_KEY_UNUSED) { + continue; + } + + key->net_idx = net_idx; + key->app_idx = app_idx; + + return key; + } + + return NULL; +} + +void bt_mesh_cdb_app_key_del(struct bt_mesh_cdb_app_key *key, bool store) +{ + BT_DBG("AppIdx 0x%03x store %u", key->app_idx, store); + + if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) { + bt_mesh_clear_cdb_app_key(key); + } + + key->net_idx = BT_MESH_ADDR_UNASSIGNED; + memset(key->keys, 0, sizeof(key->keys)); +} + +struct bt_mesh_cdb_app_key *bt_mesh_cdb_app_key_get(uint16_t app_idx) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.app_keys); i++) { + struct bt_mesh_cdb_app_key *key = &bt_mesh_cdb.app_keys[i]; + + if (key->net_idx != BT_MESH_KEY_UNUSED && + key->app_idx == app_idx) { + return key; + } + } + + return NULL; +} + +void bt_mesh_cdb_app_key_store(const struct bt_mesh_cdb_app_key *key) +{ + if (MYNEWT_VAL(BLE_MESH_SETTINGS)) { + bt_mesh_store_cdb_app_key(key); + } +} +#endif diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/cfg.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/cfg.c new file mode 100644 index 00000000..4e149255 --- /dev/null +++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/cfg.c @@ -0,0 +1,267 @@ +/* + * Copyright (c) 2020 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "mesh/mesh.h" +#include "mesh_priv.h" +#include "net.h" +#include "rpl.h" +#include "beacon.h" +#include "settings.h" +#include "heartbeat.h" +#include "friend.h" +#include "cfg.h" +#include "mesh/glue.h" + +void bt_mesh_beacon_set(bool beacon) +{ + if (atomic_test_bit(bt_mesh.flags, BT_MESH_BEACON) == beacon) { + return; + } + + atomic_set_bit_to(bt_mesh.flags, BT_MESH_BEACON, beacon); + + if (beacon) { + bt_mesh_beacon_enable(); + } else { + bt_mesh_beacon_disable(); + } + + if (IS_ENABLED(CONFIG_BT_SETTINGS) && + atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) { + bt_mesh_store_cfg(); + } +} + +bool bt_mesh_beacon_enabled(void) +{ + return atomic_test_bit(bt_mesh.flags, BT_MESH_BEACON); +} + +static int feature_set(int feature_flag, enum bt_mesh_feat_state state) +{ + if (state != BT_MESH_FEATURE_DISABLED && + state != BT_MESH_FEATURE_ENABLED) { + return -EINVAL; + } + + if (atomic_test_bit(bt_mesh.flags, feature_flag) == + (state == BT_MESH_FEATURE_ENABLED)) { + return -EALREADY; + } + + atomic_set_bit_to(bt_mesh.flags, feature_flag, + (state == BT_MESH_FEATURE_ENABLED)); + + return 0; +} + +static enum bt_mesh_feat_state feature_get(int feature_flag) +{ + return atomic_test_bit(bt_mesh.flags, feature_flag) ? + BT_MESH_FEATURE_ENABLED : + BT_MESH_FEATURE_DISABLED; +} + +int bt_mesh_gatt_proxy_set(enum bt_mesh_feat_state gatt_proxy) +{ + int err; + + if (!IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) { + return -ENOTSUP; + } + + err = feature_set(BT_MESH_GATT_PROXY, gatt_proxy); + if (err) { + return err; + } + + bt_mesh_hb_feature_changed(BT_MESH_FEAT_PROXY); + + if (IS_ENABLED(CONFIG_BT_SETTINGS) && + atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) { + bt_mesh_store_cfg(); + } + + return 0; +} + +enum bt_mesh_feat_state bt_mesh_gatt_proxy_get(void) +{ + if (!IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) { + return BT_MESH_FEATURE_NOT_SUPPORTED; + } + + return feature_get(BT_MESH_GATT_PROXY); +} + +int bt_mesh_default_ttl_set(uint8_t default_ttl) +{ + if (default_ttl == 1 || default_ttl > BT_MESH_TTL_MAX) { + return -EINVAL; + } + + if (default_ttl == bt_mesh.default_ttl) { + return 0; + } + + bt_mesh.default_ttl = default_ttl; + + if (IS_ENABLED(CONFIG_BT_SETTINGS) && + atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) { + bt_mesh_store_cfg(); + } + + return 0; +} + +uint8_t bt_mesh_default_ttl_get(void) +{ + return bt_mesh.default_ttl; +} + +int bt_mesh_friend_set(enum bt_mesh_feat_state friendship) +{ + int err; + + if (!IS_ENABLED(CONFIG_BT_MESH_FRIEND)) { + return -ENOTSUP; + } + + err = feature_set(BT_MESH_FRIEND, friendship); + if (err) { + return err; + } + + bt_mesh_hb_feature_changed(BT_MESH_FEAT_FRIEND); + + if (IS_ENABLED(CONFIG_BT_SETTINGS) && + atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) { + bt_mesh_store_cfg(); + } + + if (friendship == BT_MESH_FEATURE_DISABLED) { + bt_mesh_friends_clear(); + } + + return 0; +} + +enum bt_mesh_feat_state bt_mesh_friend_get(void) +{ + if (!IS_ENABLED(CONFIG_BT_MESH_FRIEND)) { + return BT_MESH_FEATURE_NOT_SUPPORTED; + } + + return feature_get(BT_MESH_FRIEND); +} + +void bt_mesh_net_transmit_set(uint8_t xmit) +{ + if (bt_mesh.net_xmit == xmit) { + return; + } + + bt_mesh.net_xmit = xmit; + + if (IS_ENABLED(CONFIG_BT_SETTINGS) && + atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) { + bt_mesh_store_cfg(); + } +} + +uint8_t bt_mesh_net_transmit_get(void) +{ + return bt_mesh.net_xmit; +} + +int bt_mesh_relay_set(enum bt_mesh_feat_state relay, uint8_t xmit) +{ + int err; + + if (!CONFIG_BT_MESH_RELAY) { + return -ENOTSUP; + } + + err = feature_set(BT_MESH_RELAY, relay); + if (err == -EINVAL) { + return err; + } + + if (err == -EALREADY && bt_mesh.relay_xmit == xmit) { + return -EALREADY; + } + + bt_mesh.relay_xmit = xmit; + bt_mesh_hb_feature_changed(BT_MESH_FEAT_RELAY); + + if (IS_ENABLED(CONFIG_BT_SETTINGS) && + atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) { + bt_mesh_store_cfg(); + } + + return 0; +} + +enum bt_mesh_feat_state bt_mesh_relay_get(void) +{ + return feature_get(BT_MESH_RELAY); +} + +uint8_t bt_mesh_relay_retransmit_get(void) +{ + if (!CONFIG_BT_MESH_RELAY) { + return 0; + } + + return bt_mesh.relay_xmit; +} + +bool bt_mesh_fixed_group_match(uint16_t addr) +{ + /* Check for fixed group addresses */ + switch (addr) { + case BT_MESH_ADDR_ALL_NODES: + return true; + case BT_MESH_ADDR_PROXIES: + return (bt_mesh_gatt_proxy_get() == BT_MESH_FEATURE_ENABLED); + case BT_MESH_ADDR_FRIENDS: + return (bt_mesh_friend_get() == BT_MESH_FEATURE_ENABLED); + case BT_MESH_ADDR_RELAYS: + return (bt_mesh_relay_get() == BT_MESH_FEATURE_ENABLED); + default: + return false; + } +} + +void bt_mesh_cfg_init(void) +{ + bt_mesh.default_ttl = CONFIG_BT_MESH_DEFAULT_TTL; + bt_mesh.net_xmit = + BT_MESH_TRANSMIT(CONFIG_BT_MESH_NETWORK_TRANSMIT_COUNT, + CONFIG_BT_MESH_NETWORK_TRANSMIT_INTERVAL); + +#if defined(CONFIG_BT_MESH_RELAY) + bt_mesh.relay_xmit = + BT_MESH_TRANSMIT(CONFIG_BT_MESH_RELAY_RETRANSMIT_COUNT, + CONFIG_BT_MESH_RELAY_RETRANSMIT_INTERVAL); +#endif + + if (CONFIG_BT_MESH_RELAY_ENABLED) { + atomic_set_bit(bt_mesh.flags, BT_MESH_RELAY); + } + + if (CONFIG_BT_MESH_BEACON_ENABLED) { + atomic_set_bit(bt_mesh.flags, BT_MESH_BEACON); + } + + if (CONFIG_BT_MESH_GATT_PROXY_ENABLED) { + atomic_set_bit(bt_mesh.flags, BT_MESH_GATT_PROXY); + } + + if (CONFIG_BT_MESH_FRIEND_ENABLED) { + atomic_set_bit(bt_mesh.flags, BT_MESH_FRIEND); + } +} \ No newline at end of file diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/cfg.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/cfg.h new file mode 100644 index 00000000..6f58acf8 --- /dev/null +++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/cfg.h @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2020 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +void bt_mesh_cfg_init(void); + +bool bt_mesh_fixed_group_match(uint16_t addr); \ No newline at end of file diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/cfg_cli.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/cfg_cli.c index 2c2f6c3f..a87cd7bb 100644 --- a/src/libs/mynewt-nimble/nimble/host/mesh/src/cfg_cli.c +++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/cfg_cli.c @@ -25,11 +25,11 @@ #define DUMMY_2_BYTE_OP BT_MESH_MODEL_OP_2(0xff, 0xff) struct comp_data { - u8_t *status; + uint8_t *status; struct os_mbuf *comp; }; -static s32_t msg_timeout = K_SECONDS(5); +static int32_t msg_timeout = K_SECONDS(5); static struct bt_mesh_cfg_cli *cli; @@ -61,9 +61,9 @@ static void comp_data_status(struct bt_mesh_model *model, static void state_status_u8(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf*buf, - u32_t expect_status) + uint32_t expect_status) { - u8_t *status; + uint8_t *status; BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, @@ -110,8 +110,8 @@ static void gatt_proxy_status(struct bt_mesh_model *model, } struct relay_param { - u8_t *status; - u8_t *transmit; + uint8_t *status; + uint8_t *transmit; }; static void relay_status(struct bt_mesh_model *model, @@ -137,8 +137,8 @@ static void relay_status(struct bt_mesh_model *model, } struct net_key_param { - u8_t *status; - u16_t net_idx; + uint8_t *status; + uint16_t net_idx; }; static void net_key_status(struct bt_mesh_model *model, @@ -146,8 +146,8 @@ static void net_key_status(struct bt_mesh_model *model, struct os_mbuf *buf) { struct net_key_param *param; - u16_t net_idx, app_idx; - u8_t status; + uint16_t net_idx; + uint8_t status; BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, @@ -159,7 +159,7 @@ static void net_key_status(struct bt_mesh_model *model, } status = net_buf_simple_pull_u8(buf); - key_idx_unpack(buf, &net_idx, &app_idx); + net_idx = net_buf_simple_pull_le16(buf) & 0xfff; param = cli->op_param; if (param->net_idx != net_idx) { @@ -174,10 +174,66 @@ static void net_key_status(struct bt_mesh_model *model, k_sem_give(&cli->op_sync); } +struct net_key_list_param { + uint16_t *keys; + size_t *key_cnt; +}; + +static void net_key_list(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) +{ + struct net_key_list_param *param; + int i; + + BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", + ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, + bt_hex(buf->om_data, buf->om_len)); + + if (cli->op_pending != OP_NET_KEY_LIST) { + BT_WARN("Unexpected Net Key List message"); + return; + } + + param = cli->op_param; + + for (i = 0; i < *param->key_cnt && buf->om_len >= 3; i += 2) { + key_idx_unpack(buf, ¶m->keys[i], ¶m->keys[i + 1]); + } + + if (i < *param->key_cnt && buf->om_len >= 2) { + param->keys[i++] = net_buf_simple_pull_le16(buf) & 0xfff; + } + + *param->key_cnt = i; + + k_sem_give(&cli->op_sync); +} + +static void node_reset_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) +{ + bool *param = NULL; + BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x", + ctx->net_idx, ctx->app_idx, ctx->addr); + + if (cli->op_pending != OP_NODE_RESET_STATUS) { + BT_WARN("Unexpected Node Reset Status message"); + return; + } + + param = cli->op_param; + + if (param) { + *param = true; + } + k_sem_give(&cli->op_sync); +} + struct app_key_param { - u8_t *status; - u16_t net_idx; - u16_t app_idx; + uint8_t *status; + uint16_t net_idx; + uint16_t app_idx; }; static void app_key_status(struct bt_mesh_model *model, @@ -185,8 +241,8 @@ static void app_key_status(struct bt_mesh_model *model, struct os_mbuf*buf) { struct app_key_param *param; - u16_t net_idx, app_idx; - u8_t status; + uint16_t net_idx, app_idx; + uint8_t status; BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, @@ -213,21 +269,71 @@ static void app_key_status(struct bt_mesh_model *model, k_sem_give(&cli->op_sync); } +struct app_key_list_param { + uint16_t net_idx; + uint8_t *status; + uint16_t *keys; + size_t *key_cnt; +}; + +static void app_key_list(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) +{ + struct app_key_list_param *param; + uint16_t net_idx; + uint8_t status; + int i; + + BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", + ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, + bt_hex(buf->om_data, buf->om_len)); + + if (cli->op_pending != OP_APP_KEY_LIST) { + BT_WARN("Unexpected App Key List message"); + return; + } + + status = net_buf_simple_pull_u8(buf); + net_idx = net_buf_simple_pull_le16(buf) & 0xfff; + + param = cli->op_param; + if (param->net_idx != net_idx) { + BT_WARN("App Key List Net Key index did not match"); + return; + } + + for (i = 0; i < *param->key_cnt && buf->om_len >= 3; i += 2) { + key_idx_unpack(buf, ¶m->keys[i], ¶m->keys[i + 1]); + } + + if (i < *param->key_cnt && buf->om_len >= 2) { + param->keys[i++] = net_buf_simple_pull_le16(buf) & 0xfff; + } + + *param->key_cnt = i; + if (param->status) { + *param->status = status; + } + + k_sem_give(&cli->op_sync); +} + struct mod_app_param { - u8_t *status; - u16_t elem_addr; - u16_t mod_app_idx; - u16_t mod_id; - u16_t cid; + uint8_t *status; + uint16_t elem_addr; + uint16_t mod_app_idx; + uint16_t mod_id; + uint16_t cid; }; static void mod_app_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf*buf) { - u16_t elem_addr, mod_app_idx, mod_id, cid; + uint16_t elem_addr, mod_app_idx, mod_id, cid; struct mod_app_param *param; - u8_t status; + uint8_t status; BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, @@ -265,11 +371,92 @@ static void mod_app_status(struct bt_mesh_model *model, k_sem_give(&cli->op_sync); } +struct mod_member_list_param { + uint8_t *status; + uint16_t elem_addr; + uint16_t mod_id; + uint16_t cid; + uint16_t *members; + size_t *member_cnt; +}; + +static void mod_member_list_handle(struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf, bool vnd) +{ + struct mod_member_list_param *param; + uint16_t elem_addr, mod_id, cid; + uint8_t status; + int i; + + status = net_buf_simple_pull_u8(buf); + elem_addr = net_buf_simple_pull_le16(buf); + if (vnd) { + cid = net_buf_simple_pull_le16(buf); + } + + mod_id = net_buf_simple_pull_le16(buf); + + param = cli->op_param; + if (param->elem_addr != elem_addr || param->mod_id != mod_id || + (vnd && param->cid != cid)) { + BT_WARN("Model Member List parameters did not match"); + return; + } + + if (buf->om_len % 2) { + BT_WARN("Model Member List invalid length"); + return; + } + + for (i = 0; i < *param->member_cnt && buf->om_len; i++) { + param->members[i] = net_buf_simple_pull_le16(buf); + } + + *param->member_cnt = i; + if (param->status) { + *param->status = status; + } + + k_sem_give(&cli->op_sync); +} + +static void mod_app_list(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) +{ + BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", + ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, + bt_hex(buf->om_data, buf->om_len)); + + if (cli->op_pending != OP_SIG_MOD_APP_LIST) { + BT_WARN("Unexpected Model App List message"); + return; + } + + mod_member_list_handle(ctx, buf, false); +} + +static void mod_app_list_vnd(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) +{ + BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", + ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, + bt_hex(buf->om_data, buf->om_len)); + + if (cli->op_pending != OP_VND_MOD_APP_LIST) { + BT_WARN("Unexpected Model App List Vendor message"); + return; + } + + mod_member_list_handle(ctx, buf, true); +} + struct mod_pub_param { - u16_t mod_id; - u16_t cid; - u16_t elem_addr; - u8_t *status; + uint16_t mod_id; + uint16_t cid; + uint16_t elem_addr; + uint8_t *status; struct bt_mesh_cfg_mod_pub *pub; }; @@ -277,9 +464,9 @@ static void mod_pub_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf*buf) { - u16_t mod_id, cid, elem_addr; + uint16_t mod_id, cid, elem_addr; struct mod_pub_param *param; - u8_t status; + uint8_t status; BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, @@ -341,21 +528,21 @@ static void mod_pub_status(struct bt_mesh_model *model, } struct mod_sub_param { - u8_t *status; - u16_t elem_addr; - u16_t *sub_addr; - u16_t *expect_sub; - u16_t mod_id; - u16_t cid; + uint8_t *status; + uint16_t elem_addr; + uint16_t *sub_addr; + uint16_t *expect_sub; + uint16_t mod_id; + uint16_t cid; }; static void mod_sub_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf*buf) { - u16_t elem_addr, sub_addr, mod_id, cid; + uint16_t elem_addr, sub_addr, mod_id, cid; struct mod_sub_param *param; - u8_t status; + uint8_t status; BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, @@ -397,8 +584,40 @@ static void mod_sub_status(struct bt_mesh_model *model, k_sem_give(&cli->op_sync); } +static void mod_sub_list(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) +{ + BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", + ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, + bt_hex(buf->om_data, buf->om_len)); + + if (cli->op_pending != OP_MOD_SUB_LIST) { + BT_WARN("Unexpected Model Subscription List message"); + return; + } + + mod_member_list_handle(ctx, buf, false); +} + +static void mod_sub_list_vnd(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) +{ + BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", + ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, + bt_hex(buf->om_data, buf->om_len)); + + if (cli->op_pending != OP_MOD_SUB_LIST_VND) { + BT_WARN("Unexpected Model Subscription List Vendor message"); + return; + } + + mod_member_list_handle(ctx, buf, true); +} + struct hb_sub_param { - u8_t *status; + uint8_t *status; struct bt_mesh_cfg_hb_sub *sub; }; @@ -432,7 +651,7 @@ static void hb_sub_status(struct bt_mesh_model *model, } struct hb_pub_param { - u8_t *status; + uint8_t *status; struct bt_mesh_cfg_hb_pub *pub; }; @@ -475,12 +694,19 @@ const struct bt_mesh_model_op bt_mesh_cfg_cli_op[] = { { OP_GATT_PROXY_STATUS, 1, gatt_proxy_status }, { OP_RELAY_STATUS, 2, relay_status }, { OP_NET_KEY_STATUS, 3, net_key_status }, + { OP_NET_KEY_LIST, 0, net_key_list }, { OP_APP_KEY_STATUS, 4, app_key_status }, + { OP_APP_KEY_LIST, 3, app_key_list }, { OP_MOD_APP_STATUS, 7, mod_app_status }, + { OP_SIG_MOD_APP_LIST, 5, mod_app_list}, + { OP_VND_MOD_APP_LIST, 7, mod_app_list_vnd}, { OP_MOD_PUB_STATUS, 12, mod_pub_status }, { OP_MOD_SUB_STATUS, 7, mod_sub_status }, + { OP_MOD_SUB_LIST, 5, mod_sub_list}, + { OP_MOD_SUB_LIST_VND, 7, mod_sub_list_vnd}, { OP_HEARTBEAT_SUB_STATUS, 9, hb_sub_status }, { OP_HEARTBEAT_PUB_STATUS, 10, hb_pub_status }, + { OP_NODE_RESET_STATUS, 0, node_reset_status}, BT_MESH_MODEL_OP_END, }; @@ -516,7 +742,7 @@ const struct bt_mesh_model_cb bt_mesh_cfg_cli_cb = { .init = cfg_cli_init, }; -static int cli_prepare(void *param, u32_t op) +static int cli_prepare(void *param, uint32_t op) { if (!cli) { BT_ERR("No available Configuration Client context!"); @@ -551,8 +777,8 @@ static int cli_wait(void) return err; } -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_comp_data_get(uint16_t net_idx, uint16_t addr, uint8_t page, + uint8_t *status, struct os_mbuf *comp) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_DEV_COMP_DATA_GET, 1); struct bt_mesh_msg_ctx ctx = { @@ -588,8 +814,8 @@ done: return err; } -static int get_state_u8(u16_t net_idx, u16_t addr, u32_t op, u32_t rsp, - u8_t *val) +static int get_state_u8(uint16_t net_idx, uint16_t addr, uint32_t op, uint32_t rsp, + uint8_t *val) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(DUMMY_2_BYTE_OP, 0); struct bt_mesh_msg_ctx ctx = { @@ -620,8 +846,8 @@ done: return err; } -static int set_state_u8(u16_t net_idx, u16_t addr, u32_t op, u32_t rsp, - u8_t new_val, u8_t *val) +static int set_state_u8(uint16_t net_idx, uint16_t addr, uint32_t op, uint32_t rsp, + uint8_t new_val, uint8_t *val) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(DUMMY_2_BYTE_OP, 1); struct bt_mesh_msg_ctx ctx = { @@ -653,57 +879,71 @@ done: return err; } -int bt_mesh_cfg_beacon_get(u16_t net_idx, u16_t addr, u8_t *status) +int bt_mesh_cfg_beacon_get(uint16_t net_idx, uint16_t addr, uint8_t *status) { return get_state_u8(net_idx, addr, OP_BEACON_GET, OP_BEACON_STATUS, status); } -int bt_mesh_cfg_beacon_set(u16_t net_idx, u16_t addr, u8_t val, u8_t *status) +int bt_mesh_cfg_beacon_set(uint16_t net_idx, uint16_t addr, uint8_t val, uint8_t *status) { return set_state_u8(net_idx, addr, OP_BEACON_SET, OP_BEACON_STATUS, val, status); } -int bt_mesh_cfg_ttl_get(u16_t net_idx, u16_t addr, u8_t *ttl) +int bt_mesh_cfg_ttl_get(uint16_t net_idx, uint16_t addr, uint8_t *ttl) { return get_state_u8(net_idx, addr, OP_DEFAULT_TTL_GET, OP_DEFAULT_TTL_STATUS, ttl); } -int bt_mesh_cfg_ttl_set(u16_t net_idx, u16_t addr, u8_t val, u8_t *ttl) +int bt_mesh_cfg_ttl_set(uint16_t net_idx, uint16_t addr, uint8_t val, uint8_t *ttl) { return set_state_u8(net_idx, addr, OP_DEFAULT_TTL_SET, OP_DEFAULT_TTL_STATUS, val, ttl); } -int bt_mesh_cfg_friend_get(u16_t net_idx, u16_t addr, u8_t *status) +int bt_mesh_cfg_friend_get(uint16_t net_idx, uint16_t addr, uint8_t *status) { return get_state_u8(net_idx, addr, OP_FRIEND_GET, OP_FRIEND_STATUS, status); } -int bt_mesh_cfg_friend_set(u16_t net_idx, u16_t addr, u8_t val, u8_t *status) +int bt_mesh_cfg_friend_set(uint16_t net_idx, uint16_t addr, uint8_t val, uint8_t *status) { return set_state_u8(net_idx, addr, OP_FRIEND_SET, OP_FRIEND_STATUS, val, status); } -int bt_mesh_cfg_gatt_proxy_get(u16_t net_idx, u16_t addr, u8_t *status) +int bt_mesh_cfg_gatt_proxy_get(uint16_t net_idx, uint16_t addr, uint8_t *status) { return get_state_u8(net_idx, addr, OP_GATT_PROXY_GET, OP_GATT_PROXY_STATUS, 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_set(uint16_t net_idx, uint16_t addr, uint8_t val, + uint8_t *status) { return set_state_u8(net_idx, addr, OP_GATT_PROXY_SET, OP_GATT_PROXY_STATUS, val, status); } -int bt_mesh_cfg_relay_get(u16_t net_idx, u16_t addr, u8_t *status, - u8_t *transmit) +int bt_mesh_cfg_net_transmit_set(uint16_t net_idx, uint16_t addr, + uint8_t val, uint8_t *transmit) +{ + return set_state_u8(net_idx, addr, OP_NET_TRANSMIT_SET, + OP_NET_TRANSMIT_STATUS, val, transmit); +} + +int bt_mesh_cfg_net_transmit_get(uint16_t net_idx, uint16_t addr, + uint8_t *transmit) +{ + return get_state_u8(net_idx, addr, OP_NET_TRANSMIT_GET, + OP_NET_TRANSMIT_STATUS, transmit); +} + +int bt_mesh_cfg_relay_get(uint16_t net_idx, uint16_t addr, uint8_t *status, + uint8_t *transmit) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_RELAY_GET, 0); struct bt_mesh_msg_ctx ctx = { @@ -738,8 +978,8 @@ done: return err; } -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_relay_set(uint16_t net_idx, uint16_t addr, uint8_t new_relay, + uint8_t new_transmit, uint8_t *status, uint8_t *transmit) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_RELAY_SET, 2); struct bt_mesh_msg_ctx ctx = { @@ -776,8 +1016,8 @@ done: return err; } -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_key_add(uint16_t net_idx, uint16_t addr, uint16_t key_net_idx, + const uint8_t net_key[16], uint8_t *status) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NET_KEY_ADD, 18); struct bt_mesh_msg_ctx ctx = { @@ -819,9 +1059,85 @@ done: return err; } -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_net_key_get(uint16_t net_idx, uint16_t addr, uint16_t *keys, + size_t *key_cnt) +{ + struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NET_KEY_GET, 0); + struct bt_mesh_msg_ctx ctx = { + .net_idx = net_idx, + .app_idx = BT_MESH_KEY_DEV_REMOTE, + .addr = addr, + .send_ttl = BT_MESH_TTL_DEFAULT, + }; + struct net_key_list_param param = { + .keys = keys, + .key_cnt = key_cnt, + }; + int err; + + err = cli_prepare(¶m, OP_NET_KEY_LIST); + if (err) { + return err; + } + + bt_mesh_model_msg_init(msg, OP_NET_KEY_GET); + + err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); + if (err) { + BT_ERR("model_send() failed (err %d)", err); + cli_reset(); + return err; + } + + os_mbuf_free_chain(msg); + return cli_wait(); +} + +int bt_mesh_cfg_net_key_del(uint16_t net_idx, uint16_t addr, + uint16_t key_net_idx, uint8_t *status) +{ + struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NET_KEY_DEL, 2); + struct bt_mesh_msg_ctx ctx = { + .net_idx = net_idx, + .app_idx = BT_MESH_KEY_DEV_REMOTE, + .addr = addr, + .send_ttl = BT_MESH_TTL_DEFAULT, + }; + struct net_key_param param = { + .status = status, + .net_idx = key_net_idx, + }; + int err; + + err = cli_prepare(¶m, OP_NET_KEY_STATUS); + if (err) { + goto done; + } + + bt_mesh_model_msg_init(msg, OP_NET_KEY_DEL); + net_buf_simple_add_le16(msg, key_net_idx); + + err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); + if (err) { + BT_ERR("model_send() failed (err %d)", err); + cli_reset(); + goto done; + } + + if (!status) { + cli_reset(); + goto done; + } + + err = cli_wait(); +done: + os_mbuf_free_chain(msg); + return err; +} + +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) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_APP_KEY_ADD, 19); struct bt_mesh_msg_ctx ctx = { @@ -864,9 +1180,137 @@ done: return err; } -static int mod_app_bind(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_node_reset(uint16_t net_idx, uint16_t addr, bool *status) +{ + struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NODE_RESET, 0); + struct bt_mesh_msg_ctx ctx = { + .net_idx = net_idx, + .app_idx = BT_MESH_KEY_DEV_REMOTE, + .addr = addr, + .send_ttl = BT_MESH_TTL_DEFAULT, + }; + + int err; + + if (status) { + *status = false; + } + + err = cli_prepare(status, OP_NODE_RESET_STATUS); + if (err) { + goto done; + } + + bt_mesh_model_msg_init(msg, OP_NODE_RESET); + + err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); + if (err) { + BT_ERR("model_send() failed (err %d)", err); + cli_reset(); + goto done; + } + + if (!status) { + cli_reset(); + goto done; + } + + err = cli_wait(); +done: + os_mbuf_free_chain(msg); + if (err) { + return err; + } else { + return 0; + } +} + +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) +{ + struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_APP_KEY_GET, 2); + struct bt_mesh_msg_ctx ctx = { + .net_idx = net_idx, + .app_idx = BT_MESH_KEY_DEV_REMOTE, + .addr = addr, + .send_ttl = BT_MESH_TTL_DEFAULT, + }; + struct app_key_list_param param = { + .net_idx = key_net_idx, + .status = status, + .keys = keys, + .key_cnt = key_cnt, + }; + int err; + + err = cli_prepare(¶m, OP_APP_KEY_LIST); + if (err) { + os_mbuf_free_chain(msg); + return err; + } + + bt_mesh_model_msg_init(msg, OP_APP_KEY_GET); + net_buf_simple_add_le16(msg, key_net_idx); + + err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); + if (err) { + BT_ERR("model_send() failed (err %d)", err); + os_mbuf_free_chain(msg); + cli_reset(); + return err; + } + + os_mbuf_free_chain(msg); + return cli_wait(); +} + +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) +{ + struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_APP_KEY_DEL, 3); + struct bt_mesh_msg_ctx ctx = { + .net_idx = net_idx, + .app_idx = BT_MESH_KEY_DEV_REMOTE, + .addr = addr, + .send_ttl = BT_MESH_TTL_DEFAULT, + }; + struct app_key_param param = { + .status = status, + .net_idx = key_net_idx, + .app_idx = key_app_idx, + }; + int err; + + err = cli_prepare(¶m, OP_APP_KEY_STATUS); + if (err) { + os_mbuf_free_chain(msg); + return err; + } + + bt_mesh_model_msg_init(msg, OP_APP_KEY_DEL); + key_idx_pack(msg, key_net_idx, key_app_idx); + + err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); + if (err) { + BT_ERR("model_send() failed (err %d)", err); + os_mbuf_free_chain(msg); + cli_reset(); + return err; + } + + if (!status) { + cli_reset(); + os_mbuf_free_chain(msg); + return 0; + } + + os_mbuf_free_chain(msg); + return cli_wait(); +} + +static int mod_app_bind(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) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_MOD_APP_BIND, 8); struct bt_mesh_msg_ctx ctx = { @@ -917,16 +1361,16 @@ done: return err; } -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_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) { return mod_app_bind(net_idx, addr, elem_addr, mod_app_idx, mod_id, CID_NVAL, status); } -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_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) { if (cid == CID_NVAL) { return -EINVAL; @@ -936,8 +1380,160 @@ int bt_mesh_cfg_mod_app_bind_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr, status); } -static int mod_sub(u32_t op, 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) +static int mod_app_unbind(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) +{ + struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_MOD_APP_UNBIND, 8); + struct bt_mesh_msg_ctx ctx = { + .net_idx = net_idx, + .app_idx = BT_MESH_KEY_DEV_REMOTE, + .addr = addr, + .send_ttl = BT_MESH_TTL_DEFAULT, + }; + struct mod_app_param param = { + .status = status, + .elem_addr = elem_addr, + .mod_app_idx = mod_app_idx, + .mod_id = mod_id, + .cid = cid, + }; + int err; + + err = cli_prepare(¶m, OP_MOD_APP_STATUS); + if (err) { + goto done; + } + + bt_mesh_model_msg_init(msg, OP_MOD_APP_UNBIND); + net_buf_simple_add_le16(msg, elem_addr); + net_buf_simple_add_le16(msg, mod_app_idx); + + if (cid != CID_NVAL) { + net_buf_simple_add_le16(msg, cid); + } + + net_buf_simple_add_le16(msg, mod_id); + + err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); + if (err) { + BT_ERR("model_send() failed (err %d)", err); + cli_reset(); + goto done; + } + + if (!status) { + cli_reset(); + err = 0; + goto done; + } + +done: + os_mbuf_free_chain(msg); + if (err) { + return err; + } else { + return cli_wait(); + } +} + +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) +{ + return mod_app_unbind(net_idx, addr, elem_addr, mod_app_idx, mod_id, + CID_NVAL, 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) +{ + if (cid == CID_NVAL) { + return -EINVAL; + } + + return mod_app_unbind(net_idx, addr, elem_addr, mod_app_idx, + mod_id, cid, status); +} + +static int mod_member_list_get(uint32_t op, uint32_t expect_op, 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) +{ + struct os_mbuf *msg = BT_MESH_MODEL_BUF(DUMMY_2_BYTE_OP, 6); + struct bt_mesh_msg_ctx ctx = { + .net_idx = net_idx, + .app_idx = BT_MESH_KEY_DEV_REMOTE, + .addr = addr, + .send_ttl = BT_MESH_TTL_DEFAULT, + }; + struct mod_member_list_param param = { + .status = status, + .elem_addr = elem_addr, + .mod_id = mod_id, + .cid = cid, + .members = apps, + .member_cnt = app_cnt, + }; + int err; + + err = cli_prepare(¶m, expect_op); + if (err) { + goto done; + } + + BT_DBG("net_idx 0x%04x addr 0x%04x elem_addr 0x%04x", + net_idx, addr, elem_addr); + BT_DBG("mod_id 0x%04x cid 0x%04x op: %x", mod_id, cid, op); + + bt_mesh_model_msg_init(msg, op); + net_buf_simple_add_le16(msg, elem_addr); + + if (cid != CID_NVAL) { + net_buf_simple_add_le16(msg, cid); + } + + net_buf_simple_add_le16(msg, mod_id); + + err = bt_mesh_model_send(cli->model, &ctx, msg, NULL, NULL); + if (err) { + BT_ERR("model_send() failed (err %d)", err); + cli_reset(); + goto done; + } + + err = cli_wait(); +done: + os_mbuf_free_chain(msg); + return err; +} + +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) +{ + return mod_member_list_get(OP_SIG_MOD_APP_GET, OP_SIG_MOD_APP_LIST, + net_idx, addr, elem_addr, mod_id, CID_NVAL, + status, apps, 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) +{ + if (cid == CID_NVAL) { + return -EINVAL; + } + + return mod_member_list_get(OP_VND_MOD_APP_GET, OP_VND_MOD_APP_LIST, + net_idx, addr, elem_addr, mod_id, CID_NVAL, + status, apps, app_cnt); +} + +static int mod_sub(uint32_t op, 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) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(DUMMY_2_BYTE_OP, 8); struct bt_mesh_msg_ctx ctx = { @@ -979,6 +1575,7 @@ static int mod_sub(u32_t op, u16_t net_idx, u16_t addr, u16_t elem_addr, if (!status) { cli_reset(); + err = 0; goto done; } @@ -988,16 +1585,16 @@ done: return err; } -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) { return mod_sub(OP_MOD_SUB_ADD, net_idx, addr, elem_addr, sub_addr, mod_id, CID_NVAL, 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) { if (cid == CID_NVAL) { return -EINVAL; @@ -1007,16 +1604,16 @@ int bt_mesh_cfg_mod_sub_add_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr, mod_id, cid, 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) { return mod_sub(OP_MOD_SUB_DEL, net_idx, addr, elem_addr, sub_addr, mod_id, CID_NVAL, 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) { if (cid == CID_NVAL) { return -EINVAL; @@ -1026,16 +1623,16 @@ int bt_mesh_cfg_mod_sub_del_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr, mod_id, cid, 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) { return mod_sub(OP_MOD_SUB_OVERWRITE, net_idx, addr, elem_addr, sub_addr, mod_id, CID_NVAL, 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) { if (cid == CID_NVAL) { return -EINVAL; @@ -1045,9 +1642,9 @@ int bt_mesh_cfg_mod_sub_overwrite_vnd(u16_t net_idx, u16_t addr, sub_addr, mod_id, cid, status); } -static int mod_sub_va(u32_t op, 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) +static int mod_sub_va(uint32_t op, 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) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(DUMMY_2_BYTE_OP, 22); struct bt_mesh_msg_ctx ctx = { @@ -1102,17 +1699,17 @@ done: return err; } -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) { return mod_sub_va(OP_MOD_SUB_VA_ADD, net_idx, addr, elem_addr, label, mod_id, CID_NVAL, virt_addr, 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) { if (cid == CID_NVAL) { return -EINVAL; @@ -1122,17 +1719,17 @@ int bt_mesh_cfg_mod_sub_va_add_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr, mod_id, cid, virt_addr, 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) { return mod_sub_va(OP_MOD_SUB_VA_DEL, net_idx, addr, elem_addr, label, mod_id, CID_NVAL, virt_addr, 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) { if (cid == CID_NVAL) { return -EINVAL; @@ -1142,19 +1739,19 @@ int bt_mesh_cfg_mod_sub_va_del_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr, mod_id, cid, virt_addr, 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) { return mod_sub_va(OP_MOD_SUB_VA_OVERWRITE, net_idx, addr, elem_addr, label, mod_id, CID_NVAL, virt_addr, 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) { if (cid == CID_NVAL) { return -EINVAL; @@ -1164,9 +1761,31 @@ int bt_mesh_cfg_mod_sub_va_overwrite_vnd(u16_t net_idx, u16_t addr, label, mod_id, cid, virt_addr, status); } -static int mod_pub_get(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_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) +{ + return mod_member_list_get(OP_MOD_SUB_GET, OP_MOD_SUB_LIST, net_idx, + addr, elem_addr, mod_id, CID_NVAL, status, + subs, 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) +{ + if (cid == CID_NVAL) { + return -EINVAL; + } + + return mod_member_list_get(OP_MOD_SUB_GET_VND, OP_MOD_SUB_LIST_VND, + net_idx, addr, elem_addr, mod_id, CID_NVAL, + status, subs, sub_cnt); +} + +static int mod_pub_get(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) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_MOD_PUB_GET, 6); struct bt_mesh_msg_ctx ctx = { @@ -1217,17 +1836,17 @@ done: return err; } -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) { return mod_pub_get(net_idx, addr, elem_addr, mod_id, CID_NVAL, pub, 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) { if (cid == CID_NVAL) { return -EINVAL; @@ -1236,9 +1855,9 @@ int bt_mesh_cfg_mod_pub_get_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr, return mod_pub_get(net_idx, addr, elem_addr, mod_id, cid, pub, status); } -static int mod_pub_set(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) +static int mod_pub_set(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) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_MOD_PUB_SET, 13); struct bt_mesh_msg_ctx ctx = { @@ -1265,7 +1884,7 @@ static int mod_pub_set(u16_t net_idx, u16_t addr, u16_t elem_addr, net_buf_simple_add_le16(msg, elem_addr); net_buf_simple_add_le16(msg, pub->addr); - net_buf_simple_add_le16(msg, (pub->app_idx | (pub->cred_flag << 12))); + net_buf_simple_add_le16(msg, (pub->app_idx & (pub->cred_flag << 12))); net_buf_simple_add_u8(msg, pub->ttl); net_buf_simple_add_u8(msg, pub->period); net_buf_simple_add_u8(msg, pub->transmit); @@ -1294,17 +1913,17 @@ done: return err; } -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) { return mod_pub_set(net_idx, addr, elem_addr, mod_id, CID_NVAL, pub, 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) { if (cid == CID_NVAL) { return -EINVAL; @@ -1313,8 +1932,8 @@ int bt_mesh_cfg_mod_pub_set_vnd(u16_t net_idx, u16_t addr, u16_t elem_addr, return mod_pub_set(net_idx, addr, elem_addr, mod_id, cid, pub, status); } -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) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEARTBEAT_SUB_SET, 5); struct bt_mesh_msg_ctx ctx = { @@ -1357,8 +1976,8 @@ done: return err; } -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 os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEARTBEAT_SUB_GET, 0); struct bt_mesh_msg_ctx ctx = { @@ -1398,8 +2017,8 @@ done: return err; } -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) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEARTBEAT_PUB_SET, 9); struct bt_mesh_msg_ctx ctx = { @@ -1444,8 +2063,8 @@ done: return err; } -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) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEARTBEAT_PUB_GET, 0); struct bt_mesh_msg_ctx ctx = { @@ -1485,12 +2104,12 @@ done: return err; } -s32_t bt_mesh_cfg_cli_timeout_get(void) +int32_t bt_mesh_cfg_cli_timeout_get(void) { return msg_timeout; } -void bt_mesh_cfg_cli_timeout_set(s32_t timeout) +void bt_mesh_cfg_cli_timeout_set(int32_t timeout) { msg_timeout = timeout; } diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/cfg_srv.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/cfg_srv.c index 57aac90a..8a085bd7 100644 --- a/src/libs/mynewt-nimble/nimble/host/mesh/src/cfg_srv.c +++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/cfg_srv.c @@ -17,9 +17,12 @@ #include "mesh_priv.h" #include "adv.h" +#include "app_keys.h" #include "net.h" +#include "rpl.h" #include "lpn.h" #include "transport.h" +#include "heartbeat.h" #include "crypto.h" #include "access.h" #include "beacon.h" @@ -28,12 +31,10 @@ #include "friend.h" #include "testing.h" #include "settings.h" +#include "cfg.h" -#define DEFAULT_TTL 7 - -static struct bt_mesh_cfg_srv *conf; - -static struct label labels[CONFIG_BT_MESH_LABEL_COUNT]; +void (*bt_mesh_app_key_cb_list[1]) (uint16_t app_idx, uint16_t net_idx, + enum bt_mesh_key_evt evt); static int comp_add_elem(struct os_mbuf *buf, struct bt_mesh_elem *elem, bool primary) @@ -42,7 +43,7 @@ static int comp_add_elem(struct os_mbuf *buf, struct bt_mesh_elem *elem, int i; if (net_buf_simple_tailroom(buf) < - 4 + (elem->model_count * 2) + (elem->vnd_model_count * 2)) { + 4 + (elem->model_count * 2) + (elem->vnd_model_count * 4)) { BT_ERR("Too large device composition"); return -E2BIG; } @@ -68,7 +69,7 @@ static int comp_add_elem(struct os_mbuf *buf, struct bt_mesh_elem *elem, static int comp_get_page_0(struct os_mbuf *buf) { - u16_t feat = 0; + uint16_t feat = 0; const struct bt_mesh_comp *comp; int i; @@ -113,7 +114,7 @@ static void dev_comp_data_get(struct bt_mesh_model *model, struct os_mbuf *buf) { struct os_mbuf *sdu = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX); - u8_t page; + uint8_t page; BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, @@ -145,7 +146,7 @@ static struct bt_mesh_model *get_model(struct bt_mesh_elem *elem, struct os_mbuf *buf, bool *vnd) { if (buf->om_len < 4) { - u16_t id; + uint16_t id; id = net_buf_simple_pull_le16(buf); @@ -155,7 +156,7 @@ static struct bt_mesh_model *get_model(struct bt_mesh_elem *elem, return bt_mesh_model_find(elem, id); } else { - u16_t company, id; + uint16_t company, id; company = net_buf_simple_pull_le16(buf); id = net_buf_simple_pull_le16(buf); @@ -169,25 +170,9 @@ static struct bt_mesh_model *get_model(struct bt_mesh_elem *elem, } } -static bool app_key_is_valid(u16_t app_idx) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(bt_mesh.app_keys); i++) { - struct bt_mesh_app_key *key = &bt_mesh.app_keys[i]; - - if (key->net_idx != BT_MESH_KEY_UNUSED && - key->app_idx == app_idx) { - return true; - } - } - - return false; -} - -static u8_t _mod_pub_set(struct bt_mesh_model *model, u16_t pub_addr, - u16_t app_idx, u8_t cred_flag, u8_t ttl, u8_t period, - u8_t retransmit, bool store) +static uint8_t _mod_pub_set(struct bt_mesh_model *model, uint16_t pub_addr, + uint16_t app_idx, uint8_t cred_flag, uint8_t ttl, uint8_t period, + uint8_t retransmit, bool store) { if (!model->pub) { return STATUS_NVAL_PUB_PARAM; @@ -225,10 +210,20 @@ static u8_t _mod_pub_set(struct bt_mesh_model *model, u16_t pub_addr, return STATUS_SUCCESS; } - if (!bt_mesh_app_key_find(app_idx)) { + if (!bt_mesh_app_key_exists(app_idx)) { return STATUS_INVALID_APPKEY; } +#if CONFIG_BT_MESH_LABEL_COUNT > 0 + if (BT_MESH_ADDR_IS_VIRTUAL(model->pub->addr)) { + uint8_t *uuid = bt_mesh_va_label_get(model->pub->addr); + + if (uuid) { + bt_mesh_va_del(uuid, NULL); + } + } +#endif + model->pub->addr = pub_addr; model->pub->key = app_idx; model->pub->cred = cred_flag; @@ -237,12 +232,12 @@ static u8_t _mod_pub_set(struct bt_mesh_model *model, u16_t pub_addr, model->pub->retransmit = retransmit; if (model->pub->update) { - s32_t period_ms; + int32_t period_ms; period_ms = bt_mesh_model_pub_period_get(model); BT_DBG("period %u ms", (unsigned) period_ms); - if (period_ms) { + if (period_ms > 0) { k_delayed_work_submit(&model->pub->timer, period_ms); } else { k_delayed_work_cancel(&model->pub->timer); @@ -256,13 +251,13 @@ static u8_t _mod_pub_set(struct bt_mesh_model *model, u16_t pub_addr, return STATUS_SUCCESS; } -u8_t mod_bind(struct bt_mesh_model *model, u16_t key_idx) +uint8_t mod_bind(struct bt_mesh_model *model, uint16_t key_idx) { int i; BT_DBG("model %p key_idx 0x%03x", model, key_idx); - if (!app_key_is_valid(key_idx)) { + if (!bt_mesh_app_key_exists(key_idx)) { return STATUS_INVALID_APPKEY; } @@ -288,13 +283,13 @@ u8_t mod_bind(struct bt_mesh_model *model, u16_t key_idx) return STATUS_INSUFF_RESOURCES; } -u8_t mod_unbind(struct bt_mesh_model *model, u16_t key_idx, bool store) +uint8_t mod_unbind(struct bt_mesh_model *model, uint16_t key_idx, bool store) { int i; BT_DBG("model %p key_idx 0x%03x store %u", model, key_idx, store); - if (!app_key_is_valid(key_idx)) { + if (!bt_mesh_app_key_exists(key_idx)) { return STATUS_INVALID_APPKEY; } @@ -318,240 +313,88 @@ u8_t mod_unbind(struct bt_mesh_model *model, u16_t key_idx, bool store) return STATUS_SUCCESS; } -struct bt_mesh_app_key *bt_mesh_app_key_alloc(u16_t app_idx) +static void send_app_key_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + uint8_t status, + uint16_t app_idx, uint16_t net_idx) { - int i; + struct os_mbuf *msg = NET_BUF_SIMPLE( + BT_MESH_MODEL_BUF_LEN(OP_APP_KEY_STATUS, 4)); - for (i = 0; i < ARRAY_SIZE(bt_mesh.app_keys); i++) { - struct bt_mesh_app_key *key = &bt_mesh.app_keys[i]; + bt_mesh_model_msg_init(msg, OP_APP_KEY_STATUS); + net_buf_simple_add_u8(msg, status); + key_idx_pack(msg, net_idx, app_idx); - if (key->net_idx == BT_MESH_KEY_UNUSED) { - return key; - } + if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { + BT_ERR("Unable to send App Key Status response"); } - return NULL; -} - -static u8_t app_key_set(u16_t net_idx, u16_t app_idx, const u8_t val[16], - bool update) -{ - struct bt_mesh_app_keys *keys; - struct bt_mesh_app_key *key; - struct bt_mesh_subnet *sub; - - BT_DBG("net_idx 0x%04x app_idx %04x update %u val %s", - net_idx, app_idx, update, bt_hex(val, 16)); - - sub = bt_mesh_subnet_get(net_idx); - if (!sub) { - return STATUS_INVALID_NETKEY; - } - - key = bt_mesh_app_key_find(app_idx); - if (update) { - if (!key) { - return STATUS_INVALID_APPKEY; - } - - if (key->net_idx != net_idx) { - return STATUS_INVALID_BINDING; - } - - keys = &key->keys[1]; - - /* The AppKey Update message shall generate an error when node - * is in normal operation, Phase 2, or Phase 3 or in Phase 1 - * when the AppKey Update message on a valid AppKeyIndex when - * the AppKey value is different. - */ - if (sub->kr_phase != BT_MESH_KR_PHASE_1) { - return STATUS_CANNOT_UPDATE; - } - - if (key->updated) { - if (memcmp(keys->val, val, 16)) { - return STATUS_CANNOT_UPDATE; - } else { - return STATUS_SUCCESS; - } - } - - key->updated = true; - } else { - if (key) { - if (key->net_idx == net_idx && - !memcmp(key->keys[0].val, val, 16)) { - return STATUS_SUCCESS; - } - - if (key->net_idx == net_idx) { - return STATUS_IDX_ALREADY_STORED; - } else { - return STATUS_INVALID_NETKEY; - } - } - - key = bt_mesh_app_key_alloc(app_idx); - if (!key) { - return STATUS_INSUFF_RESOURCES; - } - - keys = &key->keys[0]; - } - - if (bt_mesh_app_id(val, &keys->id)) { - if (update) { - key->updated = false; - } - - return STATUS_STORAGE_FAIL; - } - - BT_DBG("app_idx 0x%04x AID 0x%02x", app_idx, keys->id); - - key->net_idx = net_idx; - key->app_idx = app_idx; - memcpy(keys->val, val, 16); - - if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - BT_DBG("Storing AppKey persistently"); - bt_mesh_store_app_key(key); - } - - return STATUS_SUCCESS; + os_mbuf_free_chain(msg); } static void app_key_add(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { - struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_APP_KEY_STATUS, 4); - u16_t key_net_idx, key_app_idx; - u8_t status; + uint16_t key_net_idx, key_app_idx; + uint8_t status; key_idx_unpack(buf, &key_net_idx, &key_app_idx); BT_DBG("AppIdx 0x%04x NetIdx 0x%04x", key_app_idx, key_net_idx); - bt_mesh_model_msg_init(msg, OP_APP_KEY_STATUS); + status = bt_mesh_app_key_add(key_app_idx, key_net_idx, buf->om_data); - status = app_key_set(key_net_idx, key_app_idx, buf->om_data, false); - BT_DBG("status 0x%02x", status); - net_buf_simple_add_u8(msg, status); - - key_idx_pack(msg, key_net_idx, key_app_idx); - - if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { - BT_ERR("Unable to send App Key Status response"); - } - - os_mbuf_free_chain(msg); + send_app_key_status(model, ctx, status, key_app_idx, key_net_idx); } static void app_key_update(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { - struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_APP_KEY_STATUS, 4); - u16_t key_net_idx, key_app_idx; - u8_t status; + uint16_t key_net_idx, key_app_idx; + uint8_t status; key_idx_unpack(buf, &key_net_idx, &key_app_idx); BT_DBG("AppIdx 0x%04x NetIdx 0x%04x", key_app_idx, key_net_idx); - bt_mesh_model_msg_init(msg, OP_APP_KEY_STATUS); - - status = app_key_set(key_net_idx, key_app_idx, buf->om_data, true); + status = bt_mesh_app_key_update(key_app_idx, key_net_idx, buf->om_data); BT_DBG("status 0x%02x", status); - net_buf_simple_add_u8(msg, status); - - key_idx_pack(msg, key_net_idx, key_app_idx); - - if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { - BT_ERR("Unable to send App Key Status response"); - } - - os_mbuf_free_chain(msg); + send_app_key_status(model, ctx, status, key_app_idx, key_net_idx); } -struct unbind_data { - u16_t app_idx; - bool store; -}; - -static void _mod_unbind(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, - bool vnd, bool primary, void *user_data) +static void mod_app_key_del(struct bt_mesh_model *mod, + struct bt_mesh_elem *elem, bool vnd, bool primary, + void *user_data) { - struct unbind_data *data = user_data; + uint16_t *app_idx = user_data; - mod_unbind(mod, data->app_idx, data->store); + mod_unbind(mod, *app_idx, true); } -void bt_mesh_app_key_del(struct bt_mesh_app_key *key, bool store) +static void app_key_evt(uint16_t app_idx, uint16_t net_idx, + enum bt_mesh_key_evt evt) { - struct unbind_data data = { .app_idx = key->app_idx, .store = store }; - - BT_DBG("AppIdx 0x%03x store %u", key->app_idx, store); - - bt_mesh_model_foreach(_mod_unbind, &data); - - if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) { - bt_mesh_clear_app_key(key); + if (evt == BT_MESH_KEY_DELETED) { + bt_mesh_model_foreach(&mod_app_key_del, &app_idx); } - - key->net_idx = BT_MESH_KEY_UNUSED; - memset(key->keys, 0, sizeof(key->keys)); } static void app_key_del(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { - struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_APP_KEY_STATUS, 4); - u16_t key_net_idx, key_app_idx; - struct bt_mesh_app_key *key; - u8_t status; + uint16_t key_net_idx, key_app_idx; + uint8_t status; key_idx_unpack(buf, &key_net_idx, &key_app_idx); BT_DBG("AppIdx 0x%04x NetIdx 0x%04x", key_app_idx, key_net_idx); - if (!bt_mesh_subnet_get(key_net_idx)) { - status = STATUS_INVALID_NETKEY; - goto send_status; - } + status = bt_mesh_app_key_del(key_app_idx, key_net_idx); - key = bt_mesh_app_key_find(key_app_idx); - if (!key) { - /* Treat as success since the client might have missed a - * previous response and is resending the request. - */ - status = STATUS_SUCCESS; - goto send_status; - } - - if (key->net_idx != key_net_idx) { - status = STATUS_INVALID_BINDING; - goto send_status; - } - - bt_mesh_app_key_del(key, true); - status = STATUS_SUCCESS; - -send_status: - bt_mesh_model_msg_init(msg, OP_APP_KEY_STATUS); - - net_buf_simple_add_u8(msg, status); - - key_idx_pack(msg, key_net_idx, key_app_idx); - - if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { - BT_ERR("Unable to send App Key Status response"); - } - - os_mbuf_free_chain(msg); + send_app_key_status(model, ctx, status, key_app_idx, key_net_idx); } /* Index list length: 3 bytes for every pair and 2 bytes for an odd idx */ @@ -564,8 +407,11 @@ static void app_key_get(struct bt_mesh_model *model, struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_APP_KEY_LIST, 3 + IDX_LEN(CONFIG_BT_MESH_APP_KEY_COUNT)); - u16_t get_idx, i, prev; - u8_t status; + uint16_t app_idx[CONFIG_BT_MESH_APP_KEY_COUNT]; + uint16_t get_idx; + uint8_t status; + ssize_t count; + int i; get_idx = net_buf_simple_pull_le16(buf); if (get_idx > 0xfff) { @@ -577,7 +423,7 @@ static void app_key_get(struct bt_mesh_model *model, bt_mesh_model_msg_init(msg, OP_APP_KEY_LIST); - if (!bt_mesh_subnet_get(get_idx)) { + if (!bt_mesh_subnet_exists(get_idx)) { status = STATUS_INVALID_NETKEY; } else { status = STATUS_SUCCESS; @@ -590,25 +436,17 @@ static void app_key_get(struct bt_mesh_model *model, goto send_status; } - prev = BT_MESH_KEY_UNUSED; - for (i = 0; i < ARRAY_SIZE(bt_mesh.app_keys); i++) { - struct bt_mesh_app_key *key = &bt_mesh.app_keys[i]; - - if (key->net_idx != get_idx) { - continue; - } - - if (prev == BT_MESH_KEY_UNUSED) { - prev = key->app_idx; - continue; - } - - key_idx_pack(msg, prev, key->app_idx); - prev = BT_MESH_KEY_UNUSED; + count = bt_mesh_app_keys_get(get_idx, app_idx, ARRAY_SIZE(app_idx), 0); + if (count < 0 || count > ARRAY_SIZE(app_idx)) { + count = ARRAY_SIZE(app_idx); } - if (prev != BT_MESH_KEY_UNUSED) { - net_buf_simple_add_le16(msg, prev); + for (i = 0; i < count - 1; i += 2) { + key_idx_pack(msg, app_idx[i], app_idx[i + 1]); + } + + if (i < count) { + net_buf_simple_add_le16(msg, app_idx[i]); } send_status: @@ -631,7 +469,7 @@ static void beacon_get(struct bt_mesh_model *model, bt_hex(buf->om_data, buf->om_len)); bt_mesh_model_msg_init(msg, OP_BEACON_STATUS); - net_buf_simple_add_u8(msg, bt_mesh_beacon_get()); + net_buf_simple_add_u8(msg, bt_mesh_beacon_enabled()); if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { BT_ERR("Unable to send Config Beacon Status response"); @@ -644,35 +482,20 @@ static void beacon_set(struct bt_mesh_model *model, struct os_mbuf *buf) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_BEACON_STATUS, 1); - struct bt_mesh_cfg_srv *cfg = model->user_data; BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, bt_hex(buf->om_data, buf->om_len)); - if (!cfg) { - BT_WARN("No Configuration Server context available"); - } else if (buf->om_data[0] == 0x00 || buf->om_data[0] == 0x01) { - if (buf->om_data[0] != cfg->beacon) { - cfg->beacon = buf->om_data[0]; - - if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - bt_mesh_store_cfg(); - } - - if (cfg->beacon) { - bt_mesh_beacon_enable(); - } else { - bt_mesh_beacon_disable(); - } - } - } else { + if (buf->om_data[0] != 0x00 && buf->om_data[0] != 0x01) { BT_WARN("Invalid Config Beacon value 0x%02x", buf->om_data[0]); goto done; } + bt_mesh_beacon_set(buf->om_data[0]); + bt_mesh_model_msg_init(msg, OP_BEACON_STATUS); - net_buf_simple_add_u8(msg, bt_mesh_beacon_get()); + net_buf_simple_add_u8(msg, buf->om_data[0]); if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { BT_ERR("Unable to send Config Beacon Status response"); @@ -709,29 +532,20 @@ static void default_ttl_set(struct bt_mesh_model *model, struct os_mbuf *buf) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_DEFAULT_TTL_STATUS, 1); - struct bt_mesh_cfg_srv *cfg = model->user_data; + int err; BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, bt_hex(buf->om_data, buf->om_len)); - if (!cfg) { - BT_WARN("No Configuration Server context available"); - } else if (buf->om_data[0] <= BT_MESH_TTL_MAX && buf->om_data[0] != 0x01) { - if (cfg->default_ttl != buf->om_data[0]) { - cfg->default_ttl = buf->om_data[0]; - - if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - bt_mesh_store_cfg(); - } - } - } else { + err = bt_mesh_default_ttl_set(buf->om_data[0]); + if (err) { BT_WARN("Prohibited Default TTL value 0x%02x", buf->om_data[0]); goto done; } bt_mesh_model_msg_init(msg, OP_DEFAULT_TTL_STATUS); - net_buf_simple_add_u8(msg, bt_mesh_default_ttl_get()); + net_buf_simple_add_u8(msg, buf->om_data[0]); if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { BT_ERR("Unable to send Default TTL Status response"); @@ -772,8 +586,6 @@ static void gatt_proxy_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { - struct bt_mesh_cfg_srv *cfg = model->user_data; - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, bt_hex(buf->om_data, buf->om_len)); @@ -783,35 +595,8 @@ static void gatt_proxy_set(struct bt_mesh_model *model, return; } - if (!(MYNEWT_VAL(BLE_MESH_GATT_PROXY)) || - bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_NOT_SUPPORTED) { - goto send_status; - } + (void)bt_mesh_gatt_proxy_set(buf->om_data[0]); - if (!cfg) { - BT_WARN("No Configuration Server context available"); - goto send_status; - } - - BT_DBG("GATT Proxy 0x%02x -> 0x%02x", cfg->gatt_proxy, buf->om_data[0]); - - if (cfg->gatt_proxy == buf->om_data[0]) { - goto send_status; - } - - cfg->gatt_proxy = buf->om_data[0]; - - if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - bt_mesh_store_cfg(); - } - - bt_mesh_adv_update(); - - if (cfg->hb_pub.feat & BT_MESH_FEAT_PROXY) { - bt_mesh_heartbeat_send(); - } - -send_status: send_gatt_proxy_status(model, ctx); } @@ -841,7 +626,6 @@ static void net_transmit_set(struct bt_mesh_model *model, struct os_mbuf *buf) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NET_TRANSMIT_STATUS, 1); - struct bt_mesh_cfg_srv *cfg = model->user_data; BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, @@ -851,18 +635,10 @@ static void net_transmit_set(struct bt_mesh_model *model, BT_MESH_TRANSMIT_COUNT(buf->om_data[0]), BT_MESH_TRANSMIT_INT(buf->om_data[0])); - if (!cfg) { - BT_WARN("No Configuration Server context available"); - } else { - cfg->net_transmit = buf->om_data[0]; - - if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - bt_mesh_store_cfg(); - } - } + bt_mesh_net_transmit_set(buf->om_data[0]); bt_mesh_model_msg_init(msg, OP_NET_TRANSMIT_STATUS); - net_buf_simple_add_u8(msg, bt_mesh_net_transmit_get()); + net_buf_simple_add_u8(msg, buf->om_data[0]); if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { BT_ERR("Unable to send Network Transmit Status"); @@ -898,43 +674,18 @@ static void relay_set(struct bt_mesh_model *model, struct os_mbuf *buf) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_RELAY_STATUS, 2); - struct bt_mesh_cfg_srv *cfg = model->user_data; BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, bt_hex(buf->om_data, buf->om_len)); - if (!cfg) { - BT_WARN("No Configuration Server context available"); - } else if (buf->om_data[0] == 0x00 || buf->om_data[0] == 0x01) { - bool change; - - if (cfg->relay == BT_MESH_RELAY_NOT_SUPPORTED) { - change = false; - } else { - change = (cfg->relay != buf->om_data[0]); - cfg->relay = buf->om_data[0]; - cfg->relay_retransmit = buf->om_data[1]; - - if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - bt_mesh_store_cfg(); - } - } - - BT_DBG("Relay 0x%02x (%s) xmit 0x%02x (count %u interval %u)", - cfg->relay, change ? "changed" : "not changed", - cfg->relay_retransmit, - BT_MESH_TRANSMIT_COUNT(cfg->relay_retransmit), - BT_MESH_TRANSMIT_INT(cfg->relay_retransmit)); - - if ((cfg->hb_pub.feat & BT_MESH_FEAT_RELAY) && change) { - bt_mesh_heartbeat_send(); - } - } else { + if (buf->om_data[0] != 0x00 && buf->om_data[0] != 0x01) { BT_WARN("Invalid Relay value 0x%02x", buf->om_data[0]); goto done; } + (void)bt_mesh_relay_set(buf->om_data[0], buf->om_data[1]); + bt_mesh_model_msg_init(msg, OP_RELAY_STATUS); net_buf_simple_add_u8(msg, bt_mesh_relay_get()); net_buf_simple_add_u8(msg, bt_mesh_relay_retransmit_get()); @@ -950,9 +701,9 @@ done: static void send_mod_pub_status(struct bt_mesh_model *cfg_mod, struct bt_mesh_msg_ctx *ctx, - u16_t elem_addr, u16_t pub_addr, + uint16_t elem_addr, uint16_t pub_addr, bool vnd, struct bt_mesh_model *mod, - u8_t status, u8_t *mod_id) + uint8_t status, uint8_t *mod_id) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_MOD_PUB_STATUS, 14); @@ -964,11 +715,11 @@ static void send_mod_pub_status(struct bt_mesh_model *cfg_mod, if (status != STATUS_SUCCESS) { memset(net_buf_simple_add(msg, 7), 0, 7); } else { - u16_t idx_cred; + uint16_t idx_cred; net_buf_simple_add_le16(msg, pub_addr); - idx_cred = mod->pub->key | (u16_t)mod->pub->cred << 12; + idx_cred = mod->pub->key | (uint16_t)mod->pub->cred << 12; net_buf_simple_add_le16(msg, idx_cred); net_buf_simple_add_u8(msg, mod->pub->ttl); net_buf_simple_add_u8(msg, mod->pub->period); @@ -992,10 +743,10 @@ static void mod_pub_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { - u16_t elem_addr, pub_addr = 0; + uint16_t elem_addr, pub_addr = 0; struct bt_mesh_model *mod; struct bt_mesh_elem *elem; - u8_t *mod_id, status; + uint8_t *mod_id, status; bool vnd; elem_addr = net_buf_simple_pull_le16(buf); @@ -1039,11 +790,11 @@ static void mod_pub_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { - u8_t retransmit, status, pub_ttl, pub_period, cred_flag; - u16_t elem_addr, pub_addr, pub_app_idx; + uint8_t retransmit, status, pub_ttl, pub_period, cred_flag; + uint16_t elem_addr, pub_addr, pub_app_idx; struct bt_mesh_model *mod; struct bt_mesh_elem *elem; - u8_t *mod_id; + uint8_t *mod_id; bool vnd; elem_addr = net_buf_simple_pull_le16(buf); @@ -1097,102 +848,9 @@ send_status: status, mod_id); } -struct label *get_label(u16_t index) -{ - if (index >= ARRAY_SIZE(labels)) { - return NULL; - } - - return &labels[index]; -} - -#if CONFIG_BT_MESH_LABEL_COUNT > 0 -static inline void va_store(struct label *store) -{ - atomic_set_bit(store->flags, BT_MESH_VA_CHANGED); - if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - bt_mesh_store_label(); - } -} - -static struct label *va_find(const u8_t *label_uuid, - struct label **free_slot) -{ - struct label *match = NULL; - int i; - - if (free_slot != NULL) { - *free_slot = NULL; - } - - for (i = 0; i < ARRAY_SIZE(labels); i++) { - if (labels[i].ref == 0) { - if (free_slot != NULL) { - *free_slot = &labels[i]; - } - continue; - } - - if (!memcmp(labels[i].uuid, label_uuid, 16)) { - match = &labels[i]; - } - } - - return match; -} - -static u8_t va_add(u8_t *label_uuid, u16_t *addr) -{ - struct label *update, *free_slot = NULL; - - update = va_find(label_uuid, &free_slot); - if (update) { - update->ref++; - va_store(update); - return 0; - } - - if (!free_slot) { - return STATUS_INSUFF_RESOURCES; - } - - if (bt_mesh_virtual_addr(label_uuid, addr) < 0) { - return STATUS_UNSPECIFIED; - } - - free_slot->ref = 1; - free_slot->addr = *addr; - memcpy(free_slot->uuid, label_uuid, 16); - va_store(free_slot); - - return STATUS_SUCCESS; -} - -static u8_t va_del(u8_t *label_uuid, u16_t *addr) -{ - struct label *update; - - update = va_find(label_uuid, NULL); - if (update) { - update->ref--; - - if (addr) { - *addr = update->addr; - } - - va_store(update); - } - - if (addr) { - *addr = BT_MESH_ADDR_UNASSIGNED; - } - - return STATUS_CANNOT_REMOVE; -} - static size_t mod_sub_list_clear(struct bt_mesh_model *mod) { - u8_t *label_uuid; + uint8_t *label_uuid; size_t clear_count; int i; @@ -1207,13 +865,13 @@ static size_t mod_sub_list_clear(struct bt_mesh_model *mod) continue; } - label_uuid = bt_mesh_label_uuid_get(mod->groups[i]); + label_uuid = bt_mesh_va_label_get(mod->groups[i]); mod->groups[i] = BT_MESH_ADDR_UNASSIGNED; clear_count++; if (label_uuid) { - va_del(label_uuid, NULL); + bt_mesh_va_del(label_uuid, NULL); } else { BT_ERR("Label UUID not found"); } @@ -1226,12 +884,12 @@ static void mod_pub_va_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { - u8_t retransmit, status, pub_ttl, pub_period, cred_flag; - u16_t elem_addr, pub_addr, pub_app_idx; + uint8_t retransmit, status, pub_ttl, pub_period, cred_flag; + uint16_t elem_addr, pub_addr, pub_app_idx; struct bt_mesh_model *mod; struct bt_mesh_elem *elem; - u8_t *label_uuid; - u8_t *mod_id; + uint8_t *label_uuid; + uint8_t *mod_id; bool vnd; elem_addr = net_buf_simple_pull_le16(buf); @@ -1277,85 +935,25 @@ static void mod_pub_va_set(struct bt_mesh_model *model, goto send_status; } - status = va_add(label_uuid, &pub_addr); - if (status == STATUS_SUCCESS) { - status = _mod_pub_set(mod, pub_addr, pub_app_idx, cred_flag, - pub_ttl, pub_period, retransmit, true); + status = bt_mesh_va_add(label_uuid, &pub_addr); + if (status != STATUS_SUCCESS) { + goto send_status; + } + + status = _mod_pub_set(mod, pub_addr, pub_app_idx, cred_flag, pub_ttl, + pub_period, retransmit, true); + if (status != STATUS_SUCCESS) { + bt_mesh_va_del(label_uuid, NULL); } send_status: send_mod_pub_status(model, ctx, elem_addr, pub_addr, vnd, mod, status, mod_id); } -#else -static size_t mod_sub_list_clear(struct bt_mesh_model *mod) -{ - size_t clear_count; - int i; - - /* Unref stored labels related to this model */ - for (i = 0, clear_count = 0; i < ARRAY_SIZE(mod->groups); i++) { - if (mod->groups[i] != BT_MESH_ADDR_UNASSIGNED) { - mod->groups[i] = BT_MESH_ADDR_UNASSIGNED; - clear_count++; - } - } - - return clear_count; -} - -static void mod_pub_va_set(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - u8_t *mod_id, status; - struct bt_mesh_model *mod; - struct bt_mesh_elem *elem; - u16_t elem_addr, pub_addr = 0; - bool vnd; - - elem_addr = net_buf_simple_pull_le16(buf); - if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) { - BT_WARN("Prohibited element address"); - return; - } - - net_buf_simple_pull(buf, 16); - mod_id = net_buf_simple_pull(buf, 4); - - BT_DBG("elem_addr 0x%04x", elem_addr); - - elem = bt_mesh_elem_find(elem_addr); - if (!elem) { - mod = NULL; - vnd = (buf->om_len == 4); - status = STATUS_INVALID_ADDRESS; - goto send_status; - } - - mod = get_model(elem, buf, &vnd); - if (!mod) { - status = STATUS_INVALID_MODEL; - goto send_status; - } - - if (!mod->pub) { - status = STATUS_NVAL_PUB_PARAM; - goto send_status; - } - - pub_addr = mod->pub->addr; - status = STATUS_INSUFF_RESOURCES; - -send_status: - send_mod_pub_status(model, ctx, elem_addr, pub_addr, vnd, mod, - status, mod_id); -} -#endif /* MYNEWT_VAL(BLE_MESH_LABEL_COUNT) > 0 */ static void send_mod_sub_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, u8_t status, - u16_t elem_addr, u16_t sub_addr, u8_t *mod_id, + struct bt_mesh_msg_ctx *ctx, uint8_t status, + uint16_t elem_addr, uint16_t sub_addr, uint8_t *mod_id, bool vnd) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_MOD_SUB_STATUS, 9); @@ -1386,12 +984,12 @@ static void mod_sub_add(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { - u16_t elem_addr, sub_addr; + uint16_t elem_addr, sub_addr; struct bt_mesh_model *mod; struct bt_mesh_elem *elem; - u8_t *mod_id; - u8_t status; - u16_t *entry; + uint8_t *mod_id; + uint8_t status; + uint16_t *entry; bool vnd; elem_addr = net_buf_simple_pull_le16(buf); @@ -1459,12 +1057,12 @@ static void mod_sub_del(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { - u16_t elem_addr, sub_addr; + uint16_t elem_addr, sub_addr; struct bt_mesh_model *mod; struct bt_mesh_elem *elem; - u8_t *mod_id; - u16_t *match; - u8_t status; + uint8_t *mod_id; + uint16_t *match; + uint8_t status; bool vnd; elem_addr = net_buf_simple_pull_le16(buf); @@ -1522,7 +1120,7 @@ send_status: } static enum bt_mesh_walk mod_sub_clear_visitor(struct bt_mesh_model *mod, - u32_t depth, void *user_data) + uint32_t depth, void *user_data) { if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) { bt_mesh_lpn_group_del(mod->groups, ARRAY_SIZE(mod->groups)); @@ -1537,11 +1135,11 @@ static void mod_sub_overwrite(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { - u16_t elem_addr, sub_addr; + uint16_t elem_addr, sub_addr; struct bt_mesh_model *mod; struct bt_mesh_elem *elem; - u8_t *mod_id; - u8_t status; + uint8_t *mod_id; + uint8_t status; bool vnd; elem_addr = net_buf_simple_pull_le16(buf); @@ -1605,9 +1203,9 @@ static void mod_sub_del_all(struct bt_mesh_model *model, { struct bt_mesh_model *mod; struct bt_mesh_elem *elem; - u16_t elem_addr; - u8_t *mod_id; - u8_t status; + uint16_t elem_addr; + uint8_t *mod_id; + uint8_t status; bool vnd; elem_addr = net_buf_simple_pull_le16(buf); @@ -1649,12 +1247,12 @@ send_status: } struct mod_sub_list_ctx { - u16_t elem_idx; + uint16_t elem_idx; struct os_mbuf *msg; }; static enum bt_mesh_walk mod_sub_list_visitor(struct bt_mesh_model *mod, - u32_t depth, void *ctx) + uint32_t depth, void *ctx) { struct mod_sub_list_ctx *visit = ctx; int count = 0; @@ -1693,7 +1291,7 @@ static void mod_sub_get(struct bt_mesh_model *model, struct mod_sub_list_ctx visit_ctx; struct bt_mesh_model *mod; struct bt_mesh_elem *elem; - u16_t addr, id; + uint16_t addr, id; addr = net_buf_simple_pull_le16(buf); if (!BT_MESH_ADDR_IS_UNICAST(addr)) { @@ -1748,9 +1346,10 @@ static void mod_sub_get_vnd(struct bt_mesh_model *model, struct os_mbuf *buf) { struct os_mbuf *msg = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX); + struct mod_sub_list_ctx visit_ctx; struct bt_mesh_model *mod; struct bt_mesh_elem *elem; - u16_t company, addr, id; + uint16_t company, addr, id; addr = net_buf_simple_pull_le16(buf); if (!BT_MESH_ADDR_IS_UNICAST(addr)) { @@ -1789,8 +1388,10 @@ static void mod_sub_get_vnd(struct bt_mesh_model *model, net_buf_simple_add_le16(msg, company); net_buf_simple_add_le16(msg, id); + visit_ctx.msg = msg; + visit_ctx.elem_idx = mod->elem_idx; bt_mesh_model_tree_walk(bt_mesh_model_root(mod), mod_sub_list_visitor, - msg); + &visit_ctx); send_list: if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { @@ -1802,18 +1403,17 @@ done: } -#if MYNEWT_VAL(BLE_MESH_LABEL_COUNT) > 0 static void mod_sub_va_add(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { - u16_t elem_addr, sub_addr; + uint16_t elem_addr, sub_addr; struct bt_mesh_model *mod; struct bt_mesh_elem *elem; - u8_t *label_uuid; - u8_t *mod_id; - u16_t *entry; - u8_t status; + uint8_t *label_uuid; + uint8_t *mod_id; + uint16_t *entry; + uint8_t status; bool vnd; elem_addr = net_buf_simple_pull_le16(buf); @@ -1843,7 +1443,7 @@ static void mod_sub_va_add(struct bt_mesh_model *model, goto send_status; } - status = va_add(label_uuid, &sub_addr); + status = bt_mesh_va_add(label_uuid, &sub_addr); if (status != STATUS_SUCCESS) { goto send_status; } @@ -1851,6 +1451,7 @@ static void mod_sub_va_add(struct bt_mesh_model *model, if (bt_mesh_model_find_group(&mod, sub_addr)) { /* Tried to add existing subscription */ status = STATUS_SUCCESS; + bt_mesh_va_del(label_uuid, NULL); goto send_status; } @@ -1858,6 +1459,7 @@ static void mod_sub_va_add(struct bt_mesh_model *model, entry = bt_mesh_model_find_group(&mod, BT_MESH_ADDR_UNASSIGNED); if (!entry) { status = STATUS_INSUFF_RESOURCES; + bt_mesh_va_del(label_uuid, NULL); goto send_status; } @@ -1882,13 +1484,13 @@ static void mod_sub_va_del(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { - u16_t elem_addr, sub_addr; + uint16_t elem_addr, sub_addr; struct bt_mesh_model *mod; struct bt_mesh_elem *elem; - u8_t *label_uuid; - u8_t *mod_id; - u16_t *match; - u8_t status; + uint8_t *label_uuid; + uint8_t *mod_id; + uint16_t *match; + uint8_t status; bool vnd; elem_addr = net_buf_simple_pull_le16(buf); @@ -1919,7 +1521,7 @@ static void mod_sub_va_del(struct bt_mesh_model *model, goto send_status; } - status = va_del(label_uuid, &sub_addr); + status = bt_mesh_va_del(label_uuid, &sub_addr); if (sub_addr == BT_MESH_ADDR_UNASSIGNED) { goto send_status; } @@ -1950,12 +1552,12 @@ static void mod_sub_va_overwrite(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { - u16_t elem_addr, sub_addr = BT_MESH_ADDR_UNASSIGNED; + uint16_t elem_addr, sub_addr = BT_MESH_ADDR_UNASSIGNED; struct bt_mesh_model *mod; struct bt_mesh_elem *elem; - u8_t *label_uuid; - u8_t *mod_id; - u8_t status; + uint8_t *label_uuid; + uint8_t *mod_id; + uint8_t status; bool vnd; elem_addr = net_buf_simple_pull_le16(buf); @@ -1985,11 +1587,10 @@ static void mod_sub_va_overwrite(struct bt_mesh_model *model, } if (ARRAY_SIZE(mod->groups) > 0) { - bt_mesh_model_tree_walk(bt_mesh_model_root(mod), - mod_sub_clear_visitor, NULL); - - status = va_add(label_uuid, &sub_addr); + status = bt_mesh_va_add(label_uuid, &sub_addr); if (status == STATUS_SUCCESS) { + bt_mesh_model_tree_walk(bt_mesh_model_root(mod), + mod_sub_clear_visitor, NULL); mod->groups[0] = sub_addr; if (IS_ENABLED(CONFIG_BT_SETTINGS)) { @@ -2008,131 +1609,10 @@ send_status: send_mod_sub_status(model, ctx, status, elem_addr, sub_addr, mod_id, vnd); } -#else -static void mod_sub_va_add(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - struct bt_mesh_model *mod; - struct bt_mesh_elem *elem; - u16_t elem_addr; - u8_t *mod_id; - u8_t status; - bool vnd; - - elem_addr = net_buf_simple_pull_le16(buf); - if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) { - BT_WARN("Prohibited element address"); - return; - } - - net_buf_simple_pull(buf, 16); - - mod_id = buf->om_data; - - elem = bt_mesh_elem_find(elem_addr); - if (!elem) { - mod = NULL; - vnd = (buf->om_len == 4); - status = STATUS_INVALID_ADDRESS; - goto send_status; - } - - mod = get_model(elem, buf, &vnd); - if (!mod) { - status = STATUS_INVALID_MODEL; - goto send_status; - } - - status = STATUS_INSUFF_RESOURCES; - -send_status: - send_mod_sub_status(model, ctx, status, elem_addr, - BT_MESH_ADDR_UNASSIGNED, mod_id, vnd); -} - -static void mod_sub_va_del(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - struct bt_mesh_elem *elem; - u16_t elem_addr; - u8_t *mod_id; - u8_t status; - bool vnd; - - elem_addr = net_buf_simple_pull_le16(buf); - if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) { - BT_WARN("Prohibited element address"); - return; - } - - net_buf_simple_pull(buf, 16); - - mod_id = buf->om_data; - - elem = bt_mesh_elem_find(elem_addr); - if (!elem) { - vnd = (buf->om_len == 4); - status = STATUS_INVALID_ADDRESS; - goto send_status; - } - - if (!get_model(elem, buf, &vnd)) { - status = STATUS_INVALID_MODEL; - goto send_status; - } - - status = STATUS_INSUFF_RESOURCES; - -send_status: - send_mod_sub_status(model, ctx, status, elem_addr, - BT_MESH_ADDR_UNASSIGNED, mod_id, vnd); -} - -static void mod_sub_va_overwrite(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, - struct os_mbuf *buf) -{ - struct bt_mesh_elem *elem; - u16_t elem_addr; - u8_t *mod_id; - u8_t status; - bool vnd; - - elem_addr = net_buf_simple_pull_le16(buf); - if (!BT_MESH_ADDR_IS_UNICAST(elem_addr)) { - BT_WARN("Prohibited element address"); - return; - } - - net_buf_simple_pull(buf, 18); - - mod_id = buf->om_data; - - elem = bt_mesh_elem_find(elem_addr); - if (!elem) { - vnd = (buf->om_len == 4); - status = STATUS_INVALID_ADDRESS; - goto send_status; - } - - if (!get_model(elem, buf, &vnd)) { - status = STATUS_INVALID_MODEL; - goto send_status; - } - - status = STATUS_INSUFF_RESOURCES; - -send_status: - send_mod_sub_status(model, ctx, status, elem_addr, - BT_MESH_ADDR_UNASSIGNED, mod_id, vnd); -} -#endif /* MYNEWT_VAL(BLE_MESH_LABEL_COUNT) > 0 */ static void send_net_key_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, - u16_t idx, u8_t status) + uint16_t idx, uint8_t status) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NET_KEY_STATUS, 3); @@ -2152,9 +1632,8 @@ static void net_key_add(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { - struct bt_mesh_subnet *sub; - u16_t idx; - int err; + uint8_t status; + uint16_t idx; idx = net_buf_simple_pull_le16(buf); if (idx > 0xfff) { @@ -2164,72 +1643,16 @@ static void net_key_add(struct bt_mesh_model *model, BT_DBG("idx 0x%04x", idx); - sub = bt_mesh_subnet_get(idx); - if (!sub) { - int i; - - for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) { - if (bt_mesh.sub[i].net_idx == BT_MESH_KEY_UNUSED) { - sub = &bt_mesh.sub[i]; - break; - } - } - - if (!sub) { - send_net_key_status(model, ctx, idx, - STATUS_INSUFF_RESOURCES); - return; - } - } - - /* Check for already existing subnet */ - if (sub->net_idx == idx) { - u8_t status; - - if (memcmp(buf->om_data, sub->keys[0].net, 16)) { - status = STATUS_IDX_ALREADY_STORED; - } else { - status = STATUS_SUCCESS; - } - - send_net_key_status(model, ctx, idx, status); - return; - } - - err = bt_mesh_net_keys_create(&sub->keys[0], buf->om_data); - if (err) { - send_net_key_status(model, ctx, idx, STATUS_UNSPECIFIED); - return; - } - - sub->net_idx = idx; - - if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - BT_DBG("Storing NetKey persistently"); - bt_mesh_store_subnet(sub); - } - - /* Make sure we have valid beacon data to be sent */ - bt_mesh_net_beacon_update(sub); - - if ((MYNEWT_VAL(BLE_MESH_GATT_PROXY))) { - sub->node_id = BT_MESH_NODE_IDENTITY_STOPPED; - bt_mesh_proxy_beacon_send(sub); - bt_mesh_adv_update(); - } else { - sub->node_id = BT_MESH_NODE_IDENTITY_NOT_SUPPORTED; - } - - send_net_key_status(model, ctx, idx, STATUS_SUCCESS); + status = bt_mesh_subnet_add(idx, buf->om_data); + send_net_key_status(model, ctx, idx, status); } static void net_key_update(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { - struct bt_mesh_subnet *sub; - u16_t idx; - int err; + uint8_t status; + uint16_t idx; idx = net_buf_simple_pull_le16(buf); if (idx > 0xfff) { @@ -2237,80 +1660,16 @@ static void net_key_update(struct bt_mesh_model *model, return; } - BT_DBG("idx 0x%04x", idx); + status = bt_mesh_subnet_update(idx, buf->om_data); - sub = bt_mesh_subnet_get(idx); - if (!sub) { - send_net_key_status(model, ctx, idx, STATUS_INVALID_NETKEY); - return; - } - - /* The node shall successfully process a NetKey Update message on a - * valid NetKeyIndex when the NetKey value is different and the Key - * Refresh procedure has not been started, or when the NetKey value is - * the same in Phase 1. The NetKey Update message shall generate an - * error when the node is in Phase 2, or Phase 3. - */ - switch (sub->kr_phase) { - case BT_MESH_KR_NORMAL: - if (!memcmp(buf->om_data, sub->keys[0].net, 16)) { - return; - } - break; - case BT_MESH_KR_PHASE_1: - if (!memcmp(buf->om_data, sub->keys[1].net, 16)) { - send_net_key_status(model, ctx, idx, STATUS_SUCCESS); - return; - } - /* fall through */ - case BT_MESH_KR_PHASE_2: - case BT_MESH_KR_PHASE_3: - send_net_key_status(model, ctx, idx, STATUS_CANNOT_UPDATE); - return; - } - - err = bt_mesh_net_keys_create(&sub->keys[1], buf->om_data); - if (!err && ((MYNEWT_VAL(BLE_MESH_LOW_POWER)) || - (MYNEWT_VAL(BLE_MESH_FRIEND)))) { - err = friend_cred_update(sub); - } - - if (err) { - send_net_key_status(model, ctx, idx, STATUS_UNSPECIFIED); - return; - } - - sub->kr_phase = BT_MESH_KR_PHASE_1; - - if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - BT_DBG("Storing NetKey persistently"); - bt_mesh_store_subnet(sub); - } - - bt_mesh_net_beacon_update(sub); - - send_net_key_status(model, ctx, idx, STATUS_SUCCESS); -} - -static void hb_pub_disable(struct bt_mesh_cfg_srv *cfg) -{ - BT_DBG(""); - - cfg->hb_pub.dst = BT_MESH_ADDR_UNASSIGNED; - cfg->hb_pub.count = 0; - cfg->hb_pub.ttl = 0; - cfg->hb_pub.period = 0; - - k_delayed_work_cancel(&cfg->hb_pub.timer); + send_net_key_status(model, ctx, idx, status); } static void net_key_del(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { - struct bt_mesh_subnet *sub; - u16_t del_idx; - u8_t status; + uint16_t del_idx; del_idx = net_buf_simple_pull_le16(buf); if (del_idx > 0xfff) { @@ -2320,28 +1679,18 @@ static void net_key_del(struct bt_mesh_model *model, BT_DBG("idx 0x%04x", del_idx); - sub = bt_mesh_subnet_get(del_idx); - if (!sub) { - /* This could be a retry of a previous attempt that had its - * response lost, so pretend that it was a success. - */ - status = STATUS_SUCCESS; - goto send_status; - } - /* The key that the message was encrypted with cannot be removed. * The NetKey List must contain a minimum of one NetKey. */ if (ctx->net_idx == del_idx) { - status = STATUS_CANNOT_REMOVE; - goto send_status; + send_net_key_status(model, ctx, del_idx, + STATUS_CANNOT_REMOVE); + return; } - bt_mesh_subnet_del(sub, true); - status = STATUS_SUCCESS; + bt_mesh_subnet_del(del_idx); -send_status: - send_net_key_status(model, ctx, del_idx, status); + send_net_key_status(model, ctx, del_idx, STATUS_SUCCESS); } static void net_key_get(struct bt_mesh_model *model, @@ -2351,29 +1700,23 @@ static void net_key_get(struct bt_mesh_model *model, struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NET_KEY_LIST, IDX_LEN(CONFIG_BT_MESH_SUBNET_COUNT)); - u16_t prev, i; + uint16_t net_idx[CONFIG_BT_MESH_SUBNET_COUNT]; + ssize_t count; + int i; bt_mesh_model_msg_init(msg, OP_NET_KEY_LIST); - prev = BT_MESH_KEY_UNUSED; - for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) { - struct bt_mesh_subnet *sub = &bt_mesh.sub[i]; - - if (sub->net_idx == BT_MESH_KEY_UNUSED) { - continue; - } - - if (prev == BT_MESH_KEY_UNUSED) { - prev = sub->net_idx; - continue; - } - - key_idx_pack(msg, prev, sub->net_idx); - prev = BT_MESH_KEY_UNUSED; + count = bt_mesh_subnets_get(net_idx, ARRAY_SIZE(net_idx), 0); + if (count < 0 || count > ARRAY_SIZE(net_idx)) { + count = ARRAY_SIZE(net_idx); } - if (prev != BT_MESH_KEY_UNUSED) { - net_buf_simple_add_le16(msg, prev); + for (i = 0; i < count - 1; i += 2) { + key_idx_pack(msg, net_idx[i], net_idx[i + 1]); + } + + if (i < count) { + net_buf_simple_add_le16(msg, net_idx[i]); } if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { @@ -2383,14 +1726,32 @@ static void net_key_get(struct bt_mesh_model *model, os_mbuf_free_chain(msg); } +static void send_node_id_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + uint8_t status, + uint16_t net_idx, uint8_t node_id) +{ + struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NODE_IDENTITY_STATUS, 4); + + bt_mesh_model_msg_init(msg, OP_NODE_IDENTITY_STATUS); + net_buf_simple_add_u8(msg, status); + net_buf_simple_add_le16(msg, net_idx); + net_buf_simple_add_u8(msg, node_id); + + if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { + BT_ERR("Unable to send Node Identity Status"); + } + + os_mbuf_free_chain(msg); +} + static void node_identity_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { - struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NODE_IDENTITY_STATUS, 4); - struct bt_mesh_subnet *sub; - u8_t node_id; - u16_t idx; + enum bt_mesh_feat_state node_id; + uint8_t status; + uint16_t idx; BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, @@ -2399,39 +1760,20 @@ static void node_identity_get(struct bt_mesh_model *model, idx = net_buf_simple_pull_le16(buf); if (idx > 0xfff) { BT_ERR("Invalid NetKeyIndex 0x%04x", idx); - goto done; + return; } - bt_mesh_model_msg_init(msg, OP_NODE_IDENTITY_STATUS); + status = bt_mesh_subnet_node_id_get(idx, &node_id); - sub = bt_mesh_subnet_get(idx); - if (!sub) { - net_buf_simple_add_u8(msg, STATUS_INVALID_NETKEY); - node_id = 0x00; - } else { - net_buf_simple_add_u8(msg, STATUS_SUCCESS); - node_id = sub->node_id; - } - - net_buf_simple_add_le16(msg, idx); - net_buf_simple_add_u8(msg, node_id); - - if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { - BT_ERR("Unable to send Node Identity Status"); - } - -done: - os_mbuf_free_chain(msg); + send_node_id_status(model, ctx, status, idx, node_id); } static void node_identity_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { - struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NODE_IDENTITY_STATUS, 4); - struct bt_mesh_subnet *sub; - u8_t node_id; - u16_t idx; + uint8_t node_id, status; + uint16_t idx; BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, @@ -2440,51 +1782,36 @@ static void node_identity_set(struct bt_mesh_model *model, idx = net_buf_simple_pull_le16(buf); if (idx > 0xfff) { BT_WARN("Invalid NetKeyIndex 0x%04x", idx); - goto done; + return; } node_id = net_buf_simple_pull_u8(buf); if (node_id != 0x00 && node_id != 0x01) { BT_WARN("Invalid Node ID value 0x%02x", node_id); - goto done; + return; } - bt_mesh_model_msg_init(msg, OP_NODE_IDENTITY_STATUS); - - sub = bt_mesh_subnet_get(idx); - if (!sub) { - net_buf_simple_add_u8(msg, STATUS_INVALID_NETKEY); - net_buf_simple_add_le16(msg, idx); - net_buf_simple_add_u8(msg, node_id); - } else { - net_buf_simple_add_u8(msg, STATUS_SUCCESS); - net_buf_simple_add_le16(msg, idx); - - if (MYNEWT_VAL(BLE_MESH_GATT_PROXY)) { - if (node_id) { - bt_mesh_proxy_identity_start(sub); - } else { - bt_mesh_proxy_identity_stop(sub); - } - bt_mesh_adv_update(); - } - - net_buf_simple_add_u8(msg, sub->node_id); + status = bt_mesh_subnet_node_id_set(idx, node_id); + if (status == STATUS_INVALID_NETKEY) { + send_node_id_status(model, ctx, status, idx, + BT_MESH_NODE_IDENTITY_STOPPED); + return; } - if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { - BT_ERR("Unable to send Node Identity Status"); + if (status == STATUS_FEAT_NOT_SUPP) { + /* Should return success, even if feature isn't supported: */ + send_node_id_status(model, ctx, STATUS_SUCCESS, idx, + BT_MESH_NODE_IDENTITY_NOT_SUPPORTED); + return; } -done: - os_mbuf_free_chain(msg); - + send_node_id_status(model, ctx, status, idx, node_id); } static void create_mod_app_status(struct os_mbuf *msg, struct bt_mesh_model *mod, bool vnd, - u16_t elem_addr, u16_t app_idx, - u8_t status, u8_t *mod_id) + uint16_t elem_addr, uint16_t app_idx, + uint8_t status, uint8_t *mod_id) { bt_mesh_model_msg_init(msg, OP_MOD_APP_STATUS); @@ -2504,10 +1831,10 @@ static void mod_app_bind(struct bt_mesh_model *model, struct os_mbuf *buf) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_MOD_APP_STATUS, 9); - u16_t elem_addr, key_app_idx; + uint16_t elem_addr, key_app_idx; struct bt_mesh_model *mod; struct bt_mesh_elem *elem; - u8_t *mod_id, status; + uint8_t *mod_id, status; bool vnd; elem_addr = net_buf_simple_pull_le16(buf); @@ -2565,10 +1892,10 @@ static void mod_app_unbind(struct bt_mesh_model *model, struct os_mbuf *buf) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_MOD_APP_STATUS, 9); - u16_t elem_addr, key_app_idx; + uint16_t elem_addr, key_app_idx; struct bt_mesh_model *mod; struct bt_mesh_elem *elem; - u8_t *mod_id, status; + uint8_t *mod_id, status; bool vnd; elem_addr = net_buf_simple_pull_le16(buf); @@ -2626,8 +1953,8 @@ static void mod_app_get(struct bt_mesh_model *model, struct bt_mesh_model *mod; struct bt_mesh_elem *elem; - u8_t *mod_id, status; - u16_t elem_addr; + uint8_t *mod_id, status; + uint16_t elem_addr; bool vnd; elem_addr = net_buf_simple_pull_le16(buf); @@ -2694,6 +2021,8 @@ static void node_reset(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { + static struct bt_mesh_proxy_idle_cb proxy_idle = {.cb = bt_mesh_reset}; + struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_NODE_RESET_STATUS, 0); BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", @@ -2710,7 +2039,15 @@ static void node_reset(struct bt_mesh_model *model, BT_ERR("Unable to send Node Reset Status"); } - bt_mesh_reset(); + if (!IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) { + bt_mesh_reset(); + return; + } + + /* If the response goes to a proxy node, we'll wait for the sending to + * complete before moving on. + */ + bt_mesh_proxy_on_idle(&proxy_idle); os_mbuf_free_chain(msg); } @@ -2718,10 +2055,9 @@ static void send_friend_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_FRIEND_STATUS, 1); - struct bt_mesh_cfg_srv *cfg = model->user_data; bt_mesh_model_msg_init(msg, OP_FRIEND_STATUS); - net_buf_simple_add_u8(msg, cfg->frnd); + net_buf_simple_add_u8(msg, bt_mesh_friend_get()); if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { BT_ERR("Unable to send Friend Status"); @@ -2744,8 +2080,6 @@ static void friend_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { - struct bt_mesh_cfg_srv *cfg = model->user_data; - BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, bt_hex(buf->om_data, buf->om_len)); @@ -2755,34 +2089,8 @@ static void friend_set(struct bt_mesh_model *model, return; } - if (!cfg) { - BT_WARN("No Configuration Server context available"); - goto send_status; - } + (void)bt_mesh_friend_set(buf->om_data[0]); - BT_DBG("Friend 0x%02x -> 0x%02x", cfg->frnd, buf->om_data[0]); - - if (cfg->frnd == buf->om_data[0]) { - goto send_status; - } - - if (MYNEWT_VAL(BLE_MESH_FRIEND)) { - cfg->frnd = buf->om_data[0]; - - if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - bt_mesh_store_cfg(); - } - - if (cfg->frnd == BT_MESH_FRIEND_DISABLED) { - bt_mesh_friend_clear_net_idx(BT_MESH_KEY_ANY); - } - } - - if (cfg->hb_pub.feat & BT_MESH_FEAT_FRIEND) { - bt_mesh_heartbeat_send(); - } - -send_status: send_friend_status(model, ctx); } @@ -2792,8 +2100,8 @@ static void lpn_timeout_get(struct bt_mesh_model *model, { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_LPN_TIMEOUT_STATUS, 5); struct bt_mesh_friend *frnd; - u16_t lpn_addr; - s32_t timeout; + uint16_t lpn_addr; + int32_t timeout; lpn_addr = net_buf_simple_pull_le16(buf); @@ -2823,9 +2131,7 @@ static void lpn_timeout_get(struct bt_mesh_model *model, timeout = k_delayed_work_remaining_get(&frnd->timer) / 100; send_rsp: - net_buf_simple_add_u8(msg, timeout); - net_buf_simple_add_u8(msg, timeout >> 8); - net_buf_simple_add_u8(msg, timeout >> 16); + net_buf_simple_add_le24(msg, timeout); if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { BT_ERR("Unable to send LPN PollTimeout Status"); @@ -2837,7 +2143,7 @@ done: static void send_krp_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, - u16_t idx, u8_t phase, u8_t status) + uint16_t idx, uint8_t phase, uint8_t status) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_KRP_STATUS, 4); @@ -2857,8 +2163,8 @@ static void send_krp_status(struct bt_mesh_model *model, static void krp_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { - struct bt_mesh_subnet *sub; - u16_t idx; + uint8_t kr_phase, status; + uint16_t idx; idx = net_buf_simple_pull_le16(buf); if (idx > 0xfff) { @@ -2868,21 +2174,16 @@ static void krp_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, BT_DBG("idx 0x%04x", idx); - sub = bt_mesh_subnet_get(idx); - if (!sub) { - send_krp_status(model, ctx, idx, 0x00, STATUS_INVALID_NETKEY); - } else { - send_krp_status(model, ctx, idx, sub->kr_phase, - STATUS_SUCCESS); - } + status = bt_mesh_subnet_kr_phase_get(idx, &kr_phase); + + send_krp_status(model, ctx, idx, kr_phase, status); } static void krp_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { - struct bt_mesh_subnet *sub; - u8_t phase; - u16_t idx; + uint8_t phase, status; + uint16_t idx; idx = net_buf_simple_pull_le16(buf); phase = net_buf_simple_pull_u8(buf); @@ -2892,56 +2193,16 @@ static void krp_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, return; } - BT_DBG("idx 0x%04x transition 0x%02x", idx, phase); - - sub = bt_mesh_subnet_get(idx); - if (!sub) { - send_krp_status(model, ctx, idx, 0x00, STATUS_INVALID_NETKEY); + status = bt_mesh_subnet_kr_phase_set(idx, &phase); + if (status == STATUS_CANNOT_UPDATE) { + BT_ERR("Invalid kr phase transition 0x%02x", phase); return; } - BT_DBG("%u -> %u", sub->kr_phase, phase); - - if (phase < BT_MESH_KR_PHASE_2 || phase > BT_MESH_KR_PHASE_3 || - (sub->kr_phase == BT_MESH_KR_NORMAL && - phase == BT_MESH_KR_PHASE_2)) { - BT_WARN("Prohibited transition %u -> %u", sub->kr_phase, phase); - return; - } - - if (sub->kr_phase == BT_MESH_KR_PHASE_1 && - phase == BT_MESH_KR_PHASE_2) { - sub->kr_phase = BT_MESH_KR_PHASE_2; - sub->kr_flag = 1; - bt_mesh_net_beacon_update(sub); - } else if ((sub->kr_phase == BT_MESH_KR_PHASE_1 || - sub->kr_phase == BT_MESH_KR_PHASE_2) && - phase == BT_MESH_KR_PHASE_3) { - bt_mesh_net_revoke_keys(sub); - if ((MYNEWT_VAL(BLE_MESH_LOW_POWER)) || - (MYNEWT_VAL(BLE_MESH_FRIEND))) { - friend_cred_refresh(ctx->net_idx); - } - sub->kr_phase = BT_MESH_KR_NORMAL; - sub->kr_flag = 0; - bt_mesh_net_beacon_update(sub); - } - - send_krp_status(model, ctx, idx, sub->kr_phase, STATUS_SUCCESS); + send_krp_status(model, ctx, idx, phase, status); } -static u8_t hb_log(u16_t val) -{ - if (!val) { - return 0x00; - } else if (val == 0xffff) { - return 0xff; - } else { - return 32 - __builtin_clz(val); - } -} - -static u8_t hb_pub_count_log(u16_t val) +static uint8_t hb_pub_count_log(uint16_t val) { if (!val) { return 0x00; @@ -2954,32 +2215,20 @@ static u8_t hb_pub_count_log(u16_t val) } } -static u16_t hb_pwr2(u8_t val, u8_t sub) -{ - if (!val) { - return 0x0000; - } else if (val == 0xff || val == 0x11) { - return 0xffff; - } else { - return (1 << (val - sub)); - } -} - struct hb_pub_param { - u16_t dst; - u8_t count_log; - u8_t period_log; - u8_t ttl; - u16_t feat; - u16_t net_idx; + uint16_t dst; + uint8_t count_log; + uint8_t period_log; + uint8_t ttl; + uint16_t feat; + uint16_t net_idx; } __packed; static void hb_pub_send_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, u8_t status, - struct hb_pub_param *orig_msg) + struct bt_mesh_msg_ctx *ctx, uint8_t status, + const struct bt_mesh_hb_pub *pub) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEARTBEAT_PUB_STATUS, 10); - struct bt_mesh_cfg_srv *cfg = model->user_data; BT_DBG("src 0x%04x status 0x%02x", ctx->addr, status); @@ -2987,20 +2236,13 @@ static void hb_pub_send_status(struct bt_mesh_model *model, net_buf_simple_add_u8(msg, status); - if (orig_msg) { - memcpy(net_buf_simple_add(msg, sizeof(*orig_msg)), orig_msg, - sizeof(*orig_msg)); - goto send; - } + net_buf_simple_add_le16(msg, pub->dst); + net_buf_simple_add_u8(msg, hb_pub_count_log(pub->count)); + net_buf_simple_add_u8(msg, bt_mesh_hb_log(pub->period)); + net_buf_simple_add_u8(msg, pub->ttl); + net_buf_simple_add_le16(msg, pub->feat); + net_buf_simple_add_le16(msg, pub->net_idx); - net_buf_simple_add_le16(msg, cfg->hb_pub.dst); - net_buf_simple_add_u8(msg, hb_pub_count_log(cfg->hb_pub.count)); - net_buf_simple_add_u8(msg, cfg->hb_pub.period); - net_buf_simple_add_u8(msg, cfg->hb_pub.ttl); - net_buf_simple_add_le16(msg, cfg->hb_pub.feat); - net_buf_simple_add_le16(msg, cfg->hb_pub.net_idx); - -send: if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { BT_ERR("Unable to send Heartbeat Publication Status"); } @@ -3012,9 +2254,13 @@ static void heartbeat_pub_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { + struct bt_mesh_hb_pub pub; + BT_DBG("src 0x%04x", ctx->addr); - hb_pub_send_status(model, ctx, STATUS_SUCCESS, NULL); + bt_mesh_hb_pub_get(&pub); + + hb_pub_send_status(model, ctx, STATUS_SUCCESS, &pub); } static void heartbeat_pub_set(struct bt_mesh_model *model, @@ -3022,27 +2268,32 @@ static void heartbeat_pub_set(struct bt_mesh_model *model, struct os_mbuf *buf) { struct hb_pub_param *param = (void *)buf->om_data; - struct bt_mesh_cfg_srv *cfg = model->user_data; - u16_t dst, feat, idx; - u8_t status; + struct bt_mesh_hb_pub pub; + uint8_t status; BT_DBG("src 0x%04x", ctx->addr); - dst = sys_le16_to_cpu(param->dst); + pub.dst = sys_le16_to_cpu(param->dst); + pub.count = bt_mesh_hb_pwr2(param->count_log); + pub.period = bt_mesh_hb_pwr2(param->period_log); + pub.ttl = param->ttl; + pub.feat = sys_le16_to_cpu(param->feat); + pub.net_idx = sys_le16_to_cpu(param->net_idx); + /* All other address types but virtual are valid */ - if (BT_MESH_ADDR_IS_VIRTUAL(dst)) { + if (BT_MESH_ADDR_IS_VIRTUAL(pub.dst)) { status = STATUS_INVALID_ADDRESS; - goto failed; + goto rsp; } if (param->count_log > 0x11 && param->count_log != 0xff) { status = STATUS_CANNOT_SET; - goto failed; + goto rsp; } if (param->period_log > 0x10) { status = STATUS_CANNOT_SET; - goto failed; + goto rsp; } if (param->ttl > BT_MESH_TTL_MAX && param->ttl != BT_MESH_TTL_DEFAULT) { @@ -3050,84 +2301,32 @@ static void heartbeat_pub_set(struct bt_mesh_model *model, return; } - feat = sys_le16_to_cpu(param->feat); - - idx = sys_le16_to_cpu(param->net_idx); - if (idx > 0xfff) { - BT_ERR("Invalid NetKeyIndex 0x%04x", idx); + if (pub.net_idx > 0xfff) { + BT_ERR("Invalid NetKeyIndex 0x%04x", pub.net_idx); return; } - if (!bt_mesh_subnet_get(idx)) { - status = STATUS_INVALID_NETKEY; - goto failed; - } - - cfg->hb_pub.dst = dst; - cfg->hb_pub.period = param->period_log; - cfg->hb_pub.feat = feat & BT_MESH_FEAT_SUPPORTED; - cfg->hb_pub.net_idx = idx; - - if (dst == BT_MESH_ADDR_UNASSIGNED) { - hb_pub_disable(cfg); - } else { - /* 2^(n-1) */ - cfg->hb_pub.count = hb_pwr2(param->count_log, 1); - cfg->hb_pub.ttl = param->ttl; - - BT_DBG("period %u ms", hb_pwr2(param->period_log, 1) * 1000); - - /* The first Heartbeat message shall be published as soon - * as possible after the Heartbeat Publication Period state - * has been configured for periodic publishing. - */ - if (param->period_log && param->count_log) { - k_work_submit(&cfg->hb_pub.timer.work); - } else { - k_delayed_work_cancel(&cfg->hb_pub.timer); - } - } - - if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - bt_mesh_store_hb_pub(); - } - - hb_pub_send_status(model, ctx, STATUS_SUCCESS, NULL); - - return; - -failed: - hb_pub_send_status(model, ctx, status, param); + status = bt_mesh_hb_pub_set(&pub); +rsp: + hb_pub_send_status(model, ctx, status, &pub); } static void hb_sub_send_status(struct bt_mesh_model *model, - struct bt_mesh_msg_ctx *ctx, u8_t status) + struct bt_mesh_msg_ctx *ctx, + const struct bt_mesh_hb_sub *sub) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEARTBEAT_SUB_STATUS, 9); - struct bt_mesh_cfg_srv *cfg = model->user_data; - u16_t period; - s64_t uptime; - - BT_DBG("src 0x%04x status 0x%02x", ctx->addr, status); - - uptime = k_uptime_get(); - if (uptime > cfg->hb_sub.expiry) { - period = 0; - } else { - period = (cfg->hb_sub.expiry - uptime) / 1000; - } + BT_DBG("src 0x%04x ", ctx->addr); bt_mesh_model_msg_init(msg, OP_HEARTBEAT_SUB_STATUS); - net_buf_simple_add_u8(msg, status); - - net_buf_simple_add_le16(msg, cfg->hb_sub.src); - net_buf_simple_add_le16(msg, cfg->hb_sub.dst); - - net_buf_simple_add_u8(msg, hb_log(period)); - net_buf_simple_add_u8(msg, hb_log(cfg->hb_sub.count)); - net_buf_simple_add_u8(msg, cfg->hb_sub.min_hops); - net_buf_simple_add_u8(msg, cfg->hb_sub.max_hops); + net_buf_simple_add_u8(msg, STATUS_SUCCESS); + net_buf_simple_add_le16(msg, sub->src); + net_buf_simple_add_le16(msg, sub->dst); + net_buf_simple_add_u8(msg, bt_mesh_hb_log(sub->remaining)); + net_buf_simple_add_u8(msg, bt_mesh_hb_log(sub->count)); + net_buf_simple_add_u8(msg, sub->min_hops); + net_buf_simple_add_u8(msg, sub->max_hops); if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { @@ -3141,92 +2340,58 @@ static void heartbeat_sub_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { + struct bt_mesh_hb_sub sub; + BT_DBG("src 0x%04x", ctx->addr); - hb_sub_send_status(model, ctx, STATUS_SUCCESS); + bt_mesh_hb_sub_get(&sub); + + hb_sub_send_status(model, ctx, &sub); } static void heartbeat_sub_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { - struct bt_mesh_cfg_srv *cfg = model->user_data; - u16_t sub_src, sub_dst; - u8_t sub_period; - s32_t period_ms; + uint8_t period_log, status; + struct bt_mesh_hb_sub sub; + uint16_t sub_src, sub_dst; + uint32_t period; BT_DBG("src 0x%04x", ctx->addr); sub_src = net_buf_simple_pull_le16(buf); sub_dst = net_buf_simple_pull_le16(buf); - sub_period = net_buf_simple_pull_u8(buf); + period_log = net_buf_simple_pull_u8(buf); BT_DBG("sub_src 0x%04x sub_dst 0x%04x period 0x%02x", - sub_src, sub_dst, sub_period); + sub_src, sub_dst, period_log); - if (sub_src != BT_MESH_ADDR_UNASSIGNED && - !BT_MESH_ADDR_IS_UNICAST(sub_src)) { - BT_WARN("Prohibited source address"); + if (period_log > 0x11) { + BT_WARN("Prohibited subscription period 0x%02x", period_log); return; } - if (BT_MESH_ADDR_IS_VIRTUAL(sub_dst) || BT_MESH_ADDR_IS_RFU(sub_dst) || - (BT_MESH_ADDR_IS_UNICAST(sub_dst) && - sub_dst != bt_mesh_primary_addr())) { - BT_WARN("Prohibited destination address"); - return; - } + period = bt_mesh_hb_pwr2(period_log); - if (sub_period > 0x11) { - BT_WARN("Prohibited subscription period 0x%02x", sub_period); - return; - } - - if (sub_src == BT_MESH_ADDR_UNASSIGNED || - sub_dst == BT_MESH_ADDR_UNASSIGNED || - sub_period == 0x00) { - /* Only an explicit address change to unassigned should - * trigger clearing of the values according to - * MESH/NODE/CFG/HBS/BV-02-C. + status = bt_mesh_hb_sub_set(sub_src, sub_dst, period); + if (status != STATUS_SUCCESS) { + /* All errors are caused by invalid packets, which should be + * ignored. */ - if (sub_src == BT_MESH_ADDR_UNASSIGNED || - sub_dst == BT_MESH_ADDR_UNASSIGNED) { - cfg->hb_sub.src = BT_MESH_ADDR_UNASSIGNED; - cfg->hb_sub.dst = BT_MESH_ADDR_UNASSIGNED; - cfg->hb_sub.min_hops = BT_MESH_TTL_MAX; - cfg->hb_sub.max_hops = 0; - cfg->hb_sub.count = 0; - } - - period_ms = 0; - } else { - cfg->hb_sub.src = sub_src; - cfg->hb_sub.dst = sub_dst; - cfg->hb_sub.min_hops = BT_MESH_TTL_MAX; - cfg->hb_sub.max_hops = 0; - cfg->hb_sub.count = 0; - period_ms = hb_pwr2(sub_period, 1) * 1000; + return; } - /* Let the transport layer know it needs to handle this address */ - bt_mesh_set_hb_sub_dst(cfg->hb_sub.dst); - - BT_DBG("period_ms %u", (unsigned) period_ms); - - if (period_ms) { - cfg->hb_sub.expiry = k_uptime_get() + period_ms; - } else { - cfg->hb_sub.expiry = 0; - } - - hb_sub_send_status(model, ctx, STATUS_SUCCESS); + bt_mesh_hb_sub_get(&sub); /* MESH/NODE/CFG/HBS/BV-01-C expects the MinHops to be 0x7f after * disabling subscription, but 0x00 for subsequent Get requests. */ - if (!period_ms) { - cfg->hb_sub.min_hops = 0; + if (!period_log) { + sub.min_hops = BT_MESH_TTL_MAX; } + + hb_sub_send_status(model, ctx, &sub); } const struct bt_mesh_model_op bt_mesh_cfg_srv_op[] = { @@ -3280,58 +2445,9 @@ const struct bt_mesh_model_op bt_mesh_cfg_srv_op[] = { BT_MESH_MODEL_OP_END, }; -static void hb_publish(struct ble_npl_event *work) -{ - struct bt_mesh_cfg_srv *cfg = ble_npl_event_get_arg(work); - struct bt_mesh_subnet *sub; - u16_t period_ms; - - BT_DBG("hb_pub.count: %u", cfg->hb_pub.count); - - sub = bt_mesh_subnet_get(cfg->hb_pub.net_idx); - if (!sub) { - BT_ERR("No matching subnet for idx 0x%02x", - cfg->hb_pub.net_idx); - cfg->hb_pub.dst = BT_MESH_ADDR_UNASSIGNED; - return; - } - - if (cfg->hb_pub.count == 0) { - return; - } - - period_ms = hb_pwr2(cfg->hb_pub.period, 1) * 1000; - if (period_ms && cfg->hb_pub.count > 1) { - k_delayed_work_submit(&cfg->hb_pub.timer, period_ms); - } - - bt_mesh_heartbeat_send(); - - if (cfg->hb_pub.count != 0xffff) { - cfg->hb_pub.count--; - } -} - -static bool conf_is_valid(struct bt_mesh_cfg_srv *cfg) -{ - if (cfg->relay > 0x02) { - return false; - } - - if (cfg->beacon > 0x01) { - return false; - } - - if (cfg->default_ttl > BT_MESH_TTL_MAX) { - return false; - } - - return true; -} - static int cfg_srv_init(struct bt_mesh_model *model) { - struct bt_mesh_cfg_srv *cfg = model->user_data; + bt_mesh_app_key_cb_list[0] = app_key_evt; BT_DBG(""); @@ -3340,43 +2456,12 @@ static int cfg_srv_init(struct bt_mesh_model *model) return -EINVAL; } - if (!cfg) { - BT_ERR("No Configuration Server context provided"); - return -EINVAL; - } - - if (!conf_is_valid(cfg)) { - BT_ERR("Invalid values in configuration"); - return -EINVAL; - } - /* * Configuration Model security is device-key based and only the local * device-key is allowed to access this model. */ model->keys[0] = BT_MESH_KEY_DEV_LOCAL; - if (!(MYNEWT_VAL(BLE_MESH_RELAY))) { - cfg->relay = BT_MESH_RELAY_NOT_SUPPORTED; - } - - if (!(MYNEWT_VAL(BLE_MESH_FRIEND))) { - cfg->frnd = BT_MESH_FRIEND_NOT_SUPPORTED; - } - - if (!(MYNEWT_VAL(BLE_MESH_GATT_PROXY))) { - cfg->gatt_proxy = BT_MESH_GATT_PROXY_NOT_SUPPORTED; - } - - k_delayed_work_init(&cfg->hb_pub.timer, hb_publish); - k_delayed_work_add_arg(&cfg->hb_pub.timer, cfg); - cfg->hb_pub.net_idx = BT_MESH_KEY_UNUSED; - cfg->hb_sub.expiry = 0; - - cfg->model = model; - - conf = cfg; - return 0; } @@ -3401,8 +2486,6 @@ static void mod_reset(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, if (clear_count) { bt_mesh_store_mod_sub(mod); } - - bt_mesh_model_data_store(mod, vnd, NULL, 0); } if (mod->cb && mod->cb->reset) { @@ -3412,208 +2495,5 @@ static void mod_reset(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, void bt_mesh_cfg_reset(void) { - struct bt_mesh_cfg_srv *cfg = conf; - int i; - - BT_DBG(""); - - if (!cfg) { - return; - } - - bt_mesh_set_hb_sub_dst(BT_MESH_ADDR_UNASSIGNED); - - cfg->hb_sub.src = BT_MESH_ADDR_UNASSIGNED; - cfg->hb_sub.dst = BT_MESH_ADDR_UNASSIGNED; - cfg->hb_sub.expiry = 0; - - /* Delete all net keys, which also takes care of all app keys which - * are associated with each net key. - */ - for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) { - struct bt_mesh_subnet *sub = &bt_mesh.sub[i]; - - if (sub->net_idx != BT_MESH_KEY_UNUSED) { - bt_mesh_subnet_del(sub, true); - } - } - bt_mesh_model_foreach(mod_reset, NULL); - - memset(labels, 0, sizeof(labels)); -} - -void bt_mesh_heartbeat(u16_t src, u16_t dst, u8_t hops, u16_t feat) -{ - struct bt_mesh_cfg_srv *cfg = conf; - - if (!cfg) { - BT_WARN("No configuaration server context available"); - return; - } - - if (src != cfg->hb_sub.src || dst != cfg->hb_sub.dst) { - BT_WARN("No subscription for received heartbeat"); - return; - } - - if (k_uptime_get() > cfg->hb_sub.expiry) { - BT_WARN("Heartbeat subscription period expired"); - return; - } - - cfg->hb_sub.min_hops = min(cfg->hb_sub.min_hops, hops); - cfg->hb_sub.max_hops = max(cfg->hb_sub.max_hops, hops); - - if (cfg->hb_sub.count < 0xffff) { - cfg->hb_sub.count++; - } - - BT_DBG("src 0x%04x dst 0x%04x hops %u min %u max %u count %u", src, - dst, hops, cfg->hb_sub.min_hops, cfg->hb_sub.max_hops, - cfg->hb_sub.count); - - if (cfg->hb_sub.func) { - cfg->hb_sub.func(hops, feat); - } -} - -u8_t bt_mesh_net_transmit_get(void) -{ - if (conf) { - return conf->net_transmit; - } - - return 0; -} - -u8_t bt_mesh_relay_get(void) -{ - if (conf) { - return conf->relay; - } - - return BT_MESH_RELAY_NOT_SUPPORTED; -} - -u8_t bt_mesh_friend_get(void) -{ - BT_DBG("conf %p conf->frnd 0x%02x", conf, conf->frnd); - - if (conf) { - return conf->frnd; - } - - return BT_MESH_FRIEND_NOT_SUPPORTED; -} - -u8_t bt_mesh_relay_retransmit_get(void) -{ - if (conf) { - return conf->relay_retransmit; - } - - return 0; -} - -u8_t bt_mesh_beacon_get(void) -{ - if (conf) { - return conf->beacon; - } - - return BT_MESH_BEACON_DISABLED; -} - -u8_t bt_mesh_gatt_proxy_get(void) -{ - if (conf) { - return conf->gatt_proxy; - } - - return BT_MESH_GATT_PROXY_NOT_SUPPORTED; -} - -u8_t bt_mesh_default_ttl_get(void) -{ - if (conf) { - return conf->default_ttl; - } - - return DEFAULT_TTL; -} - -u8_t *bt_mesh_label_uuid_get(u16_t addr) -{ - int i; - - BT_DBG("addr 0x%04x", addr); - - for (i = 0; i < ARRAY_SIZE(labels); i++) { - if (labels[i].addr == addr) { - BT_DBG("Found Label UUID for 0x%04x: %s", addr, - bt_hex(labels[i].uuid, 16)); - return labels[i].uuid; - } - } - - BT_WARN("No matching Label UUID for 0x%04x", addr); - - return NULL; -} - -struct bt_mesh_hb_pub *bt_mesh_hb_pub_get(void) -{ - if (!conf) { - return NULL; - } - - return &conf->hb_pub; -} - -void bt_mesh_hb_pub_disable(void) -{ - if (conf) { - hb_pub_disable(conf); - } -} - -struct bt_mesh_cfg_srv *bt_mesh_cfg_get(void) -{ - return conf; -} - -void bt_mesh_subnet_del(struct bt_mesh_subnet *sub, bool store) -{ - int i; - - BT_DBG("NetIdx 0x%03x store %u", sub->net_idx, store); - - if (conf && conf->hb_pub.net_idx == sub->net_idx) { - hb_pub_disable(conf); - - if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) { - bt_mesh_store_hb_pub(); - } - } - - /* Delete any app keys bound to this NetKey index */ - for (i = 0; i < ARRAY_SIZE(bt_mesh.app_keys); i++) { - struct bt_mesh_app_key *key = &bt_mesh.app_keys[i]; - - if (key->net_idx == sub->net_idx) { - bt_mesh_app_key_del(key, store); - } - } - - if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) { - bt_mesh_friend_clear_net_idx(sub->net_idx); - } - - if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) { - bt_mesh_clear_subnet(sub); - } - - memset(sub, 0, sizeof(*sub)); - sub->net_idx = BT_MESH_KEY_UNUSED; } diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/crypto.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/crypto.c index b6a0ba21..3111a6ef 100644 --- a/src/libs/mynewt-nimble/nimble/host/mesh/src/crypto.c +++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/crypto.c @@ -24,8 +24,8 @@ #define NET_MIC_LEN(pdu) (((pdu)[1] & 0x80) ? 8 : 4) #define APP_MIC_LEN(aszmic) ((aszmic) ? 8 : 4) -int bt_mesh_aes_cmac(const u8_t key[16], struct bt_mesh_sg *sg, - size_t sg_len, u8_t mac[16]) +int bt_mesh_aes_cmac(const uint8_t key[16], struct bt_mesh_sg *sg, + size_t sg_len, uint8_t mac[16]) { struct tc_aes_key_sched_struct sched; struct tc_cmac_struct state; @@ -48,8 +48,8 @@ int bt_mesh_aes_cmac(const u8_t key[16], struct bt_mesh_sg *sg, return 0; } -int bt_mesh_k1(const u8_t *ikm, size_t ikm_len, const u8_t salt[16], - const char *info, u8_t okm[16]) +int bt_mesh_k1(const uint8_t *ikm, size_t ikm_len, const uint8_t salt[16], + const char *info, uint8_t okm[16]) { int err; @@ -61,14 +61,14 @@ int bt_mesh_k1(const u8_t *ikm, size_t ikm_len, const u8_t salt[16], return bt_mesh_aes_cmac_one(okm, info, strlen(info), okm); } -int bt_mesh_k2(const u8_t n[16], const u8_t *p, size_t p_len, - u8_t net_id[1], u8_t enc_key[16], u8_t priv_key[16]) +int bt_mesh_k2(const uint8_t n[16], const uint8_t *p, size_t p_len, + uint8_t net_id[1], uint8_t enc_key[16], uint8_t priv_key[16]) { struct bt_mesh_sg sg[3]; - u8_t salt[16]; - u8_t out[16]; - u8_t t[16]; - u8_t pad; + uint8_t salt[16]; + uint8_t out[16]; + uint8_t t[16]; + uint8_t pad; int err; BT_DBG("n %s", bt_hex(n, 16)); @@ -126,11 +126,11 @@ int bt_mesh_k2(const u8_t n[16], const u8_t *p, size_t p_len, return 0; } -int bt_mesh_k3(const u8_t n[16], u8_t out[8]) +int bt_mesh_k3(const uint8_t n[16], uint8_t out[8]) { - u8_t id64[] = { 'i', 'd', '6', '4', 0x01 }; - u8_t tmp[16]; - u8_t t[16]; + uint8_t id64[] = { 'i', 'd', '6', '4', 0x01 }; + uint8_t tmp[16]; + uint8_t t[16]; int err; err = bt_mesh_s1("smk3", tmp); @@ -153,11 +153,11 @@ int bt_mesh_k3(const u8_t n[16], u8_t out[8]) return 0; } -int bt_mesh_k4(const u8_t n[16], u8_t out[1]) +int bt_mesh_k4(const uint8_t n[16], uint8_t out[1]) { - u8_t id6[] = { 'i', 'd', '6', 0x01 }; - u8_t tmp[16]; - u8_t t[16]; + uint8_t id6[] = { 'i', 'd', '6', 0x01 }; + uint8_t tmp[16]; + uint8_t t[16]; int err; err = bt_mesh_s1("smk4", tmp); @@ -180,10 +180,10 @@ int bt_mesh_k4(const u8_t n[16], u8_t out[1]) return 0; } -int bt_mesh_id128(const u8_t n[16], const char *s, u8_t out[16]) +int bt_mesh_id128(const uint8_t n[16], const char *s, uint8_t out[16]) { const char *id128 = "id128\x01"; - u8_t salt[16]; + uint8_t salt[16]; int err; err = bt_mesh_s1(s, salt); @@ -194,326 +194,8 @@ int bt_mesh_id128(const u8_t n[16], const char *s, u8_t out[16]) return bt_mesh_k1(n, 16, salt, id128, out); } -static int bt_mesh_ccm_decrypt(const u8_t key[16], u8_t nonce[13], - const u8_t *enc_msg, size_t msg_len, - const u8_t *aad, size_t aad_len, - u8_t *out_msg, size_t mic_size) -{ - u8_t msg[16], pmsg[16], cmic[16], cmsg[16], Xn[16], mic[16]; - u16_t last_blk, blk_cnt; - size_t i, j; - int err; - - if (msg_len < 1 || aad_len >= 0xff00) { - return -EINVAL; - } - - /* C_mic = e(AppKey, 0x01 || nonce || 0x0000) */ - pmsg[0] = 0x01; - memcpy(pmsg + 1, nonce, 13); - sys_put_be16(0x0000, pmsg + 14); - - err = bt_encrypt_be(key, pmsg, cmic); - if (err) { - return err; - } - - /* X_0 = e(AppKey, 0x09 || nonce || length) */ - if (mic_size == sizeof(u64_t)) { - pmsg[0] = 0x19 | (aad_len ? 0x40 : 0x00); - } else { - pmsg[0] = 0x09 | (aad_len ? 0x40 : 0x00); - } - - memcpy(pmsg + 1, nonce, 13); - sys_put_be16(msg_len, pmsg + 14); - - err = bt_encrypt_be(key, pmsg, Xn); - if (err) { - return err; - } - - /* If AAD is being used to authenticate, include it here */ - if (aad_len) { - sys_put_be16(aad_len, pmsg); - - for (i = 0; i < sizeof(u16_t); i++) { - pmsg[i] = Xn[i] ^ pmsg[i]; - } - - j = 0; - aad_len += sizeof(u16_t); - while (aad_len > 16) { - do { - pmsg[i] = Xn[i] ^ aad[j]; - i++, j++; - } while (i < 16); - - aad_len -= 16; - i = 0; - - err = bt_encrypt_be(key, pmsg, Xn); - if (err) { - return err; - } - } - - for (; i < aad_len; i++, j++) { - pmsg[i] = Xn[i] ^ aad[j]; - } - - for (i = aad_len; i < 16; i++) { - pmsg[i] = Xn[i]; - } - - err = bt_encrypt_be(key, pmsg, Xn); - if (err) { - return err; - } - } - - last_blk = msg_len % 16; - blk_cnt = (msg_len + 15) / 16; - if (!last_blk) { - last_blk = 16; - } - - for (j = 0; j < blk_cnt; j++) { - if (j + 1 == blk_cnt) { - /* C_1 = e(AppKey, 0x01 || nonce || 0x0001) */ - pmsg[0] = 0x01; - memcpy(pmsg + 1, nonce, 13); - sys_put_be16(j + 1, pmsg + 14); - - err = bt_encrypt_be(key, pmsg, cmsg); - if (err) { - return err; - } - - /* Encrypted = Payload[0-15] ^ C_1 */ - for (i = 0; i < last_blk; i++) { - msg[i] = enc_msg[(j * 16) + i] ^ cmsg[i]; - } - - memcpy(out_msg + (j * 16), msg, last_blk); - - /* X_1 = e(AppKey, X_0 ^ Payload[0-15]) */ - for (i = 0; i < last_blk; i++) { - pmsg[i] = Xn[i] ^ msg[i]; - } - - for (i = last_blk; i < 16; i++) { - pmsg[i] = Xn[i] ^ 0x00; - } - - err = bt_encrypt_be(key, pmsg, Xn); - if (err) { - return err; - } - - /* MIC = C_mic ^ X_1 */ - for (i = 0; i < sizeof(mic); i++) { - mic[i] = cmic[i] ^ Xn[i]; - } - } else { - /* C_1 = e(AppKey, 0x01 || nonce || 0x0001) */ - pmsg[0] = 0x01; - memcpy(pmsg + 1, nonce, 13); - sys_put_be16(j + 1, pmsg + 14); - - err = bt_encrypt_be(key, pmsg, cmsg); - if (err) { - return err; - } - - /* Encrypted = Payload[0-15] ^ C_1 */ - for (i = 0; i < 16; i++) { - msg[i] = enc_msg[(j * 16) + i] ^ cmsg[i]; - } - - memcpy(out_msg + (j * 16), msg, 16); - - /* X_1 = e(AppKey, X_0 ^ Payload[0-15]) */ - for (i = 0; i < 16; i++) { - pmsg[i] = Xn[i] ^ msg[i]; - } - - err = bt_encrypt_be(key, pmsg, Xn); - if (err) { - return err; - } - } - } - - if (memcmp(mic, enc_msg + msg_len, mic_size)) { - return -EBADMSG; - } - - return 0; -} - -static int bt_mesh_ccm_encrypt(const u8_t key[16], u8_t nonce[13], - const u8_t *msg, size_t msg_len, - const u8_t *aad, size_t aad_len, - u8_t *out_msg, size_t mic_size) -{ - u8_t pmsg[16], cmic[16], cmsg[16], mic[16], Xn[16]; - u16_t blk_cnt, last_blk; - size_t i, j; - int err; - - BT_DBG("key %s", bt_hex(key, 16)); - BT_DBG("nonce %s", bt_hex(nonce, 13)); - BT_DBG("msg (len %zu) %s", msg_len, bt_hex(msg, msg_len)); - BT_DBG("aad_len %zu mic_size %zu", aad_len, mic_size); - - /* Unsupported AAD size */ - if (aad_len >= 0xff00) { - return -EINVAL; - } - - /* C_mic = e(AppKey, 0x01 || nonce || 0x0000) */ - pmsg[0] = 0x01; - memcpy(pmsg + 1, nonce, 13); - sys_put_be16(0x0000, pmsg + 14); - - err = bt_encrypt_be(key, pmsg, cmic); - if (err) { - return err; - } - - /* X_0 = e(AppKey, 0x09 || nonce || length) */ - if (mic_size == sizeof(u64_t)) { - pmsg[0] = 0x19 | (aad_len ? 0x40 : 0x00); - } else { - pmsg[0] = 0x09 | (aad_len ? 0x40 : 0x00); - } - - memcpy(pmsg + 1, nonce, 13); - sys_put_be16(msg_len, pmsg + 14); - - err = bt_encrypt_be(key, pmsg, Xn); - if (err) { - return err; - } - - /* If AAD is being used to authenticate, include it here */ - if (aad_len) { - sys_put_be16(aad_len, pmsg); - - for (i = 0; i < sizeof(u16_t); i++) { - pmsg[i] = Xn[i] ^ pmsg[i]; - } - - j = 0; - aad_len += sizeof(u16_t); - while (aad_len > 16) { - do { - pmsg[i] = Xn[i] ^ aad[j]; - i++, j++; - } while (i < 16); - - aad_len -= 16; - i = 0; - - err = bt_encrypt_be(key, pmsg, Xn); - if (err) { - return err; - } - } - - for (; i < aad_len; i++, j++) { - pmsg[i] = Xn[i] ^ aad[j]; - } - - for (i = aad_len; i < 16; i++) { - pmsg[i] = Xn[i]; - } - - err = bt_encrypt_be(key, pmsg, Xn); - if (err) { - return err; - } - } - - last_blk = msg_len % 16; - blk_cnt = (msg_len + 15) / 16; - if (!last_blk) { - last_blk = 16; - } - - for (j = 0; j < blk_cnt; j++) { - if (j + 1 == blk_cnt) { - /* X_1 = e(AppKey, X_0 ^ Payload[0-15]) */ - for (i = 0; i < last_blk; i++) { - pmsg[i] = Xn[i] ^ msg[(j * 16) + i]; - } - for (i = last_blk; i < 16; i++) { - pmsg[i] = Xn[i] ^ 0x00; - } - - err = bt_encrypt_be(key, pmsg, Xn); - if (err) { - return err; - } - - /* MIC = C_mic ^ X_1 */ - for (i = 0; i < sizeof(mic); i++) { - mic[i] = cmic[i] ^ Xn[i]; - } - - /* C_1 = e(AppKey, 0x01 || nonce || 0x0001) */ - pmsg[0] = 0x01; - memcpy(pmsg + 1, nonce, 13); - sys_put_be16(j + 1, pmsg + 14); - - err = bt_encrypt_be(key, pmsg, cmsg); - if (err) { - return err; - } - - /* Encrypted = Payload[0-15] ^ C_1 */ - for (i = 0; i < last_blk; i++) { - out_msg[(j * 16) + i] = - msg[(j * 16) + i] ^ cmsg[i]; - } - } else { - /* X_1 = e(AppKey, X_0 ^ Payload[0-15]) */ - for (i = 0; i < 16; i++) { - pmsg[i] = Xn[i] ^ msg[(j * 16) + i]; - } - - err = bt_encrypt_be(key, pmsg, Xn); - if (err) { - return err; - } - - /* C_1 = e(AppKey, 0x01 || nonce || 0x0001) */ - pmsg[0] = 0x01; - memcpy(pmsg + 1, nonce, 13); - sys_put_be16(j + 1, pmsg + 14); - - err = bt_encrypt_be(key, pmsg, cmsg); - if (err) { - return err; - } - - /* Encrypted = Payload[0-15] ^ C_N */ - for (i = 0; i < 16; i++) { - out_msg[(j * 16) + i] = - msg[(j * 16) + i] ^ cmsg[i]; - } - - } - } - - memcpy(out_msg + msg_len, mic, mic_size); - - return 0; -} - -static void create_proxy_nonce(u8_t nonce[13], const u8_t *pdu, - u32_t iv_index) +static void create_proxy_nonce(uint8_t nonce[13], const uint8_t *pdu, + uint32_t iv_index) { /* Nonce Type */ nonce[0] = 0x03; @@ -538,8 +220,8 @@ static void create_proxy_nonce(u8_t nonce[13], const u8_t *pdu, sys_put_be32(iv_index, &nonce[9]); } -static void create_net_nonce(u8_t nonce[13], const u8_t *pdu, - u32_t iv_index) +static void create_net_nonce(uint8_t nonce[13], const uint8_t *pdu, + uint32_t iv_index) { /* Nonce Type */ nonce[0] = 0x00; @@ -564,11 +246,11 @@ static void create_net_nonce(u8_t nonce[13], const u8_t *pdu, sys_put_be32(iv_index, &nonce[9]); } -int bt_mesh_net_obfuscate(u8_t *pdu, u32_t iv_index, - const u8_t privacy_key[16]) +int bt_mesh_net_obfuscate(uint8_t *pdu, uint32_t iv_index, + const uint8_t privacy_key[16]) { - u8_t priv_rand[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, }; - u8_t tmp[16]; + uint8_t priv_rand[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, }; + uint8_t tmp[16]; int err, i; BT_DBG("IVIndex %u, PrivacyKey %s", (unsigned) iv_index, @@ -591,11 +273,11 @@ int bt_mesh_net_obfuscate(u8_t *pdu, u32_t iv_index, return 0; } -int bt_mesh_net_encrypt(const u8_t key[16], struct os_mbuf *buf, - u32_t iv_index, bool proxy) +int bt_mesh_net_encrypt(const uint8_t key[16], struct os_mbuf *buf, + uint32_t iv_index, bool proxy) { - u8_t mic_len = NET_MIC_LEN(buf->om_data); - u8_t nonce[13]; + uint8_t mic_len = NET_MIC_LEN(buf->om_data); + uint8_t nonce[13]; int err; BT_DBG("IVIndex %u EncKey %s mic_len %u", (unsigned) iv_index, @@ -610,7 +292,7 @@ int bt_mesh_net_encrypt(const u8_t key[16], struct os_mbuf *buf, BT_DBG("Nonce %s", bt_hex(nonce, 13)); - err = bt_mesh_ccm_encrypt(key, nonce, &buf->om_data[7], buf->om_len - 7, + err = bt_ccm_encrypt(key, nonce, &buf->om_data[7], buf->om_len - 7, NULL, 0, &buf->om_data[7], mic_len); if (!err) { net_buf_simple_add(buf, mic_len); @@ -619,11 +301,11 @@ int bt_mesh_net_encrypt(const u8_t key[16], struct os_mbuf *buf, return err; } -int bt_mesh_net_decrypt(const u8_t key[16], struct os_mbuf *buf, - u32_t iv_index, bool proxy) +int bt_mesh_net_decrypt(const uint8_t key[16], struct os_mbuf *buf, + uint32_t iv_index, bool proxy) { - u8_t mic_len = NET_MIC_LEN(buf->om_data); - u8_t nonce[13]; + uint8_t mic_len = NET_MIC_LEN(buf->om_data); + uint8_t nonce[13]; BT_DBG("PDU (%u bytes) %s", buf->om_len, bt_hex(buf->om_data, buf->om_len)); BT_DBG("iv_index %u, key %s mic_len %u", (unsigned) iv_index, @@ -639,118 +321,74 @@ int bt_mesh_net_decrypt(const u8_t key[16], struct os_mbuf *buf, buf->om_len -= mic_len; - return bt_mesh_ccm_decrypt(key, nonce, &buf->om_data[7], buf->om_len - 7, + return bt_ccm_decrypt(key, nonce, &buf->om_data[7], buf->om_len - 7, NULL, 0, &buf->om_data[7], mic_len); } -static void create_app_nonce(u8_t nonce[13], bool dev_key, u8_t aszmic, - u16_t src, u16_t dst, u32_t seq_num, - u32_t iv_index) +static void create_app_nonce(uint8_t nonce[13], + const struct bt_mesh_app_crypto_ctx *ctx) { - if (dev_key) { + if (ctx->dev_key) { nonce[0] = 0x02; } else { nonce[0] = 0x01; } - sys_put_be32((seq_num | ((u32_t)aszmic << 31)), &nonce[1]); + sys_put_be32((ctx->seq_num | ((uint32_t)ctx->aszmic << 31)), &nonce[1]); - sys_put_be16(src, &nonce[5]); - sys_put_be16(dst, &nonce[7]); + sys_put_be16(ctx->src, &nonce[5]); + sys_put_be16(ctx->dst, &nonce[7]); - sys_put_be32(iv_index, &nonce[9]); + sys_put_be32(ctx->iv_index, &nonce[9]); } -static int mesh_app_encrypt(const u8_t key[16], bool dev_key, u8_t aszmic, - struct os_mbuf *buf, const u8_t *ad, - u16_t src, u16_t dst, u32_t seq_num, u32_t iv_index) +int bt_mesh_app_encrypt(const uint8_t key[16], + const struct bt_mesh_app_crypto_ctx *ctx, + struct os_mbuf *buf) { - u8_t nonce[13]; + int err; + uint8_t nonce[13]; BT_DBG("AppKey %s", bt_hex(key, 16)); - BT_DBG("dev_key %u src 0x%04x dst 0x%04x", dev_key, src, dst); - BT_DBG("seq_num 0x%08x iv_index 0x%08x", (unsigned) seq_num, - (unsigned) iv_index); + BT_DBG("dev_key %u src 0x%04x dst 0x%04x", ctx->dev_key, ctx->src, + ctx->dst); + BT_DBG("seq_num 0x%08x iv_index 0x%08x", ctx->seq_num, ctx->iv_index); BT_DBG("Clear: %s", bt_hex(buf->om_data, buf->om_len)); - create_app_nonce(nonce, dev_key, aszmic, src, dst, seq_num, iv_index); + create_app_nonce(nonce, ctx); BT_DBG("Nonce %s", bt_hex(nonce, 13)); - return bt_mesh_ccm_encrypt(key, nonce, buf->om_data, buf->om_len, ad, - ad ? 16 : 0, buf->om_data, - APP_MIC_LEN(aszmic)); -} + err = bt_ccm_encrypt(key, nonce, buf->om_data, buf->om_len, ctx->ad, + ctx->ad ? 16 : 0, buf->om_data, + APP_MIC_LEN(ctx->aszmic)); -int bt_mesh_app_encrypt_in_place(const u8_t key[16], bool dev_key, u8_t aszmic, - struct os_mbuf *buf, const u8_t *ad, u16_t src, - u16_t dst, u32_t seq_num, u32_t iv_index) -{ - int err; - - err = mesh_app_encrypt(key, dev_key, aszmic, buf, ad, src, dst, - seq_num, iv_index); if (!err) { + net_buf_simple_add(buf, APP_MIC_LEN(ctx->aszmic)); BT_DBG("Encr: %s", bt_hex(buf->om_data, buf->om_len)); } return err; } -int bt_mesh_app_encrypt(const u8_t key[16], bool dev_key, u8_t aszmic, - struct os_mbuf *buf, const u8_t *ad, - u16_t src, u16_t dst, u32_t seq_num, u32_t iv_index) +int bt_mesh_app_decrypt(const uint8_t key[16], + const struct bt_mesh_app_crypto_ctx *ctx, + struct os_mbuf *buf, struct os_mbuf *out) { + uint8_t nonce[13]; int err; - err = mesh_app_encrypt(key, dev_key, aszmic, buf, ad, src, dst, - seq_num, iv_index); - - if (!err) { - net_buf_simple_add(buf, APP_MIC_LEN(aszmic)); - BT_DBG("Encr: %s", bt_hex(buf->om_data, buf->om_len)); - } - - return err; -} - -static int mesh_app_decrypt(const u8_t key[16], bool dev_key, u8_t aszmic, - struct os_mbuf *buf, struct os_mbuf *out, - const u8_t *ad, u16_t src, u16_t dst, - u32_t seq_num, u32_t iv_index) -{ - u8_t nonce[13]; - BT_DBG("EncData (len %u) %s", buf->om_len, bt_hex(buf->om_data, buf->om_len)); - create_app_nonce(nonce, dev_key, aszmic, src, dst, seq_num, iv_index); + create_app_nonce(nonce, ctx); BT_DBG("AppKey %s", bt_hex(key, 16)); BT_DBG("Nonce %s", bt_hex(nonce, 13)); - return bt_mesh_ccm_decrypt(key, nonce, buf->om_data, buf->om_len, ad, - ad ? 16 : 0, out->om_data, - APP_MIC_LEN(aszmic)); -} - -int bt_mesh_app_decrypt_in_place(const u8_t key[16], bool dev_key, u8_t aszmic, - struct os_mbuf *buf, const u8_t *ad, u16_t src, - u16_t dst, u32_t seq_num, u32_t iv_index) -{ - return mesh_app_decrypt(key, dev_key, aszmic, buf, buf, - ad, src, dst, seq_num, iv_index); -} - -int bt_mesh_app_decrypt(const u8_t key[16], bool dev_key, u8_t aszmic, - struct os_mbuf *buf, struct os_mbuf *out, - const u8_t *ad, u16_t src, u16_t dst, u32_t seq_num, - u32_t iv_index) -{ - int err; - - err = mesh_app_decrypt(key, dev_key, aszmic, buf, out, - ad, src, dst, seq_num, iv_index); + err = bt_ccm_decrypt(key, nonce, buf->om_data, buf->om_len, ctx->ad, + ctx->ad ? 16 : 0, out->om_data, + APP_MIC_LEN(ctx->aszmic)); if (!err) { net_buf_simple_add(out, buf->om_len); } @@ -759,7 +397,7 @@ int bt_mesh_app_decrypt(const u8_t key[16], bool dev_key, u8_t aszmic, } /* reversed, 8-bit, poly=0x07 */ -static const u8_t crc_table[256] = { +static const uint8_t crc_table[256] = { 0x00, 0x91, 0xe3, 0x72, 0x07, 0x96, 0xe4, 0x75, 0x0e, 0x9f, 0xed, 0x7c, 0x09, 0x98, 0xea, 0x7b, 0x1c, 0x8d, 0xff, 0x6e, 0x1b, 0x8a, 0xf8, 0x69, @@ -801,9 +439,9 @@ static const u8_t crc_table[256] = { 0xba, 0x2b, 0x59, 0xc8, 0xbd, 0x2c, 0x5e, 0xcf }; -u8_t bt_mesh_fcs_calc(const u8_t *data, u8_t data_len) +uint8_t bt_mesh_fcs_calc(const uint8_t *data, uint8_t data_len) { - u8_t fcs = 0xff; + uint8_t fcs = 0xff; while (data_len--) { fcs = crc_table[fcs ^ *data++]; @@ -814,11 +452,11 @@ u8_t bt_mesh_fcs_calc(const u8_t *data, u8_t data_len) return 0xff - fcs; } -bool bt_mesh_fcs_check(struct os_mbuf *buf, u8_t received_fcs) +bool bt_mesh_fcs_check(struct os_mbuf *buf, uint8_t received_fcs) { - const u8_t *data = buf->om_data; - u16_t data_len = buf->om_len; - u8_t fcs = 0xff; + const uint8_t *data = buf->om_data; + uint16_t data_len = buf->om_len; + uint8_t fcs = 0xff; while (data_len--) { fcs = crc_table[fcs ^ *data++]; @@ -827,10 +465,10 @@ bool bt_mesh_fcs_check(struct os_mbuf *buf, u8_t received_fcs) return crc_table[fcs ^ received_fcs] == 0xcf; } -int bt_mesh_virtual_addr(const u8_t virtual_label[16], u16_t *addr) +int bt_mesh_virtual_addr(const uint8_t virtual_label[16], uint16_t *addr) { - u8_t salt[16]; - u8_t tmp[16]; + uint8_t salt[16]; + uint8_t tmp[16]; int err; err = bt_mesh_s1("vtad", salt); @@ -848,21 +486,21 @@ int bt_mesh_virtual_addr(const u8_t virtual_label[16], u16_t *addr) return 0; } -int bt_mesh_prov_conf_salt(const u8_t conf_inputs[145], u8_t salt[16]) +int bt_mesh_prov_conf_salt(const uint8_t conf_inputs[145], uint8_t salt[16]) { - const u8_t conf_salt_key[16] = { 0 }; + const uint8_t conf_salt_key[16] = { 0 }; return bt_mesh_aes_cmac_one(conf_salt_key, conf_inputs, 145, salt); } -int bt_mesh_prov_conf_key(const u8_t dhkey[32], const u8_t conf_salt[16], - u8_t conf_key[16]) +int bt_mesh_prov_conf_key(const uint8_t dhkey[32], const uint8_t conf_salt[16], + uint8_t conf_key[16]) { return bt_mesh_k1(dhkey, 32, conf_salt, "prck", conf_key); } -int bt_mesh_prov_conf(const u8_t conf_key[16], const u8_t rand[16], - const u8_t auth[16], u8_t conf[16]) +int bt_mesh_prov_conf(const uint8_t conf_key[16], const uint8_t rand[16], + const uint8_t auth[16], uint8_t conf[16]) { struct bt_mesh_sg sg[] = { { rand, 16 }, { auth, 16 } }; @@ -873,23 +511,23 @@ int bt_mesh_prov_conf(const u8_t conf_key[16], const u8_t rand[16], return bt_mesh_aes_cmac(conf_key, sg, ARRAY_SIZE(sg), conf); } -int bt_mesh_prov_decrypt(const u8_t key[16], u8_t nonce[13], - const u8_t data[25 + 8], u8_t out[25]) +int bt_mesh_prov_decrypt(const uint8_t key[16], uint8_t nonce[13], + const uint8_t data[25 + 8], uint8_t out[25]) { - return bt_mesh_ccm_decrypt(key, nonce, data, 25, NULL, 0, out, 8); + return bt_ccm_decrypt(key, nonce, data, 25, NULL, 0, out, 8); } -int bt_mesh_prov_encrypt(const u8_t key[16], u8_t nonce[13], - const u8_t data[25], u8_t out[25 + 8]) +int bt_mesh_prov_encrypt(const uint8_t key[16], uint8_t nonce[13], + const uint8_t data[25], uint8_t out[25 + 8]) { - return bt_mesh_ccm_encrypt(key, nonce, data, 25, NULL, 0, out, 8); + return bt_ccm_encrypt(key, nonce, data, 25, NULL, 0, out, 8); } -int bt_mesh_beacon_auth(const u8_t beacon_key[16], u8_t flags, - const u8_t net_id[8], u32_t iv_index, - u8_t auth[8]) +int bt_mesh_beacon_auth(const uint8_t beacon_key[16], uint8_t flags, + const uint8_t net_id[8], uint32_t iv_index, + uint8_t auth[8]) { - u8_t msg[13], tmp[16]; + uint8_t msg[13], tmp[16]; int err; BT_DBG("BeaconKey %s", bt_hex(beacon_key, 16)); diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/crypto.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/crypto.h index 745cf324..637d13e7 100644 --- a/src/libs/mynewt-nimble/nimble/host/mesh/src/crypto.h +++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/crypto.h @@ -15,81 +15,81 @@ struct bt_mesh_sg { size_t len; }; -int bt_mesh_aes_cmac(const u8_t key[16], struct bt_mesh_sg *sg, - size_t sg_len, u8_t mac[16]); +int bt_mesh_aes_cmac(const uint8_t key[16], struct bt_mesh_sg *sg, + size_t sg_len, uint8_t mac[16]); -static inline int bt_mesh_aes_cmac_one(const u8_t key[16], const void *m, - size_t len, u8_t mac[16]) +static inline int bt_mesh_aes_cmac_one(const uint8_t key[16], const void *m, + size_t len, uint8_t mac[16]) { struct bt_mesh_sg sg = { m, len }; return bt_mesh_aes_cmac(key, &sg, 1, mac); } -static inline bool bt_mesh_s1(const char *m, u8_t salt[16]) +static inline bool bt_mesh_s1(const char *m, uint8_t salt[16]) { - const u8_t zero[16] = { 0 }; + const uint8_t zero[16] = { 0 }; return bt_mesh_aes_cmac_one(zero, m, strlen(m), salt); } -int bt_mesh_k1(const u8_t *ikm, size_t ikm_len, const u8_t salt[16], - const char *info, u8_t okm[16]); +int bt_mesh_k1(const uint8_t *ikm, size_t ikm_len, const uint8_t salt[16], + const char *info, uint8_t okm[16]); #define bt_mesh_k1_str(ikm, ikm_len, salt_str, info, okm) \ ({ \ - const u8_t salt[16] = salt_str; \ + const uint8_t salt[16] = salt_str; \ bt_mesh_k1(ikm, ikm_len, salt, info, okm); \ }) -int bt_mesh_k2(const u8_t n[16], const u8_t *p, size_t p_len, - u8_t net_id[1], u8_t enc_key[16], u8_t priv_key[16]); +int bt_mesh_k2(const uint8_t n[16], const uint8_t *p, size_t p_len, + uint8_t net_id[1], uint8_t enc_key[16], uint8_t priv_key[16]); -int bt_mesh_k3(const u8_t n[16], u8_t out[8]); +int bt_mesh_k3(const uint8_t n[16], uint8_t out[8]); -int bt_mesh_k4(const u8_t n[16], u8_t out[1]); +int bt_mesh_k4(const uint8_t n[16], uint8_t out[1]); -int bt_mesh_id128(const u8_t n[16], const char *s, u8_t out[16]); +int bt_mesh_id128(const uint8_t n[16], const char *s, uint8_t out[16]); -static inline int bt_mesh_id_resolving_key(const u8_t net_key[16], - u8_t resolving_key[16]) +static inline int bt_mesh_id_resolving_key(const uint8_t net_key[16], + uint8_t resolving_key[16]) { return bt_mesh_k1_str(net_key, 16, "smbt", "smbi", resolving_key); } -static inline int bt_mesh_identity_key(const u8_t net_key[16], - u8_t identity_key[16]) +static inline int bt_mesh_identity_key(const uint8_t net_key[16], + uint8_t identity_key[16]) { return bt_mesh_id128(net_key, "nkik", identity_key); } -static inline int bt_mesh_beacon_key(const u8_t net_key[16], - u8_t beacon_key[16]) +static inline int bt_mesh_beacon_key(const uint8_t net_key[16], + uint8_t beacon_key[16]) { return bt_mesh_id128(net_key, "nkbk", beacon_key); } -int bt_mesh_beacon_auth(const u8_t beacon_key[16], u8_t flags, - const u8_t net_id[16], u32_t iv_index, - u8_t auth[8]); +int bt_mesh_beacon_auth(const uint8_t beacon_key[16], uint8_t flags, + const uint8_t net_id[16], uint32_t iv_index, + uint8_t auth[8]); -static inline int bt_mesh_app_id(const u8_t app_key[16], u8_t app_id[1]) +static inline int bt_mesh_app_id(const uint8_t app_key[16], uint8_t app_id[1]) { return bt_mesh_k4(app_key, app_id); } -static inline int bt_mesh_session_key(const u8_t dhkey[32], - const u8_t prov_salt[16], - u8_t session_key[16]) +static inline int bt_mesh_session_key(const uint8_t dhkey[32], + const uint8_t prov_salt[16], + uint8_t session_key[16]) { return bt_mesh_k1(dhkey, 32, prov_salt, "prsk", session_key); } -static inline int bt_mesh_prov_nonce(const u8_t dhkey[32], - const u8_t prov_salt[16], - u8_t nonce[13]) +static inline int bt_mesh_prov_nonce(const uint8_t dhkey[32], + const uint8_t prov_salt[16], + uint8_t nonce[13]) { - u8_t tmp[16]; + uint8_t tmp[16]; int err; err = bt_mesh_k1(dhkey, 32, prov_salt, "prsn", tmp); @@ -100,19 +100,19 @@ static inline int bt_mesh_prov_nonce(const u8_t dhkey[32], return err; } -static inline int bt_mesh_dev_key(const u8_t dhkey[32], - const u8_t prov_salt[16], - u8_t dev_key[16]) +static inline int bt_mesh_dev_key(const uint8_t dhkey[32], + const uint8_t prov_salt[16], + uint8_t dev_key[16]) { return bt_mesh_k1(dhkey, 32, prov_salt, "prdk", dev_key); } -static inline int bt_mesh_prov_salt(const u8_t conf_salt[16], - const u8_t prov_rand[16], - const u8_t dev_rand[16], - u8_t prov_salt[16]) +static inline int bt_mesh_prov_salt(const uint8_t conf_salt[16], + const uint8_t prov_rand[16], + const uint8_t dev_rand[16], + uint8_t prov_salt[16]) { - const u8_t prov_salt_key[16] = { 0 }; + const uint8_t prov_salt_key[16] = { 0 }; struct bt_mesh_sg sg[] = { { conf_salt, 16 }, { prov_rand, 16 }, @@ -122,49 +122,50 @@ static inline int bt_mesh_prov_salt(const u8_t conf_salt[16], return bt_mesh_aes_cmac(prov_salt_key, sg, ARRAY_SIZE(sg), prov_salt); } -int bt_mesh_net_obfuscate(u8_t *pdu, u32_t iv_index, - const u8_t privacy_key[16]); +int bt_mesh_net_obfuscate(uint8_t *pdu, uint32_t iv_index, + const uint8_t privacy_key[16]); -int bt_mesh_net_encrypt(const u8_t key[16], struct os_mbuf *buf, - u32_t iv_index, bool proxy); +int bt_mesh_net_encrypt(const uint8_t key[16], struct os_mbuf *buf, + uint32_t iv_index, bool proxy); -int bt_mesh_net_decrypt(const u8_t key[16], struct os_mbuf *buf, - u32_t iv_index, bool proxy); +int bt_mesh_net_decrypt(const uint8_t key[16], struct os_mbuf *buf, + uint32_t iv_index, bool proxy); -int bt_mesh_app_encrypt_in_place(const u8_t key[16], bool dev_key, u8_t aszmic, - struct os_mbuf*buf, const u8_t *ad, u16_t src, - u16_t dst, u32_t seq_num, u32_t iv_index); +struct bt_mesh_app_crypto_ctx { + bool dev_key; + uint8_t aszmic; + uint16_t src; + uint16_t dst; + uint32_t seq_num; + uint32_t iv_index; + const uint8_t *ad; +}; -int bt_mesh_app_encrypt(const u8_t key[16], bool dev_key, u8_t aszmic, - struct os_mbuf*buf, const u8_t *ad, - u16_t src, u16_t dst, u32_t seq_num, u32_t iv_index); +int bt_mesh_app_encrypt(const uint8_t key[16], + const struct bt_mesh_app_crypto_ctx *ctx, + struct os_mbuf *buf); -int bt_mesh_app_decrypt_in_place(const u8_t key[16], bool dev_key, u8_t aszmic, - struct os_mbuf *buf, const u8_t *ad, u16_t src, - u16_t dst, u32_t seq_num, u32_t iv_index); +int bt_mesh_app_decrypt(const uint8_t key[16], + const struct bt_mesh_app_crypto_ctx *ctx, + struct os_mbuf *buf, struct os_mbuf *out); -int bt_mesh_app_decrypt(const u8_t key[16], bool dev_key, u8_t aszmic, - struct os_mbuf*buf, struct os_mbuf*out, - const u8_t *ad, u16_t src, u16_t dst, u32_t seq_num, - u32_t iv_index); +uint8_t bt_mesh_fcs_calc(const uint8_t *data, uint8_t data_len); -u8_t bt_mesh_fcs_calc(const u8_t *data, u8_t data_len); +bool bt_mesh_fcs_check(struct os_mbuf *buf, uint8_t received_fcs); -bool bt_mesh_fcs_check(struct os_mbuf *buf, u8_t received_fcs); +int bt_mesh_virtual_addr(const uint8_t virtual_label[16], uint16_t *addr); -int bt_mesh_virtual_addr(const u8_t virtual_label[16], u16_t *addr); +int bt_mesh_prov_conf_salt(const uint8_t conf_inputs[145], uint8_t salt[16]); -int bt_mesh_prov_conf_salt(const u8_t conf_inputs[145], u8_t salt[16]); +int bt_mesh_prov_conf_key(const uint8_t dhkey[32], const uint8_t conf_salt[16], + uint8_t conf_key[16]); -int bt_mesh_prov_conf_key(const u8_t dhkey[32], const u8_t conf_salt[16], - u8_t conf_key[16]); +int bt_mesh_prov_conf(const uint8_t conf_key[16], const uint8_t rand[16], + const uint8_t auth[16], uint8_t conf[16]); -int bt_mesh_prov_conf(const u8_t conf_key[16], const u8_t rand[16], - const u8_t auth[16], u8_t conf[16]); +int bt_mesh_prov_decrypt(const uint8_t key[16], uint8_t nonce[13], + const uint8_t data[25 + 8], uint8_t out[25]); -int bt_mesh_prov_decrypt(const u8_t key[16], u8_t nonce[13], - const u8_t data[25 + 8], u8_t out[25]); - -int bt_mesh_prov_encrypt(const u8_t key[16], u8_t nonce[13], - const u8_t data[25], u8_t out[25 + 8]); +int bt_mesh_prov_encrypt(const uint8_t key[16], uint8_t nonce[13], + const uint8_t data[25], uint8_t out[25 + 8]); #endif diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/foundation.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/foundation.h index ee615ae9..012afbbb 100644 --- a/src/libs/mynewt-nimble/nimble/host/mesh/src/foundation.h +++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/foundation.h @@ -115,57 +115,23 @@ #define STATUS_UNSPECIFIED 0x10 #define STATUS_INVALID_BINDING 0x11 -enum { - BT_MESH_VA_CHANGED, /* Label information changed */ -}; - -struct label { - u16_t ref; - u16_t addr; - u8_t uuid[16]; - atomic_t flags[1]; -}; - void bt_mesh_cfg_reset(void); -void bt_mesh_heartbeat(u16_t src, u16_t dst, u8_t hops, u16_t feat); - -void bt_mesh_attention(struct bt_mesh_model *model, u8_t time); - -struct label *get_label(u16_t index); - -u8_t *bt_mesh_label_uuid_get(u16_t addr); - -struct bt_mesh_hb_pub *bt_mesh_hb_pub_get(void); -void bt_mesh_hb_pub_disable(void); -struct bt_mesh_cfg_srv *bt_mesh_cfg_get(void); - -u8_t bt_mesh_net_transmit_get(void); -u8_t bt_mesh_relay_get(void); -u8_t bt_mesh_friend_get(void); -u8_t bt_mesh_relay_retransmit_get(void); -u8_t bt_mesh_beacon_get(void); -u8_t bt_mesh_gatt_proxy_get(void); -u8_t bt_mesh_default_ttl_get(void); - -void bt_mesh_subnet_del(struct bt_mesh_subnet *sub, bool store); - -struct bt_mesh_app_key *bt_mesh_app_key_alloc(u16_t app_idx); -void bt_mesh_app_key_del(struct bt_mesh_app_key *key, bool store); +void bt_mesh_attention(struct bt_mesh_model *model, uint8_t time); static inline void key_idx_pack(struct os_mbuf *buf, - u16_t idx1, u16_t idx2) + uint16_t idx1, uint16_t idx2) { net_buf_simple_add_le16(buf, idx1 | ((idx2 & 0x00f) << 12)); net_buf_simple_add_u8(buf, idx2 >> 4); } static inline void key_idx_unpack(struct os_mbuf *buf, - u16_t *idx1, u16_t *idx2) + uint16_t *idx1, uint16_t *idx2) { *idx1 = sys_get_le16(&buf->om_data[0]) & 0xfff; *idx2 = sys_get_le16(&buf->om_data[1]) >> 4; - net_buf_simple_pull(buf, 3); + net_buf_simple_pull_mem(buf, 3); } #endif diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/friend.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/friend.c index 9056a865..9a83c87f 100644 --- a/src/libs/mynewt-nimble/nimble/host/mesh/src/friend.c +++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/friend.c @@ -7,7 +7,7 @@ */ #include "syscfg/syscfg.h" -#define MESH_LOG_MODULE BLE_MESH_CRYPTO_LOG +#define MESH_LOG_MODULE BLE_MESH_FRIEND_LOG #if MYNEWT_VAL(BLE_MESH_FRIEND) @@ -21,10 +21,12 @@ #include "crypto.h" #include "adv.h" #include "net.h" +#include "app_keys.h" #include "transport.h" #include "access.h" #include "foundation.h" #include "friend.h" +#include "subnet.h" /* We reserve one extra buffer for each friendship, since we need to be able * to resend the last sent PDU, which sits separately outside of the queue. @@ -48,20 +50,20 @@ static struct os_mempool friend_buf_mempool; #define FRIEND_XMIT BT_MESH_TRANSMIT(0, 20) struct friend_pdu_info { - u16_t src; - u16_t dst; + uint16_t src; + uint16_t dst; - u8_t seq[3]; + uint8_t seq[3]; - u8_t ttl:7, + uint8_t ttl:7, ctl:1; - u32_t iv_index; + uint32_t iv_index; }; static struct friend_adv { struct bt_mesh_adv adv; - u16_t app_idx; + uint16_t app_idx; } adv_pool[FRIEND_BUF_COUNT]; static struct bt_mesh_adv *adv_alloc(int id) @@ -70,7 +72,7 @@ static struct bt_mesh_adv *adv_alloc(int id) return &adv_pool[id].adv; } -static bool is_lpn_unicast(struct bt_mesh_friend *frnd, u16_t addr) +static bool is_lpn_unicast(struct bt_mesh_friend *frnd, uint16_t addr) { if (frnd->lpn == BT_MESH_ADDR_UNASSIGNED) { return false; @@ -79,7 +81,7 @@ static bool is_lpn_unicast(struct bt_mesh_friend *frnd, u16_t addr) return (addr >= frnd->lpn && addr < (frnd->lpn + frnd->num_elem)); } -struct bt_mesh_friend *bt_mesh_friend_find(u16_t net_idx, u16_t lpn_addr, +struct bt_mesh_friend *bt_mesh_friend_find(uint16_t net_idx, uint16_t lpn_addr, bool valid, bool established) { int i; @@ -89,7 +91,7 @@ struct bt_mesh_friend *bt_mesh_friend_find(u16_t net_idx, u16_t lpn_addr, for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) { struct bt_mesh_friend *frnd = &bt_mesh.frnd[i]; - if (valid && !frnd->valid) { + if (valid && !frnd->subnet) { continue; } @@ -97,7 +99,8 @@ struct bt_mesh_friend *bt_mesh_friend_find(u16_t net_idx, u16_t lpn_addr, continue; } - if (net_idx != BT_MESH_KEY_ANY && frnd->net_idx != net_idx) { + if (net_idx != BT_MESH_KEY_ANY && + (!frnd->subnet || frnd->subnet->net_idx != net_idx)) { continue; } @@ -109,11 +112,18 @@ struct bt_mesh_friend *bt_mesh_friend_find(u16_t net_idx, u16_t lpn_addr, return NULL; } +static int friend_cred_create(struct bt_mesh_friend *frnd, uint8_t idx) +{ + return bt_mesh_friend_cred_create(&frnd->cred[idx], frnd->lpn, + bt_mesh_primary_addr(), + frnd->lpn_counter, frnd->counter, + frnd->subnet->keys[idx].net); +} + static void purge_buffers(struct net_buf_slist_t *list) { - struct os_mbuf *buf; - while (!net_buf_slist_is_empty(list)) { + struct os_mbuf *buf; buf = (void *)net_buf_slist_get(list); BT_MESH_ADV(buf)->flags &= ~NET_BUF_FRAGS; net_buf_unref(buf); @@ -125,10 +135,10 @@ static void purge_buffers(struct net_buf_slist_t *list) * like the PTS, where the receiver might not have sufficiently compensated * for internal latencies required to start scanning. */ -static s32_t recv_delay(struct bt_mesh_friend *frnd) +static int32_t recv_delay(struct bt_mesh_friend *frnd) { #if CONFIG_BT_MESH_FRIEND_RECV_WIN > 50 - return (s32_t)frnd->recv_delay + (CONFIG_BT_MESH_FRIEND_RECV_WIN / 5); + return (int32_t)frnd->recv_delay + (CONFIG_BT_MESH_FRIEND_RECV_WIN / 5); #else return frnd->recv_delay; #endif @@ -142,7 +152,7 @@ static void friend_clear(struct bt_mesh_friend *frnd) k_delayed_work_cancel(&frnd->timer); - friend_cred_del(frnd->net_idx, frnd->lpn); + memset(frnd->cred, 0, sizeof(frnd->cred)); if (frnd->last) { /* Cancel the sending if necessary */ @@ -163,7 +173,8 @@ static void friend_clear(struct bt_mesh_friend *frnd) seg->seg_count = 0U; } - frnd->valid = 0; + frnd->counter++; + frnd->subnet = NULL; frnd->established = 0; frnd->pending_buf = 0; frnd->fsn = 0; @@ -172,26 +183,26 @@ static void friend_clear(struct bt_mesh_friend *frnd) memset(frnd->sub_list, 0, sizeof(frnd->sub_list)); } -void bt_mesh_friend_clear_net_idx(u16_t net_idx) +void bt_mesh_friends_clear(void) { int i; - BT_DBG("net_idx 0x%04x", net_idx); + BT_DBG(""); for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) { struct bt_mesh_friend *frnd = &bt_mesh.frnd[i]; - if (frnd->net_idx == BT_MESH_KEY_UNUSED) { + if (!frnd->subnet) { continue; } - if (net_idx == BT_MESH_KEY_ANY || frnd->net_idx == net_idx) { - friend_clear(frnd); - } + friend_clear(frnd); } } -void bt_mesh_friend_sec_update(u16_t net_idx) +static void enqueue_update(struct bt_mesh_friend *frnd, uint8_t md); + +void bt_mesh_friend_sec_update(uint16_t net_idx) { int i; @@ -200,12 +211,13 @@ void bt_mesh_friend_sec_update(u16_t net_idx) for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) { struct bt_mesh_friend *frnd = &bt_mesh.frnd[i]; - if (frnd->net_idx == BT_MESH_KEY_UNUSED) { + if (!frnd->subnet) { continue; } - if (net_idx == BT_MESH_KEY_ANY || frnd->net_idx == net_idx) { - frnd->sec_update = 1; + if (net_idx == BT_MESH_KEY_ANY || + frnd->subnet->net_idx == net_idx) { + enqueue_update(frnd, 0x00); } } } @@ -214,7 +226,7 @@ int bt_mesh_friend_clear(struct bt_mesh_net_rx *rx, struct os_mbuf *buf) { struct bt_mesh_ctl_friend_clear *msg = (void *)buf->om_data; struct bt_mesh_friend *frnd; - u16_t lpn_addr, lpn_counter; + uint16_t lpn_addr, lpn_counter; struct bt_mesh_net_tx tx = { .sub = rx->sub, .ctx = &rx->ctx, @@ -257,14 +269,14 @@ int bt_mesh_friend_clear(struct bt_mesh_net_rx *rx, struct os_mbuf *buf) cfm.lpn_counter = msg->lpn_counter; bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_CLEAR_CFM, &cfm, - sizeof(cfm), NULL, NULL, NULL); + sizeof(cfm), NULL, NULL); friend_clear(frnd); return 0; } -static void friend_sub_add(struct bt_mesh_friend *frnd, u16_t addr) +static void friend_sub_add(struct bt_mesh_friend *frnd, uint16_t addr) { int i; @@ -278,7 +290,7 @@ static void friend_sub_add(struct bt_mesh_friend *frnd, u16_t addr) BT_WARN("No space in friend subscription list"); } -static void friend_sub_rem(struct bt_mesh_friend *frnd, u16_t addr) +static void friend_sub_rem(struct bt_mesh_friend *frnd, uint16_t addr) { int i; @@ -322,38 +334,41 @@ static struct os_mbuf *create_friend_pdu(struct bt_mesh_friend *frnd, } struct unseg_app_sdu_meta { - struct bt_mesh_net_rx net; - const u8_t *key; + struct bt_mesh_app_crypto_ctx crypto; + const uint8_t *key; struct bt_mesh_subnet *subnet; - bool is_dev_key; - u8_t aid; - u8_t *ad; + uint8_t aid; }; static int unseg_app_sdu_unpack(struct bt_mesh_friend *frnd, struct os_mbuf *buf, struct unseg_app_sdu_meta *meta) { - u16_t app_idx = FRIEND_ADV(buf)->app_idx; + uint16_t app_idx = FRIEND_ADV(buf)->app_idx; + struct bt_mesh_net_rx net; int err; - meta->subnet = bt_mesh_subnet_get(frnd->net_idx); - meta->is_dev_key = (app_idx == BT_MESH_KEY_DEV); - meta->is_dev_key = BT_MESH_IS_DEV_KEY(app_idx); - bt_mesh_net_header_parse(buf, &meta->net); - err = bt_mesh_app_key_get(meta->subnet, app_idx, meta->net.ctx.recv_dst, - &meta->key, &meta->aid); + meta->subnet = frnd->subnet; + bt_mesh_net_header_parse(buf, &net); + err = bt_mesh_keys_resolve(&net.ctx, &net.sub, &meta->key, &meta->aid); if (err) { return err; } - if (BT_MESH_ADDR_IS_VIRTUAL(meta->net.ctx.recv_dst)) { - meta->ad = bt_mesh_label_uuid_get(meta->net.ctx.recv_dst); - if (!meta->ad) { + meta->crypto.src = net.ctx.addr; + meta->crypto.dst = net.ctx.recv_dst; + meta->crypto.iv_index = BT_MESH_NET_IVI_TX; + meta->crypto.dev_key = BT_MESH_IS_DEV_KEY(app_idx); + meta->crypto.seq_num = net.seq; + meta->crypto.aszmic = 0; + + if (BT_MESH_ADDR_IS_VIRTUAL(meta->crypto.dst)) { + meta->crypto.ad = bt_mesh_va_label_get(meta->crypto.dst); + if (!meta->crypto.ad) { return -ENOENT; } } else { - meta->ad = NULL; + meta->crypto.ad = NULL; } return 0; @@ -372,12 +387,10 @@ static int unseg_app_sdu_decrypt(struct bt_mesh_friend *frnd, net_buf_simple_pull_mem(buf, 10); buf->om_len -= 4; - err = bt_mesh_app_decrypt_in_place(meta->key, meta->is_dev_key, - 0, buf, meta->ad, meta->net.ctx.addr, - meta->net.ctx.recv_dst, meta->net.seq, - BT_MESH_NET_IVI_TX); + err = bt_mesh_app_decrypt(meta->key, &meta->crypto, buf, buf); net_buf_simple_restore(buf, &state); + net_buf_unref(buf); return err; } @@ -394,10 +407,7 @@ static int unseg_app_sdu_encrypt(struct bt_mesh_friend *frnd, net_buf_simple_pull_mem(buf, 10); buf->om_len -= 4; - err = bt_mesh_app_encrypt_in_place(meta->key, meta->is_dev_key, 0, buf, - meta->ad, meta->net.ctx.addr, - meta->net.ctx.recv_dst, bt_mesh.seq, - BT_MESH_NET_IVI_TX); + err = bt_mesh_app_encrypt(meta->key, &meta->crypto, buf); net_buf_simple_restore(buf, &state); return err; @@ -423,7 +433,7 @@ static int unseg_app_sdu_prepare(struct bt_mesh_friend *frnd, /* No need to reencrypt the message if the sequence number is * unchanged. */ - if (meta.net.seq == bt_mesh.seq) { + if (meta.crypto.seq_num == bt_mesh.seq) { return 0; } @@ -444,28 +454,22 @@ static int unseg_app_sdu_prepare(struct bt_mesh_friend *frnd, static int encrypt_friend_pdu(struct bt_mesh_friend *frnd, struct os_mbuf *buf, bool master_cred) { - struct bt_mesh_subnet *sub = bt_mesh_subnet_get(frnd->net_idx); - const u8_t *enc, *priv; - u32_t iv_index; - u16_t src; - u8_t nid; + const struct bt_mesh_net_cred *cred; + uint32_t iv_index; + uint16_t src; int err; if (master_cred) { - enc = sub->keys[sub->kr_flag].enc; - priv = sub->keys[sub->kr_flag].privacy; - nid = sub->keys[sub->kr_flag].nid; + cred = &frnd->subnet->keys[SUBNET_KEY_TX_IDX(frnd->subnet)] + .msg; } else { - if (friend_cred_get(sub, frnd->lpn, &nid, &enc, &priv)) { - BT_ERR("friend_cred_get failed"); - return -ENOENT; - } + cred = &frnd->cred[SUBNET_KEY_TX_IDX(frnd->subnet)]; } src = sys_get_be16(&buf->om_data[5]); if (bt_mesh_elem_find(src)) { - u32_t seq; + uint32_t seq; if (FRIEND_ADV(buf)->app_idx != BT_MESH_KEY_UNUSED) { err = unseg_app_sdu_prepare(frnd, buf); @@ -475,25 +479,23 @@ static int encrypt_friend_pdu(struct bt_mesh_friend *frnd, struct os_mbuf *buf, } seq = bt_mesh_next_seq(); - buf->om_data[2] = seq >> 16; - buf->om_data[3] = seq >> 8; - buf->om_data[4] = seq; + sys_put_be24(seq, &buf->om_data[2]); iv_index = BT_MESH_NET_IVI_TX; FRIEND_ADV(buf)->app_idx = BT_MESH_KEY_UNUSED; } else { - u8_t ivi = (buf->om_data[0] >> 7); + uint8_t ivi = (buf->om_data[0] >> 7); iv_index = (bt_mesh.iv_index - ((bt_mesh.iv_index & 1) != ivi)); } - buf->om_data[0] = (nid | (iv_index & 1) << 7); + buf->om_data[0] = (cred->nid | (iv_index & 1) << 7); - if (bt_mesh_net_encrypt(enc, buf, iv_index, false)) { + if (bt_mesh_net_encrypt(cred->enc, buf, iv_index, false)) { BT_ERR("Encrypting failed"); return -EINVAL; } - if (bt_mesh_net_obfuscate(buf->om_data, iv_index, priv)) { + if (bt_mesh_net_obfuscate(buf->om_data, iv_index, cred->privacy)) { BT_ERR("Obfuscating failed"); return -EINVAL; } @@ -502,7 +504,7 @@ static int encrypt_friend_pdu(struct bt_mesh_friend *frnd, struct os_mbuf *buf, } static struct os_mbuf *encode_friend_ctl(struct bt_mesh_friend *frnd, - u8_t ctl_op, + uint8_t ctl_op, struct os_mbuf *sdu) { struct friend_pdu_info info; @@ -524,21 +526,20 @@ static struct os_mbuf *encode_friend_ctl(struct bt_mesh_friend *frnd, return create_friend_pdu(frnd, &info, sdu); } -static struct os_mbuf *encode_update(struct bt_mesh_friend *frnd, u8_t md) +static struct os_mbuf *encode_update(struct bt_mesh_friend *frnd, uint8_t md) { struct bt_mesh_ctl_friend_update *upd; struct os_mbuf *sdu = NET_BUF_SIMPLE(1 + sizeof(*upd)); - struct bt_mesh_subnet *sub = bt_mesh_subnet_get(frnd->net_idx); struct os_mbuf *buf; - __ASSERT_NO_MSG(sub != NULL); + __ASSERT_NO_MSG(frnd->subnet); BT_DBG("lpn 0x%04x md 0x%02x", frnd->lpn, md); net_buf_simple_init(sdu, 1); upd = net_buf_simple_add(sdu, sizeof(*upd)); - upd->flags = bt_mesh_net_flags(sub); + upd->flags = bt_mesh_net_flags(frnd->subnet); upd->iv_index = sys_cpu_to_be32(bt_mesh.iv_index); upd->md = md; @@ -548,7 +549,7 @@ static struct os_mbuf *encode_update(struct bt_mesh_friend *frnd, u8_t md) return buf; } -static void enqueue_sub_cfm(struct bt_mesh_friend *frnd, u8_t xact) +static void enqueue_sub_cfm(struct bt_mesh_friend *frnd, uint8_t xact) { struct bt_mesh_ctl_friend_sub_confirm *cfm; struct os_mbuf *sdu = NET_BUF_SIMPLE(1 + sizeof(*cfm)); @@ -585,16 +586,18 @@ done: static void friend_recv_delay(struct bt_mesh_friend *frnd) { + int32_t delay = recv_delay(frnd); + frnd->pending_req = 1; - k_delayed_work_submit(&frnd->timer, recv_delay(frnd)); - BT_DBG("Waiting RecvDelay of %d ms", (int) recv_delay(frnd)); + k_delayed_work_submit(&frnd->timer, K_MSEC(delay)); + BT_DBG("Waiting RecvDelay of %d ms", delay); } int bt_mesh_friend_sub_add(struct bt_mesh_net_rx *rx, struct os_mbuf *buf) { struct bt_mesh_friend *frnd; - u8_t xact; + uint8_t xact; if (buf->om_len < BT_MESH_FRIEND_SUB_MIN_LEN) { BT_WARN("Too short Friend Subscription Add"); @@ -629,7 +632,7 @@ int bt_mesh_friend_sub_rem(struct bt_mesh_net_rx *rx, struct os_mbuf *buf) { struct bt_mesh_friend *frnd; - u8_t xact; + uint8_t xact; if (buf->om_len < BT_MESH_FRIEND_SUB_MIN_LEN) { BT_WARN("Too short Friend Subscription Remove"); @@ -666,7 +669,7 @@ static void enqueue_buf(struct bt_mesh_friend *frnd, struct os_mbuf *buf) frnd->queue_size++; } -static void enqueue_update(struct bt_mesh_friend *frnd, u8_t md) +static void enqueue_update(struct bt_mesh_friend *frnd, uint8_t md) { struct os_mbuf *buf; @@ -676,7 +679,6 @@ static void enqueue_update(struct bt_mesh_friend *frnd, u8_t md) return; } - frnd->sec_update = 0; enqueue_buf(frnd, buf); } @@ -735,7 +737,7 @@ int bt_mesh_friend_poll(struct bt_mesh_net_rx *rx, struct os_mbuf *buf) return 0; } -static struct bt_mesh_friend *find_clear(u16_t prev_friend) +static struct bt_mesh_friend *find_clear(uint16_t prev_friend) { int i; @@ -766,13 +768,13 @@ static const struct bt_mesh_send_cb clear_sent_cb = { static void send_friend_clear(struct bt_mesh_friend *frnd) { struct bt_mesh_msg_ctx ctx = { - .net_idx = frnd->net_idx, + .net_idx = frnd->subnet->net_idx, .app_idx = BT_MESH_KEY_UNUSED, .addr = frnd->clear.frnd, .send_ttl = BT_MESH_TTL_MAX, }; struct bt_mesh_net_tx tx = { - .sub = &bt_mesh.sub[0], + .sub = frnd->subnet, .ctx = &ctx, .src = bt_mesh_primary_addr(), .xmit = bt_mesh_net_transmit_get(), @@ -785,13 +787,13 @@ static void send_friend_clear(struct bt_mesh_friend *frnd) BT_DBG(""); bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_CLEAR, &req, - sizeof(req), NULL, &clear_sent_cb, frnd); + sizeof(req), &clear_sent_cb, frnd); } static void clear_timeout(struct ble_npl_event *work) { struct bt_mesh_friend *frnd = ble_npl_event_get_arg(work); - u32_t duration; + uint32_t duration; BT_DBG("LPN 0x%04x (old) Friend 0x%04x", frnd->lpn, frnd->clear.frnd); @@ -820,7 +822,7 @@ int bt_mesh_friend_clear_cfm(struct bt_mesh_net_rx *rx, { struct bt_mesh_ctl_friend_clear_confirm *msg = (void *)buf->om_data; struct bt_mesh_friend *frnd; - u16_t lpn_addr, lpn_counter; + uint16_t lpn_addr, lpn_counter; BT_DBG(""); @@ -855,7 +857,7 @@ int bt_mesh_friend_clear_cfm(struct bt_mesh_net_rx *rx, return 0; } -static void enqueue_offer(struct bt_mesh_friend *frnd, s8_t rssi) +static void enqueue_offer(struct bt_mesh_friend *frnd, int8_t rssi) { struct bt_mesh_ctl_friend_offer *off; struct os_mbuf *sdu = NET_BUF_SIMPLE(1 + sizeof(*off)); @@ -880,11 +882,9 @@ static void enqueue_offer(struct bt_mesh_friend *frnd, s8_t rssi) } if (encrypt_friend_pdu(frnd, buf, true)) { - return; + goto done; } - frnd->counter++; - if (frnd->last) { net_buf_unref(frnd->last); } @@ -897,43 +897,45 @@ done: } #define RECV_WIN CONFIG_BT_MESH_FRIEND_RECV_WIN -#define RSSI_FACT(crit) (((crit) >> 5) & (u8_t)BIT_MASK(2)) -#define RECV_WIN_FACT(crit) (((crit) >> 3) & (u8_t)BIT_MASK(2)) -#define MIN_QUEUE_SIZE_LOG(crit) ((crit) & (u8_t)BIT_MASK(3)) -#define MIN_QUEUE_SIZE(crit) ((u32_t)BIT(MIN_QUEUE_SIZE_LOG(crit))) +#define RSSI_FACT(crit) (((crit) >> 5) & (uint8_t)BIT_MASK(2)) +#define RECV_WIN_FACT(crit) (((crit) >> 3) & (uint8_t)BIT_MASK(2)) +#define MIN_QUEUE_SIZE_LOG(crit) ((crit) & (uint8_t)BIT_MASK(3)) +#define MIN_QUEUE_SIZE(crit) ((uint32_t)BIT(MIN_QUEUE_SIZE_LOG(crit))) -static s32_t offer_delay(struct bt_mesh_friend *frnd, s8_t rssi, u8_t crit) +static int32_t offer_delay(struct bt_mesh_friend *frnd, int8_t rssi, uint8_t crit) { /* Scaling factors. The actual values are 1, 1.5, 2 & 2.5, but we * want to avoid floating-point arithmetic. */ - static const u8_t fact[] = { 10, 15, 20, 25 }; - s32_t delay; + static const uint8_t fact[] = { 10, 15, 20, 25 }; + int32_t delay; BT_DBG("ReceiveWindowFactor %u ReceiveWindow %u RSSIFactor %u RSSI %d", fact[RECV_WIN_FACT(crit)], RECV_WIN, fact[RSSI_FACT(crit)], rssi); /* Delay = ReceiveWindowFactor * ReceiveWindow - RSSIFactor * RSSI */ - delay = (s32_t)fact[RECV_WIN_FACT(crit)] * RECV_WIN; - delay -= (s32_t)fact[RSSI_FACT(crit)] * rssi; + delay = (int32_t)fact[RECV_WIN_FACT(crit)] * RECV_WIN; + delay -= (int32_t)fact[RSSI_FACT(crit)] * rssi; delay /= 10; BT_DBG("Local Delay calculated as %d ms", (int) delay); - if (delay < 100) { - return K_MSEC(100); - } - - return K_MSEC(delay); + return MAX(delay, 100); } int bt_mesh_friend_req(struct bt_mesh_net_rx *rx, struct os_mbuf *buf) { struct bt_mesh_ctl_friend_req *msg = (void *)buf->om_data; struct bt_mesh_friend *frnd = NULL; - u32_t poll_to; - int i; + uint32_t poll_to; + int32_t delay; + int i, err; + + if (rx->net_if == BT_MESH_NET_IF_LOCAL) { + BT_WARN("Ignoring Friend request from local interface"); + return 0; + } if (buf->om_len < sizeof(*msg)) { BT_WARN("Too short Friend Request"); @@ -945,9 +947,7 @@ int bt_mesh_friend_req(struct bt_mesh_net_rx *rx, struct os_mbuf *buf) return -EINVAL; } - poll_to = (((u32_t)msg->poll_to[0] << 16) | - ((u32_t)msg->poll_to[1] << 8) | - ((u32_t)msg->poll_to[2])); + poll_to = sys_get_be24(msg->poll_to); if (poll_to <= 0x000009 || poll_to >= 0x34bc00) { BT_WARN("Prohibited PollTimeout (0x%06x)", (unsigned) poll_to); @@ -984,9 +984,8 @@ int bt_mesh_friend_req(struct bt_mesh_net_rx *rx, struct os_mbuf *buf) } for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) { - if (!bt_mesh.frnd[i].valid) { + if (!bt_mesh.frnd[i].subnet) { frnd = &bt_mesh.frnd[i]; - frnd->valid = 1; break; } } @@ -999,12 +998,19 @@ int bt_mesh_friend_req(struct bt_mesh_net_rx *rx, struct os_mbuf *buf) init_friend: frnd->lpn = rx->ctx.addr; frnd->num_elem = msg->num_elem; - frnd->net_idx = rx->sub->net_idx; + frnd->subnet = rx->sub; frnd->recv_delay = msg->recv_delay; frnd->poll_to = poll_to * 100; frnd->lpn_counter = sys_be16_to_cpu(msg->lpn_counter); frnd->clear.frnd = sys_be16_to_cpu(msg->prev_addr); + err = friend_cred_create(frnd, SUBNET_KEY_TX_IDX(frnd->subnet)); + if (err) { + BT_ERR("Failed to create friend credentials"); + friend_clear(frnd); + return -EIO; + } + BT_DBG("LPN 0x%04x rssi %d recv_delay %u poll_to %ums", frnd->lpn, rx->ctx.recv_rssi, frnd->recv_delay, (unsigned) frnd->poll_to); @@ -1014,24 +1020,20 @@ init_friend: clear_procedure_start(frnd); } - k_delayed_work_submit(&frnd->timer, - offer_delay(frnd, rx->ctx.recv_rssi, - msg->criteria)); - - friend_cred_create(rx->sub, frnd->lpn, frnd->lpn_counter, - frnd->counter); + delay = offer_delay(frnd, rx->ctx.recv_rssi, msg->criteria); + k_delayed_work_submit(&frnd->timer, K_MSEC(delay)); enqueue_offer(frnd, rx->ctx.recv_rssi); return 0; } -static bool is_seg(struct bt_mesh_friend_seg *seg, u16_t src, u16_t seq_zero) +static bool is_seg(struct bt_mesh_friend_seg *seg, uint16_t src, uint16_t seq_zero) { struct os_mbuf *buf = (void *)net_buf_slist_peek_head(&seg->queue); struct net_buf_simple_state state; - u16_t buf_seq_zero; - u16_t buf_src; + uint16_t buf_seq_zero; + uint16_t buf_src; if (!buf) { return false; @@ -1048,8 +1050,8 @@ static bool is_seg(struct bt_mesh_friend_seg *seg, u16_t src, u16_t seq_zero) } static struct bt_mesh_friend_seg *get_seg(struct bt_mesh_friend *frnd, - u16_t src, u16_t seq_zero, - u8_t seg_count) + uint16_t src, uint16_t seq_zero, + uint8_t seg_count) { struct bt_mesh_friend_seg *unassigned = NULL; int i; @@ -1075,7 +1077,7 @@ static struct bt_mesh_friend_seg *get_seg(struct bt_mesh_friend *frnd, static void enqueue_friend_pdu(struct bt_mesh_friend *frnd, enum bt_mesh_friend_pdu_type type, - u16_t src, u8_t seg_count, + uint16_t src, uint8_t seg_count, struct os_mbuf *buf) { struct bt_mesh_friend_seg *seg; @@ -1083,15 +1085,11 @@ static void enqueue_friend_pdu(struct bt_mesh_friend *frnd, BT_DBG("type %u", type); if (type == BT_MESH_FRIEND_PDU_SINGLE) { - if (frnd->sec_update) { - enqueue_update(frnd, 1); - } - enqueue_buf(frnd, buf); return; } - u16_t seq_zero = (((buf->om_data[10] << 8 | buf->om_data[11]) >> 2) & TRANS_SEQ_ZERO_MASK); + uint16_t seq_zero = (((buf->om_data[10] << 8 | buf->om_data[11]) >> 2) & TRANS_SEQ_ZERO_MASK); seg = get_seg(frnd, src, seq_zero, seg_count); if (!seg) { @@ -1103,10 +1101,6 @@ static void enqueue_friend_pdu(struct bt_mesh_friend *frnd, net_buf_slist_put(&seg->queue, buf); if (type == BT_MESH_FRIEND_PDU_COMPLETE) { - if (frnd->sec_update) { - enqueue_update(frnd, 1); - } - net_buf_slist_merge_slist(&frnd->queue, &seg->queue); frnd->queue_size += seg->seg_count; @@ -1117,7 +1111,7 @@ static void enqueue_friend_pdu(struct bt_mesh_friend *frnd, } } -static void buf_send_start(u16_t duration, int err, void *user_data) +static void buf_send_start(uint16_t duration, int err, void *user_data) { struct bt_mesh_friend *frnd = user_data; @@ -1126,7 +1120,7 @@ static void buf_send_start(u16_t duration, int err, void *user_data) frnd->pending_buf = 0; /* Friend Offer doesn't follow the re-sending semantics */ - if (!frnd->established) { + if (!frnd->established && frnd->last) { net_buf_unref(frnd->last); frnd->last = NULL; } @@ -1154,6 +1148,38 @@ static void buf_send_end(int err, void *user_data) } } +static void update_overwrite(struct os_mbuf *buf, uint8_t md) +{ + struct net_buf_simple_state state; + struct bt_mesh_ctl_friend_update *upd; + + if (buf->om_len != 16) { + return; + } + + net_buf_simple_save(buf, &state); + + net_buf_skip(buf, 1); /* skip IVI, NID */ + + if (!(net_buf_pull_u8(buf) >> 7)) { + goto end; + } + + net_buf_skip(buf, 7); /* skip seqnum src dec*/ + + if (TRANS_CTL_OP((uint8_t *) net_buf_pull_mem(buf, 1)) + != TRANS_CTL_OP_FRIEND_UPDATE) { + goto end; + } + + upd = net_buf_pull_mem(buf, sizeof(*upd)); + BT_DBG("Update Previous Friend Update MD 0x%02x -> 0x%02x", upd->md, md); + upd->md = md; + +end: + net_buf_simple_restore(buf, &state); +} + static void friend_timeout(struct ble_npl_event *work) { struct bt_mesh_friend *frnd = ble_npl_event_get_arg(work); @@ -1162,6 +1188,8 @@ static void friend_timeout(struct ble_npl_event *work) .end = buf_send_end, }; + uint8_t md; + __ASSERT_NO_MSG(frnd->pending_buf == 0); BT_DBG("lpn 0x%04x send_last %u last %p", frnd->lpn, @@ -1187,12 +1215,17 @@ static void friend_timeout(struct ble_npl_event *work) return; } + md = (uint8_t)(net_buf_slist_peek_head(&frnd->queue) != NULL); + + update_overwrite(frnd->last, md); + if (encrypt_friend_pdu(frnd, frnd->last, false)) { return; } /* Clear the flag we use for segment tracking */ BT_MESH_ADV(frnd->last)->flags &= ~NET_BUF_FRAGS; + BT_MESH_ADV(frnd->last)->flags = 0; BT_DBG("Sending buf %p from Friend Queue of LPN 0x%04x", frnd->last, frnd->lpn); @@ -1204,8 +1237,56 @@ send_last: bt_mesh_adv_send(frnd->last, &buf_sent_cb, frnd); } +static void subnet_evt(struct bt_mesh_subnet *sub, enum bt_mesh_key_evt evt) +{ + int i, err; + + if (evt == BT_MESH_KEY_ADDED) { + return; + } + + for (i = 0; i < ARRAY_SIZE(bt_mesh.frnd); i++) { + struct bt_mesh_friend *frnd = &bt_mesh.frnd[i]; + + if (frnd->subnet != sub) { + continue; + } + + switch (evt) { + case BT_MESH_KEY_DELETED: + BT_DBG("Cleared network for 0x%04x", frnd->lpn); + friend_clear(frnd); + break; + case BT_MESH_KEY_UPDATED: + BT_DBG("Generating new keys for 0x%04x", frnd->lpn); + err = friend_cred_create(frnd, 1); + if (err) { + BT_ERR("Failed updating friend cred for 0x%04x", + frnd->lpn); + friend_clear(frnd); + } + break; + case BT_MESH_KEY_SWAPPED: + enqueue_update(frnd, 0); + break; + case BT_MESH_KEY_REVOKED: + BT_DBG("Revoking old keys for 0x%04x", frnd->lpn); + memcpy(&frnd->cred[0], &frnd->cred[1], + sizeof(frnd->cred[0])); + memset(&frnd->cred[1], 0, sizeof(frnd->cred[1])); + enqueue_update(frnd, 0); + break; + default: + break; + } + } +} + int bt_mesh_friend_init(void) { + if (!bt_mesh_subnet_cb_list[3]) { + bt_mesh_subnet_cb_list[3] = subnet_evt; + } int rc; int i; @@ -1223,8 +1304,6 @@ int bt_mesh_friend_init(void) struct bt_mesh_friend *frnd = &bt_mesh.frnd[i]; int j; - frnd->net_idx = BT_MESH_KEY_UNUSED; - net_buf_slist_init(&frnd->queue); k_delayed_work_init(&frnd->timer, friend_timeout); @@ -1240,7 +1319,7 @@ int bt_mesh_friend_init(void) return 0; } -static bool is_segack(struct os_mbuf *buf, u64_t *seqauth, u16_t src) +static bool is_segack(struct os_mbuf *buf, uint64_t *seqauth, uint16_t src) { struct net_buf_simple_state state; bool found = false; @@ -1265,7 +1344,7 @@ static bool is_segack(struct os_mbuf *buf, u64_t *seqauth, u16_t src) net_buf_skip(buf, 2); /* skip dst */ - if (TRANS_CTL_OP((u8_t *) net_buf_pull_mem(buf, 1)) != TRANS_CTL_OP_ACK) { + if (TRANS_CTL_OP((uint8_t *) net_buf_pull_mem(buf, 1)) != TRANS_CTL_OP_ACK) { goto end; } @@ -1276,8 +1355,8 @@ end: return found; } -static void friend_purge_old_ack(struct bt_mesh_friend *frnd, u64_t *seq_auth, - u16_t src) +static void friend_purge_old_ack(struct bt_mesh_friend *frnd, uint64_t *seq_auth, + uint16_t src) { struct os_mbuf *cur, *prev = NULL; @@ -1302,7 +1381,7 @@ static void friend_purge_old_ack(struct bt_mesh_friend *frnd, u64_t *seq_auth, static void friend_lpn_enqueue_rx(struct bt_mesh_friend *frnd, struct bt_mesh_net_rx *rx, enum bt_mesh_friend_pdu_type type, - u64_t *seq_auth, u8_t seg_count, + uint64_t *seq_auth, uint8_t seg_count, struct os_mbuf *sbuf) { struct friend_pdu_info info; @@ -1334,9 +1413,7 @@ static void friend_lpn_enqueue_rx(struct bt_mesh_friend *frnd, info.ctl = rx->ctl; - info.seq[0] = (rx->seq >> 16); - info.seq[1] = (rx->seq >> 8); - info.seq[2] = rx->seq; + sys_put_be24(rx->seq, info.seq); info.iv_index = BT_MESH_NET_IVI_RX(rx); @@ -1355,7 +1432,7 @@ static void friend_lpn_enqueue_rx(struct bt_mesh_friend *frnd, static void friend_lpn_enqueue_tx(struct bt_mesh_friend *frnd, struct bt_mesh_net_tx *tx, enum bt_mesh_friend_pdu_type type, - u64_t *seq_auth, u8_t seg_count, + uint64_t *seq_auth, uint8_t seg_count, struct os_mbuf *sbuf) { struct friend_pdu_info info; @@ -1373,9 +1450,7 @@ static void friend_lpn_enqueue_tx(struct bt_mesh_friend *frnd, info.ttl = tx->ctx->send_ttl; info.ctl = (tx->ctx->app_idx == BT_MESH_KEY_UNUSED); - info.seq[0] = (bt_mesh.seq >> 16); - info.seq[1] = (bt_mesh.seq >> 8); - info.seq[2] = bt_mesh.seq; + sys_put_be24(bt_mesh.seq, info.seq); info.iv_index = BT_MESH_NET_IVI_TX; @@ -1398,8 +1473,8 @@ static void friend_lpn_enqueue_tx(struct bt_mesh_friend *frnd, BT_DBG("Queued message for LPN 0x%04x", frnd->lpn); } -static bool friend_lpn_matches(struct bt_mesh_friend *frnd, u16_t net_idx, - u16_t addr) +static bool friend_lpn_matches(struct bt_mesh_friend *frnd, uint16_t net_idx, + uint16_t addr) { int i; @@ -1407,7 +1482,7 @@ static bool friend_lpn_matches(struct bt_mesh_friend *frnd, u16_t net_idx, return false; } - if (net_idx != frnd->net_idx) { + if (net_idx != frnd->subnet->net_idx) { return false; } @@ -1424,7 +1499,7 @@ static bool friend_lpn_matches(struct bt_mesh_friend *frnd, u16_t net_idx, return false; } -bool bt_mesh_friend_match(u16_t net_idx, u16_t addr) +bool bt_mesh_friend_match(uint16_t net_idx, uint16_t addr) { int i; @@ -1443,10 +1518,10 @@ bool bt_mesh_friend_match(u16_t net_idx, u16_t addr) return false; } -static bool friend_queue_has_space(struct bt_mesh_friend *frnd, u16_t addr, - u64_t *seq_auth, u8_t seg_count) +static bool friend_queue_has_space(struct bt_mesh_friend *frnd, uint16_t addr, + uint64_t *seq_auth, uint8_t seg_count) { - u32_t total = 0; + uint32_t total = 0; int i; if (seg_count > CONFIG_BT_MESH_FRIEND_QUEUE_SIZE) { @@ -1474,8 +1549,8 @@ static bool friend_queue_has_space(struct bt_mesh_friend *frnd, u16_t addr, return (CONFIG_BT_MESH_FRIEND_QUEUE_SIZE - total) > seg_count; } -bool bt_mesh_friend_queue_has_space(u16_t net_idx, u16_t src, u16_t dst, - u64_t *seq_auth, u8_t seg_count) +bool bt_mesh_friend_queue_has_space(uint16_t net_idx, uint16_t src, uint16_t dst, + uint64_t *seq_auth, uint8_t seg_count) { bool someone_has_space = false, friend_match = false; int i; @@ -1509,11 +1584,11 @@ bool bt_mesh_friend_queue_has_space(u16_t net_idx, u16_t src, u16_t dst, return someone_has_space; } -static bool friend_queue_prepare_space(struct bt_mesh_friend *frnd, u16_t addr, - u64_t *seq_auth, u8_t seg_count) +static bool friend_queue_prepare_space(struct bt_mesh_friend *frnd, uint16_t addr, + uint64_t *seq_auth, uint8_t seg_count) { bool pending_segments; - u8_t avail_space; + uint8_t avail_space; if (!friend_queue_has_space(frnd, addr, seq_auth, seg_count)) { return false; @@ -1547,7 +1622,7 @@ static bool friend_queue_prepare_space(struct bt_mesh_friend *frnd, u16_t addr, void bt_mesh_friend_enqueue_rx(struct bt_mesh_net_rx *rx, enum bt_mesh_friend_pdu_type type, - u64_t *seq_auth, u8_t seg_count, + uint64_t *seq_auth, uint8_t seg_count, struct os_mbuf *sbuf) { int i; @@ -1570,6 +1645,11 @@ void bt_mesh_friend_enqueue_rx(struct bt_mesh_net_rx *rx, continue; } + if (friend_lpn_matches(frnd, rx->sub->net_idx, + rx->ctx.addr)) { + continue; + } + if (!friend_queue_prepare_space(frnd, rx->ctx.addr, seq_auth, seg_count)) { continue; @@ -1582,7 +1662,7 @@ void bt_mesh_friend_enqueue_rx(struct bt_mesh_net_rx *rx, bool bt_mesh_friend_enqueue_tx(struct bt_mesh_net_tx *tx, enum bt_mesh_friend_pdu_type type, - u64_t *seq_auth, u8_t seg_count, + uint64_t *seq_auth, uint8_t seg_count, struct os_mbuf *sbuf) { bool matched = false; @@ -1617,8 +1697,22 @@ bool bt_mesh_friend_enqueue_tx(struct bt_mesh_net_tx *tx, return matched; } -void bt_mesh_friend_clear_incomplete(struct bt_mesh_subnet *sub, u16_t src, - u16_t dst, u64_t *seq_auth) +int bt_mesh_friend_terminate(uint16_t lpn_addr) +{ + struct bt_mesh_friend *frnd; + + frnd = bt_mesh_friend_find(BT_MESH_KEY_ANY, lpn_addr, false, false); + if (!frnd) { + return -ENOENT; + } + + friend_clear(frnd); + + return 0; +} + +void bt_mesh_friend_clear_incomplete(struct bt_mesh_subnet *sub, uint16_t src, + uint16_t dst, uint64_t *seq_auth) { int i; diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/friend.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/friend.h index 10ffa819..ee783f33 100644 --- a/src/libs/mynewt-nimble/nimble/host/mesh/src/friend.h +++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/friend.h @@ -17,29 +17,29 @@ enum bt_mesh_friend_pdu_type { BT_MESH_FRIEND_PDU_COMPLETE, }; -bool bt_mesh_friend_match(u16_t net_idx, u16_t addr); +bool bt_mesh_friend_match(uint16_t net_idx, uint16_t addr); -struct bt_mesh_friend *bt_mesh_friend_find(u16_t net_idx, u16_t lpn_addr, +struct bt_mesh_friend *bt_mesh_friend_find(uint16_t net_idx, uint16_t lpn_addr, bool valid, bool established); -bool bt_mesh_friend_queue_has_space(u16_t net_idx, u16_t src, u16_t dst, - u64_t *seq_auth, u8_t seg_count); +bool bt_mesh_friend_queue_has_space(uint16_t net_idx, uint16_t src, uint16_t dst, + uint64_t *seq_auth, uint8_t seg_count); void bt_mesh_friend_enqueue_rx(struct bt_mesh_net_rx *rx, enum bt_mesh_friend_pdu_type type, - u64_t *seq_auth, u8_t seg_count, + uint64_t *seq_auth, uint8_t seg_count, struct os_mbuf *sbuf); bool bt_mesh_friend_enqueue_tx(struct bt_mesh_net_tx *tx, enum bt_mesh_friend_pdu_type type, - u64_t *seq_auth, u8_t seg_count, + uint64_t *seq_auth, uint8_t seg_count, struct os_mbuf *sbuf); -void bt_mesh_friend_clear_incomplete(struct bt_mesh_subnet *sub, u16_t src, - u16_t dst, u64_t *seq_auth); +void bt_mesh_friend_clear_incomplete(struct bt_mesh_subnet *sub, uint16_t src, + uint16_t dst, uint64_t *seq_auth); -void bt_mesh_friend_sec_update(u16_t net_idx); +void bt_mesh_friend_sec_update(uint16_t net_idx); -void bt_mesh_friend_clear_net_idx(u16_t net_idx); +void bt_mesh_friends_clear(void); int bt_mesh_friend_poll(struct bt_mesh_net_rx *rx, struct os_mbuf *buf); int bt_mesh_friend_req(struct bt_mesh_net_rx *rx, struct os_mbuf *buf); diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/glue.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/glue.c index 896f3d1a..aab7f374 100644 --- a/src/libs/mynewt-nimble/nimble/host/mesh/src/glue.c +++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/glue.c @@ -30,7 +30,7 @@ #include "base64/base64.h" #endif -extern u8_t g_mesh_addr_type; +extern uint8_t g_mesh_addr_type; #if MYNEWT_VAL(BLE_EXT_ADV) /* Store configuration for different bearers */ @@ -44,8 +44,8 @@ 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; @@ -214,6 +214,14 @@ net_buf_simple_add_be16(struct os_mbuf *om, uint16_t val) ASSERT_NOT_CHAIN(om); } +void +net_buf_simple_add_le24(struct os_mbuf *om, uint32_t val) +{ + val = htole32(val); + os_mbuf_append(om, &val, 3); + ASSERT_NOT_CHAIN(om); +} + void net_buf_simple_add_be32(struct os_mbuf *om, uint32_t val) { @@ -269,6 +277,22 @@ net_buf_simple_push_be16(struct os_mbuf *om, uint16_t val) ASSERT_NOT_CHAIN(om); } +void +net_buf_simple_push_be24(struct os_mbuf *om, uint32_t val) +{ + uint8_t headroom = om->om_data - &om->om_databuf[om->om_pkthdr_len]; + + assert(headroom >= 3); + om->om_data -= 3; + put_be24(om->om_data, val); + om->om_len += 3; + + if (om->om_pkthdr_len) { + OS_MBUF_PKTHDR(om)->omp_len += 3; + } + ASSERT_NOT_CHAIN(om); +} + void net_buf_simple_push_u8(struct os_mbuf *om, uint8_t val) { @@ -333,7 +357,7 @@ k_fifo_is_empty(struct ble_npl_eventq *q) return ble_npl_eventq_is_empty(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) { struct ble_npl_event *ev = ble_npl_eventq_get(fifo, 0); @@ -384,6 +408,12 @@ k_delayed_work_init(struct k_delayed_work *w, ble_npl_event_fn *f) #endif } +bool +k_delayed_work_pending(struct k_delayed_work *w) +{ + return ble_npl_callout_is_active(&w->work); +} + void k_delayed_work_cancel(struct k_delayed_work *w) { @@ -440,7 +470,7 @@ int64_t k_uptime_get(void) return ble_npl_time_ticks_to_ms32(ble_npl_time_get()); } -u32_t k_uptime_get_32(void) +uint32_t k_uptime_get_32(void) { return k_uptime_get(); } @@ -459,7 +489,7 @@ static uint8_t priv[32]; static bool has_pub = false; int -bt_dh_key_gen(const u8_t remote_pk[64], bt_dh_key_cb_t cb) +bt_dh_key_gen(const uint8_t remote_pk[64], bt_dh_key_cb_t cb) { uint8_t dh[32]; @@ -510,7 +540,7 @@ bt_pub_key_get(void) } static int -set_ad(const struct bt_data *ad, size_t ad_len, u8_t *buf, u8_t *buf_len) +set_ad(const struct bt_data *ad, size_t ad_len, uint8_t *buf, uint8_t *buf_len) { int i; @@ -846,6 +876,52 @@ void net_buf_slist_merge_slist(struct net_buf_slist_t *list, } } +/** Memory slab methods */ +extern void k_mem_slab_free(struct k_mem_slab *slab, void **mem) +{ + **(char ***)mem = slab->free_list; + slab->free_list = *(char **)mem; + slab->num_used--; +} + +extern int k_mem_slab_alloc(struct k_mem_slab *slab, void **mem) +{ + int result; + + if (slab->free_list != NULL) { + /* take a free block */ + *mem = slab->free_list; + slab->free_list = *(char **)(slab->free_list); + slab->num_used++; + result = 0; + } else { + *mem = NULL; + result = -ENOMEM; + } + return result; +} + +int create_free_list(struct k_mem_slab *slab) +{ + uint32_t j; + char *p; + + if(((slab->block_size | (uintptr_t)slab->buffer) & + (sizeof(void *) - 1)) != 0) { + return -EINVAL; + } + + slab->free_list = NULL; + p = slab->buffer; + + for (j = 0U; j < slab->num_blocks; j++) { + *(char **)p = slab->free_list; + slab->free_list = p; + p += slab->block_size; + } + return 0; +} + #if MYNEWT_VAL(BLE_MESH_SETTINGS) int settings_bytes_from_str(char *val_str, void *vp, int *len) @@ -867,4 +943,3 @@ char *settings_str_from_bytes(const void *vp, int vp_len, } #endif /* MYNEWT_VAL(BLE_MESH_SETTINGS) */ - diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/health_cli.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/health_cli.c index 193279c2..76d639c5 100644 --- a/src/libs/mynewt-nimble/nimble/host/mesh/src/health_cli.c +++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/health_cli.c @@ -21,15 +21,15 @@ #include "foundation.h" #include "mesh/health_cli.h" -static s32_t msg_timeout = K_SECONDS(5); +static int32_t msg_timeout = K_SECONDS(5); static struct bt_mesh_health_cli *health_cli; struct health_fault_param { - u16_t cid; - u8_t *expect_test_id; - u8_t *test_id; - u8_t *faults; + uint16_t cid; + uint8_t *expect_test_id; + uint8_t *test_id; + uint8_t *faults; size_t *fault_count; }; @@ -38,8 +38,8 @@ static void health_fault_status(struct bt_mesh_model *model, struct os_mbuf *buf) { struct health_fault_param *param; - u8_t test_id; - u16_t cid; + uint8_t test_id; + uint16_t cid; BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, @@ -84,8 +84,8 @@ static void health_current_status(struct bt_mesh_model *model, struct os_mbuf *buf) { struct bt_mesh_health_cli *cli = model->user_data; - u8_t test_id; - u16_t cid; + uint8_t test_id; + uint16_t cid; BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", ctx->net_idx, ctx->app_idx, ctx->addr, buf->om_len, @@ -106,7 +106,7 @@ static void health_current_status(struct bt_mesh_model *model, } struct health_period_param { - u8_t *divisor; + uint8_t *divisor; }; static void health_period_status(struct bt_mesh_model *model, @@ -132,7 +132,7 @@ static void health_period_status(struct bt_mesh_model *model, } struct health_attention_param { - u8_t *attention; + uint8_t *attention; }; static void health_attention_status(struct bt_mesh_model *model, @@ -167,7 +167,7 @@ const struct bt_mesh_model_op bt_mesh_health_cli_op[] = { BT_MESH_MODEL_OP_END, }; -static int cli_prepare(void *param, u32_t op) +static int cli_prepare(void *param, uint32_t op) { if (!health_cli) { BT_ERR("No available Health Client context!"); @@ -202,12 +202,10 @@ static int cli_wait(void) return err; } -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) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_ATTENTION_GET, 0); struct bt_mesh_msg_ctx ctx = { - .net_idx = net_idx, .app_idx = app_idx, .addr = addr, .send_ttl = BT_MESH_TTL_DEFAULT, @@ -237,12 +235,11 @@ done: return err; } -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) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_ATTENTION_SET, 1); struct bt_mesh_msg_ctx ctx = { - .net_idx = net_idx, .app_idx = app_idx, .addr = addr, .send_ttl = BT_MESH_TTL_DEFAULT, @@ -283,12 +280,10 @@ done: return err; } -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) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEALTH_PERIOD_GET, 0); struct bt_mesh_msg_ctx ctx = { - .net_idx = net_idx, .app_idx = app_idx, .addr = addr, .send_ttl = BT_MESH_TTL_DEFAULT, @@ -318,12 +313,11 @@ done: return err; } -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) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEALTH_PERIOD_SET, 1); struct bt_mesh_msg_ctx ctx = { - .net_idx = net_idx, .app_idx = app_idx, .addr = addr, .send_ttl = BT_MESH_TTL_DEFAULT, @@ -364,13 +358,12 @@ done: return err; } -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, - size_t *fault_count) +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) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEALTH_FAULT_TEST, 3); struct bt_mesh_msg_ctx ctx = { - .net_idx = net_idx, .app_idx = app_idx, .addr = addr, .send_ttl = BT_MESH_TTL_DEFAULT, @@ -415,13 +408,12 @@ done: return err; } -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, - size_t *fault_count) +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) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEALTH_FAULT_CLEAR, 2); struct bt_mesh_msg_ctx ctx = { - .net_idx = net_idx, .app_idx = app_idx, .addr = addr, .send_ttl = BT_MESH_TTL_DEFAULT, @@ -465,13 +457,12 @@ done: return err; } -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, - size_t *fault_count) +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) { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_HEALTH_FAULT_GET, 2); struct bt_mesh_msg_ctx ctx = { - .net_idx = net_idx, .app_idx = app_idx, .addr = addr, .send_ttl = BT_MESH_TTL_DEFAULT, @@ -505,12 +496,12 @@ done: return err; } -s32_t bt_mesh_health_cli_timeout_get(void) +int32_t bt_mesh_health_cli_timeout_get(void) { return msg_timeout; } -void bt_mesh_health_cli_timeout_set(s32_t timeout) +void bt_mesh_health_cli_timeout_set(int32_t timeout) { msg_timeout = timeout; } @@ -523,6 +514,7 @@ int bt_mesh_health_cli_set(struct bt_mesh_model *model) } health_cli = model->user_data; + msg_timeout = 2 * MSEC_PER_SEC; return 0; } diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/health_srv.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/health_srv.c index 16de83a9..dd90533b 100644 --- a/src/libs/mynewt-nimble/nimble/host/mesh/src/health_srv.c +++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/health_srv.c @@ -27,11 +27,11 @@ struct bt_mesh_health_srv *health_srv; static void health_get_registered(struct bt_mesh_model *mod, - u16_t company_id, + uint16_t company_id, struct os_mbuf *msg) { struct bt_mesh_health_srv *srv = mod->user_data; - u8_t *test_id; + uint8_t *test_id; BT_DBG("Company ID 0x%04x", company_id); @@ -41,7 +41,7 @@ static void health_get_registered(struct bt_mesh_model *mod, net_buf_simple_add_le16(msg, company_id); if (srv->cb && srv->cb->fault_get_reg) { - u8_t fault_count = net_buf_simple_tailroom(msg) - 4; + uint8_t fault_count = net_buf_simple_tailroom(msg) - 4; int err; err = srv->cb->fault_get_reg(mod, company_id, test_id, @@ -64,9 +64,9 @@ static size_t health_get_current(struct bt_mesh_model *mod, { struct bt_mesh_health_srv *srv = mod->user_data; const struct bt_mesh_comp *comp; - u8_t *test_id, *company_ptr; - u16_t company_id; - u8_t fault_count; + uint8_t *test_id, *company_ptr; + uint16_t company_id; + uint8_t fault_count; int err; bt_mesh_model_msg_init(msg, OP_HEALTH_CURRENT_STATUS); @@ -104,7 +104,7 @@ static void health_fault_get(struct bt_mesh_model *model, struct os_mbuf *buf) { struct os_mbuf *sdu = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX); - u16_t company_id; + uint16_t company_id; company_id = net_buf_simple_pull_le16(buf); @@ -124,7 +124,7 @@ static void health_fault_clear_unrel(struct bt_mesh_model *model, struct os_mbuf *buf) { struct bt_mesh_health_srv *srv = model->user_data; - u16_t company_id; + uint16_t company_id; company_id = net_buf_simple_pull_le16(buf); @@ -141,7 +141,7 @@ static void health_fault_clear(struct bt_mesh_model *model, { struct os_mbuf *sdu = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX); struct bt_mesh_health_srv *srv = model->user_data; - u16_t company_id; + uint16_t company_id; company_id = net_buf_simple_pull_le16(buf); @@ -165,8 +165,8 @@ static void health_fault_test_unrel(struct bt_mesh_model *model, struct os_mbuf *buf) { struct bt_mesh_health_srv *srv = model->user_data; - u16_t company_id; - u8_t test_id; + uint16_t company_id; + uint8_t test_id; test_id = net_buf_simple_pull_u8(buf); company_id = net_buf_simple_pull_le16(buf); @@ -184,8 +184,8 @@ static void health_fault_test(struct bt_mesh_model *model, { struct os_mbuf *sdu = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX); struct bt_mesh_health_srv *srv = model->user_data; - u16_t company_id; - u8_t test_id; + uint16_t company_id; + uint8_t test_id; BT_DBG(""); @@ -219,7 +219,7 @@ static void send_attention_status(struct bt_mesh_model *model, { struct os_mbuf *msg = BT_MESH_MODEL_BUF(OP_ATTENTION_STATUS, 1); struct bt_mesh_health_srv *srv = model->user_data; - u8_t time; + uint8_t time; time = k_delayed_work_remaining_get(&srv->attn_timer) / 1000; BT_DBG("%u second%s", time, (time == 1) ? "" : "s"); @@ -248,7 +248,7 @@ static void attention_set_unrel(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { - u8_t time; + uint8_t time; time = net_buf_simple_pull_u8(buf); @@ -297,7 +297,7 @@ static void health_period_set_unrel(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { - u8_t period; + uint8_t period; period = net_buf_simple_pull_u8(buf); if (period > 15) { @@ -389,10 +389,6 @@ static int health_srv_init(struct bt_mesh_model *model) struct bt_mesh_health_srv *srv = model->user_data; if (!srv) { - if (!bt_mesh_model_in_primary(model)) { - return 0; - } - BT_ERR("No Health Server context provided"); return -EINVAL; } @@ -420,7 +416,7 @@ const struct bt_mesh_model_cb bt_mesh_health_srv_cb = { .init = health_srv_init, }; -void bt_mesh_attention(struct bt_mesh_model *model, u8_t time) +void bt_mesh_attention(struct bt_mesh_model *model, uint8_t time) { struct bt_mesh_health_srv *srv; diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/heartbeat.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/heartbeat.c new file mode 100644 index 00000000..538a1cb6 --- /dev/null +++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/heartbeat.c @@ -0,0 +1,351 @@ +/* + * Copyright (c) 2020 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define MESH_LOG_MODULE BLE_MESH_HEARTBEAT_LOG + +#include "mesh_priv.h" +#include "net.h" +#include "rpl.h" +#include "access.h" +#include "lpn.h" +#include "settings.h" +#include "transport.h" +#include "heartbeat.h" +#include "foundation.h" +#include "mesh/glue.h" + +struct bt_mesh_hb_cb hb_cb; + +static struct bt_mesh_hb_pub pub; +static struct bt_mesh_hb_sub sub; +static struct k_delayed_work sub_timer; +static struct k_delayed_work pub_timer; + +static int64_t sub_remaining(void) +{ + if (sub.dst == BT_MESH_ADDR_UNASSIGNED) { + return 0U; + } + + return k_delayed_work_remaining_get(&sub_timer) / MSEC_PER_SEC; +} + +static void hb_publish_end_cb(int err, void *cb_data) +{ + if (pub.period && pub.count > 1) { + k_delayed_work_submit(&pub_timer, K_SECONDS(pub.period)); + } + + if (pub.count != 0xffff) { + pub.count--; + } +} + +static void notify_recv(uint8_t hops, uint16_t feat) +{ + sub.remaining = sub_remaining(); + + if (hb_cb.recv != NULL) { + hb_cb.recv(&sub, hops, feat); + } +} + +static void notify_sub_end(void) +{ + sub.remaining = 0; + + if (hb_cb.sub_end != NULL) { + hb_cb.sub_end(&sub); + } +} + +static void sub_end(struct ble_npl_event *work) +{ + notify_sub_end(); +} + +static int heartbeat_send(const struct bt_mesh_send_cb *cb, void *cb_data) +{ + uint16_t feat = 0U; + struct __packed { + uint8_t init_ttl; + uint16_t feat; + } hb; + struct bt_mesh_msg_ctx ctx = { + .net_idx = pub.net_idx, + .app_idx = BT_MESH_KEY_UNUSED, + .addr = pub.dst, + .send_ttl = pub.ttl, + }; + struct bt_mesh_net_tx tx = { + .sub = bt_mesh_subnet_get(pub.net_idx), + .ctx = &ctx, + .src = bt_mesh_primary_addr(), + .xmit = bt_mesh_net_transmit_get(), + }; + + /* Do nothing if heartbeat publication is not enabled */ + if (pub.dst == BT_MESH_ADDR_UNASSIGNED) { + return 0U; + } + + hb.init_ttl = pub.ttl; + + if (bt_mesh_relay_get() == BT_MESH_RELAY_ENABLED) { + feat |= BT_MESH_FEAT_RELAY; + } + + if (bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED) { + feat |= BT_MESH_FEAT_PROXY; + } + + if (bt_mesh_friend_get() == BT_MESH_FRIEND_ENABLED) { + feat |= BT_MESH_FEAT_FRIEND; + } + + if (bt_mesh_lpn_established()) { + feat |= BT_MESH_FEAT_LOW_POWER; + } + + hb.feat = sys_cpu_to_be16(feat); + + BT_DBG("InitTTL %u feat 0x%04x", pub.ttl, feat); + + return bt_mesh_ctl_send(&tx, TRANS_CTL_OP_HEARTBEAT, &hb, sizeof(hb), + cb, cb_data); +} + +static void hb_publish_start_cb(uint16_t duration, int err, void *cb_data) +{ + if (err) { + hb_publish_end_cb(err, cb_data); + } +} + +static void hb_publish(struct ble_npl_event *work) +{ + static const struct bt_mesh_send_cb publish_cb = { + .start = hb_publish_start_cb, + .end = hb_publish_end_cb, + }; + struct bt_mesh_subnet *sub; + int err; + + BT_DBG("hb_pub.count: %u", pub.count); + + sub = bt_mesh_subnet_get(pub.net_idx); + if (!sub) { + BT_ERR("No matching subnet for idx 0x%02x", pub.net_idx); + pub.dst = BT_MESH_ADDR_UNASSIGNED; + return; + } + + if (pub.count == 0U) { + return; + } + + err = heartbeat_send(&publish_cb, NULL); + if (err) { + hb_publish_end_cb(err, NULL); + } +} + +int bt_mesh_hb_recv(struct bt_mesh_net_rx *rx, struct os_mbuf *buf) +{ + uint8_t init_ttl, hops; + uint16_t feat; + + if (buf->om_len < 3) { + BT_ERR("Too short heartbeat message"); + return -EINVAL; + } + + init_ttl = (net_buf_simple_pull_u8(buf) & 0x7f); + feat = net_buf_simple_pull_be16(buf); + + hops = (init_ttl - rx->ctx.recv_ttl + 1); + + if (rx->ctx.addr != sub.src || rx->ctx.recv_dst != sub.dst) { + BT_DBG("No subscription for received heartbeat"); + return 0; + } + + if (!k_delayed_work_pending(&sub_timer)) { + BT_DBG("Heartbeat subscription period expired"); + return 0; + } + + sub.min_hops = MIN(sub.min_hops, hops); + sub.max_hops = MAX(sub.max_hops, hops); + + if (sub.count < 0xffff) { + sub.count++; + } + + BT_DBG("src 0x%04x TTL %u InitTTL %u (%u hop%s) feat 0x%04x", + rx->ctx.addr, rx->ctx.recv_ttl, init_ttl, hops, + (hops == 1U) ? "" : "s", feat); + + notify_recv(hops, feat); + + return 0; +} + +static void pub_disable(void) +{ + BT_DBG(""); + + pub.dst = BT_MESH_ADDR_UNASSIGNED; + pub.count = 0U; + pub.ttl = 0U; + pub.period = 0U; + + k_delayed_work_cancel(&pub_timer); +} + +uint8_t bt_mesh_hb_pub_set(struct bt_mesh_hb_pub *new_pub) +{ + if (!new_pub || new_pub->dst == BT_MESH_ADDR_UNASSIGNED) { + pub_disable(); + + if (IS_ENABLED(CONFIG_BT_SETTINGS) && + bt_mesh_is_provisioned()) { + bt_mesh_store_hb_pub(); + } + + return STATUS_SUCCESS; + } + + if (!bt_mesh_subnet_get(new_pub->net_idx)) { + BT_ERR("Unknown NetKey 0x%04x", new_pub->net_idx); + return STATUS_INVALID_NETKEY; + } + + new_pub->feat &= BT_MESH_FEAT_SUPPORTED; + pub = *new_pub; + + if (!bt_mesh_is_provisioned()) { + return STATUS_SUCCESS; + } + + /* The first Heartbeat message shall be published as soon as possible + * after the Heartbeat Publication Period state has been configured for + * periodic publishing. + */ + if (pub.period && pub.count) { + k_delayed_work_submit(&pub_timer, K_NO_WAIT); + } else { + k_delayed_work_cancel(&pub_timer); + } + + if (IS_ENABLED(CONFIG_BT_SETTINGS)) { + bt_mesh_store_hb_pub(); + } + + return STATUS_SUCCESS; +} + +void bt_mesh_hb_pub_get(struct bt_mesh_hb_pub *get) +{ + *get = pub; +} + +uint8_t bt_mesh_hb_sub_set(uint16_t src, uint16_t dst, uint32_t period) +{ + if (src != BT_MESH_ADDR_UNASSIGNED && !BT_MESH_ADDR_IS_UNICAST(src)) { + BT_WARN("Prohibited source address"); + return STATUS_INVALID_ADDRESS; + } + + if (BT_MESH_ADDR_IS_VIRTUAL(dst) || BT_MESH_ADDR_IS_RFU(dst) || + (BT_MESH_ADDR_IS_UNICAST(dst) && dst != bt_mesh_primary_addr())) { + BT_WARN("Prohibited destination address"); + return STATUS_INVALID_ADDRESS; + } + + if (period > (1U << 16)) { + BT_WARN("Prohibited subscription period %u s", period); + return STATUS_CANNOT_SET; + } + + /* Only an explicit address change to unassigned should trigger clearing + * of the values according to MESH/NODE/CFG/HBS/BV-02-C. + */ + if (src == BT_MESH_ADDR_UNASSIGNED || dst == BT_MESH_ADDR_UNASSIGNED) { + sub.src = BT_MESH_ADDR_UNASSIGNED; + sub.dst = BT_MESH_ADDR_UNASSIGNED; + sub.min_hops = 0U; + sub.max_hops = 0U; + sub.count = 0U; + sub.period = sub.period - sub_remaining(); + k_delayed_work_cancel(&sub_timer); + notify_sub_end(); + } else if (period) { + sub.src = src; + sub.dst = dst; + sub.min_hops = BT_MESH_TTL_MAX; + sub.max_hops = 0U; + sub.count = 0U; + sub.period = period; + k_delayed_work_submit(&sub_timer, K_SECONDS(period)); + } else { + /* Clearing the period should stop heartbeat subscription + * without clearing the parameters, so we can still read them. + */ + sub.period = sub.period - sub_remaining(); + k_delayed_work_cancel(&sub_timer); + notify_sub_end(); + } + + return STATUS_SUCCESS; +} + +void bt_mesh_hb_sub_get(struct bt_mesh_hb_sub *get) +{ + *get = sub; + get->remaining = sub_remaining(); +} + +void bt_mesh_hb_feature_changed(uint16_t features) +{ + if (pub.dst == BT_MESH_ADDR_UNASSIGNED) { + return; + } + + if (!(pub.feat & features)) { + return; + } + + heartbeat_send(NULL, NULL); +} + +void bt_mesh_hb_init(void) +{ + pub.net_idx = BT_MESH_KEY_UNUSED; + k_delayed_work_init(&pub_timer, hb_publish); + k_delayed_work_init(&sub_timer, sub_end); +} + +void bt_mesh_hb_start(void) +{ + if (pub.count && pub.period) { + BT_DBG("Starting heartbeat publication"); + k_delayed_work_submit(&pub_timer, K_NO_WAIT); + } +} + +void bt_mesh_hb_suspend(void) +{ + k_delayed_work_cancel(&pub_timer); +} + +void bt_mesh_hb_resume(void) +{ + if (pub.period && pub.count) { + BT_DBG("Starting heartbeat publication"); + k_delayed_work_submit(&pub_timer, K_NO_WAIT); + } +} diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/heartbeat.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/heartbeat.h new file mode 100644 index 00000000..c43683fe --- /dev/null +++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/heartbeat.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2020 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "mesh/heartbeat.h" + +static inline uint16_t bt_mesh_hb_pwr2(uint8_t val) +{ + if (!val) { + return 0x0000; + } else if (val == 0xff || val == 0x11) { + return 0xffff; + } else { + return (1 << (val - 1)); + } +} + +static inline uint8_t bt_mesh_hb_log(uint32_t val) +{ + if (!val) { + return 0x00; + } else if (val == 0xffff) { + return 0xff; + } else { + return 32 - __builtin_clz(val); + } +} + +void bt_mesh_hb_init(void); +void bt_mesh_hb_start(void); +void bt_mesh_hb_suspend(void); +void bt_mesh_hb_resume(void); + +int bt_mesh_hb_recv(struct bt_mesh_net_rx *rx, struct os_mbuf *buf); +void bt_mesh_hb_feature_changed(uint16_t features); + +uint8_t bt_mesh_hb_pub_set(struct bt_mesh_hb_pub *hb_pub); +uint8_t bt_mesh_hb_sub_set(uint16_t src, uint16_t dst, uint32_t period); diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/light_model.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/light_model.c index b6d83818..bc4792c6 100644 --- a/src/libs/mynewt-nimble/nimble/host/mesh/src/light_model.c +++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/light_model.c @@ -6,52 +6,52 @@ #include "light_model.h" -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 update_light_state(void) { - console_printf("Light state: onoff=%d lvl=0x%04x\n", gen_onoff_state, (u16_t)gen_level_state); + console_printf("Light state: onoff=%d lvl=0x%04x\n", gen_onoff_state, (uint16_t)gen_level_state); } -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); } diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/light_model.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/light_model.h index 95fcdb78..d5f95943 100644 --- a/src/libs/mynewt-nimble/nimble/host/mesh/src/light_model.h +++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/light_model.h @@ -9,11 +9,11 @@ #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); #endif diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/lpn.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/lpn.c index ec012a5f..bd48c088 100644 --- a/src/libs/mynewt-nimble/nimble/host/mesh/src/lpn.c +++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/lpn.c @@ -19,6 +19,7 @@ #include "adv.h" #include "net.h" #include "transport.h" +#include "heartbeat.h" #include "access.h" #include "beacon.h" #include "foundation.h" @@ -42,27 +43,33 @@ #define POLL_RETRY_TIMEOUT K_MSEC(100) -#define REQ_RETRY_DURATION(lpn) (4 * (LPN_RECV_DELAY + (lpn)->adv_duration + \ - (lpn)->recv_win + POLL_RETRY_TIMEOUT)) +#define REQ_RETRY_DURATION(lpn) (LPN_RECV_DELAY + (lpn)->adv_duration + \ + (lpn)->recv_win + POLL_RETRY_TIMEOUT) #define POLL_TIMEOUT_INIT (MYNEWT_VAL(BLE_MESH_LPN_INIT_POLL_TIMEOUT) * 100) -#define POLL_TIMEOUT_MAX(lpn) ((MYNEWT_VAL(BLE_MESH_LPN_POLL_TIMEOUT) * 100) - \ - REQ_RETRY_DURATION(lpn)) -#define REQ_ATTEMPTS(lpn) (POLL_TIMEOUT_MAX(lpn) < K_SECONDS(3) ? 2 : 4) -#define CLEAR_ATTEMPTS 2 +#define POLL_TIMEOUT (MYNEWT_VAL(BLE_MESH_LPN_RECV_DELAY) * 100) + +#define REQ_ATTEMPTS_MAX 6 +#define REQ_ATTEMPTS(lpn) MIN(REQ_ATTEMPTS_MAX, \ + POLL_TIMEOUT / REQ_RETRY_DURATION(lpn)) + +#define POLL_TIMEOUT_MAX(lpn) (POLL_TIMEOUT - \ + (REQ_ATTEMPTS(lpn) * REQ_RETRY_DURATION(lpn))) + +#define CLEAR_ATTEMPTS 3 #define LPN_CRITERIA ((MYNEWT_VAL(BLE_MESH_LPN_MIN_QUEUE_SIZE)) | \ (MYNEWT_VAL(BLE_MESH_LPN_RSSI_FACTOR) << 3) | \ (MYNEWT_VAL(BLE_MESH_LPN_RECV_WIN_FACTOR) << 5)) -#define POLL_TO(to) { (u8_t)((to) >> 16), (u8_t)((to) >> 8), (u8_t)(to) } +#define POLL_TO(to) { (uint8_t)((to) >> 16), (uint8_t)((to) >> 8), (uint8_t)(to) } #define LPN_POLL_TO POLL_TO(MYNEWT_VAL(BLE_MESH_LPN_POLL_TIMEOUT)) /* 2 transmissions, 20ms interval */ #define POLL_XMIT BT_MESH_TRANSMIT(1, 20) -static void (*lpn_cb)(u16_t friend_addr, bool established); +static void (*lpn_cb)(uint16_t friend_addr, bool established); #if MYNEWT_VAL(BLE_MESH_LOW_POWER_LOG_LVL) == LOG_LEVEL_DEBUG static const char *state2str(int state) @@ -145,10 +152,7 @@ static void friend_clear_sent(int err, void *user_data) { struct bt_mesh_lpn *lpn = &bt_mesh.lpn; - /* We're switching away from Low Power behavior, so permanently - * enable scanning. - */ - bt_mesh_scan_enable(); + /* Scanning will enable if lpn state still enabled */ lpn->req_attempts++; @@ -170,31 +174,30 @@ static const struct bt_mesh_send_cb clear_sent_cb = { static int send_friend_clear(void) { struct bt_mesh_msg_ctx ctx = { - .net_idx = bt_mesh.sub[0].net_idx, + .net_idx = bt_mesh.lpn.sub->net_idx, .app_idx = BT_MESH_KEY_UNUSED, .addr = bt_mesh.lpn.frnd, .send_ttl = 0, }; struct bt_mesh_net_tx tx = { - .sub = &bt_mesh.sub[0], + .sub = bt_mesh.lpn.sub, .ctx = &ctx, .src = bt_mesh_primary_addr(), .xmit = bt_mesh_net_transmit_get(), }; struct bt_mesh_ctl_friend_clear req = { .lpn_addr = sys_cpu_to_be16(tx.src), - .lpn_counter = sys_cpu_to_be16(bt_mesh.lpn.counter), + .lpn_counter = sys_cpu_to_be16(bt_mesh.lpn.lpn_counter), }; BT_DBG(""); return bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_CLEAR, &req, - sizeof(req), NULL, &clear_sent_cb, NULL); + sizeof(req), &clear_sent_cb, NULL); } static void clear_friendship(bool force, bool disable) { - struct bt_mesh_cfg_srv *cfg = bt_mesh_cfg_get(); struct bt_mesh_lpn *lpn = &bt_mesh.lpn; BT_DBG("force %u disable %u", force, disable); @@ -210,8 +213,6 @@ static void clear_friendship(bool force, bool disable) k_delayed_work_cancel(&lpn->timer); - friend_cred_del(bt_mesh.sub[0].net_idx, lpn->frnd); - if (lpn->clear_success) { lpn->old_friend = BT_MESH_ADDR_UNASSIGNED; } else { @@ -231,6 +232,7 @@ static void clear_friendship(bool force, bool disable) lpn->sent_req = 0; lpn->established = 0; lpn->clear_success = 0; + lpn->sub = NULL; group_zero(lpn->added); group_zero(lpn->pending); @@ -242,9 +244,7 @@ static void clear_friendship(bool force, bool disable) */ lpn->groups_changed = 1; - if (cfg->hb_pub.feat & BT_MESH_FEAT_LOW_POWER) { - bt_mesh_heartbeat_send(); - } + bt_mesh_hb_feature_changed(BT_MESH_FEAT_LOW_POWER); if (disable) { lpn_set_state(BT_MESH_LPN_DISABLED); @@ -255,7 +255,7 @@ static void clear_friendship(bool force, bool disable) k_delayed_work_submit(&lpn->timer, FRIEND_REQ_RETRY_TIMEOUT); } -static void friend_req_sent(u16_t duration, int err, void *user_data) +static void friend_req_sent(uint16_t duration, int err, void *user_data) { struct bt_mesh_lpn *lpn = &bt_mesh.lpn; @@ -284,33 +284,43 @@ static int send_friend_req(struct bt_mesh_lpn *lpn) { const struct bt_mesh_comp *comp = bt_mesh_comp_get(); struct bt_mesh_msg_ctx ctx = { - .net_idx = bt_mesh.sub[0].net_idx, .app_idx = BT_MESH_KEY_UNUSED, .addr = BT_MESH_ADDR_FRIENDS, .send_ttl = 0, }; struct bt_mesh_net_tx tx = { - .sub = &bt_mesh.sub[0], .ctx = &ctx, .src = bt_mesh_primary_addr(), .xmit = POLL_XMIT, }; + + lpn->lpn_counter++; + struct bt_mesh_ctl_friend_req req = { .criteria = LPN_CRITERIA, .recv_delay = LPN_RECV_DELAY, .poll_to = LPN_POLL_TO, - .prev_addr = lpn->old_friend, + .prev_addr = sys_cpu_to_be16(lpn->old_friend), .num_elem = comp->elem_count, - .lpn_counter = sys_cpu_to_be16(lpn->counter), + .lpn_counter = sys_cpu_to_be16(lpn->lpn_counter), }; BT_DBG(""); + lpn->sub = bt_mesh_subnet_next(NULL); + if (!lpn->sub) { + BT_ERR("No subnets, can't start LPN mode"); + return -ENOENT; + } + + ctx.net_idx = lpn->sub->net_idx; + tx.sub = lpn->sub; + return bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_REQ, &req, - sizeof(req), NULL, &friend_req_sent_cb, NULL); + sizeof(req), &friend_req_sent_cb, NULL); } -static void req_sent(u16_t duration, int err, void *user_data) +static void req_sent(uint16_t duration, int err, void *user_data) { struct bt_mesh_lpn *lpn = &bt_mesh.lpn; @@ -337,6 +347,7 @@ static void req_sent(u16_t duration, int err, void *user_data) k_delayed_work_submit(&lpn->timer, LPN_RECV_DELAY - SCAN_LATENCY); } else { + lpn_set_state(BT_MESH_LPN_WAIT_UPDATE); k_delayed_work_submit(&lpn->timer, LPN_RECV_DELAY + duration + lpn->recv_win); @@ -350,20 +361,20 @@ static const struct bt_mesh_send_cb req_sent_cb = { static int send_friend_poll(void) { struct bt_mesh_msg_ctx ctx = { - .net_idx = bt_mesh.sub[0].net_idx, + .net_idx = bt_mesh.lpn.sub->net_idx, .app_idx = BT_MESH_KEY_UNUSED, .addr = bt_mesh.lpn.frnd, .send_ttl = 0, }; struct bt_mesh_net_tx tx = { - .sub = &bt_mesh.sub[0], + .sub = bt_mesh.lpn.sub, .ctx = &ctx, .src = bt_mesh_primary_addr(), .xmit = POLL_XMIT, .friend_cred = true, }; struct bt_mesh_lpn *lpn = &bt_mesh.lpn; - u8_t fsn = lpn->fsn; + uint8_t fsn = lpn->fsn; int err; BT_DBG("lpn->sent_req 0x%02x", lpn->sent_req); @@ -377,7 +388,7 @@ static int send_friend_poll(void) } err = bt_mesh_ctl_send(&tx, TRANS_CTL_OP_FRIEND_POLL, &fsn, 1, - NULL, &req_sent_cb, NULL); + &req_sent_cb, NULL); if (err == 0) { lpn->pending_poll = 0; lpn->sent_req = TRANS_CTL_OP_FRIEND_POLL; @@ -477,14 +488,22 @@ void bt_mesh_lpn_msg_received(struct bt_mesh_net_rx *rx) send_friend_poll(); } +static int friend_cred_create(struct bt_mesh_net_cred *cred, + const uint8_t key[16]) +{ + struct bt_mesh_lpn *lpn = &bt_mesh.lpn; + + return bt_mesh_friend_cred_create(cred, bt_mesh_primary_addr(), + lpn->frnd, lpn->lpn_counter, + lpn->frnd_counter, key); +} + int bt_mesh_lpn_friend_offer(struct bt_mesh_net_rx *rx, struct os_mbuf *buf) { struct bt_mesh_ctl_friend_offer *msg = (void *)buf->om_data; struct bt_mesh_lpn *lpn = &bt_mesh.lpn; - struct bt_mesh_subnet *sub = rx->sub; - struct friend_cred *cred; - u16_t frnd_counter; + uint16_t frnd_counter; int err; if (buf->om_len < sizeof(*msg)) { @@ -508,16 +527,24 @@ int bt_mesh_lpn_friend_offer(struct bt_mesh_net_rx *rx, msg->recv_win, msg->queue_size, msg->sub_list_size, msg->rssi, frnd_counter); + lpn->frnd_counter = frnd_counter; lpn->frnd = rx->ctx.addr; - cred = friend_cred_create(sub, lpn->frnd, lpn->counter, frnd_counter); - if (!cred) { - lpn->frnd = BT_MESH_ADDR_UNASSIGNED; - return -ENOMEM; + /* Create friend credentials for each of the valid keys in the + * friendship subnet: + */ + for (int i = 0; i < ARRAY_SIZE(lpn->cred); i++) { + if (!lpn->sub->keys[i].valid) { + continue; + } + + err = friend_cred_create(&lpn->cred[i], lpn->sub->keys[i].net); + if (err) { + lpn->frnd = BT_MESH_ADDR_UNASSIGNED; + return err; + } } - /* TODO: Add offer acceptance criteria check */ - k_delayed_work_cancel(&lpn->timer); lpn->recv_win = msg->recv_win; @@ -525,15 +552,13 @@ int bt_mesh_lpn_friend_offer(struct bt_mesh_net_rx *rx, err = send_friend_poll(); if (err) { - friend_cred_clear(cred); + lpn->sub = NULL; lpn->frnd = BT_MESH_ADDR_UNASSIGNED; lpn->recv_win = 0; lpn->queue_size = 0; return err; } - lpn->counter++; - return 0; } @@ -542,7 +567,7 @@ int bt_mesh_lpn_friend_clear_cfm(struct bt_mesh_net_rx *rx, { struct bt_mesh_ctl_friend_clear_confirm *msg = (void *)buf->om_data; struct bt_mesh_lpn *lpn = &bt_mesh.lpn; - u16_t addr, counter; + uint16_t addr, counter; if (buf->om_len < sizeof(*msg)) { BT_WARN("Too short Friend Clear Confirm"); @@ -559,7 +584,7 @@ int bt_mesh_lpn_friend_clear_cfm(struct bt_mesh_net_rx *rx, BT_DBG("LPNAddress 0x%04x LPNCounter 0x%04x", addr, counter); - if (addr != bt_mesh_primary_addr() || counter != lpn->counter) { + if (addr != bt_mesh_primary_addr() || counter != lpn->lpn_counter) { BT_WARN("Invalid parameters in Friend Clear Confirm"); return 0; } @@ -570,10 +595,10 @@ int bt_mesh_lpn_friend_clear_cfm(struct bt_mesh_net_rx *rx, return 0; } -static void lpn_group_add(u16_t group) +static void lpn_group_add(uint16_t group) { struct bt_mesh_lpn *lpn = &bt_mesh.lpn; - u16_t *free_slot = NULL; + uint16_t *free_slot = NULL; int i; for (i = 0; i < ARRAY_SIZE(lpn->groups); i++) { @@ -596,7 +621,7 @@ static void lpn_group_add(u16_t group) lpn->groups_changed = 1; } -static void lpn_group_del(u16_t group) +static void lpn_group_del(uint16_t group) { struct bt_mesh_lpn *lpn = &bt_mesh.lpn; int i; @@ -627,18 +652,18 @@ static inline int group_popcount(atomic_t *target) #endif } -static bool sub_update(u8_t op) +static bool sub_update(uint8_t op) { struct bt_mesh_lpn *lpn = &bt_mesh.lpn; int added_count = group_popcount(lpn->added); struct bt_mesh_msg_ctx ctx = { - .net_idx = bt_mesh.sub[0].net_idx, + .net_idx = lpn->sub->net_idx, .app_idx = BT_MESH_KEY_UNUSED, .addr = lpn->frnd, .send_ttl = 0, }; struct bt_mesh_net_tx tx = { - .sub = &bt_mesh.sub[0], + .sub = lpn->sub, .ctx = &ctx, .src = bt_mesh_primary_addr(), .xmit = POLL_XMIT, @@ -688,8 +713,8 @@ static bool sub_update(u8_t op) req.xact = lpn->xact_next++; - if (bt_mesh_ctl_send(&tx, op, &req, 1 + g * 2, NULL, - &req_sent_cb, NULL) < 0) { + if (bt_mesh_ctl_send(&tx, op, &req, 1 + g * 2, + &req_sent_cb, NULL) < 0) { group_zero(lpn->pending); return false; } @@ -711,7 +736,7 @@ static void update_timeout(struct bt_mesh_lpn *lpn) bt_mesh_scan_disable(); } - if (lpn->req_attempts < 6) { + if (lpn->req_attempts < REQ_ATTEMPTS(lpn)) { BT_WARN("Retrying first Friend Poll"); lpn->sent_req = 0; if (send_friend_poll() == 0) { @@ -759,14 +784,14 @@ static void lpn_timeout(struct ble_npl_event *work) if (IS_ENABLED(CONFIG_BT_MESH_LPN_ESTABLISHMENT)) { bt_mesh_scan_disable(); } - lpn->counter++; + lpn->lpn_counter++; lpn_set_state(BT_MESH_LPN_ENABLED); lpn->sent_req = 0U; k_delayed_work_submit(&lpn->timer, FRIEND_REQ_RETRY_TIMEOUT); break; case BT_MESH_LPN_ESTABLISHED: if (lpn->req_attempts < REQ_ATTEMPTS(lpn)) { - u8_t req = lpn->sent_req; + uint8_t req = lpn->sent_req; lpn->sent_req = 0; @@ -800,7 +825,7 @@ static void lpn_timeout(struct ble_npl_event *work) } } -void bt_mesh_lpn_group_add(u16_t group) +void bt_mesh_lpn_group_add(uint16_t group) { BT_DBG("group 0x%04x", group); @@ -813,7 +838,7 @@ void bt_mesh_lpn_group_add(u16_t group) sub_update(TRANS_CTL_OP_FRIEND_SUB_ADD); } -void bt_mesh_lpn_group_del(u16_t *groups, size_t group_count) +void bt_mesh_lpn_group_del(uint16_t *groups, size_t group_count) { int i; @@ -831,7 +856,7 @@ void bt_mesh_lpn_group_del(u16_t *groups, size_t group_count) sub_update(TRANS_CTL_OP_FRIEND_SUB_REM); } -static s32_t poll_timeout(struct bt_mesh_lpn *lpn) +static int32_t poll_timeout(struct bt_mesh_lpn *lpn) { /* If we're waiting for segment acks keep polling at high freq */ if (bt_mesh_tx_in_progress()) { @@ -908,7 +933,9 @@ int bt_mesh_lpn_friend_sub_cfm(struct bt_mesh_net_rx *rx, } if (!lpn->sent_req) { - k_delayed_work_submit(&lpn->timer, poll_timeout(lpn)); + int32_t timeout = poll_timeout(lpn); + + k_delayed_work_submit(&lpn->timer, K_MSEC(timeout)); } return 0; @@ -920,7 +947,7 @@ int bt_mesh_lpn_friend_update(struct bt_mesh_net_rx *rx, struct bt_mesh_ctl_friend_update *msg = (void *)buf->om_data; struct bt_mesh_lpn *lpn = &bt_mesh.lpn; struct bt_mesh_subnet *sub = rx->sub; - u32_t iv_index; + uint32_t iv_index; if (buf->om_len < sizeof(*msg)) { BT_WARN("Too short Friend Update"); @@ -944,8 +971,6 @@ int bt_mesh_lpn_friend_update(struct bt_mesh_net_rx *rx, } if (!lpn->established) { - struct bt_mesh_cfg_srv *cfg = bt_mesh_cfg_get(); - /* This is normally checked on the transport layer, however * in this state we're also still accepting master * credentials so we need to ensure the right ones (Friend @@ -960,9 +985,7 @@ int bt_mesh_lpn_friend_update(struct bt_mesh_net_rx *rx, BT_INFO("Friendship established with 0x%04x", lpn->frnd); - if (cfg->hb_pub.feat & BT_MESH_FEAT_LOW_POWER) { - bt_mesh_heartbeat_send(); - } + bt_mesh_hb_feature_changed(BT_MESH_FEAT_LOW_POWER); if (lpn_cb) { lpn_cb(lpn->frnd, true); @@ -980,11 +1003,7 @@ int bt_mesh_lpn_friend_update(struct bt_mesh_net_rx *rx, BT_DBG("flags 0x%02x iv_index 0x%08x md %u", msg->flags, (unsigned) iv_index, msg->md); - if (bt_mesh_kr_update(sub, BT_MESH_KEY_REFRESH(msg->flags), - rx->new_key)) { - bt_mesh_net_beacon_update(sub); - } - + bt_mesh_kr_update(sub, BT_MESH_KEY_REFRESH(msg->flags), rx->new_key); bt_mesh_net_iv_update(iv_index, BT_MESH_IV_UPDATE(msg->flags)); if (lpn->groups_changed) { @@ -1002,7 +1021,9 @@ int bt_mesh_lpn_friend_update(struct bt_mesh_net_rx *rx, } if (!lpn->sent_req) { - k_delayed_work_submit(&lpn->timer, poll_timeout(lpn)); + int32_t timeout = poll_timeout(lpn); + + k_delayed_work_submit(&lpn->timer, K_MSEC(timeout)); } return 0; @@ -1019,17 +1040,41 @@ int bt_mesh_lpn_poll(void) return send_friend_poll(); } -void bt_mesh_lpn_set_cb(void (*cb)(u16_t friend_addr, bool established)) +void bt_mesh_lpn_set_cb(void (*cb)(uint16_t friend_addr, bool established)) { lpn_cb = cb; } +static void subnet_evt(struct bt_mesh_subnet *sub, enum bt_mesh_key_evt evt) +{ + switch (evt) { + case BT_MESH_KEY_DELETED: + if (sub == bt_mesh.lpn.sub) { + BT_DBG("NetKey deleted"); + clear_friendship(true, false); + } + break; + case BT_MESH_KEY_UPDATED: + BT_DBG("NetKey updated"); + friend_cred_create(&bt_mesh.lpn.cred[1], sub->keys[1].net); + break; + default: + break; + } +} + int bt_mesh_lpn_init(void) { struct bt_mesh_lpn *lpn = &bt_mesh.lpn; + if (!bt_mesh_subnet_cb_list[2]) { + bt_mesh_subnet_cb_list[2] = subnet_evt; + } + BT_DBG(""); + lpn->groups_changed = 0; + k_delayed_work_init(&lpn->timer, lpn_timeout); if (lpn->state == BT_MESH_LPN_ENABLED) { diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/lpn.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/lpn.h index 0ff6c9cf..90de2ca0 100644 --- a/src/libs/mynewt-nimble/nimble/host/mesh/src/lpn.h +++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/lpn.h @@ -28,7 +28,7 @@ static inline bool bt_mesh_lpn_established(void) #endif } -static inline bool bt_mesh_lpn_match(u16_t addr) +static inline bool bt_mesh_lpn_match(uint16_t addr) { #if (MYNEWT_VAL(BLE_MESH_LOW_POWER)) if (bt_mesh_lpn_established()) { @@ -58,8 +58,8 @@ static inline bool bt_mesh_lpn_timer(void) void bt_mesh_lpn_msg_received(struct bt_mesh_net_rx *rx); -void bt_mesh_lpn_group_add(u16_t group); -void bt_mesh_lpn_group_del(u16_t *groups, size_t group_count); +void bt_mesh_lpn_group_add(uint16_t group); +void bt_mesh_lpn_group_del(uint16_t *groups, size_t group_count); void bt_mesh_lpn_disable(bool force); diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/mesh.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/mesh.c index 52fbdbf6..bfb0e1af 100644 --- a/src/libs/mynewt-nimble/nimble/host/mesh/src/mesh.c +++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/mesh.c @@ -18,7 +18,12 @@ #include "adv.h" #include "prov.h" +#include "provisioner.h" #include "net.h" +#include "subnet.h" +#include "app_keys.h" +#include "rpl.h" +#include "cfg.h" #include "beacon.h" #include "lpn.h" #include "friend.h" @@ -26,16 +31,18 @@ #include "access.h" #include "foundation.h" #include "proxy.h" +#include "heartbeat.h" #include "shell.h" #include "mesh_priv.h" #include "settings.h" -u8_t g_mesh_addr_type; + +uint8_t g_mesh_addr_type; static struct ble_gap_event_listener mesh_event_listener; -int bt_mesh_provision(const u8_t net_key[16], u16_t net_idx, - u8_t flags, u32_t iv_index, u16_t addr, - const u8_t dev_key[16]) +int bt_mesh_provision(const uint8_t net_key[16], uint16_t net_idx, + uint8_t flags, uint32_t iv_index, uint16_t addr, + const uint8_t dev_key[16]) { bool pb_gatt_enabled; int err; @@ -58,6 +65,53 @@ int bt_mesh_provision(const u8_t net_key[16], u16_t net_idx, pb_gatt_enabled = false; } + /* + * FIXME: + * Should net_key and iv_index be over-ridden? + */ + if (IS_ENABLED(BLE_MESH_CDB)) { + const struct bt_mesh_comp *comp; + const struct bt_mesh_prov *prov; + struct bt_mesh_cdb_node *node; + + if (!atomic_test_bit(bt_mesh_cdb.flags, + BT_MESH_CDB_VALID)) { + BT_ERR("No valid network"); + atomic_clear_bit(bt_mesh.flags, BT_MESH_VALID); + return -EINVAL; + } + + comp = bt_mesh_comp_get(); + if (comp == NULL) { + BT_ERR("Failed to get node composition"); + atomic_clear_bit(bt_mesh.flags, BT_MESH_VALID); + return -EINVAL; + } + + if (!bt_mesh_cdb_subnet_get(net_idx)) { + BT_ERR("No subnet with idx %d", net_idx); + atomic_clear_bit(bt_mesh.flags, BT_MESH_VALID); + return -ENOENT; + } + + prov = bt_mesh_prov_get(); + node = bt_mesh_cdb_node_alloc(prov->uuid, addr, + comp->elem_count, net_idx); + if (node == NULL) { + BT_ERR("Failed to allocate database node"); + atomic_clear_bit(bt_mesh.flags, BT_MESH_VALID); + return -ENOMEM; + } + + addr = node->addr; + iv_index = bt_mesh_cdb.iv_index; + memcpy(node->dev_key, dev_key, 16); + + if (IS_ENABLED(CONFIG_BT_SETTINGS)) { + bt_mesh_store_cdb_node(node); + } + } + err = bt_mesh_net_create(net_idx, flags, net_key, iv_index); if (err) { atomic_clear_bit(bt_mesh.flags, BT_MESH_VALID); @@ -75,20 +129,18 @@ int bt_mesh_provision(const u8_t net_key[16], u16_t net_idx, memcpy(bt_mesh.dev_key, dev_key, 16); - if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - BT_DBG("Storing network information persistently"); - bt_mesh_store_net(); - bt_mesh_store_subnet(&bt_mesh.sub[0]); - bt_mesh_store_iv(false); + if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER) && + IS_ENABLED(CONFIG_BT_MESH_LPN_SUB_ALL_NODES_ADDR)) { + bt_mesh_lpn_group_add(BT_MESH_ADDR_ALL_NODES); } - bt_mesh_net_start(); + bt_mesh_start(); return 0; } -int bt_mesh_provision_adv(const u8_t uuid[16], u16_t net_idx, u16_t addr, - u8_t attention_duration) +int bt_mesh_provision_adv(const uint8_t uuid[16], uint16_t net_idx, uint16_t addr, + uint8_t attention_duration) { if (!atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) { return -EINVAL; @@ -122,25 +174,30 @@ void bt_mesh_reset(void) bt_mesh_cfg_reset(); - bt_mesh_rx_reset(); - bt_mesh_tx_reset(); + bt_mesh_trans_reset(); + bt_mesh_app_keys_reset(); + bt_mesh_net_keys_reset(); + + bt_mesh_net_loopback_clear(BT_MESH_KEY_ANY); if ((MYNEWT_VAL(BLE_MESH_LOW_POWER))) { + if (IS_ENABLED(CONFIG_BT_MESH_LPN_SUB_ALL_NODES_ADDR)) { + uint16_t group = BT_MESH_ADDR_ALL_NODES; + + bt_mesh_lpn_group_del(&group, 1); + } + bt_mesh_lpn_disable(true); } if ((MYNEWT_VAL(BLE_MESH_FRIEND))) { - bt_mesh_friend_clear_net_idx(BT_MESH_KEY_ANY); + bt_mesh_friends_clear(); } if ((MYNEWT_VAL(BLE_MESH_GATT_PROXY))) { bt_mesh_proxy_gatt_disable(); } - if ((MYNEWT_VAL(BLE_MESH_PB_GATT))) { - bt_mesh_proxy_prov_enable(); - } - if (IS_ENABLED(CONFIG_BT_SETTINGS)) { bt_mesh_clear_net(); } @@ -162,55 +219,6 @@ bool bt_mesh_is_provisioned(void) return atomic_test_bit(bt_mesh.flags, BT_MESH_VALID); } -int bt_mesh_prov_enable(bt_mesh_prov_bearer_t bearers) -{ - if (bt_mesh_is_provisioned()) { - return -EALREADY; - } - - char uuid_buf[BLE_UUID_STR_LEN]; - const struct bt_mesh_prov *prov = bt_mesh_prov_get(); - ble_uuid_t *uuid = BLE_UUID128_DECLARE(); - - memcpy(BLE_UUID128(uuid)->value, prov->uuid, 16); - BT_INFO("Device UUID: %s", ble_uuid_to_str(uuid, uuid_buf)); - - if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV) && - (bearers & BT_MESH_PROV_ADV)) { - /* Make sure we're scanning for provisioning inviations */ - bt_mesh_scan_enable(); - /* Enable unprovisioned beacon sending */ - bt_mesh_beacon_enable(); - } - - if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT) && - (bearers & BT_MESH_PROV_GATT)) { - bt_mesh_proxy_prov_enable(); - bt_mesh_adv_update(); - } - - return 0; -} - -int bt_mesh_prov_disable(bt_mesh_prov_bearer_t bearers) -{ - if (bt_mesh_is_provisioned()) { - return -EALREADY; - } - - if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV) && - (bearers & BT_MESH_PROV_ADV)) { - bt_mesh_beacon_disable(); - bt_mesh_scan_disable(); - } - - if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT) && - (bearers & BT_MESH_PROV_GATT)) { - bt_mesh_proxy_prov_disable(true); - } - - return 0; -} static int bt_mesh_gap_event(struct ble_gap_event *event, void *arg) { @@ -251,9 +259,9 @@ int bt_mesh_suspend(void) return err; } - bt_mesh_hb_pub_disable(); + bt_mesh_hb_suspend(); - if (bt_mesh_beacon_get() == BT_MESH_BEACON_ENABLED) { + if (bt_mesh_beacon_enabled()) { bt_mesh_beacon_disable(); } @@ -266,7 +274,7 @@ static void model_resume(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, bool vnd, bool primary, void *user_data) { if (mod->pub && mod->pub->update) { - s32_t period_ms = bt_mesh_model_pub_period_get(mod); + int32_t period_ms = bt_mesh_model_pub_period_get(mod); if (period_ms) { k_delayed_work_submit(&mod->pub->timer, period_ms); @@ -293,7 +301,9 @@ int bt_mesh_resume(void) return err; } - if (bt_mesh_beacon_get() == BT_MESH_BEACON_ENABLED) { + bt_mesh_hb_resume(); + + if (bt_mesh_beacon_enabled()) { bt_mesh_beacon_enable(); } @@ -317,6 +327,10 @@ int bt_mesh_init(uint8_t own_addr_type, const struct bt_mesh_prov *prov, return err; } +#if (MYNEWT_VAL(BLE_MESH_PROXY)) + bt_mesh_proxy_init(); +#endif + #if (MYNEWT_VAL(BLE_MESH_PROV)) err = bt_mesh_prov_init(prov); if (err) { @@ -324,38 +338,65 @@ int bt_mesh_init(uint8_t own_addr_type, const struct bt_mesh_prov *prov, } #endif -#if (MYNEWT_VAL(BLE_MESH_PROXY)) - bt_mesh_proxy_init(); -#endif - -#if (MYNEWT_VAL(BLE_MESH_PROV)) - /* Need this to proper link.rx.buf allocation */ - bt_mesh_prov_reset_link(); -#endif - + bt_mesh_cfg_init(); bt_mesh_net_init(); bt_mesh_trans_init(); + bt_mesh_hb_init(); bt_mesh_beacon_init(); bt_mesh_adv_init(); -#if (MYNEWT_VAL(BLE_MESH_PB_ADV)) - /* Make sure we're scanning for provisioning inviations */ - bt_mesh_scan_enable(); - /* Enable unprovisioned beacon sending */ - - bt_mesh_beacon_enable(); -#endif - -#if (MYNEWT_VAL(BLE_MESH_PB_GATT)) - bt_mesh_proxy_prov_enable(); -#endif - - ble_gap_event_listener_register(&mesh_event_listener, - bt_mesh_gap_event, NULL); - #if (MYNEWT_VAL(BLE_MESH_SETTINGS)) bt_mesh_settings_init(); #endif + ble_gap_event_listener_register(&mesh_event_listener, + bt_mesh_gap_event, NULL); + return 0; } + +static void model_start(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, + bool vnd, bool primary, void *user_data) +{ + if (mod->cb && mod->cb->start) { + mod->cb->start(mod); + } +} + +int bt_mesh_start(void) +{ + if (bt_mesh_beacon_enabled()) { + bt_mesh_beacon_enable(); + } else { + bt_mesh_beacon_disable(); + } + + if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) && + bt_mesh_gatt_proxy_get() != BT_MESH_GATT_PROXY_NOT_SUPPORTED) { + bt_mesh_proxy_gatt_enable(); + bt_mesh_adv_update(); + } + + if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) { + bt_mesh_lpn_init(); + } else { + bt_mesh_scan_enable(); + } + + if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) { + bt_mesh_friend_init(); + } + + if (IS_ENABLED(CONFIG_BT_MESH_PROV)) { + struct bt_mesh_subnet *sub = bt_mesh_subnet_next(NULL); + uint16_t addr = bt_mesh_primary_addr(); + + bt_mesh_prov_complete(sub->net_idx, addr); + } + + bt_mesh_hb_start(); + + bt_mesh_model_foreach(model_start, NULL); + + return 0; +} \ No newline at end of file diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/mesh_priv.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/mesh_priv.h index f09bb230..213f5437 100644 --- a/src/libs/mynewt-nimble/nimble/host/mesh/src/mesh_priv.h +++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/mesh_priv.h @@ -8,14 +8,28 @@ #ifndef __MESH_PRIV_H #define __MESH_PRIV_H +#include +#include + #define BT_MESH_KEY_PRIMARY 0x0000 #define BT_MESH_KEY_ANY 0xffff -#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) +enum bt_mesh_key_evt { + BT_MESH_KEY_ADDED, /* New key added */ + BT_MESH_KEY_DELETED, /* Existing key deleted */ + BT_MESH_KEY_UPDATED, /* KR phase 1, second key added */ + BT_MESH_KEY_SWAPPED, /* KR phase 2, now sending on second key */ + BT_MESH_KEY_REVOKED, /* KR phase 3, old key removed */ +}; + +/** Appkey callback. Instantiate with @ref BT_MESH_APP_KEY_CB */ +struct bt_mesh_app_key_cb { + void (*evt_handler)(uint16_t app_idx, uint16_t net_idx, + enum bt_mesh_key_evt evt); +}; + struct bt_mesh_net; +int bt_mesh_start(void); #define OP_GEN_ONOFF_GET BT_MESH_MODEL_OP_2(0x82, 0x01) #define OP_GEN_ONOFF_SET BT_MESH_MODEL_OP_2(0x82, 0x02) diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/model_cli.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/model_cli.c index b00cfa52..9755ec1f 100644 --- a/src/libs/mynewt-nimble/nimble/host/mesh/src/model_cli.c +++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/model_cli.c @@ -11,19 +11,19 @@ #include "mesh/model_cli.h" #include "mesh_priv.h" -static s32_t msg_timeout = K_SECONDS(5); +static int32_t msg_timeout = K_SECONDS(5); static struct bt_mesh_gen_model_cli *gen_onoff_cli; static struct bt_mesh_gen_model_cli *gen_level_cli; -static u8_t transaction_id = 0; +static uint8_t transaction_id = 0; struct gen_onoff_param { - u8_t *state; + uint8_t *state; }; struct gen_level_param { - s16_t *level; + int16_t *level; }; static void gen_onoff_status(struct bt_mesh_model *model, @@ -32,7 +32,7 @@ static void gen_onoff_status(struct bt_mesh_model *model, { struct bt_mesh_gen_model_cli *cli = model->user_data; struct gen_onoff_param *param; - u8_t state; + uint8_t state; BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", @@ -62,7 +62,7 @@ static void gen_level_status(struct bt_mesh_model *model, { struct bt_mesh_gen_model_cli *cli = model->user_data; struct gen_level_param *param; - s16_t level; + int16_t level; BT_DBG("net_idx 0x%04x app_idx 0x%04x src 0x%04x len %u: %s", @@ -138,7 +138,7 @@ const struct bt_mesh_model_cb bt_mesh_gen_level_cli_cb = { .init = level_cli_init, }; -static int cli_wait(struct bt_mesh_gen_model_cli *cli, void *param, u32_t op) +static int cli_wait(struct bt_mesh_gen_model_cli *cli, void *param, uint32_t op) { int err; @@ -155,8 +155,8 @@ static int cli_wait(struct bt_mesh_gen_model_cli *cli, void *param, u32_t op) return err; } -int bt_mesh_gen_onoff_get(u16_t net_idx, u16_t addr, u16_t app_idx, - u8_t *state) +int bt_mesh_gen_onoff_get(uint16_t net_idx, uint16_t addr, uint16_t app_idx, + uint8_t *state) { struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 0 + 4); struct bt_mesh_msg_ctx ctx = { @@ -184,8 +184,8 @@ done: return err; } -int bt_mesh_gen_onoff_set(u16_t net_idx, u16_t addr, u16_t app_idx, - u8_t val, u8_t *state) +int bt_mesh_gen_onoff_set(uint16_t net_idx, uint16_t addr, uint16_t app_idx, + uint8_t val, uint8_t *state) { struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 2 + 4); struct bt_mesh_msg_ctx ctx = { @@ -227,8 +227,8 @@ done: return err; } -int bt_mesh_gen_level_get(u16_t net_idx, u16_t addr, u16_t app_idx, - s16_t *level) +int bt_mesh_gen_level_get(uint16_t net_idx, uint16_t addr, uint16_t app_idx, + int16_t *level) { struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 0 + 4); struct bt_mesh_msg_ctx ctx = { @@ -256,8 +256,8 @@ done: return err; } -int bt_mesh_gen_level_set(u16_t net_idx, u16_t addr, u16_t app_idx, - s16_t val, s16_t *state) +int bt_mesh_gen_level_set(uint16_t net_idx, uint16_t addr, uint16_t app_idx, + int16_t val, int16_t *state) { struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 3 + 4); struct bt_mesh_msg_ctx ctx = { diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/model_srv.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/model_srv.c index 5f5a8df4..b6f34360 100644 --- a/src/libs/mynewt-nimble/nimble/host/mesh/src/model_srv.c +++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/model_srv.c @@ -20,7 +20,7 @@ static void gen_onoff_status(struct bt_mesh_model *model, { struct bt_mesh_gen_onoff_srv *cb = model->user_data; struct os_mbuf *msg = NET_BUF_SIMPLE(3); - u8_t *state; + uint8_t *state; bt_mesh_model_msg_init(msg, OP_GEN_ONOFF_STATUS); state = net_buf_simple_add(msg, 1); @@ -51,7 +51,7 @@ static void gen_onoff_set_unack(struct bt_mesh_model *model, struct os_mbuf *buf) { struct bt_mesh_gen_onoff_srv *cb = model->user_data; - u8_t state; + uint8_t state; state = buf->om_data[0]; @@ -77,7 +77,7 @@ static void gen_level_status(struct bt_mesh_model *model, { struct bt_mesh_gen_level_srv *cb = model->user_data; struct os_mbuf *msg = NET_BUF_SIMPLE(4); - s16_t *level; + int16_t *level; bt_mesh_model_msg_init(msg, OP_GEN_LEVEL_STATUS); level = net_buf_simple_add(msg, 2); @@ -107,9 +107,9 @@ static void gen_level_set_unack(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { struct bt_mesh_gen_level_srv *cb = model->user_data; - s16_t level; + int16_t level; - level = (s16_t) net_buf_simple_pull_le16(buf); + level = (int16_t) net_buf_simple_pull_le16(buf); BT_DBG("level: %d", level); if (cb && cb->set) { @@ -130,7 +130,7 @@ static void light_lightness_status(struct bt_mesh_model *model, { struct bt_mesh_light_lightness_srv *cb = model->user_data; struct os_mbuf *msg = NET_BUF_SIMPLE(4); - s16_t *lightness; + int16_t *lightness; bt_mesh_model_msg_init(msg, OP_LIGHT_LIGHTNESS_STATUS); lightness = net_buf_simple_add(msg, 2); @@ -160,9 +160,9 @@ static void light_lightness_set_unack(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { struct bt_mesh_light_lightness_srv *cb = model->user_data; - s16_t lightness; + int16_t lightness; - lightness = (s16_t) net_buf_simple_pull_le16(buf); + lightness = (int16_t) net_buf_simple_pull_le16(buf); BT_DBG("lightness: %d", lightness); if (cb && cb->set) { diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/net.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/net.c index 240314d4..8b86935d 100644 --- a/src/libs/mynewt-nimble/nimble/host/mesh/src/net.c +++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/net.c @@ -20,6 +20,7 @@ #include "adv.h" #include "mesh_priv.h" #include "net.h" +#include "rpl.h" #include "lpn.h" #include "friend.h" #include "proxy.h" @@ -29,6 +30,9 @@ #include "beacon.h" #include "settings.h" #include "prov.h" +#include "cfg.h" +#include "mesh/glue.h" +#include "mesh/slist.h" /* Minimum valid Mesh Network PDU length. The Network headers * themselves take up 9 bytes. After that there is a minumum of 1 byte @@ -38,6 +42,10 @@ */ #define BT_MESH_NET_MIN_PDU_LEN (BT_MESH_NET_HDR_LEN + 1 + 8) +#define LOOPBACK_MAX_PDU_LEN (BT_MESH_NET_HDR_LEN + 16) +#define LOOPBACK_USER_DATA_SIZE sizeof(struct bt_mesh_subnet *) +#define LOOPBACK_BUF_SUB(buf) (*(struct bt_mesh_subnet **)net_buf_user_data(buf)) + /* Seq limit after IV Update is triggered */ #define IV_UPDATE_SEQ_LIMIT 8000000 @@ -45,54 +53,34 @@ #define NID(pdu) ((pdu)[0] & 0x7f) #define CTL(pdu) ((pdu)[1] >> 7) #define TTL(pdu) ((pdu)[1] & 0x7f) -#define SEQ(pdu) (((u32_t)(pdu)[2] << 16) | \ - ((u32_t)(pdu)[3] << 8) | (u32_t)(pdu)[4]); +#define SEQ(pdu) (sys_get_be24(&pdu[2])) #define SRC(pdu) (sys_get_be16(&(pdu)[5])) #define DST(pdu) (sys_get_be16(&(pdu)[7])) -/* Determine how many friendship credentials we need */ -#if (MYNEWT_VAL(BLE_MESH_FRIEND)) -#define FRIEND_CRED_COUNT MYNEWT_VAL(BLE_MESH_FRIEND_LPN_COUNT) -#elif (MYNEWT_VAL(BLE_MESH_LOW_POWER)) -#define FRIEND_CRED_COUNT MYNEWT_VAL(BLE_MESH_SUBNET_COUNT) -#else -#define FRIEND_CRED_COUNT 0 -#endif - -static struct friend_cred friend_cred[FRIEND_CRED_COUNT]; - -static u64_t msg_cache[MYNEWT_VAL(BLE_MESH_MSG_CACHE_SIZE)]; -static u16_t msg_cache_next; +static struct { + uint32_t src : 15, /* MSb of source is always 0 */ + seq : 17; +} msg_cache[MYNEWT_VAL(BLE_MESH_MSG_CACHE_SIZE)]; +static uint16_t msg_cache_next; /* Singleton network context (the implementation only supports one) */ struct bt_mesh_net bt_mesh = { .local_queue = STAILQ_HEAD_INITIALIZER(bt_mesh.local_queue), - .sub = { - [0 ... (MYNEWT_VAL(BLE_MESH_SUBNET_COUNT) - 1)] = { - .net_idx = BT_MESH_KEY_UNUSED, - } - }, - .app_keys = { - [0 ... (MYNEWT_VAL(BLE_MESH_APP_KEY_COUNT) - 1)] = { - .net_idx = BT_MESH_KEY_UNUSED, - } - }, -#if MYNEWT_VAL(BLE_MESH_PROVISIONER) - .nodes = { - [0 ... (CONFIG_BT_MESH_NODE_COUNT - 1)] = { - .net_idx = BT_MESH_KEY_UNUSED, - } - }, -#endif }; -static u32_t dup_cache[4]; +static struct os_mbuf_pool loopback_os_mbuf_pool; +static struct os_mempool loopback_buf_mempool; +os_membuf_t loopback_mbuf_membuf[ + OS_MEMPOOL_SIZE(LOOPBACK_MAX_PDU_LEN + BT_MESH_MBUF_HEADER_SIZE, + MYNEWT_VAL(BLE_MESH_LOOPBACK_BUFS))]; + +static uint32_t dup_cache[MYNEWT_VAL(BLE_MESH_MSG_CACHE_SIZE)]; static int dup_cache_next; static bool check_dup(struct os_mbuf *data) { - const u8_t *tail = net_buf_simple_tail(data); - u32_t val; + const uint8_t *tail = net_buf_simple_tail(data); + uint32_t val; int i; val = sys_get_be32(tail - 4) ^ sys_get_be32(tail - 8); @@ -109,364 +97,52 @@ static bool check_dup(struct os_mbuf *data) return false; } -static u64_t msg_hash(struct bt_mesh_net_rx *rx, struct os_mbuf *pdu) +static bool msg_cache_match(struct os_mbuf *pdu) { - u32_t hash1, hash2; - - /* Three least significant bytes of IVI + first byte of SEQ */ - hash1 = (BT_MESH_NET_IVI_RX(rx) << 8) | pdu->om_data[2]; - - /* Two last bytes of SEQ + SRC */ - memcpy(&hash2, &pdu->om_data[3], 4); - - return (u64_t)hash1 << 32 | (u64_t)hash2; -} - -static bool msg_cache_match(struct bt_mesh_net_rx *rx, - struct os_mbuf *pdu) -{ - u64_t hash = msg_hash(rx, pdu); - u16_t i; + uint16_t i; for (i = 0; i < ARRAY_SIZE(msg_cache); i++) { - if (msg_cache[i] == hash) { + if (msg_cache[i].src == SRC(pdu->om_data) && + msg_cache[i].seq == (SEQ(pdu->om_data) & BIT_MASK(17))) { return true; } } - /* Add to the cache */ - rx->msg_cache_idx = msg_cache_next++; - msg_cache[rx->msg_cache_idx] = hash; - msg_cache_next %= ARRAY_SIZE(msg_cache); - return false; } -struct bt_mesh_subnet *bt_mesh_subnet_get(u16_t net_idx) +static void msg_cache_add(struct bt_mesh_net_rx *rx) { - int i; - - if (net_idx == BT_MESH_KEY_ANY) { - return &bt_mesh.sub[0]; - } - - for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) { - if (bt_mesh.sub[i].net_idx == net_idx) { - return &bt_mesh.sub[i]; - } - } - - return NULL; + /* Add to the cache */ + rx->msg_cache_idx = msg_cache_next++; + msg_cache[rx->msg_cache_idx].src = rx->ctx.addr; + msg_cache[rx->msg_cache_idx].seq = rx->seq; + msg_cache_next %= ARRAY_SIZE(msg_cache); } -int bt_mesh_net_keys_create(struct bt_mesh_subnet_keys *keys, - const u8_t key[16]) +int bt_mesh_net_create(uint16_t idx, uint8_t flags, const uint8_t key[16], + uint32_t iv_index) { - u8_t p[] = { 0 }; - u8_t nid; int err; - err = bt_mesh_k2(key, p, sizeof(p), &nid, keys->enc, keys->privacy); - if (err) { - BT_ERR("Unable to generate NID, EncKey & PrivacyKey"); - return err; - } - - memcpy(keys->net, key, 16); - - keys->nid = nid; - - BT_DBG("NID 0x%02x EncKey %s", keys->nid, bt_hex(keys->enc, 16)); - BT_DBG("PrivacyKey %s", bt_hex(keys->privacy, 16)); - - err = bt_mesh_k3(key, keys->net_id); - if (err) { - BT_ERR("Unable to generate Net ID"); - return err; - } - - BT_DBG("NetID %s", bt_hex(keys->net_id, 8)); - -#if (MYNEWT_VAL(BLE_MESH_GATT_PROXY)) - err = bt_mesh_identity_key(key, keys->identity); - if (err) { - BT_ERR("Unable to generate IdentityKey"); - return err; - } - - BT_DBG("IdentityKey %s", bt_hex(keys->identity, 16)); -#endif /* GATT_PROXY */ - - err = bt_mesh_beacon_key(key, keys->beacon); - if (err) { - BT_ERR("Unable to generate beacon key"); - return err; - } - - BT_DBG("BeaconKey %s", bt_hex(keys->beacon, 16)); - - return 0; -} - -int friend_cred_set(struct friend_cred *cred, u8_t idx, const u8_t net_key[16]) -{ - u16_t lpn_addr, frnd_addr; - int err; - u8_t p[9]; - -#if (MYNEWT_VAL(BLE_MESH_LOW_POWER)) - if (cred->addr == bt_mesh.lpn.frnd) { - lpn_addr = bt_mesh_primary_addr(); - frnd_addr = cred->addr; - } else { - lpn_addr = cred->addr; - frnd_addr = bt_mesh_primary_addr(); - } -#else - lpn_addr = cred->addr; - frnd_addr = bt_mesh_primary_addr(); -#endif - - BT_DBG("LPNAddress 0x%04x FriendAddress 0x%04x", lpn_addr, frnd_addr); - BT_DBG("LPNCounter 0x%04x FriendCounter 0x%04x", cred->lpn_counter, - cred->frnd_counter); - - p[0] = 0x01; - sys_put_be16(lpn_addr, p + 1); - sys_put_be16(frnd_addr, p + 3); - sys_put_be16(cred->lpn_counter, p + 5); - sys_put_be16(cred->frnd_counter, p + 7); - - err = bt_mesh_k2(net_key, p, sizeof(p), &cred->cred[idx].nid, - cred->cred[idx].enc, cred->cred[idx].privacy); - if (err) { - BT_ERR("Unable to generate NID, EncKey & PrivacyKey"); - return err; - } - - BT_DBG("Friend NID 0x%02x EncKey %s", cred->cred[idx].nid, - bt_hex(cred->cred[idx].enc, 16)); - BT_DBG("Friend PrivacyKey %s", bt_hex(cred->cred[idx].privacy, 16)); - - return 0; -} - -void friend_cred_refresh(u16_t net_idx) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(friend_cred); i++) { - struct friend_cred *cred = &friend_cred[i]; - - if (cred->addr != BT_MESH_ADDR_UNASSIGNED && - cred->net_idx == net_idx) { - memcpy(&cred->cred[0], &cred->cred[1], - sizeof(cred->cred[0])); - } - } -} - -int friend_cred_update(struct bt_mesh_subnet *sub) -{ - int err, i; - - BT_DBG("net_idx 0x%04x", sub->net_idx); - - for (i = 0; i < ARRAY_SIZE(friend_cred); i++) { - struct friend_cred *cred = &friend_cred[i]; - - if (cred->addr == BT_MESH_ADDR_UNASSIGNED || - cred->net_idx != sub->net_idx) { - continue; - } - - err = friend_cred_set(cred, 1, sub->keys[1].net); - if (err) { - return err; - } - } - - return 0; -} - -struct friend_cred *friend_cred_create(struct bt_mesh_subnet *sub, u16_t addr, - u16_t lpn_counter, u16_t frnd_counter) -{ - struct friend_cred *cred; - int i, err; - - BT_DBG("net_idx 0x%04x addr 0x%04x", sub->net_idx, addr); - - for (cred = NULL, i = 0; i < ARRAY_SIZE(friend_cred); i++) { - if ((friend_cred[i].addr == BT_MESH_ADDR_UNASSIGNED) || - (friend_cred[i].addr == addr && - friend_cred[i].net_idx == sub->net_idx)) { - cred = &friend_cred[i]; - break; - } - } - - if (!cred) { - BT_WARN("No free friend credential slots"); - return NULL; - } - - cred->net_idx = sub->net_idx; - cred->addr = addr; - cred->lpn_counter = lpn_counter; - cred->frnd_counter = frnd_counter; - - err = friend_cred_set(cred, 0, sub->keys[0].net); - if (err) { - friend_cred_clear(cred); - return NULL; - } - - if (sub->kr_flag) { - err = friend_cred_set(cred, 1, sub->keys[1].net); - if (err) { - friend_cred_clear(cred); - return NULL; - } - } - - return cred; -} - -void friend_cred_clear(struct friend_cred *cred) -{ - cred->net_idx = BT_MESH_KEY_UNUSED; - cred->addr = BT_MESH_ADDR_UNASSIGNED; - cred->lpn_counter = 0; - cred->frnd_counter = 0; - memset(cred->cred, 0, sizeof(cred->cred)); -} - -int friend_cred_del(u16_t net_idx, u16_t addr) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(friend_cred); i++) { - struct friend_cred *cred = &friend_cred[i]; - - if (cred->addr == addr && cred->net_idx == net_idx) { - friend_cred_clear(cred); - return 0; - } - } - - return -ENOENT; -} - -int friend_cred_get(struct bt_mesh_subnet *sub, u16_t addr, u8_t *nid, - const u8_t **enc, const u8_t **priv) -{ - int i; - - BT_DBG("net_idx 0x%04x addr 0x%04x", sub->net_idx, addr); - - for (i = 0; i < ARRAY_SIZE(friend_cred); i++) { - struct friend_cred *cred = &friend_cred[i]; - - if (cred->net_idx != sub->net_idx) { - continue; - } - - if (addr != BT_MESH_ADDR_UNASSIGNED && cred->addr != addr) { - continue; - } - - if (nid) { - *nid = cred->cred[sub->kr_flag].nid; - } - - if (enc) { - *enc = cred->cred[sub->kr_flag].enc; - } - - if (priv) { - *priv = cred->cred[sub->kr_flag].privacy; - } - - return 0; - } - - return -ENOENT; -} - -u8_t bt_mesh_net_flags(struct bt_mesh_subnet *sub) -{ - u8_t flags = 0x00; - - if (sub && sub->kr_flag) { - flags |= BT_MESH_NET_FLAG_KR; - } - - if (atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS)) { - flags |= BT_MESH_NET_FLAG_IVU; - } - - return flags; -} - -int bt_mesh_net_beacon_update(struct bt_mesh_subnet *sub) -{ - u8_t flags = bt_mesh_net_flags(sub); - struct bt_mesh_subnet_keys *keys; - - if (sub->kr_flag) { - BT_DBG("NetIndex %u Using new key", sub->net_idx); - keys = &sub->keys[1]; - } else { - BT_DBG("NetIndex %u Using current key", sub->net_idx); - keys = &sub->keys[0]; - } - - BT_DBG("flags 0x%02x, IVI 0x%08x", flags, (unsigned) bt_mesh.iv_index); - - return bt_mesh_beacon_auth(keys->beacon, flags, keys->net_id, - bt_mesh.iv_index, sub->auth); -} - -int bt_mesh_net_create(u16_t idx, u8_t flags, const u8_t key[16], - u32_t iv_index) -{ - struct bt_mesh_subnet *sub; - int err; - - BT_DBG("idx %u flags 0x%02x iv_index %u", idx, flags, - (unsigned) iv_index); + BT_DBG("idx %u flags 0x%02x iv_index %u", idx, flags, iv_index); BT_DBG("NetKey %s", bt_hex(key, 16)); + if (BT_MESH_KEY_REFRESH(flags)) { + err = bt_mesh_subnet_set(idx, BT_MESH_KR_PHASE_2, NULL, key); + } else { + err = bt_mesh_subnet_set(idx, BT_MESH_KR_NORMAL, key, NULL); + } + + if (err) { + BT_ERR("Failed creating subnet"); + return err; + } + (void)memset(msg_cache, 0, sizeof(msg_cache)); msg_cache_next = 0U; - sub = &bt_mesh.sub[0]; - - sub->kr_flag = BT_MESH_KEY_REFRESH(flags); - if (sub->kr_flag) { - err = bt_mesh_net_keys_create(&sub->keys[1], key); - if (err) { - return -EIO; - } - - sub->kr_phase = BT_MESH_KR_PHASE_2; - } else { - err = bt_mesh_net_keys_create(&sub->keys[0], key); - if (err) { - return -EIO; - } - } - - sub->net_idx = idx; - - if ((MYNEWT_VAL(BLE_MESH_GATT_PROXY))) { - sub->node_id = BT_MESH_NODE_IDENTITY_STOPPED; - } else { - sub->node_id = BT_MESH_NODE_IDENTITY_NOT_SUPPORTED; - } - bt_mesh.iv_index = iv_index; atomic_set_bit_to(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS, BT_MESH_IV_UPDATE(flags)); @@ -477,96 +153,16 @@ int bt_mesh_net_create(u16_t idx, u8_t flags, const u8_t key[16], */ bt_mesh.ivu_duration = BT_MESH_IVU_MIN_HOURS; - /* Make sure we have valid beacon data to be sent */ - bt_mesh_net_beacon_update(sub); + if (IS_ENABLED(CONFIG_BT_SETTINGS)) { + BT_DBG("Storing network information persistently"); + bt_mesh_store_net(); + bt_mesh_store_subnet(idx); + bt_mesh_store_iv(false); + } return 0; } -void bt_mesh_net_revoke_keys(struct bt_mesh_subnet *sub) -{ - int i; - - BT_DBG("idx 0x%04x", sub->net_idx); - - memcpy(&sub->keys[0], &sub->keys[1], sizeof(sub->keys[0])); - - for (i = 0; i < ARRAY_SIZE(bt_mesh.app_keys); i++) { - struct bt_mesh_app_key *key = &bt_mesh.app_keys[i]; - - if (key->net_idx != sub->net_idx || !key->updated) { - continue; - } - - memcpy(&key->keys[0], &key->keys[1], sizeof(key->keys[0])); - key->updated = false; - } -} - -bool bt_mesh_kr_update(struct bt_mesh_subnet *sub, u8_t new_kr, bool new_key) -{ - if (new_kr != sub->kr_flag && sub->kr_phase == BT_MESH_KR_NORMAL) { - BT_WARN("KR change in normal operation. Are we blacklisted?"); - return false; - } - - sub->kr_flag = new_kr; - - if (sub->kr_flag) { - if (sub->kr_phase == BT_MESH_KR_PHASE_1) { - BT_DBG("Phase 1 -> Phase 2"); - sub->kr_phase = BT_MESH_KR_PHASE_2; - return true; - } - } else { - switch (sub->kr_phase) { - case BT_MESH_KR_PHASE_1: - if (!new_key) { - /* Ignore */ - break; - } - /* Upon receiving a Secure Network beacon with the KR flag set - * to 0 using the new NetKey in Phase 1, the node shall - * immediately transition to Phase 3, which effectively skips - * Phase 2. - * - * Intentional fall-through. - */ - case BT_MESH_KR_PHASE_2: - BT_DBG("KR Phase 0x%02x -> Normal", sub->kr_phase); - bt_mesh_net_revoke_keys(sub); - if ((MYNEWT_VAL(BLE_MESH_LOW_POWER)) || - (MYNEWT_VAL(BLE_MESH_FRIEND))) { - friend_cred_refresh(sub->net_idx); - } - sub->kr_phase = BT_MESH_KR_NORMAL; - return true; - } - } - - return false; -} - -void bt_mesh_rpl_reset(void) -{ - int i; - - /* Discard "old old" IV Index entries from RPL and flag - * any other ones (which are valid) as old. - */ - for (i = 0; i < ARRAY_SIZE(bt_mesh.rpl); i++) { - struct bt_mesh_rpl *rpl = &bt_mesh.rpl[i]; - - if (rpl->src) { - if (rpl->old_iv) { - memset(rpl, 0, sizeof(*rpl)); - } else { - rpl->old_iv = true; - } - } - } -} - #if MYNEWT_VAL(BLE_MESH_IV_UPDATE_TEST) void bt_mesh_iv_update_test(bool enable) { @@ -588,29 +184,12 @@ bool bt_mesh_iv_update(void) bt_mesh_net_iv_update(bt_mesh.iv_index + 1, true); } - bt_mesh_net_sec_update(NULL); - return atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS); } #endif /* CONFIG_BT_MESH_IV_UPDATE_TEST */ -/* Used for sending immediate beacons to Friend queues and GATT clients */ -void bt_mesh_net_sec_update(struct bt_mesh_subnet *sub) +bool bt_mesh_net_iv_update(uint32_t iv_index, bool iv_update) { - if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) { - bt_mesh_friend_sec_update(sub ? sub->net_idx : BT_MESH_KEY_ANY); - } - - if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) && - bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED) { - bt_mesh_proxy_beacon_send(sub); - } -} - -bool bt_mesh_net_iv_update(u32_t iv_index, bool iv_update) -{ - int i; - if (atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS)) { /* We're currently in IV Update mode */ @@ -644,7 +223,7 @@ bool bt_mesh_net_iv_update(u32_t iv_index, bool iv_update) if (iv_index > bt_mesh.iv_index + 1) { BT_WARN("Performing IV Index Recovery"); - memset(bt_mesh.rpl, 0, sizeof(bt_mesh.rpl)); + bt_mesh_rpl_clear(); bt_mesh.iv_index = iv_index; bt_mesh.seq = 0; goto do_update; @@ -694,10 +273,20 @@ do_update: k_delayed_work_submit(&bt_mesh.ivu_timer, BT_MESH_IVU_TIMEOUT); - for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) { - if (bt_mesh.sub[i].net_idx != BT_MESH_KEY_UNUSED) { - bt_mesh_net_beacon_update(&bt_mesh.sub[i]); - } + /* Notify other modules */ + if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) { + bt_mesh_friend_sec_update(BT_MESH_KEY_ANY); + } + + if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) && + bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED) { + bt_mesh_proxy_beacon_send(NULL); + } + + bt_mesh_subnet_foreach(bt_mesh_beacon_update); + + if (MYNEWT_VAL(BLE_MESH_CDB)) { + bt_mesh_cdb_iv_update(iv_index, iv_update); } if (IS_ENABLED(CONFIG_BT_SETTINGS)) { @@ -707,9 +296,9 @@ do_update: return true; } -u32_t bt_mesh_next_seq(void) +uint32_t bt_mesh_next_seq(void) { - u32_t seq = bt_mesh.seq++; + uint32_t seq = bt_mesh.seq++; if (IS_ENABLED(CONFIG_BT_SETTINGS)) { bt_mesh_store_seq(); @@ -720,89 +309,63 @@ u32_t bt_mesh_next_seq(void) bt_mesh_subnet_get(BT_MESH_KEY_PRIMARY)) { bt_mesh_beacon_ivu_initiator(true); bt_mesh_net_iv_update(bt_mesh.iv_index + 1, true); - bt_mesh_net_sec_update(NULL); } return seq; } -int bt_mesh_net_resend(struct bt_mesh_subnet *sub, struct os_mbuf *buf, - bool new_key, const struct bt_mesh_send_cb *cb, - void *cb_data) -{ - const u8_t *enc, *priv; - u32_t seq; - u16_t dst; - int err; - - BT_DBG("net_idx 0x%04x new_key %u len %u", sub->net_idx, new_key, - buf->om_len); - - enc = sub->keys[new_key].enc; - priv = sub->keys[new_key].privacy; - - err = bt_mesh_net_obfuscate(buf->om_data, BT_MESH_NET_IVI_TX, priv); - if (err) { - BT_ERR("deobfuscate failed (err %d)", err); - return err; - } - - err = bt_mesh_net_decrypt(enc, buf, BT_MESH_NET_IVI_TX, false); - if (err) { - BT_ERR("decrypt failed (err %d)", err); - return err; - } - - seq = bt_mesh_next_seq(); - buf->om_data[2] = seq >> 16; - buf->om_data[3] = seq >> 8; - buf->om_data[4] = seq; - - /* Get destination, in case it's a proxy client */ - dst = DST(buf->om_data); - - err = bt_mesh_net_encrypt(enc, buf, BT_MESH_NET_IVI_TX, false); - if (err) { - BT_ERR("encrypt failed (err %d)", err); - return err; - } - - err = bt_mesh_net_obfuscate(buf->om_data, BT_MESH_NET_IVI_TX, priv); - if (err) { - BT_ERR("obfuscate failed (err %d)", err); - return err; - } - - if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) && - bt_mesh_proxy_relay(buf, dst)) { - send_cb_finalize(cb, cb_data); - } else { - bt_mesh_adv_send(buf, cb, cb_data); - } - - return 0; -} - static void bt_mesh_net_local(struct ble_npl_event *work) { struct os_mbuf *buf; while ((buf = net_buf_slist_get(&bt_mesh.local_queue))) { - BT_DBG("len %u: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len)); - bt_mesh_net_recv(buf, 0, BT_MESH_NET_IF_LOCAL); + struct bt_mesh_subnet *sub = LOOPBACK_BUF_SUB(buf); + struct bt_mesh_net_rx rx = { + .ctx = { + .net_idx = sub->net_idx, + /* Initialize AppIdx to a sane value */ + .app_idx = BT_MESH_KEY_UNUSED, + .recv_ttl = TTL(buf->om_data), + /* TTL=1 only goes to local IF */ + .send_ttl = 1U, + .addr = SRC(buf->om_data), + .recv_dst = DST(buf->om_data), + .recv_rssi = 0, + }, + .net_if = BT_MESH_NET_IF_LOCAL, + .sub = sub, + .old_iv = (IVI(buf->om_data) != (bt_mesh.iv_index & 0x01)), + .ctl = CTL(buf->om_data), + .seq = SEQ(buf->om_data), + .new_key = SUBNET_KEY_TX_IDX(sub), + .local_match = 1U, + .friend_match = 0U, + }; + + BT_DBG("src: 0x%04x dst: 0x%04x seq 0x%06x sub %p", rx.ctx.addr, + rx.ctx.addr, rx.seq, sub); + + (void) bt_mesh_trans_recv(buf, &rx); net_buf_unref(buf); } } -int bt_mesh_net_encode(struct bt_mesh_net_tx *tx, struct os_mbuf *buf, - bool proxy) +static const struct bt_mesh_net_cred *net_tx_cred_get(struct bt_mesh_net_tx *tx) +{ +#if defined(BLE_MESH_LOW_POWER) + if (tx->friend_cred && bt_mesh_lpn_established()) { + return &bt_mesh.lpn.cred[SUBNET_KEY_TX_IDX(tx->sub)]; + } +#endif + + tx->friend_cred = 0U; + return &tx->sub->keys[SUBNET_KEY_TX_IDX(tx->sub)].msg; +} + +static int net_header_encode(struct bt_mesh_net_tx *tx, uint8_t nid, + struct os_mbuf *buf) { const bool ctl = (tx->ctx->app_idx == BT_MESH_KEY_UNUSED); - u32_t seq_val; - u8_t nid; - const u8_t *enc, *priv; - u8_t *seq; - int err; if (ctl && net_buf_simple_tailroom(buf) < 8) { BT_ERR("Insufficient MIC space for CTL PDU"); @@ -818,11 +381,7 @@ int bt_mesh_net_encode(struct bt_mesh_net_tx *tx, struct os_mbuf *buf, net_buf_simple_push_be16(buf, tx->ctx->addr); net_buf_simple_push_be16(buf, tx->src); - seq = net_buf_simple_push(buf, 3); - seq_val = bt_mesh_next_seq(); - seq[0] = seq_val >> 16; - seq[1] = seq_val >> 8; - seq[2] = seq_val; + net_buf_simple_push_be24(buf, bt_mesh_next_seq()); if (ctl) { net_buf_simple_push_u8(buf, tx->ctx->send_ttl | 0x80); @@ -830,37 +389,68 @@ int bt_mesh_net_encode(struct bt_mesh_net_tx *tx, struct os_mbuf *buf, net_buf_simple_push_u8(buf, tx->ctx->send_ttl); } - if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER) && tx->friend_cred) { - if (friend_cred_get(tx->sub, BT_MESH_ADDR_UNASSIGNED, - &nid, &enc, &priv)) { - BT_WARN("Falling back to master credentials"); - - tx->friend_cred = 0; - - nid = tx->sub->keys[tx->sub->kr_flag].nid; - enc = tx->sub->keys[tx->sub->kr_flag].enc; - priv = tx->sub->keys[tx->sub->kr_flag].privacy; - } - } else { - tx->friend_cred = 0; - nid = tx->sub->keys[tx->sub->kr_flag].nid; - enc = tx->sub->keys[tx->sub->kr_flag].enc; - priv = tx->sub->keys[tx->sub->kr_flag].privacy; - } - net_buf_simple_push_u8(buf, (nid | (BT_MESH_NET_IVI_TX & 1) << 7)); - err = bt_mesh_net_encrypt(enc, buf, BT_MESH_NET_IVI_TX, proxy); + return 0; +} + +static int net_encrypt(struct os_mbuf *buf, + const struct bt_mesh_net_cred *cred, uint32_t iv_index, + bool proxy) +{ + int err; + + err = bt_mesh_net_encrypt(cred->enc, buf, iv_index, proxy); if (err) { return err; } - return bt_mesh_net_obfuscate(buf->om_data, BT_MESH_NET_IVI_TX, priv); + return bt_mesh_net_obfuscate(buf->om_data, iv_index, cred->privacy); +} + +int bt_mesh_net_encode(struct bt_mesh_net_tx *tx, struct os_mbuf *buf, + bool proxy) +{ + const struct bt_mesh_net_cred *cred; + int err; + + cred = net_tx_cred_get(tx); + err = net_header_encode(tx, cred->nid, buf); + if (err) { + return err; + } + + return net_encrypt(buf, cred, BT_MESH_NET_IVI_TX, proxy); +} + +static int loopback(const struct bt_mesh_net_tx *tx, const uint8_t *data, + size_t len) +{ + struct os_mbuf *buf; + + buf = os_mbuf_get_pkthdr(&loopback_os_mbuf_pool, 0); + if (!buf) { + BT_WARN("Unable to allocate loopback"); + return -ENOMEM; + } + + BT_DBG(""); + + LOOPBACK_BUF_SUB(buf) = tx->sub; + + net_buf_add_mem(buf, data, len); + + net_buf_slist_put(&bt_mesh.local_queue, buf); + + k_work_submit(&bt_mesh.local_work); + + return 0; } int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct os_mbuf *buf, const struct bt_mesh_send_cb *cb, void *cb_data) { + const struct bt_mesh_net_cred *cred; int err; BT_DBG("src 0x%04x dst 0x%04x len %u headroom %zu tailroom %zu", @@ -869,11 +459,8 @@ int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct os_mbuf *buf, BT_DBG("Payload len %u: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len)); BT_DBG("Seq 0x%06x", bt_mesh.seq); - if (tx->ctx->send_ttl == BT_MESH_TTL_DEFAULT) { - tx->ctx->send_ttl = bt_mesh_default_ttl_get(); - } - - err = bt_mesh_net_encode(tx, buf, false); + cred = net_tx_cred_get(tx); + err = net_header_encode(tx, cred->nid, buf); if (err) { goto done; } @@ -881,225 +468,118 @@ int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct os_mbuf *buf, BT_DBG("encoded %u bytes: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len)); - /* Deliver to GATT Proxy Clients if necessary. Mesh spec 3.4.5.2: - * "The output filter of the interface connected to advertising or - * GATT bearers shall drop all messages with TTL value set to 1." - */ - if (MYNEWT_VAL(BLE_MESH_GATT_PROXY) && - tx->ctx->send_ttl != 1) { - if (bt_mesh_proxy_relay(buf, tx->ctx->addr) && - BT_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) { - /* Notify completion if this only went - * through the Mesh Proxy. - */ - send_cb_finalize(cb, cb_data); - - err = 0; - goto done; - } - } - /* Deliver to local network interface if necessary */ if (bt_mesh_fixed_group_match(tx->ctx->addr) || bt_mesh_elem_find(tx->ctx->addr)) { - if (cb && cb->start) { - cb->start(0, 0, cb_data); + err = loopback(tx, buf->om_data, buf->om_len); + + /* Local unicast messages should not go out to network */ + if (BT_MESH_ADDR_IS_UNICAST(tx->ctx->addr) || + tx->ctx->send_ttl == 1U) { + if (!err) { + send_cb_finalize(cb, cb_data); + } + + goto done; } - net_buf_slist_put(&bt_mesh.local_queue, net_buf_ref(buf)); - if (cb && cb->end) { - cb->end(0, cb_data); - } - k_work_submit(&bt_mesh.local_work); - } else if (tx->ctx->send_ttl != 1) { - /* Deliver to to the advertising network interface. Mesh spec - * 3.4.5.2: "The output filter of the interface connected to - * advertising or GATT bearers shall drop all messages with - * TTL value set to 1." - */ - bt_mesh_adv_send(buf, cb, cb_data); } + /* Mesh spec 3.4.5.2: "The output filter of the interface connected to + * advertising or GATT bearers shall drop all messages with TTL value + * set to 1." If a TTL=1 packet wasn't for a local interface, it is + * invalid. + */ + if (tx->ctx->send_ttl == 1U) { + err = -EINVAL; + goto done; + } + + err = net_encrypt(buf, cred, BT_MESH_NET_IVI_TX, false); + if (err) { + goto done; + } + + /* Deliver to GATT Proxy Clients if necessary. */ + if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) && + bt_mesh_proxy_relay(buf, tx->ctx->addr) && + BT_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) { + /* Notify completion if this only went through the Mesh Proxy */ + send_cb_finalize(cb, cb_data); + + err = 0; + goto done; + } + + bt_mesh_adv_send(buf, cb, cb_data); done: net_buf_unref(buf); return err; } -static bool auth_match(struct bt_mesh_subnet_keys *keys, - const u8_t net_id[8], u8_t flags, - u32_t iv_index, const u8_t auth[8]) +void bt_mesh_net_loopback_clear(uint16_t net_idx) { - u8_t net_auth[8]; + struct net_buf_slist_t new_list; + struct os_mbuf *buf; - if (memcmp(net_id, keys->net_id, 8)) { + BT_DBG("0x%04x", net_idx); + + net_buf_slist_init(&new_list); + + while ((buf = net_buf_slist_get(&bt_mesh.local_queue))) { + struct bt_mesh_subnet *sub = LOOPBACK_BUF_SUB(buf); + + if (net_idx == BT_MESH_KEY_ANY || net_idx == sub->net_idx) { + BT_DBG("Dropped 0x%06x", SEQ(buf->om_data)); + net_buf_unref(buf); + } else { + net_buf_slist_put(&new_list, buf); + } + } + + bt_mesh.local_queue = new_list; +} + +static bool net_decrypt(struct bt_mesh_net_rx *rx, struct os_mbuf *in, + struct os_mbuf *out, + const struct bt_mesh_net_cred *cred) +{ + bool proxy = (rx->net_if == BT_MESH_NET_IF_PROXY_CFG); + + if (NID(in->om_data) != cred->nid) { return false; } - bt_mesh_beacon_auth(keys->beacon, flags, keys->net_id, iv_index, - net_auth); + BT_DBG("NID 0x%02x", NID(in->om_data)); + BT_DBG("IVI %u net->iv_index 0x%08x", IVI(in->om_data), bt_mesh.iv_index); - if (memcmp(auth, net_auth, 8)) { - BT_WARN("Authentication Value %s != %s", - bt_hex(auth, 8), bt_hex(net_auth, 8)); + rx->old_iv = (IVI(in->om_data) != (bt_mesh.iv_index & 0x01)); + net_buf_simple_reset(out); + net_buf_simple_add_mem(out, in->om_data, in->om_len); + + if (bt_mesh_net_obfuscate(out->om_data, BT_MESH_NET_IVI_RX(rx), + cred->privacy)) { return false; } - return true; -} - -struct bt_mesh_subnet *bt_mesh_subnet_find(const u8_t net_id[8], u8_t flags, - u32_t iv_index, const u8_t auth[8], - bool *new_key) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) { - struct bt_mesh_subnet *sub = &bt_mesh.sub[i]; - - if (sub->net_idx == BT_MESH_KEY_UNUSED) { - continue; - } - - if (auth_match(&sub->keys[0], net_id, flags, iv_index, auth)) { - *new_key = false; - return sub; - } - - if (sub->kr_phase == BT_MESH_KR_NORMAL) { - continue; - } - - if (auth_match(&sub->keys[1], net_id, flags, iv_index, auth)) { - *new_key = true; - return sub; - } - } - - return NULL; -} - -static int net_decrypt(struct bt_mesh_subnet *sub, const u8_t *enc, - const u8_t *priv, const u8_t *data, - size_t data_len, struct bt_mesh_net_rx *rx, - struct os_mbuf *buf) -{ - BT_DBG("NID 0x%02x net_idx 0x%04x", NID(data), sub->net_idx); - BT_DBG("IVI %u net->iv_index 0x%08x", IVI(data), - (unsigned) bt_mesh.iv_index); - - rx->old_iv = (IVI(data) != (bt_mesh.iv_index & 0x01)); - - net_buf_simple_init(buf, 0); - memcpy(net_buf_simple_add(buf, data_len), data, data_len); - - if (bt_mesh_net_obfuscate(buf->om_data, BT_MESH_NET_IVI_RX(rx), priv)) { - return -ENOENT; - } - - if (rx->net_if == BT_MESH_NET_IF_ADV && msg_cache_match(rx, buf)) { - BT_WARN("Duplicate found in Network Message Cache"); - return -EALREADY; - } - - rx->ctx.addr = SRC(buf->om_data); + rx->ctx.addr = SRC(out->om_data); if (!BT_MESH_ADDR_IS_UNICAST(rx->ctx.addr)) { - BT_WARN("Ignoring non-unicast src addr 0x%04x", rx->ctx.addr); - return -EINVAL; + BT_DBG("Ignoring non-unicast src addr 0x%04x", rx->ctx.addr); + return false; + } + + if (bt_mesh_elem_find(rx->ctx.addr)) { + BT_DBG("Dropping locally originated packet"); + return false; + } + + if (rx->net_if == BT_MESH_NET_IF_ADV && msg_cache_match(out)) { + BT_DBG("Duplicate found in Network Message Cache"); + return false; } BT_DBG("src 0x%04x", rx->ctx.addr); - - if ((MYNEWT_VAL(BLE_MESH_PROXY)) && - rx->net_if == BT_MESH_NET_IF_PROXY_CFG) { - return bt_mesh_net_decrypt(enc, buf, BT_MESH_NET_IVI_RX(rx), - true); - } - - return bt_mesh_net_decrypt(enc, buf, BT_MESH_NET_IVI_RX(rx), false); -} - -static int friend_decrypt(struct bt_mesh_subnet *sub, const u8_t *data, - size_t data_len, struct bt_mesh_net_rx *rx, - struct os_mbuf *buf) -{ - int i; - - BT_DBG("NID 0x%02x net_idx 0x%04x", NID(data), sub->net_idx); - - for (i = 0; i < ARRAY_SIZE(friend_cred); i++) { - struct friend_cred *cred = &friend_cred[i]; - - if (cred->net_idx != sub->net_idx) { - continue; - } - - if (NID(data) == cred->cred[0].nid && - !net_decrypt(sub, cred->cred[0].enc, cred->cred[0].privacy, - data, data_len, rx, buf)) { - return 0; - } - - if (sub->kr_phase == BT_MESH_KR_NORMAL) { - continue; - } - - if (NID(data) == cred->cred[1].nid && - !net_decrypt(sub, cred->cred[1].enc, cred->cred[1].privacy, - data, data_len, rx, buf)) { - rx->new_key = 1; - return 0; - } - } - - return -ENOENT; -} - -static bool net_find_and_decrypt(const u8_t *data, size_t data_len, - struct bt_mesh_net_rx *rx, - struct os_mbuf *buf) -{ - struct bt_mesh_subnet *sub; - unsigned int i; - - BT_DBG(""); - - for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) { - sub = &bt_mesh.sub[i]; - if (sub->net_idx == BT_MESH_KEY_UNUSED) { - continue; - } - - if ((IS_ENABLED(CONFIG_BT_MESH_LOW_POWER) || - IS_ENABLED(CONFIG_BT_MESH_FRIEND)) && - !friend_decrypt(sub, data, data_len, rx, buf)) { - rx->friend_cred = 1U; - rx->ctx.net_idx = sub->net_idx; - rx->sub = sub; - return true; - } - - if (NID(data) == sub->keys[0].nid && - !net_decrypt(sub, sub->keys[0].enc, sub->keys[0].privacy, - data, data_len, rx, buf)) { - rx->ctx.net_idx = sub->net_idx; - rx->sub = sub; - return true; - } - - if (sub->kr_phase == BT_MESH_KR_NORMAL) { - continue; - } - - if (NID(data) == sub->keys[1].nid && - !net_decrypt(sub, sub->keys[1].enc, sub->keys[1].privacy, - data, data_len, rx, buf)) { - rx->new_key = 1; - rx->ctx.net_idx = sub->net_idx; - rx->sub = sub; - return true; - } - } - - return false; + return bt_mesh_net_decrypt(cred->enc, out, BT_MESH_NET_IVI_RX(rx), + proxy) == 0; } /* Relaying from advertising to the advertising bearer should only happen @@ -1110,8 +590,6 @@ static bool net_find_and_decrypt(const u8_t *data, size_t data_len, static bool relay_to_adv(enum bt_mesh_net_if net_if) { switch (net_if) { - case BT_MESH_NET_IF_LOCAL: - return true; case BT_MESH_NET_IF_ADV: return (bt_mesh_relay_get() == BT_MESH_RELAY_ENABLED); case BT_MESH_NET_IF_PROXY: @@ -1124,27 +602,16 @@ static bool relay_to_adv(enum bt_mesh_net_if net_if) static void bt_mesh_net_relay(struct os_mbuf *sbuf, struct bt_mesh_net_rx *rx) { - const u8_t *enc, *priv; + const struct bt_mesh_net_cred *cred; struct os_mbuf *buf; - u8_t nid, transmit; + uint8_t transmit; - if (rx->net_if == BT_MESH_NET_IF_LOCAL) { - /* Locally originated PDUs with TTL=1 will only be delivered - * to local elements as per Mesh Profile 1.0 section 3.4.5.2: - * "The output filter of the interface connected to - * advertising or GATT bearers shall drop all messages with - * TTL value set to 1." - */ - if (rx->ctx.recv_ttl == 1) { - return; - } - } else { - if (rx->ctx.recv_ttl <= 1) { - return; - } + if (rx->ctx.recv_ttl <= 1U) { + return; } if (rx->net_if == BT_MESH_NET_IF_ADV && + !rx->friend_cred && bt_mesh_relay_get() != BT_MESH_RELAY_ENABLED && bt_mesh_gatt_proxy_get() != BT_MESH_GATT_PROXY_ENABLED) { return; @@ -1157,7 +624,7 @@ static void bt_mesh_net_relay(struct os_mbuf *sbuf, * Anything else (like GATT to adv, or locally originated packets) * use the Network Transmit state. */ - if (rx->net_if == BT_MESH_NET_IF_ADV) { + if (rx->net_if == BT_MESH_NET_IF_ADV && !rx->friend_cred) { transmit = bt_mesh_relay_retransmit_get(); } else { transmit = bt_mesh_net_transmit_get(); @@ -1169,57 +636,45 @@ static void bt_mesh_net_relay(struct os_mbuf *sbuf, return; } - /* Only decrement TTL for non-locally originated packets */ - if (rx->net_if != BT_MESH_NET_IF_LOCAL) { - /* Leave CTL bit intact */ - sbuf->om_data[1] &= 0x80; - sbuf->om_data[1] |= rx->ctx.recv_ttl - 1; - } + /* Leave CTL bit intact */ + sbuf->om_data[1] &= 0x80; + sbuf->om_data[1] |= rx->ctx.recv_ttl - 1U; net_buf_add_mem(buf, sbuf->om_data, sbuf->om_len); - enc = rx->sub->keys[rx->sub->kr_flag].enc; - priv = rx->sub->keys[rx->sub->kr_flag].privacy; - nid = rx->sub->keys[rx->sub->kr_flag].nid; + cred = &rx->sub->keys[SUBNET_KEY_TX_IDX(rx->sub)].msg; BT_DBG("Relaying packet. TTL is now %u", TTL(buf->om_data)); /* Update NID if RX or RX was with friend credentials */ if (rx->friend_cred) { buf->om_data[0] &= 0x80; /* Clear everything except IVI */ - buf->om_data[0] |= nid; + buf->om_data[0] |= cred->nid; } /* We re-encrypt and obfuscate using the received IVI rather than * the normal TX IVI (which may be different) since the transport * layer nonce includes the IVI. */ - if (bt_mesh_net_encrypt(enc, buf, BT_MESH_NET_IVI_RX(rx), false)) { + if (net_encrypt(buf, cred, BT_MESH_NET_IVI_RX(rx), false)) { BT_ERR("Re-encrypting failed"); goto done; } - if (bt_mesh_net_obfuscate(buf->om_data, BT_MESH_NET_IVI_RX(rx), priv)) { - BT_ERR("Re-obfuscating failed"); - goto done; - } - BT_DBG("encoded %u bytes: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len)); - /* Sending to the GATT bearer should only happen if GATT Proxy - * is enabled or the message originates from the local node. + /* When the Friend node relays message for lpn, the message will be + * retransmitted using the managed master security credentials and + * the Network PDU shall be retransmitted to all network interfaces. */ if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) && - (bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED || - rx->net_if == BT_MESH_NET_IF_LOCAL)) { - if (bt_mesh_proxy_relay(buf, rx->ctx.recv_dst) && - BT_MESH_ADDR_IS_UNICAST(rx->ctx.recv_dst)) { - goto done; - } + (rx->friend_cred || + bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED)) { + bt_mesh_proxy_relay(buf, rx->ctx.recv_dst); } - if (relay_to_adv(rx->net_if)) { + if (relay_to_adv(rx->net_if) || rx->friend_cred) { bt_mesh_adv_send(buf, NULL, NULL); } @@ -1238,26 +693,26 @@ void bt_mesh_net_header_parse(struct os_mbuf *buf, rx->ctx.recv_dst = DST(buf->om_data); } -int bt_mesh_net_decode(struct os_mbuf *data, enum bt_mesh_net_if net_if, - struct bt_mesh_net_rx *rx, struct os_mbuf *buf) +int bt_mesh_net_decode(struct os_mbuf *in, enum bt_mesh_net_if net_if, + struct bt_mesh_net_rx *rx, struct os_mbuf *out) { - if (data->om_len < BT_MESH_NET_MIN_PDU_LEN) { - BT_WARN("Dropping too short mesh packet (len %u)", data->om_len); - BT_WARN("%s", bt_hex(data->om_data, data->om_len)); + if (in->om_len < BT_MESH_NET_MIN_PDU_LEN) { + BT_WARN("Dropping too short mesh packet (len %u)", in->om_len); + BT_WARN("%s", bt_hex(in->om_data, in->om_len)); return -EINVAL; } - if (net_if == BT_MESH_NET_IF_ADV && check_dup(data)) { - BT_DBG("duplicate packet; dropping %u bytes: %s", data->om_len, - bt_hex(data->om_data, data->om_len)); + if (net_if == BT_MESH_NET_IF_ADV && check_dup(in)) { + BT_DBG("duplicate packet; dropping %u bytes: %s", in->om_len, + bt_hex(in->om_data, in->om_len)); return -EINVAL; } - BT_DBG("%u bytes: %s", data->om_len, bt_hex(data->om_data, data->om_len)); + BT_DBG("%u bytes: %s", in->om_len, bt_hex(in->om_data, in->om_len)); rx->net_if = net_if; - if (!net_find_and_decrypt(data->om_data, data->om_len, rx, buf)) { + if (!bt_mesh_net_cred_find(rx, in, out, net_decrypt)) { BT_DBG("Unable to find matching net for packet"); return -ENOENT; } @@ -1265,7 +720,7 @@ int bt_mesh_net_decode(struct os_mbuf *data, enum bt_mesh_net_if net_if, /* Initialize AppIdx to a sane value */ rx->ctx.app_idx = BT_MESH_KEY_UNUSED; - rx->ctx.recv_ttl = TTL(buf->om_data); + rx->ctx.recv_ttl = TTL(out->om_data); /* Default to responding with TTL 0 for non-routed messages */ if (rx->ctx.recv_ttl == 0) { @@ -1274,12 +729,12 @@ int bt_mesh_net_decode(struct os_mbuf *data, enum bt_mesh_net_if net_if, rx->ctx.send_ttl = BT_MESH_TTL_DEFAULT; } - rx->ctl = CTL(buf->om_data); - rx->seq = SEQ(buf->om_data); - rx->ctx.recv_dst = DST(buf->om_data); + rx->ctl = CTL(out->om_data); + rx->seq = SEQ(out->om_data); + rx->ctx.recv_dst = DST(out->om_data); - BT_DBG("Decryption successful. Payload len %u: %s", buf->om_len, - bt_hex(buf->om_data, buf->om_len)); + BT_DBG("Decryption successful. Payload len %u: %s", out->om_len, + bt_hex(out->om_data, out->om_len)); if (net_if != BT_MESH_NET_IF_PROXY_CFG && rx->ctx.recv_dst == BT_MESH_ADDR_UNASSIGNED) { @@ -1287,24 +742,16 @@ int bt_mesh_net_decode(struct os_mbuf *data, enum bt_mesh_net_if net_if, return -EBADMSG; } - if (BT_MESH_ADDR_IS_RFU(rx->ctx.recv_dst)) { - BT_ERR("Destination address is RFU; dropping packet"); - return -EBADMSG; - } - - if (net_if != BT_MESH_NET_IF_LOCAL && bt_mesh_elem_find(rx->ctx.addr)) { - BT_DBG("Dropping locally originated packet"); - return -EBADMSG; - } - BT_DBG("src 0x%04x dst 0x%04x ttl %u", rx->ctx.addr, rx->ctx.recv_dst, rx->ctx.recv_ttl); - BT_DBG("PDU: %s", bt_hex(buf->om_data, buf->om_len)); + BT_DBG("PDU: %s", bt_hex(out->om_data, out->om_len)); + + msg_cache_add(rx); return 0; } -void bt_mesh_net_recv(struct os_mbuf *data, s8_t rssi, +void bt_mesh_net_recv(struct os_mbuf *data, int8_t rssi, enum bt_mesh_net_if net_if) { struct os_mbuf *buf = NET_BUF_SIMPLE(29); @@ -1348,7 +795,7 @@ void bt_mesh_net_recv(struct os_mbuf *data, s8_t rssi, */ if (bt_mesh_trans_recv(buf, &rx) == -EAGAIN) { BT_WARN("Removing rejected message from Network Message Cache"); - msg_cache[rx.msg_cache_idx] = 0ULL; + msg_cache[rx.msg_cache_idx].src = BT_MESH_ADDR_UNASSIGNED; /* Rewind the next index now that we're not using this entry */ msg_cache_next = rx.msg_cache_idx; } @@ -1368,7 +815,8 @@ done: static void ivu_refresh(struct ble_npl_event *work) { - bt_mesh.ivu_duration += BT_MESH_IVU_HOURS; + bt_mesh.ivu_duration = MIN(UINT8_MAX, + bt_mesh.ivu_duration + BT_MESH_IVU_HOURS); BT_DBG("%s for %u hour%s", atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS) ? @@ -1392,42 +840,22 @@ static void ivu_refresh(struct ble_npl_event *work) } } -void bt_mesh_net_start(void) -{ - if (bt_mesh_beacon_get() == BT_MESH_BEACON_ENABLED) { - bt_mesh_beacon_enable(); - } else { - bt_mesh_beacon_disable(); - } - - if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) && - bt_mesh_gatt_proxy_get() != BT_MESH_GATT_PROXY_NOT_SUPPORTED) { - bt_mesh_proxy_gatt_enable(); - bt_mesh_adv_update(); - } - - if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) { - bt_mesh_lpn_init(); - } else { - bt_mesh_scan_enable(); - } - - if (IS_ENABLED(CONFIG_BT_MESH_FRIEND)) { - bt_mesh_friend_init(); - } - - if (IS_ENABLED(CONFIG_BT_MESH_PROV)) { - u16_t net_idx = bt_mesh.sub[0].net_idx; - u16_t addr = bt_mesh_primary_addr(); - - bt_mesh_prov_complete(net_idx, addr); - } -} - void bt_mesh_net_init(void) { + int rc; + k_delayed_work_init(&bt_mesh.ivu_timer, ivu_refresh); k_work_init(&bt_mesh.local_work, bt_mesh_net_local); net_buf_slist_init(&bt_mesh.local_queue); + + rc = os_mempool_init(&loopback_buf_mempool, MYNEWT_VAL(BLE_MESH_LOOPBACK_BUFS), + LOOPBACK_MAX_PDU_LEN + BT_MESH_MBUF_HEADER_SIZE, + &loopback_mbuf_membuf[0], "loopback_buf_pool"); + assert(rc == 0); + + rc = os_mbuf_pool_init(&loopback_os_mbuf_pool, &loopback_buf_mempool, + LOOPBACK_MAX_PDU_LEN + BT_MESH_MBUF_HEADER_SIZE, + MYNEWT_VAL(BLE_MESH_LOOPBACK_BUFS)); + assert(rc == 0); } diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/net.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/net.h index 976da005..f4b1192b 100644 --- a/src/libs/mynewt-nimble/nimble/host/mesh/src/net.h +++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/net.h @@ -9,13 +9,7 @@ #ifndef __NET_H__ #define __NET_H__ -#define BT_MESH_NET_FLAG_KR BIT(0) -#define BT_MESH_NET_FLAG_IVU BIT(1) - -#define BT_MESH_KR_NORMAL 0x00 -#define BT_MESH_KR_PHASE_1 0x01 -#define BT_MESH_KR_PHASE_2 0x02 -#define BT_MESH_KR_PHASE_3 0x03 +#include "subnet.h" #define BT_MESH_IV_UPDATE(flags) ((flags >> 1) & 0x01) #define BT_MESH_KEY_REFRESH(flags) (flags & 0x01) @@ -31,64 +25,13 @@ CONFIG_BT_MESH_IVU_DIVIDER) #define BT_MESH_IVU_TIMEOUT K_HOURS(BT_MESH_IVU_HOURS) -struct bt_mesh_app_key { - u16_t net_idx; - u16_t app_idx; - bool updated; - struct bt_mesh_app_keys { - u8_t id; - u8_t val[16]; - } keys[2]; -}; +struct bt_mesh_net_cred; struct bt_mesh_node { - u16_t addr; - u16_t net_idx; - u8_t dev_key[16]; - u8_t num_elem; -}; - -struct bt_mesh_subnet { - u32_t beacon_sent; /* Timestamp of last sent beacon */ - u8_t beacons_last; /* Number of beacons during last - * observation window - */ - u8_t beacons_cur; /* Number of beaconds observed during - * currently ongoing window. - */ - - u8_t beacon_cache[21]; /* Cached last authenticated beacon */ - - u16_t net_idx; /* NetKeyIndex */ - - bool kr_flag; /* Key Refresh Flag */ - u8_t kr_phase; /* Key Refresh Phase */ - - u8_t node_id; /* Node Identity State */ - u32_t node_id_start; /* Node Identity started timestamp */ - - u8_t auth[8]; /* Beacon Authentication Value */ - - struct bt_mesh_subnet_keys { - u8_t net[16]; /* NetKey */ - u8_t nid; /* NID */ - u8_t enc[16]; /* EncKey */ - u8_t net_id[8]; /* Network ID */ -#if (MYNEWT_VAL(BLE_MESH_GATT_PROXY)) - u8_t identity[16]; /* IdentityKey */ -#endif - u8_t privacy[16]; /* PrivacyKey */ - u8_t beacon[16]; /* BeaconKey */ - } keys[2]; -}; - -struct bt_mesh_rpl { - u16_t src; - bool old_iv; -#if (MYNEWT_VAL(BLE_MESH_SETTINGS)) - bool store; -#endif - u32_t seq; + uint16_t addr; + uint16_t net_idx; + uint8_t dev_key[16]; + uint8_t num_elem; }; #if MYNEWT_VAL(BLE_MESH_FRIEND) @@ -100,23 +43,23 @@ struct bt_mesh_rpl { #endif struct bt_mesh_friend { - u16_t lpn; - u8_t recv_delay; - u8_t fsn:1, + uint16_t lpn; + uint8_t recv_delay; + uint8_t fsn:1, send_last:1, pending_req:1, - sec_update:1, pending_buf:1, - valid:1, established:1; - s32_t poll_to; - u8_t num_elem; - u16_t lpn_counter; - u16_t counter; + int32_t poll_to; + uint8_t num_elem; + uint16_t lpn_counter; + uint16_t counter; - u16_t net_idx; + struct bt_mesh_subnet *subnet; - u16_t sub_list[FRIEND_SUB_LIST_SIZE]; + struct bt_mesh_net_cred cred[2]; + + uint16_t sub_list[FRIEND_SUB_LIST_SIZE]; struct k_delayed_work timer; @@ -127,19 +70,19 @@ struct bt_mesh_friend { * the current number of segments, in the queue. This is * used for Friend Queue free space calculations. */ - u8_t seg_count; + uint8_t seg_count; } seg[FRIEND_SEG_RX]; struct os_mbuf *last; struct net_buf_slist_t queue; - u32_t queue_size; + uint32_t queue_size; /* Friend Clear Procedure */ struct { - u32_t start; /* Clear Procedure start */ - u16_t frnd; /* Previous Friend's address */ - u16_t repeat_sec; /* Repeat timeout in seconds */ + uint32_t start; /* Clear Procedure start */ + uint16_t frnd; /* Previous Friend's address */ + uint16_t repeat_sec; /* Repeat timeout in seconds */ struct k_delayed_work timer; /* Repeat timer */ } clear; }; @@ -165,23 +108,23 @@ struct bt_mesh_lpn { } state; /* Transaction Number (used for subscription list) */ - u8_t xact_next; - u8_t xact_pending; - u8_t sent_req; + uint8_t xact_next; + uint8_t xact_pending; + uint8_t sent_req; /* Address of our Friend when we're a LPN. Unassigned if we don't * have a friend yet. */ - u16_t frnd; + uint16_t frnd; /* Value from the friend offer */ - u8_t recv_win; + uint8_t recv_win; - u8_t req_attempts; /* Number of Request attempts */ + uint8_t req_attempts; /* Number of Request attempts */ - s32_t poll_timeout; + int32_t poll_timeout; - u8_t groups_changed:1, /* Friend Subscription List needs updating */ + uint8_t groups_changed:1, /* Friend Subscription List needs updating */ pending_poll:1, /* Poll to be sent after subscription */ disable:1, /* Disable LPN after clearing */ fsn:1, /* Friend Sequence Number */ @@ -189,22 +132,29 @@ struct bt_mesh_lpn { clear_success:1; /* Friend Clear Confirm received */ /* Friend Queue Size */ - u8_t queue_size; + uint8_t queue_size; + + /* FriendCounter */ + uint16_t frnd_counter; /* LPNCounter */ - u16_t counter; + uint16_t lpn_counter; /* Previous Friend of this LPN */ - u16_t old_friend; + uint16_t old_friend; /* Duration reported for last advertising packet */ - u16_t adv_duration; + uint16_t adv_duration; /* Next LPN related action timer */ struct k_delayed_work timer; /* Subscribed groups */ - u16_t groups[LPN_GROUPS]; + uint16_t groups[LPN_GROUPS]; + + struct bt_mesh_subnet *sub; + + struct bt_mesh_net_cred cred[2]; /* Bit fields for tracking which groups the Friend knows about */ ATOMIC_DEFINE(added, LPN_GROUPS); @@ -231,15 +181,20 @@ enum { BT_MESH_CFG_PENDING, BT_MESH_MOD_PENDING, BT_MESH_VA_PENDING, - BT_MESH_NODES_PENDING, + + /* Feature flags */ + BT_MESH_RELAY, + BT_MESH_BEACON, + BT_MESH_GATT_PROXY, + BT_MESH_FRIEND, /* Don't touch - intentionally last */ BT_MESH_FLAG_COUNT, }; struct bt_mesh_net { - u32_t iv_index; /* Current IV Index */ - u32_t seq; /* Next outgoing sequence number (24 bits) */ + uint32_t iv_index; /* Current IV Index */ + uint32_t seq; /* Next outgoing sequence number (24 bits) */ ATOMIC_DEFINE(flags, BT_MESH_FLAG_COUNT); @@ -257,22 +212,16 @@ struct bt_mesh_net { #endif /* Number of hours in current IV Update state */ - u8_t ivu_duration; + uint8_t ivu_duration; + + uint8_t net_xmit; + uint8_t relay_xmit; + uint8_t default_ttl; /* Timer to track duration in current IV Update state */ struct k_delayed_work ivu_timer; - u8_t dev_key[16]; - -#if MYNEWT_VAL(BLE_MESH_PROVISIONER) - struct bt_mesh_node nodes[MYNEWT_VAL(BLE_MESH_NODE_COUNT)]; -#endif - - struct bt_mesh_app_key app_keys[MYNEWT_VAL(BLE_MESH_APP_KEY_COUNT)]; - - struct bt_mesh_subnet sub[MYNEWT_VAL(BLE_MESH_SUBNET_COUNT)]; - - struct bt_mesh_rpl rpl[MYNEWT_VAL(BLE_MESH_CRPL)]; + uint8_t dev_key[16]; }; /* Network interface */ @@ -287,24 +236,24 @@ enum bt_mesh_net_if { struct bt_mesh_net_rx { struct bt_mesh_subnet *sub; struct bt_mesh_msg_ctx ctx; - u32_t seq; /* Sequence Number */ - u8_t old_iv:1, /* iv_index - 1 was used */ + uint32_t seq; /* Sequence Number */ + uint8_t old_iv:1, /* iv_index - 1 was used */ new_key:1, /* Data was encrypted with updated key */ friend_cred:1, /* Data was encrypted with friend cred */ ctl:1, /* Network Control */ net_if:2, /* Network interface */ local_match:1, /* Matched a local element */ friend_match:1; /* Matched an LPN we're friends for */ - u16_t msg_cache_idx; /* Index of entry in message cache */ + uint16_t msg_cache_idx; /* Index of entry in message cache */ }; /* Encoding context for Network/Transport data */ struct bt_mesh_net_tx { struct bt_mesh_subnet *sub; struct bt_mesh_msg_ctx *ctx; - u16_t src; - u8_t xmit; - u8_t friend_cred:1, + uint16_t src; + uint8_t xmit; + uint8_t friend_cred:1, aszmic:1, aid:6; }; @@ -318,80 +267,36 @@ extern struct bt_mesh_net bt_mesh; #define BT_MESH_NET_HDR_LEN 9 -int bt_mesh_net_keys_create(struct bt_mesh_subnet_keys *keys, - const u8_t key[16]); +static inline void *net_buf_user_data(const struct os_mbuf *buf) +{ + return (void *)buf->om_data; +} -int bt_mesh_net_create(u16_t idx, u8_t flags, const u8_t key[16], - u32_t iv_index); +int bt_mesh_net_create(uint16_t idx, uint8_t flags, const uint8_t key[16], + uint32_t iv_index); -u8_t bt_mesh_net_flags(struct bt_mesh_subnet *sub); - -bool bt_mesh_kr_update(struct bt_mesh_subnet *sub, u8_t new_kr, bool new_key); - -void bt_mesh_net_revoke_keys(struct bt_mesh_subnet *sub); - -int bt_mesh_net_beacon_update(struct bt_mesh_subnet *sub); - -void bt_mesh_rpl_reset(void); - -bool bt_mesh_net_iv_update(u32_t iv_index, bool iv_update); - -void bt_mesh_net_sec_update(struct bt_mesh_subnet *sub); - -struct bt_mesh_subnet *bt_mesh_subnet_get(u16_t net_idx); - -struct bt_mesh_subnet *bt_mesh_subnet_find(const u8_t net_id[8], u8_t flags, - u32_t iv_index, const u8_t auth[8], - bool *new_key); +bool bt_mesh_net_iv_update(uint32_t iv_index, bool iv_update); int bt_mesh_net_encode(struct bt_mesh_net_tx *tx, struct os_mbuf *buf, bool proxy); +int bt_mesh_net_decode(struct os_mbuf *in, enum bt_mesh_net_if net_if, + struct bt_mesh_net_rx *rx, struct os_mbuf *out); + int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct os_mbuf *buf, const struct bt_mesh_send_cb *cb, void *cb_data); -int bt_mesh_net_resend(struct bt_mesh_subnet *sub, struct os_mbuf *buf, - bool new_key, const struct bt_mesh_send_cb *cb, - void *cb_data); - -int bt_mesh_net_decode(struct os_mbuf *data, enum bt_mesh_net_if net_if, - struct bt_mesh_net_rx *rx, struct os_mbuf *buf); - -void bt_mesh_net_recv(struct os_mbuf *data, s8_t rssi, +void bt_mesh_net_recv(struct os_mbuf *data, int8_t rssi, enum bt_mesh_net_if net_if); -u32_t bt_mesh_next_seq(void); +void bt_mesh_net_loopback_clear(uint16_t net_idx); -void bt_mesh_net_start(void); +uint32_t bt_mesh_next_seq(void); void bt_mesh_net_init(void); void bt_mesh_net_header_parse(struct os_mbuf *buf, struct bt_mesh_net_rx *rx); -/* Friendship Credential Management */ -struct friend_cred { - u16_t net_idx; - u16_t addr; - - u16_t lpn_counter; - u16_t frnd_counter; - - struct { - u8_t nid; /* NID */ - u8_t enc[16]; /* EncKey */ - u8_t privacy[16]; /* PrivacyKey */ - } cred[2]; -}; - -int friend_cred_get(struct bt_mesh_subnet *sub, u16_t addr, u8_t *nid, - const u8_t **enc, const u8_t **priv); -int friend_cred_set(struct friend_cred *cred, u8_t idx, const u8_t net_key[16]); -void friend_cred_refresh(u16_t net_idx); -int friend_cred_update(struct bt_mesh_subnet *sub); -struct friend_cred *friend_cred_create(struct bt_mesh_subnet *sub, u16_t addr, - u16_t lpn_counter, u16_t frnd_counter); -void friend_cred_clear(struct friend_cred *cred); -int friend_cred_del(u16_t net_idx, u16_t addr); static inline void send_cb_finalize(const struct bt_mesh_send_cb *cb, void *cb_data) diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/pb_adv.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/pb_adv.c new file mode 100644 index 00000000..28391b18 --- /dev/null +++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/pb_adv.c @@ -0,0 +1,888 @@ +/* Bluetooth Mesh */ + +/* + * Copyright (c) 2017 Intel Corporation + * Copyright (c) 2020 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "syscfg/syscfg.h" +#define MESH_LOG_MODULE BLE_MESH_PROV_LOG + +#include +#include +#include "mesh/mesh.h" +#include +#include "testing.h" +#include "net.h" +#include "prov.h" +#include "adv.h" +#include "crypto.h" +#include "beacon.h" +#include "prov.h" +#include "mesh/glue.h" + +#define GPCF(gpc) (gpc & 0x03) +#define GPC_START(last_seg) (((last_seg) << 2) | 0x00) +#define GPC_ACK 0x01 +#define GPC_CONT(seg_id) (((seg_id) << 2) | 0x02) +#define GPC_CTL(op) (((op) << 2) | 0x03) + +#define START_PAYLOAD_MAX 20 +#define CONT_PAYLOAD_MAX 23 + +#define START_LAST_SEG(gpc) (gpc >> 2) +#define CONT_SEG_INDEX(gpc) (gpc >> 2) + +#define BEARER_CTL(gpc) (gpc >> 2) +#define LINK_OPEN 0x00 +#define LINK_ACK 0x01 +#define LINK_CLOSE 0x02 + +#define XACT_SEG_DATA(_seg) (&link.rx.buf->om_data[20 + ((_seg - 1) * 23)]) +#define XACT_SEG_RECV(_seg) (link.rx.seg &= ~(1 << (_seg))) + +#define XACT_ID_MAX 0x7f +#define XACT_ID_NVAL 0xff +#define SEG_NVAL 0xff + +#define RETRANSMIT_TIMEOUT K_MSEC(MYNEWT_VAL(BLE_MESH_PB_ADV_RETRANS_TIMEOUT)) +#define BUF_TIMEOUT K_MSEC(400) +#define CLOSING_TIMEOUT K_SECONDS(3) +#define TRANSACTION_TIMEOUT K_SECONDS(30) + +/* Acked messages, will do retransmissions manually, taking acks into account: + */ +#define RETRANSMITS_RELIABLE 0 +/* Unacked messages: */ +#define RETRANSMITS_UNRELIABLE 2 +/* PDU acks: */ +#define RETRANSMITS_ACK 2 + +enum { + ADV_LINK_ACTIVE, /* Link has been opened */ + ADV_LINK_ACK_RECVD, /* Ack for link has been received */ + ADV_LINK_CLOSING, /* Link is closing down */ + ADV_LINK_INVALID, /* Error occurred during provisioning */ + ADV_ACK_PENDING, /* An acknowledgment is being sent */ + ADV_PROVISIONER, /* The link was opened as provisioner */ + + ADV_NUM_FLAGS, +}; + +struct pb_adv { + uint32_t id; /* Link ID */ + + ATOMIC_DEFINE(flags, ADV_NUM_FLAGS); + + const struct prov_bearer_cb *cb; + void *cb_data; + + struct { + uint8_t id; /* Most recent transaction ID */ + uint8_t seg; /* Bit-field of unreceived segments */ + uint8_t last_seg; /* Last segment (to check length) */ + uint8_t fcs; /* Expected FCS value */ + struct os_mbuf *buf; + } rx; + + struct { + /* Start timestamp of the transaction */ + int64_t start; + + /* Transaction id */ + uint8_t id; + + /* Current ack id */ + uint8_t pending_ack; + + /* Pending outgoing buffer(s) */ + struct os_mbuf *buf[3]; + + prov_bearer_send_complete_t cb; + + void *cb_data; + + /* Retransmit timer */ + struct k_delayed_work retransmit; + } tx; + + /* Protocol timeout */ + struct k_delayed_work prot_timer; +}; + +struct prov_rx { + uint32_t link_id; + uint8_t xact_id; + uint8_t gpc; +}; + +static struct os_mbuf *rx_buf; +static struct pb_adv link; + +static void gen_prov_ack_send(uint8_t xact_id); +static void link_open(struct prov_rx *rx, struct os_mbuf *buf); +static void link_ack(struct prov_rx *rx, struct os_mbuf *buf); +static void link_close(struct prov_rx *rx, struct os_mbuf *buf); + +static void buf_sent(int err, void *user_data) +{ + BT_DBG("buf_send"); + + if (!link.tx.buf[0]) { + return; + } + + BT_DBG("submit retransmit"); + k_delayed_work_submit(&link.tx.retransmit, RETRANSMIT_TIMEOUT); +} + +static struct bt_mesh_send_cb buf_sent_cb = { + .end = buf_sent, +}; + +static uint8_t last_seg(uint8_t len) +{ + if (len <= START_PAYLOAD_MAX) { + return 0; + } + + len -= START_PAYLOAD_MAX; + + return 1 + (len / CONT_PAYLOAD_MAX); +} + +static void free_segments(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(link.tx.buf); i++) { + struct os_mbuf *buf = link.tx.buf[i]; + + if (!buf) { + break; + } + + link.tx.buf[i] = NULL; + /* Mark as canceled */ + BT_MESH_ADV(buf)->busy = 0U; + net_buf_unref(buf); + } +} + +static uint8_t next_transaction_id(uint8_t id) +{ + return (((id + 1) & XACT_ID_MAX) | (id & (XACT_ID_MAX+1))); +} + +static void prov_clear_tx(void) +{ + BT_DBG(""); + + k_delayed_work_cancel(&link.tx.retransmit); + + free_segments(); +} + +static void reset_adv_link(void) +{ + BT_DBG(""); + prov_clear_tx(); + + k_delayed_work_cancel(&link.prot_timer); + + if (atomic_test_bit(link.flags, ADV_PROVISIONER)) { + /* Clear everything except the retransmit and protocol timer + * delayed work objects. + */ + (void)memset(&link, 0, offsetof(struct pb_adv, tx.retransmit)); + link.rx.id = XACT_ID_NVAL; + } else { + /* Accept another provisioning attempt */ + link.id = 0; + atomic_clear(link.flags); + link.rx.id = XACT_ID_MAX; + link.tx.id = XACT_ID_NVAL; + } + link.tx.pending_ack = XACT_ID_NVAL; + if (!rx_buf) { + rx_buf = NET_BUF_SIMPLE(65); + } + link.rx.buf = rx_buf; + net_buf_simple_reset(link.rx.buf); +} + +static void close_link(enum prov_bearer_link_status reason) +{ + const struct prov_bearer_cb *cb = link.cb; + void *cb_data = link.cb_data; + + reset_adv_link(); + cb->link_closed(&pb_adv, cb_data, reason); +} + +static struct os_mbuf *adv_buf_create(uint8_t retransmits) +{ + struct os_mbuf *buf; + + buf = bt_mesh_adv_create(BT_MESH_ADV_PROV, + BT_MESH_TRANSMIT(retransmits, 20), + BUF_TIMEOUT); + if (!buf) { + BT_ERR("Out of provisioning buffers"); + return NULL; + } + + return buf; +} + +static void ack_complete(uint16_t duration, int err, void *user_data) +{ + BT_DBG("xact 0x%x complete", (uint8_t)link.tx.pending_ack); + atomic_clear_bit(link.flags, ADV_ACK_PENDING); +} + +static bool ack_pending(void) +{ + return atomic_test_bit(link.flags, ADV_ACK_PENDING); +} + +static void prov_failed(uint8_t err) +{ + BT_DBG("%u", err); + link.cb->error(&pb_adv, link.cb_data, err); + atomic_set_bit(link.flags, ADV_LINK_INVALID); +} + +static void prov_msg_recv(void) +{ + k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT); + + if (!bt_mesh_fcs_check(link.rx.buf, link.rx.fcs)) { + BT_ERR("Incorrect FCS"); + return; + } + + gen_prov_ack_send(link.rx.id); + + if (atomic_test_bit(link.flags, ADV_LINK_INVALID)) { + BT_WARN("Unexpected msg 0x%02x on invalidated link", + link.rx.buf->om_data[0]); + prov_failed(PROV_ERR_UNEXP_PDU); + return; + } + + link.cb->recv(&pb_adv, link.cb_data, link.rx.buf); +} + +static void protocol_timeout(struct ble_npl_event *work) +{ + BT_DBG(""); + + link.rx.seg = 0U; + close_link(PROV_BEARER_LINK_STATUS_TIMEOUT); +} +/******************************************************************************* + * Generic provisioning + ******************************************************************************/ + +static void gen_prov_ack_send(uint8_t xact_id) +{ + static const struct bt_mesh_send_cb cb = { + .start = ack_complete, + }; + const struct bt_mesh_send_cb *complete; + struct os_mbuf *buf; + bool pending = atomic_test_and_set_bit(link.flags, ADV_ACK_PENDING); + + BT_DBG("xact_id 0x%x", xact_id); + + if (pending && link.tx.pending_ack == xact_id) { + BT_DBG("Not sending duplicate ack"); + return; + } + + buf = adv_buf_create(RETRANSMITS_ACK); + if (!buf) { + atomic_clear_bit(link.flags, ADV_ACK_PENDING); + return; + } + + if (pending) { + complete = NULL; + } else { + link.tx.pending_ack = xact_id; + complete = &cb; + } + + net_buf_add_be32(buf, link.id); + net_buf_add_u8(buf, xact_id); + net_buf_add_u8(buf, GPC_ACK); + + bt_mesh_adv_send(buf, complete, NULL); + net_buf_unref(buf); +} + +static void gen_prov_cont(struct prov_rx *rx, struct os_mbuf *buf) +{ + uint8_t seg = CONT_SEG_INDEX(rx->gpc); + + BT_DBG("len %u, seg_index %u", buf->om_len, seg); + + if (!link.rx.seg && link.rx.id == rx->xact_id) { + if (!ack_pending()) { + BT_DBG("Resending ack"); + gen_prov_ack_send(rx->xact_id); + } + + return; + } + + if (!link.rx.seg && + next_transaction_id(link.rx.id) == rx->xact_id) { + BT_DBG("Start segment lost"); + + link.rx.id = rx->xact_id; + + net_buf_simple_reset(link.rx.buf); + link.rx.seg = SEG_NVAL; + link.rx.last_seg = SEG_NVAL; + + prov_clear_tx(); + } else if (rx->xact_id != link.rx.id) { + BT_WARN("Data for unknown transaction (0x%x != 0x%x)", + rx->xact_id, link.rx.id); + return; + } + + if (seg > link.rx.last_seg) { + BT_ERR("Invalid segment index %u", seg); + prov_failed(PROV_ERR_NVAL_FMT); + return; + } + + if (!(link.rx.seg & BIT(seg))) { + BT_DBG("Ignoring already received segment"); + return; + } + + memcpy(XACT_SEG_DATA(seg), buf->om_data, buf->om_len); + XACT_SEG_RECV(seg); + + if (seg == link.rx.last_seg && !(link.rx.seg & BIT(0))) { + uint8_t expect_len; + + expect_len = (link.rx.buf->om_len - 20U - + ((link.rx.last_seg - 1) * 23U)); + if (expect_len != buf->om_len) { + BT_ERR("Incorrect last seg len: %u != %u", expect_len, + buf->om_len); + prov_failed(PROV_ERR_NVAL_FMT); + return; + } + } + + if (!link.rx.seg) { + prov_msg_recv(); + } +} + +static void gen_prov_ack(struct prov_rx *rx, struct os_mbuf *buf) +{ + BT_DBG("len %u", buf->om_len); + + if (!link.tx.buf[0]) { + return; + } + + if (rx->xact_id == link.tx.id) { + /* Don't clear resending of link_close messages */ + if (!atomic_test_bit(link.flags, ADV_LINK_CLOSING)) { + prov_clear_tx(); + } + + if (link.tx.cb) { + link.tx.cb(0, link.tx.cb_data); + } + } +} + +static void gen_prov_start(struct prov_rx *rx, struct os_mbuf *buf) +{ + uint8_t seg = SEG_NVAL; + + if (rx->xact_id == link.rx.id) { + if (!link.rx.seg) { + if (!ack_pending()) { + BT_DBG("Resending ack"); + gen_prov_ack_send(rx->xact_id); + } + + return; + } + + if (!(link.rx.seg & BIT(0))) { + BT_DBG("Ignoring duplicate segment"); + return; + } + } else if (rx->xact_id != next_transaction_id(link.rx.id)) { + BT_WARN("Unexpected xact 0x%x, expected 0x%x", rx->xact_id, + next_transaction_id(link.rx.id)); + return; + } + + net_buf_simple_reset(link.rx.buf); + link.rx.buf->om_len = net_buf_simple_pull_be16(buf); + link.rx.id = rx->xact_id; + link.rx.fcs = net_buf_simple_pull_u8(buf); + + BT_DBG("%p len %u last_seg %u total_len %u fcs 0x%02x", link.rx.buf, buf->om_len, + START_LAST_SEG(rx->gpc), link.rx.buf->om_len, link.rx.fcs); + + if (link.rx.buf->om_len < 1) { + BT_ERR("Ignoring zero-length provisioning PDU"); + prov_failed(PROV_ERR_NVAL_FMT); + return; + } + + if (START_LAST_SEG(rx->gpc) > 0 && link.rx.buf->om_len <= 20U) { + BT_ERR("Too small total length for multi-segment PDU"); + prov_failed(PROV_ERR_NVAL_FMT); + return; + } + + prov_clear_tx(); + + link.rx.last_seg = START_LAST_SEG(rx->gpc); + if ((link.rx.seg & BIT(0)) && + (find_msb_set((~link.rx.seg) & SEG_NVAL) - 1 > link.rx.last_seg)) { + BT_ERR("Invalid segment index %u", seg); + prov_failed(PROV_ERR_NVAL_FMT); + return; + } + + if (link.rx.seg) { + seg = link.rx.seg; + } + + link.rx.seg = seg & ((1 << (START_LAST_SEG(rx->gpc) + 1)) - 1); + memcpy(link.rx.buf->om_data, buf->om_data, buf->om_len); + XACT_SEG_RECV(0); + + if (!link.rx.seg) { + prov_msg_recv(); + } +} + +static void gen_prov_ctl(struct prov_rx *rx, struct os_mbuf *buf) +{ + BT_DBG("op 0x%02x len %u", BEARER_CTL(rx->gpc), buf->om_len); + + switch (BEARER_CTL(rx->gpc)) { + case LINK_OPEN: + link_open(rx, buf); + break; + case LINK_ACK: + if (!atomic_test_bit(link.flags, ADV_LINK_ACTIVE)) { + return; + } + + link_ack(rx, buf); + break; + case LINK_CLOSE: + if (!atomic_test_bit(link.flags, ADV_LINK_ACTIVE)) { + return; + } + + link_close(rx, buf); + break; + default: + BT_ERR("Unknown bearer opcode: 0x%02x", BEARER_CTL(rx->gpc)); + + if (IS_ENABLED(CONFIG_BT_TESTING)) { + bt_test_mesh_prov_invalid_bearer(BEARER_CTL(rx->gpc)); + } + + return; + } +} + +static const struct { + void (*func)(struct prov_rx *rx, struct os_mbuf *buf); + bool require_link; + uint8_t min_len; +} gen_prov[] = { + { gen_prov_start, true, 3 }, + { gen_prov_ack, true, 0 }, + { gen_prov_cont, true, 0 }, + { gen_prov_ctl, false, 0 }, +}; + +static void gen_prov_recv(struct prov_rx *rx, struct os_mbuf *buf) +{ + if (buf->om_len < gen_prov[GPCF(rx->gpc)].min_len) { + BT_ERR("Too short GPC message type %u", GPCF(rx->gpc)); + return; + } + + if (!atomic_test_bit(link.flags, ADV_LINK_ACTIVE) && + gen_prov[GPCF(rx->gpc)].require_link) { + BT_DBG("Ignoring message that requires active link"); + return; + } + + gen_prov[GPCF(rx->gpc)].func(rx, buf); +} + +/******************************************************************************* + * TX + ******************************************************************************/ + +static void send_reliable(void) +{ + int i; + + link.tx.start = k_uptime_get(); + + for (i = 0; i < ARRAY_SIZE(link.tx.buf); i++) { + struct os_mbuf *buf = link.tx.buf[i]; + + if (!buf) { + break; + } + + if (i + 1 < ARRAY_SIZE(link.tx.buf) && link.tx.buf[i + 1]) { + bt_mesh_adv_send(buf, NULL, NULL); + } else { + bt_mesh_adv_send(buf, &buf_sent_cb, NULL); + } + } +} + +static void prov_retransmit(struct ble_npl_event *work) +{ + int32_t timeout_ms; + int i; + + BT_DBG(""); + + if (!atomic_test_bit(link.flags, ADV_LINK_ACTIVE)) { + BT_WARN("Link not active"); + return; + } + + /* + * According to mesh profile spec (5.3.1.4.3), the close message should + * be restransmitted at least three times. Retransmit the link_close + * message until CLOSING_TIMEOUT has elapsed. + */ + if (atomic_test_bit(link.flags, ADV_LINK_CLOSING)) { + timeout_ms = CLOSING_TIMEOUT; + } else { + timeout_ms = TRANSACTION_TIMEOUT; + } + + if (k_uptime_get() - link.tx.start > timeout_ms) { + if (atomic_test_bit(link.flags, ADV_LINK_CLOSING)) { + close_link(PROV_BEARER_LINK_STATUS_SUCCESS); + } else { + BT_WARN("Giving up transaction"); + close_link(PROV_BEARER_LINK_STATUS_TIMEOUT); + } + + return; + } + + for (i = 0; i < ARRAY_SIZE(link.tx.buf); i++) { + struct os_mbuf *buf = link.tx.buf[i]; + + if (!buf) { + break; + } + + if (BT_MESH_ADV(buf)->busy) { + continue; + } + + BT_DBG("%u bytes: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len)); + + if (i + 1 < ARRAY_SIZE(link.tx.buf) && link.tx.buf[i + 1]) { + bt_mesh_adv_send(buf, NULL, NULL); + } else { + bt_mesh_adv_send(buf, &buf_sent_cb, NULL); + } + } +} + +static int bearer_ctl_send(uint8_t op, const void *data, uint8_t data_len, + bool reliable) +{ + struct os_mbuf *buf; + + BT_DBG("op 0x%02x data_len %u", op, data_len); + + prov_clear_tx(); + k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT); + + buf = adv_buf_create(reliable ? RETRANSMITS_RELIABLE : + RETRANSMITS_UNRELIABLE); + if (!buf) { + return -ENOBUFS; + } + + net_buf_add_be32(buf, link.id); + /* Transaction ID, always 0 for Bearer messages */ + net_buf_add_u8(buf, 0x00); + net_buf_add_u8(buf, GPC_CTL(op)); + net_buf_add_mem(buf, data, data_len); + + if (reliable) { + link.tx.buf[0] = buf; + send_reliable(); + } else { + bt_mesh_adv_send(buf, &buf_sent_cb, NULL); + net_buf_unref(buf); + } + + return 0; +} + +static int prov_send_adv(struct os_mbuf *msg, + prov_bearer_send_complete_t cb, void *cb_data) +{ + struct os_mbuf *start, *buf; + uint8_t seg_len, seg_id; + + prov_clear_tx(); + k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT); + + start = adv_buf_create(RETRANSMITS_RELIABLE); + if (!start) { + return -ENOBUFS; + } + + link.tx.id = next_transaction_id(link.tx.id); + net_buf_add_be32(start, link.id); + net_buf_add_u8(start, link.tx.id); + + net_buf_add_u8(start, GPC_START(last_seg(msg->om_len))); + net_buf_add_be16(start, msg->om_len); + net_buf_add_u8(start, bt_mesh_fcs_calc(msg->om_data, msg->om_len)); + + link.tx.buf[0] = start; + link.tx.cb = cb; + link.tx.cb_data = cb_data; + + BT_DBG("xact_id: 0x%x len: %u", link.tx.id, msg->om_len); + + seg_len = MIN(msg->om_len, START_PAYLOAD_MAX); + BT_DBG("seg 0 len %u: %s", seg_len, bt_hex(msg->om_data, seg_len)); + net_buf_add_mem(start, msg->om_data, seg_len); + net_buf_simple_pull_mem(msg, seg_len); + + buf = start; + for (seg_id = 1U; msg->om_len > 0; seg_id++) { + if (seg_id >= ARRAY_SIZE(link.tx.buf)) { + BT_ERR("Too big message"); + free_segments(); + return -E2BIG; + } + + buf = adv_buf_create(RETRANSMITS_RELIABLE); + if (!buf) { + free_segments(); + return -ENOBUFS; + } + + link.tx.buf[seg_id] = buf; + + seg_len = MIN(msg->om_len, CONT_PAYLOAD_MAX); + + BT_DBG("seg %u len %u: %s", seg_id, seg_len, + bt_hex(msg->om_data, seg_len)); + + net_buf_add_be32(buf, link.id); + net_buf_add_u8(buf, link.tx.id); + net_buf_add_u8(buf, GPC_CONT(seg_id)); + net_buf_add_mem(buf, msg->om_data, seg_len); + net_buf_simple_pull_mem(msg, seg_len); + } + + send_reliable(); + + return 0; +} + +/******************************************************************************* + * Link management rx + ******************************************************************************/ + +static void link_open(struct prov_rx *rx, struct os_mbuf *buf) +{ + BT_DBG("len %u", buf->om_len); + + if (buf->om_len < 16) { + BT_ERR("Too short bearer open message (len %u)", buf->om_len); + return; + } + + if (atomic_test_bit(link.flags, ADV_LINK_ACTIVE)) { + /* Send another link ack if the provisioner missed the last */ + if (link.id == rx->link_id) { + BT_DBG("Resending link ack"); + bearer_ctl_send(LINK_ACK, NULL, 0, false); + } else { + BT_DBG("Ignoring bearer open: link already active"); + } + + return; + } + + if (memcmp(buf->om_data, bt_mesh_prov_get()->uuid, 16)) { + BT_DBG("Bearer open message not for us"); + return; + } + + link.id = rx->link_id; + atomic_set_bit(link.flags, ADV_LINK_ACTIVE); + net_buf_simple_reset(link.rx.buf); + + bearer_ctl_send(LINK_ACK, NULL, 0, false); + + link.cb->link_opened(&pb_adv, link.cb_data); +} + +static void link_ack(struct prov_rx *rx, struct os_mbuf *buf) +{ + BT_DBG("len %u", buf->om_len); + + if (atomic_test_bit(link.flags, ADV_PROVISIONER)) { + if (atomic_test_and_set_bit(link.flags, ADV_LINK_ACK_RECVD)) { + return; + } + + prov_clear_tx(); + + link.cb->link_opened(&pb_adv, link.cb_data); + } +} + +static void link_close(struct prov_rx *rx, struct os_mbuf *buf) +{ + BT_DBG("len %u", buf->om_len); + + if (buf->om_len != 1) { + return; + } + + close_link(net_buf_simple_pull_u8(buf)); +} + +/******************************************************************************* + * Higher level functionality + ******************************************************************************/ + +void bt_mesh_pb_adv_recv(struct os_mbuf *buf) +{ + struct prov_rx rx; + + if (!link.cb) { + return; + } + + if (buf->om_len < 6) { + BT_WARN("Too short provisioning packet (len %u)", buf->om_len); + return; + } + + rx.link_id = net_buf_simple_pull_be32(buf); + rx.xact_id = net_buf_simple_pull_u8(buf); + rx.gpc = net_buf_simple_pull_u8(buf); + + if (atomic_test_bit(link.flags, ADV_LINK_ACTIVE) && link.id != rx.link_id) { + return; + } + + BT_DBG("link_id 0x%08x xact_id 0x%x", rx.link_id, rx.xact_id); + + gen_prov_recv(&rx, buf); +} + +static int prov_link_open(const uint8_t uuid[16], int32_t timeout, + const struct prov_bearer_cb *cb, void *cb_data) +{ + BT_DBG("uuid %s", bt_hex(uuid, 16)); + + if (atomic_test_and_set_bit(link.flags, ADV_LINK_ACTIVE)) { + return -EBUSY; + } + + atomic_set_bit(link.flags, ADV_PROVISIONER); + + bt_rand(&link.id, sizeof(link.id)); + link.tx.id = XACT_ID_MAX; + link.rx.id = XACT_ID_NVAL; + link.cb = cb; + link.cb_data = cb_data; + + net_buf_simple_reset(link.rx.buf); + + bearer_ctl_send(LINK_OPEN, uuid, 16, true); + + return 0; +} + +static int prov_link_accept(const struct prov_bearer_cb *cb, void *cb_data) +{ + if (atomic_test_bit(link.flags, ADV_LINK_ACTIVE)) { + return -EBUSY; + } + + link.rx.id = XACT_ID_MAX; + link.tx.id = XACT_ID_NVAL; + link.cb = cb; + link.cb_data = cb_data; + + /* Make sure we're scanning for provisioning inviations */ + bt_mesh_scan_enable(); + /* Enable unprovisioned beacon sending */ + bt_mesh_beacon_enable(); + + return 0; +} + +static void prov_link_close(enum prov_bearer_link_status status) +{ + if (atomic_test_and_set_bit(link.flags, ADV_LINK_CLOSING)) { + return; + } + + bearer_ctl_send(LINK_CLOSE, &status, 1, true); +} + +void pb_adv_init(void) +{ + k_delayed_work_init(&link.prot_timer, protocol_timeout); + k_delayed_work_init(&link.tx.retransmit, prov_retransmit); + + if (!rx_buf) { + rx_buf = NET_BUF_SIMPLE(65); + } + link.rx.buf = rx_buf; + net_buf_simple_reset(link.rx.buf); +} + +void pb_adv_reset(void) +{ + reset_adv_link(); +} + +const struct prov_bearer pb_adv = { + .type = BT_MESH_PROV_ADV, + .link_open = prov_link_open, + .link_accept = prov_link_accept, + .link_close = prov_link_close, + .send = prov_send_adv, + .clear_tx = prov_clear_tx, +}; diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/pb_gatt.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/pb_gatt.c new file mode 100644 index 00000000..a8f73787 --- /dev/null +++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/pb_gatt.c @@ -0,0 +1,158 @@ +/* Bluetooth Mesh */ + +/* + * Copyright (c) 2017 Intel Corporation + * Copyright (c) 2020 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ +#define MESH_LOG_MODULE BLE_MESH_PROV_LOG + +#include "mesh/mesh.h" +#include "prov.h" +#include "net.h" +#include "proxy.h" +#include "adv.h" +#include "prov.h" + +struct prov_link { + uint16_t conn_handle; + const struct prov_bearer_cb *cb; + void *cb_data; + struct { + uint8_t id; /* Transaction ID */ + uint8_t prev_id; /* Previous Transaction ID */ + uint8_t seg; /* Bit-field of unreceived segments */ + uint8_t last_seg; /* Last segment (to check length) */ + uint8_t fcs; /* Expected FCS value */ + struct os_mbuf *buf; + } rx; + struct k_delayed_work prot_timer; +}; + +static struct prov_link link; + +static void reset_state(void) +{ + link.conn_handle = BLE_HS_CONN_HANDLE_NONE; + + k_delayed_work_cancel(&link.prot_timer); + + link.rx.buf = bt_mesh_proxy_get_buf(); +} + +static void link_closed(enum prov_bearer_link_status status) +{ + const struct prov_bearer_cb *cb = link.cb; + + void *cb_data = link.cb_data; + + reset_state(); + + cb->link_closed(&pb_gatt, cb_data, status); +} + +static void protocol_timeout(struct ble_npl_event *work) +{ + BT_DBG("Protocol timeout"); + + link_closed(PROV_BEARER_LINK_STATUS_TIMEOUT); +} + +int bt_mesh_pb_gatt_recv(uint16_t conn_handle, struct os_mbuf *buf) +{ + BT_DBG("%u bytes: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len)); + + if (link.conn_handle != conn_handle || !link.cb) { + BT_WARN("Data for unexpected connection"); + return -ENOTCONN; + } + + if (buf->om_len < 1) { + BT_WARN("Too short provisioning packet (len %u)", buf->om_len); + return -EINVAL; + } + + k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT); + + link.cb->recv(&pb_gatt, link.cb_data, buf); + + return 0; +} + +int bt_mesh_pb_gatt_open(uint16_t conn_handle) +{ + BT_DBG("conn %p", conn_handle); + + if (link.conn_handle) { + return -EBUSY; + } + + link.conn_handle = conn_handle; + k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT); + + link.cb->link_opened(&pb_gatt, link.cb_data); + + return 0; +} + +int bt_mesh_pb_gatt_close(uint16_t conn_handle) +{ + BT_DBG("conn %p", conn_handle); + + if (link.conn_handle != conn_handle) { + BT_DBG("Not connected"); + return -ENOTCONN; + } + + link.cb->link_closed(&pb_gatt, link.cb_data, + PROV_BEARER_LINK_STATUS_SUCCESS); + + reset_state(); + + return 0; +} + +static int link_accept(const struct prov_bearer_cb *cb, void *cb_data) +{ + bt_mesh_proxy_prov_enable(); + bt_mesh_adv_update(); + + link.cb = cb; + link.cb_data = cb_data; + + return 0; +} + +static int buf_send(struct os_mbuf *buf, prov_bearer_send_complete_t cb, + void *cb_data) +{ + if (!link.conn_handle) { + return -ENOTCONN; + } + + k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT); + + return bt_mesh_proxy_send(link.conn_handle, BT_MESH_PROXY_PROV, buf); +} + +static void clear_tx(void) +{ + /* No action */ +} + +void pb_gatt_init(void) +{ + k_delayed_work_init(&link.prot_timer, protocol_timeout); +} + +void pb_gatt_reset(void) +{ + reset_state(); +} +const struct prov_bearer pb_gatt = { + .type = BT_MESH_PROV_GATT, + .link_accept = link_accept, + .send = buf_send, + .clear_tx = clear_tx, +}; \ No newline at end of file diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/prov.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/prov.c index fe92c0e3..ba514dde 100644 --- a/src/libs/mynewt-nimble/nimble/host/mesh/src/prov.c +++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/prov.c @@ -9,8 +9,6 @@ #include "syscfg/syscfg.h" #define MESH_LOG_MODULE BLE_MESH_PROV_LOG -#if MYNEWT_VAL(BLE_MESH_PROV) - #include #include "mesh/mesh.h" @@ -18,700 +16,52 @@ #include "crypto.h" #include "atomic.h" -#include "adv.h" #include "net.h" #include "access.h" #include "foundation.h" -#include "proxy.h" #include "prov.h" #include "testing.h" -#include "settings.h" -#include "nodes.h" -/* 3 transmissions, 20ms interval */ -#define PROV_XMIT BT_MESH_TRANSMIT(2, 20) +struct bt_mesh_prov_link bt_mesh_prov_link; +const struct bt_mesh_prov *bt_mesh_prov; -#define AUTH_METHOD_NO_OOB 0x00 -#define AUTH_METHOD_STATIC 0x01 -#define AUTH_METHOD_OUTPUT 0x02 -#define AUTH_METHOD_INPUT 0x03 - -#define OUTPUT_OOB_BLINK 0x00 -#define OUTPUT_OOB_BEEP 0x01 -#define OUTPUT_OOB_VIBRATE 0x02 -#define OUTPUT_OOB_NUMBER 0x03 -#define OUTPUT_OOB_STRING 0x04 - -#define INPUT_OOB_PUSH 0x00 -#define INPUT_OOB_TWIST 0x01 -#define INPUT_OOB_NUMBER 0x02 -#define INPUT_OOB_STRING 0x03 - -#define PUB_KEY_NO_OOB 0x00 -#define PUB_KEY_OOB 0x01 - -#define PROV_ERR_NONE 0x00 -#define PROV_ERR_NVAL_PDU 0x01 -#define PROV_ERR_NVAL_FMT 0x02 -#define PROV_ERR_UNEXP_PDU 0x03 -#define PROV_ERR_CFM_FAILED 0x04 -#define PROV_ERR_RESOURCES 0x05 -#define PROV_ERR_DECRYPT 0x06 -#define PROV_ERR_UNEXP_ERR 0x07 -#define PROV_ERR_ADDR 0x08 - -#define PROV_INVITE 0x00 -#define PROV_CAPABILITIES 0x01 -#define PROV_START 0x02 -#define PROV_PUB_KEY 0x03 -#define PROV_INPUT_COMPLETE 0x04 -#define PROV_CONFIRM 0x05 -#define PROV_RANDOM 0x06 -#define PROV_DATA 0x07 -#define PROV_COMPLETE 0x08 -#define PROV_FAILED 0x09 - -#define PROV_NO_PDU 0xff - -#define PROV_ALG_P256 0x00 - -#define GPCF(gpc) (gpc & 0x03) -#define GPC_START(last_seg) (((last_seg) << 2) | 0x00) -#define GPC_ACK 0x01 -#define GPC_CONT(seg_id) (((seg_id) << 2) | 0x02) -#define GPC_CTL(op) (((op) << 2) | 0x03) - -#define START_PAYLOAD_MAX 20 -#define CONT_PAYLOAD_MAX 23 - -#define START_LAST_SEG(gpc) (gpc >> 2) -#define CONT_SEG_INDEX(gpc) (gpc >> 2) - -#define BEARER_CTL(gpc) (gpc >> 2) -#define LINK_OPEN 0x00 -#define LINK_ACK 0x01 -#define LINK_CLOSE 0x02 - -#define CLOSE_REASON_SUCCESS 0x00 -#define CLOSE_REASON_TIMEOUT 0x01 -#define CLOSE_REASON_FAILED 0x02 - -#define XACT_SEG_DATA(_seg) (&link.rx.buf->om_data[20 + ((_seg - 1) * 23)]) -#define XACT_SEG_RECV(_seg) (link.rx.seg &= ~(1 << (_seg))) - -#define XACT_NVAL 0xff - -enum { - WAIT_PUB_KEY, /* Waiting for local PubKey to be generated */ - LINK_ACTIVE, /* Link has been opened */ - LINK_ACK_RECVD, /* Ack for link has been received */ - LINK_CLOSING, /* Link is closing down */ - SEND_PUB_KEY, /* Waiting to send PubKey */ - WAIT_NUMBER, /* Waiting for number input from user */ - WAIT_STRING, /* Waiting for string input from user */ - NOTIFY_INPUT_COMPLETE, /* Notify that input has been completed. */ - LINK_INVALID, /* Error occurred during provisioning */ - PROVISIONER, /* The link was opened as provisioner */ - - NUM_FLAGS, -}; - -#if MYNEWT_VAL(BLE_MESH_PROVISIONER) -#define PROVISIONER_LINK 1 -#else -#define PROVISIONER_LINK 0 -#endif - -struct provisioner_link { - struct bt_mesh_node *node; - u16_t addr; - u16_t net_idx; - u8_t attention_duration; -}; - -struct prov_link { - ATOMIC_DEFINE(flags, NUM_FLAGS); -#if (MYNEWT_VAL(BLE_MESH_PB_GATT)) - uint16_t conn_handle; /* GATT connection */ -#endif - struct provisioner_link provisioner[PROVISIONER_LINK]; - - u8_t dhkey[32]; /* Calculated DHKey */ - u8_t expect; /* Next expected PDU */ - - u8_t oob_method; - u8_t oob_action; - u8_t oob_size; - - u8_t conf[16]; /* Remote Confirmation */ - u8_t rand[16]; /* Local Random */ - u8_t auth[16]; /* Authentication Value */ - - u8_t conf_salt[16]; /* ConfirmationSalt */ - u8_t conf_key[16]; /* ConfirmationKey */ - u8_t conf_inputs[145]; /* ConfirmationInputs */ - u8_t prov_salt[16]; /* Provisioning Salt */ - -#if (MYNEWT_VAL(BLE_MESH_PB_ADV)) - u32_t id; /* Link ID */ - - struct { - u8_t id; /* Transaction ID */ - u8_t prev_id; /* Previous Transaction ID */ - u8_t seg; /* Bit-field of unreceived segments */ - u8_t last_seg; /* Last segment (to check length) */ - u8_t fcs; /* Expected FCS value */ - struct os_mbuf *buf; - } rx; - - struct { - /* Start timestamp of the transaction */ - s64_t start; - - /* Transaction id*/ - u8_t id; - - /* Pending outgoing buffer(s) */ - struct os_mbuf *buf[3]; - - /* Retransmit timer */ - struct k_delayed_work retransmit; - } tx; -#endif - - struct k_delayed_work prot_timer; -}; - -struct prov_rx { - u32_t link_id; - u8_t xact_id; - u8_t gpc; -}; - -#define RETRANSMIT_TIMEOUT K_MSEC(500) -#define BUF_TIMEOUT K_MSEC(400) -#define CLOSING_TIMEOUT K_SECONDS(3) -#define TRANSACTION_TIMEOUT K_SECONDS(30) -#define PROTOCOL_TIMEOUT K_SECONDS(60) - -#if (MYNEWT_VAL(BLE_MESH_PB_GATT)) -#define PROV_BUF_HEADROOM 5 -#else -#define PROV_BUF_HEADROOM 0 -static struct os_mbuf *rx_buf; -#endif - -#define PROV_BUF(len) NET_BUF_SIMPLE(PROV_BUF_HEADROOM + len) - -static struct prov_link link; - -static const struct bt_mesh_prov *prov; - -static void pub_key_ready(const u8_t *pkey); - -static int reset_state(void) +static void pub_key_ready(const uint8_t *pkey) { - static struct bt_pub_key_cb pub_key_cb = { - .func = pub_key_ready, - }; - int err; + if (!pkey) { + BT_WARN("Public key not available"); + return; + } + BT_DBG("Local public key ready"); +} - k_delayed_work_cancel(&link.prot_timer); +int bt_mesh_prov_reset_state(void (*func)(const uint8_t key[64])) +{ + BT_DBG("bt_mesh_prov_reset_state"); + + int err; + static struct bt_pub_key_cb pub_key_cb; + const size_t offset = offsetof(struct bt_mesh_prov_link, dhkey); + + pub_key_cb.func = func ? func : pub_key_ready; /* Disable Attention Timer if it was set */ - if (link.conf_inputs[0]) { + if (bt_mesh_prov_link.conf_inputs[0]) { bt_mesh_attention(NULL, 0); } - if (IS_ENABLED(CONFIG_BT_MESH_PROVISIONER) && - link.provisioner->node != NULL) { - bt_mesh_node_del(link.provisioner->node, false); - } - -#if (MYNEWT_VAL(BLE_MESH_PB_ADV)) - /* Clear everything except the retransmit and protocol timer - * delayed work objects. - */ - (void)memset(&link, 0, offsetof(struct prov_link, tx.retransmit)); - link.rx.prev_id = XACT_NVAL; - -#if (MYNEWT_VAL(BLE_MESH_PB_GATT)) - link.rx.buf = bt_mesh_proxy_get_buf(); -#else - if (!rx_buf) { - rx_buf = NET_BUF_SIMPLE(65); - } - net_buf_simple_init(rx_buf, 0); - link.rx.buf = rx_buf; -#endif /* PB_GATT */ - -#else /* !PB_ADV */ - /* Clear everything except the protocol timer (k_delayed_work) */ - (void)memset(&link, 0, offsetof(struct prov_link, prot_timer)); -#endif /* PB_ADV */ - -#if (MYNEWT_VAL(BLE_MESH_PB_GATT)) - link.conn_handle = BLE_HS_CONN_HANDLE_NONE; -#endif + atomic_clear(bt_mesh_prov_link.flags); + (void)memset((uint8_t *)&bt_mesh_prov_link + offset, 0, + sizeof(bt_mesh_prov_link) - offset); err = bt_pub_key_gen(&pub_key_cb); if (err) { BT_ERR("Failed to generate public key (%d)", err); return err; } - return 0; } -#if (MYNEWT_VAL(BLE_MESH_PB_ADV)) -static void buf_sent(int err, void *user_data) -{ - BT_DBG("buf_sent"); - - if (!link.tx.buf[0]) { - return; - } - - k_delayed_work_submit(&link.tx.retransmit, RETRANSMIT_TIMEOUT); -} - -static struct bt_mesh_send_cb buf_sent_cb = { - .end = buf_sent, -}; - -static void free_segments(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(link.tx.buf); i++) { - struct os_mbuf *buf = link.tx.buf[i]; - - if (!buf) { - break; - } - - link.tx.buf[i] = NULL; - /* Mark as canceled */ - BT_MESH_ADV(buf)->busy = 0; - net_buf_unref(buf); - } -} - -static void prov_clear_tx(void) -{ - BT_DBG(""); - - k_delayed_work_cancel(&link.tx.retransmit); - - free_segments(); -} - -static void reset_adv_link(void) -{ - prov_clear_tx(); - - if (prov->link_close) { - prov->link_close(BT_MESH_PROV_ADV); - } - - reset_state(); -} - -static struct os_mbuf *adv_buf_create(void) -{ - struct os_mbuf *buf; - - buf = bt_mesh_adv_create(BT_MESH_ADV_PROV, PROV_XMIT, BUF_TIMEOUT); - if (!buf) { - BT_ERR("Out of provisioning buffers"); - assert(0); - return NULL; - } - - return buf; -} - -static u8_t pending_ack = XACT_NVAL; - -static void ack_complete(u16_t duration, int err, void *user_data) -{ - BT_DBG("xact %u complete", (u8_t)pending_ack); - pending_ack = XACT_NVAL; -} - -static void gen_prov_ack_send(u8_t xact_id) -{ - static const struct bt_mesh_send_cb cb = { - .start = ack_complete, - }; - const struct bt_mesh_send_cb *complete; - struct os_mbuf *buf; - - BT_DBG("xact_id %u", xact_id); - - if (pending_ack == xact_id) { - BT_DBG("Not sending duplicate ack"); - return; - } - - buf = adv_buf_create(); - if (!buf) { - return; - } - - if (pending_ack == XACT_NVAL) { - pending_ack = xact_id; - complete = &cb; - } else { - complete = NULL; - } - - net_buf_add_be32(buf, link.id); - net_buf_add_u8(buf, xact_id); - net_buf_add_u8(buf, GPC_ACK); - - bt_mesh_adv_send(buf, complete, NULL); - net_buf_unref(buf); -} - -static void send_reliable(void) -{ - int i; - - link.tx.start = k_uptime_get(); - - for (i = 0; i < ARRAY_SIZE(link.tx.buf); i++) { - struct os_mbuf *buf = link.tx.buf[i]; - - if (!buf) { - break; - } - - if (i + 1 < ARRAY_SIZE(link.tx.buf) && link.tx.buf[i + 1]) { - bt_mesh_adv_send(buf, NULL, NULL); - } else { - bt_mesh_adv_send(buf, &buf_sent_cb, NULL); - } - } -} - -static int bearer_ctl_send(u8_t op, const void *data, u8_t data_len) -{ - struct os_mbuf *buf; - - BT_DBG("op 0x%02x data_len %u", op, data_len); - - prov_clear_tx(); - - buf = adv_buf_create(); - if (!buf) { - return -ENOBUFS; - } - - net_buf_add_be32(buf, link.id); - /* Transaction ID, always 0 for Bearer messages */ - net_buf_add_u8(buf, 0x00); - net_buf_add_u8(buf, GPC_CTL(op)); - net_buf_add_mem(buf, data, data_len); - - link.tx.buf[0] = buf; - send_reliable(); - - return 0; -} - -static u8_t last_seg(u8_t len) -{ - if (len <= START_PAYLOAD_MAX) { - return 0; - } - - len -= START_PAYLOAD_MAX; - - return 1 + (len / CONT_PAYLOAD_MAX); -} - -static inline u8_t next_transaction_id(void) -{ - if (atomic_test_bit(link.flags, PROVISIONER)) { - if (link.tx.id != 0x7F) { - link.tx.id++; - } else { - link.tx.id = 0; - } - } else { - if (link.tx.id != 0U && link.tx.id != 0xFF) { - link.tx.id++; - } else { - link.tx.id = 0x80; - } - } - - return link.tx.id; -} - -static int prov_send_adv(struct os_mbuf *msg) -{ - struct os_mbuf *start, *buf; - u8_t seg_len, seg_id; - u8_t xact_id; - - BT_DBG("len %u: %s", msg->om_len, bt_hex(msg->om_data, msg->om_len)); - - prov_clear_tx(); - - start = adv_buf_create(); - if (!start) { - return -ENOBUFS; - } - - xact_id = next_transaction_id(); - net_buf_add_be32(start, link.id); - net_buf_add_u8(start, xact_id); - - net_buf_add_u8(start, GPC_START(last_seg(msg->om_len))); - net_buf_add_be16(start, msg->om_len); - net_buf_add_u8(start, bt_mesh_fcs_calc(msg->om_data, msg->om_len)); - - link.tx.buf[0] = start; - - seg_len = min(msg->om_len, START_PAYLOAD_MAX); - BT_DBG("seg 0 len %u: %s", seg_len, bt_hex(msg->om_data, seg_len)); - net_buf_add_mem(start, msg->om_data, seg_len); - net_buf_simple_pull(msg, seg_len); - - buf = start; - for (seg_id = 1; msg->om_len > 0; seg_id++) { - if (seg_id >= ARRAY_SIZE(link.tx.buf)) { - BT_ERR("Too big message"); - free_segments(); - return -E2BIG; - } - - buf = adv_buf_create(); - if (!buf) { - free_segments(); - return -ENOBUFS; - } - - link.tx.buf[seg_id] = buf; - - seg_len = min(msg->om_len, CONT_PAYLOAD_MAX); - - BT_DBG("seg_id %u len %u: %s", seg_id, seg_len, - bt_hex(msg->om_data, seg_len)); - - net_buf_add_be32(buf, link.id); - net_buf_add_u8(buf, xact_id); - net_buf_add_u8(buf, GPC_CONT(seg_id)); - net_buf_add_mem(buf, msg->om_data, seg_len); - net_buf_simple_pull(msg, seg_len); - } - - send_reliable(); - - return 0; -} - -#endif /* MYNEWT_VAL(BLE_MESH_PB_ADV) */ - -#if (MYNEWT_VAL(BLE_MESH_PB_GATT)) -static int prov_send_gatt(struct os_mbuf *msg) -{ - if (link.conn_handle == BLE_HS_CONN_HANDLE_NONE) { - BT_ERR("No connection handle!?"); - return -ENOTCONN; - } - - return bt_mesh_proxy_send(link.conn_handle, BT_MESH_PROXY_PROV, msg); -} -#endif /* MYNEWT_VAL(BLE_MESH_PB_GATT) */ - -static inline int prov_send(struct os_mbuf *buf) -{ - k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT); - -#if (MYNEWT_VAL(BLE_MESH_PB_GATT)) - if (link.conn_handle != BLE_HS_CONN_HANDLE_NONE) { - return prov_send_gatt(buf); - } -#endif -#if (MYNEWT_VAL(BLE_MESH_PB_ADV)) - return prov_send_adv(buf); -#else - return 0; -#endif -} - -static void prov_buf_init(struct os_mbuf *buf, u8_t type) -{ - net_buf_simple_init(buf, PROV_BUF_HEADROOM); - net_buf_simple_add_u8(buf, type); -} - -static void prov_send_fail_msg(u8_t err) -{ - struct os_mbuf *buf = PROV_BUF(2); - - prov_buf_init(buf, PROV_FAILED); - net_buf_simple_add_u8(buf, err); - - if (prov_send(buf)) { - BT_ERR("Failed to send Provisioning Failed message"); - } - - atomic_set_bit(link.flags, LINK_INVALID); - - os_mbuf_free_chain(buf); -} - -static void prov_invite(const u8_t *data) -{ - struct os_mbuf *buf = PROV_BUF(12); - - BT_DBG("Attention Duration: %u seconds", data[0]); - - if (data[0]) { - bt_mesh_attention(NULL, data[0]); - } - - link.conf_inputs[0] = data[0]; - - prov_buf_init(buf, PROV_CAPABILITIES); - - /* Number of Elements supported */ - net_buf_simple_add_u8(buf, bt_mesh_elem_count()); - - /* Supported algorithms - FIPS P-256 Eliptic Curve */ - net_buf_simple_add_be16(buf, BIT(PROV_ALG_P256)); - - /* Public Key Type, Only "No OOB" Public Key is supported*/ - net_buf_simple_add_u8(buf, PUB_KEY_NO_OOB); - - /* Static OOB Type */ - net_buf_simple_add_u8(buf, prov->static_val ? BIT(0) : 0x00); - - /* Output OOB Size */ - net_buf_simple_add_u8(buf, prov->output_size); - - /* Output OOB Action */ - net_buf_simple_add_be16(buf, prov->output_actions); - - /* Input OOB Size */ - net_buf_simple_add_u8(buf, prov->input_size); - - /* Input OOB Action */ - net_buf_simple_add_be16(buf, prov->input_actions); - - memcpy(&link.conf_inputs[1], &buf->om_data[1], 11); - - if (prov_send(buf)) { - BT_ERR("Failed to send capabilities"); - goto done; - } - - link.expect = PROV_START; - -done: - os_mbuf_free_chain(buf); -} - -#if MYNEWT_VAL(BLE_MESH_PB_ADV) -static void send_invite(void) -{ - struct os_mbuf *inv = PROV_BUF(2); - - BT_DBG(""); - - prov_buf_init(inv, PROV_INVITE); - net_buf_simple_add_u8(inv, link.provisioner->attention_duration); - - link.conf_inputs[0] = link.provisioner->attention_duration; - - if (prov_send(inv)) { - BT_ERR("Failed to send invite"); - goto done; - } - - link.expect = PROV_CAPABILITIES; - -done: - os_mbuf_free_chain(inv); -} -#endif - -static void send_start(void) -{ - struct os_mbuf *start = PROV_BUF(6); - - BT_DBG(""); - - prov_buf_init(start, PROV_START); - - net_buf_simple_add_u8(start, PROV_ALG_P256); - net_buf_simple_add_u8(start, PUB_KEY_NO_OOB); - net_buf_simple_add_u8(start, AUTH_METHOD_NO_OOB); - memset(link.auth, 0, sizeof(link.auth)); - - net_buf_simple_add_u8(start, 0); /* Auth Action */ - net_buf_simple_add_u8(start, 0); /* Auth Size */ - - memcpy(&link.conf_inputs[12], &start->om_data[1], 5); - - if (prov_send(start)) { - BT_ERR("Failed to send start"); - } - - os_mbuf_free_chain(start); -} - -static void prov_capabilities(const u8_t *data) -{ - u16_t algorithms, output_action, input_action; - - if (!IS_ENABLED(CONFIG_BT_MESH_PROVISIONER)) { - return; - } - - BT_DBG("Elements: %u", data[0]); - - algorithms = sys_get_be16(&data[1]); - BT_DBG("Algorithms: %u", algorithms); - - BT_DBG("Public Key Type: 0x%02x", data[3]); - BT_DBG("Static OOB Type: 0x%02x", data[4]); - BT_DBG("Output OOB Size: %u", data[5]); - - output_action = sys_get_be16(&data[6]); - BT_DBG("Output OOB Action: 0x%04x", output_action); - - BT_DBG("Input OOB Size: %u", data[8]); - - input_action = sys_get_be16(&data[9]); - BT_DBG("Input OOB Action: 0x%04x", input_action); - - if (data[0] == 0) { - BT_ERR("Invalid number of elements"); - prov_send_fail_msg(PROV_ERR_NVAL_FMT); - return; - } - - link.provisioner->node = bt_mesh_node_alloc(link.provisioner->addr, - data[0], - link.provisioner->net_idx); - if (link.provisioner->node == NULL) { - prov_send_fail_msg(PROV_ERR_RESOURCES); - return; - } - - memcpy(&link.conf_inputs[1], data, 11); - - atomic_set_bit(link.flags, SEND_PUB_KEY); - - send_start(); -} - -static bt_mesh_output_action_t output_action(u8_t action) +static bt_mesh_output_action_t output_action(uint8_t action) { switch (action) { case OUTPUT_OOB_BLINK: @@ -729,7 +79,7 @@ static bt_mesh_output_action_t output_action(u8_t action) } } -static bt_mesh_input_action_t input_action(u8_t action) +static bt_mesh_input_action_t input_action(uint8_t action) { switch (action) { case INPUT_OOB_PUSH: @@ -745,7 +95,7 @@ static bt_mesh_input_action_t input_action(u8_t action) } } -static int prov_auth(u8_t method, u8_t action, u8_t size) +int bt_mesh_prov_auth(uint8_t method, uint8_t action, uint8_t size) { bt_mesh_output_action_t output; bt_mesh_input_action_t input; @@ -756,16 +106,15 @@ static int prov_auth(u8_t method, u8_t action, u8_t size) return -EINVAL; } - memset(link.auth, 0, sizeof(link.auth)); + (void)memset(bt_mesh_prov_link.auth, 0, sizeof(bt_mesh_prov_link.auth)); return 0; case AUTH_METHOD_STATIC: if (action || size) { return -EINVAL; } - memcpy(link.auth + 16 - prov->static_val_len, - prov->static_val, prov->static_val_len); - memset(link.auth, 0, sizeof(link.auth) - prov->static_val_len); + atomic_set_bit(bt_mesh_prov_link.flags, OOB_STATIC_KEY); + return 0; case AUTH_METHOD_OUTPUT: @@ -774,19 +123,19 @@ static int prov_auth(u8_t method, u8_t action, u8_t size) return -EINVAL; } - if (!(prov->output_actions & output)) { + if (!(bt_mesh_prov->output_actions & output)) { return -EINVAL; } - if (size > prov->output_size) { + if (size > bt_mesh_prov->output_size) { return -EINVAL; } - atomic_set_bit(link.flags, NOTIFY_INPUT_COMPLETE); + atomic_set_bit(bt_mesh_prov_link.flags, NOTIFY_INPUT_COMPLETE); if (output == BT_MESH_DISPLAY_STRING) { unsigned char str[9]; - u8_t i; + uint8_t i; bt_rand(str, size); @@ -801,22 +150,23 @@ static int prov_auth(u8_t method, u8_t action, u8_t size) } str[size] = '\0'; - memcpy(link.auth, str, size); - memset(link.auth + size, 0, sizeof(link.auth) - size); + memcpy(bt_mesh_prov_link.auth, str, size); + memset(bt_mesh_prov_link.auth + size, 0, + sizeof(bt_mesh_prov_link.auth) - size); - return prov->output_string((char *)str); + return bt_mesh_prov->output_string((char *)str); } else { - u32_t div[8] = { 10, 100, 1000, 10000, 100000, + uint32_t div[8] = { 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000 }; - u32_t num; + uint32_t num; bt_rand(&num, sizeof(num)); num %= div[size - 1]; - sys_put_be32(num, &link.auth[12]); - memset(link.auth, 0, 12); + sys_put_be32(num, &bt_mesh_prov_link.auth[12]); + memset(bt_mesh_prov_link.auth, 0, 12); - return prov->output_number(output, num); + return bt_mesh_prov->output_number(output, num); } case AUTH_METHOD_INPUT: @@ -825,140 +175,38 @@ static int prov_auth(u8_t method, u8_t action, u8_t size) return -EINVAL; } - if (!(prov->input_actions & input)) { + if (!(bt_mesh_prov->input_actions & input)) { return -EINVAL; } - if (size > prov->input_size) { + if (size > bt_mesh_prov->input_size) { return -EINVAL; } if (input == BT_MESH_ENTER_STRING) { - atomic_set_bit(link.flags, WAIT_STRING); + atomic_set_bit(bt_mesh_prov_link.flags, WAIT_STRING); } else { - atomic_set_bit(link.flags, WAIT_NUMBER); + atomic_set_bit(bt_mesh_prov_link.flags, WAIT_NUMBER); } - return prov->input(input, size); + return bt_mesh_prov->input(input, size); default: return -EINVAL; } } -static void prov_start(const u8_t *data) -{ - BT_DBG("Algorithm: 0x%02x", data[0]); - BT_DBG("Public Key: 0x%02x", data[1]); - BT_DBG("Auth Method: 0x%02x", data[2]); - BT_DBG("Auth Action: 0x%02x", data[3]); - BT_DBG("Auth Size: 0x%02x", data[4]); - - if (data[0] != PROV_ALG_P256) { - BT_ERR("Unknown algorithm 0x%02x", data[0]); - prov_send_fail_msg(PROV_ERR_NVAL_FMT); - return; - } - - if (data[1] != PUB_KEY_NO_OOB) { - BT_ERR("Invalid public key type: 0x%02x", data[1]); - prov_send_fail_msg(PROV_ERR_NVAL_FMT); - return; - } - - memcpy(&link.conf_inputs[12], data, 5); - - /* TODO: reset link when auth fails? */ - link.expect = PROV_PUB_KEY; - - if (prov_auth(data[2], data[3], data[4]) < 0) { - BT_ERR("Invalid authentication method: 0x%02x; " - "action: 0x%02x; size: 0x%02x", data[2], data[3], - data[4]); - prov_send_fail_msg(PROV_ERR_NVAL_FMT); - } -} - -static void send_confirm(void) -{ - struct os_mbuf *cfm = PROV_BUF(17); - - BT_DBG("ConfInputs[0] %s", bt_hex(link.conf_inputs, 64)); - BT_DBG("ConfInputs[64] %s", bt_hex(&link.conf_inputs[64], 64)); - BT_DBG("ConfInputs[128] %s", bt_hex(&link.conf_inputs[128], 17)); - - if (bt_mesh_prov_conf_salt(link.conf_inputs, link.conf_salt)) { - BT_ERR("Unable to generate confirmation salt"); - prov_send_fail_msg(PROV_ERR_UNEXP_ERR); - goto done; - } - - BT_DBG("ConfirmationSalt: %s", bt_hex(link.conf_salt, 16)); - - if (bt_mesh_prov_conf_key(link.dhkey, link.conf_salt, link.conf_key)) { - BT_ERR("Unable to generate confirmation key"); - prov_send_fail_msg(PROV_ERR_UNEXP_ERR); - goto done; - } - - BT_DBG("ConfirmationKey: %s", bt_hex(link.conf_key, 16)); - - if (bt_rand(link.rand, 16)) { - BT_ERR("Unable to generate random number"); - prov_send_fail_msg(PROV_ERR_UNEXP_ERR); - goto done; - } - - BT_DBG("LocalRandom: %s", bt_hex(link.rand, 16)); - - prov_buf_init(cfm, PROV_CONFIRM); - - if (bt_mesh_prov_conf(link.conf_key, link.rand, link.auth, - net_buf_simple_add(cfm, 16))) { - BT_ERR("Unable to generate confirmation value"); - prov_send_fail_msg(PROV_ERR_UNEXP_ERR); - goto done; - } - - if (prov_send(cfm)) { - BT_ERR("Failed to send Provisioning Confirm"); - goto done; - } - - if (atomic_test_bit(link.flags, PROVISIONER)) { - link.expect = PROV_CONFIRM; - } else { - link.expect = PROV_RANDOM; - } - -done: - os_mbuf_free_chain(cfm); -} - -static void send_input_complete(void) -{ - struct os_mbuf *buf = PROV_BUF(1); - - prov_buf_init(buf, PROV_INPUT_COMPLETE); - if (prov_send(buf)) { - BT_ERR("Failed to send Provisioning Input Complete"); - } - link.expect = PROV_CONFIRM; - - os_mbuf_free_chain(buf); -} - -int bt_mesh_input_number(u32_t num) +int bt_mesh_input_number(uint32_t num) { BT_DBG("%u", (unsigned) num); - if (!atomic_test_and_clear_bit(link.flags, WAIT_NUMBER)) { + if (!atomic_test_and_clear_bit(bt_mesh_prov_link.flags, WAIT_NUMBER)) { return -EINVAL; } - sys_put_be32(num, &link.auth[12]); + sys_put_be32(num, &bt_mesh_prov_link.auth[12]); - send_input_complete(); + bt_mesh_prov_link.role->input_complete(); return 0; } @@ -967,991 +215,145 @@ int bt_mesh_input_string(const char *str) { BT_DBG("%s", str); - if (!atomic_test_and_clear_bit(link.flags, WAIT_STRING)) { + if (!atomic_test_and_clear_bit(bt_mesh_prov_link.flags, WAIT_STRING)) { return -EINVAL; } - strncpy((char *)link.auth, str, prov->input_size); + strncpy((char *)bt_mesh_prov_link.auth, str, bt_mesh_prov->input_size); - send_input_complete(); + bt_mesh_prov_link.role->input_complete(); return 0; } -static void send_pub_key(void) -{ - struct os_mbuf *buf = PROV_BUF(65); - const u8_t *key; - - key = bt_pub_key_get(); - if (!key) { - BT_ERR("No public key available"); - prov_send_fail_msg(PROV_ERR_UNEXP_ERR); - goto done; - } - - BT_DBG("Local Public Key: %s", bt_hex(key, 64)); - - prov_buf_init(buf, PROV_PUB_KEY); - - /* Swap X and Y halves independently to big-endian */ - sys_memcpy_swap(net_buf_simple_add(buf, 32), key, 32); - sys_memcpy_swap(net_buf_simple_add(buf, 32), &key[32], 32); - - if (atomic_test_bit(link.flags, PROVISIONER)) { - /* PublicKeyProvisioner */ - memcpy(&link.conf_inputs[17], &buf->om_data[1], 64); - } else { - /* PublicKeyRemote */ - memcpy(&link.conf_inputs[81], &buf->om_data[1], 64); - } - - if (prov_send(buf)) { - BT_ERR("Failed to send Public Key"); - goto done; - } - - if (atomic_test_bit(link.flags, PROVISIONER)) { - link.expect = PROV_PUB_KEY; - } else { - if (atomic_test_bit(link.flags, WAIT_NUMBER) || - atomic_test_bit(link.flags, WAIT_STRING)) { - link.expect = PROV_NO_PDU; /* Wait for input */ - } else { - link.expect = PROV_CONFIRM; - } - } - -done: - os_mbuf_free_chain(buf); -} - -static void prov_dh_key_cb(const u8_t dhkey[32]) -{ - BT_DBG("%p", dhkey); - - if (!dhkey) { - BT_ERR("DHKey generation failed"); - prov_send_fail_msg(PROV_ERR_UNEXP_ERR); - return; - } - - sys_memcpy_swap(link.dhkey, dhkey, 32); - - BT_DBG("DHkey: %s", bt_hex(link.dhkey, 32)); - - if (atomic_test_bit(link.flags, PROVISIONER)) { - send_confirm(); - } else { - send_pub_key(); - } -} - -static void prov_dh_key_gen(void) -{ - u8_t remote_pk_le[64], *remote_pk; - - if (atomic_test_bit(link.flags, PROVISIONER)) { - remote_pk = &link.conf_inputs[81]; - } else { - remote_pk = &link.conf_inputs[17]; - } - - /* Copy remote key in little-endian for bt_dh_key_gen(). - * X and Y halves are swapped independently. The bt_dh_key_gen() - * will also take care of validating the remote public key. - */ - sys_memcpy_swap(remote_pk_le, remote_pk, 32); - sys_memcpy_swap(&remote_pk_le[32], &remote_pk[32], 32); - - if (bt_dh_key_gen(remote_pk_le, prov_dh_key_cb)) { - BT_ERR("Failed to generate DHKey"); - prov_send_fail_msg(PROV_ERR_UNEXP_ERR); - } -} - -static void prov_pub_key(const u8_t *data) -{ - BT_DBG("Remote Public Key: %s", bt_hex(data, 64)); - - if (atomic_test_bit(link.flags, PROVISIONER)) { - /* PublicKeyDevice */ - memcpy(&link.conf_inputs[81], data, 64); - -#if (MYNEWT_VAL(BLE_MESH_PB_ADV)) - prov_clear_tx(); -#endif - } else { - /* PublicKeyProvisioner */ - memcpy(&link.conf_inputs[17], data, 64); - - if (!bt_pub_key_get()) { - /* Clear retransmit timer */ -#if (MYNEWT_VAL(BLE_MESH_PB_ADV)) - prov_clear_tx(); -#endif - - atomic_set_bit(link.flags, WAIT_PUB_KEY); - BT_WARN("Waiting for local public key"); - return; - } - } - - prov_dh_key_gen(); -} - -static void pub_key_ready(const u8_t *pkey) -{ - if (!pkey) { - BT_WARN("Public key not available"); - return; - } - - BT_DBG("Local public key ready"); - - if (atomic_test_and_clear_bit(link.flags, WAIT_PUB_KEY)) { - if (atomic_test_bit(link.flags, PROVISIONER)) { - send_pub_key(); - } else { - prov_dh_key_gen(); - } - } -} - -static void notify_input_complete(void) -{ - if (atomic_test_and_clear_bit(link.flags, NOTIFY_INPUT_COMPLETE) && - prov->input_complete) { - prov->input_complete(); - } -} - -static void prov_input_complete(const u8_t *data) -{ - BT_DBG(""); - notify_input_complete(); -} - -static void send_prov_data(void) -{ - struct os_mbuf *pdu = PROV_BUF(34); - struct bt_mesh_subnet *sub; - u8_t session_key[16]; - u8_t nonce[13]; - int err; - - err = bt_mesh_session_key(link.dhkey, link.prov_salt, session_key); - if (err) { - BT_ERR("Unable to generate session key"); - prov_send_fail_msg(PROV_ERR_UNEXP_ERR); - goto done; - } - - BT_DBG("SessionKey: %s", bt_hex(session_key, 16)); - - err = bt_mesh_prov_nonce(link.dhkey, link.prov_salt, nonce); - if (err) { - BT_ERR("Unable to generate session nonce"); - prov_send_fail_msg(PROV_ERR_UNEXP_ERR); - goto done; - } - - BT_DBG("Nonce: %s", bt_hex(nonce, 13)); - - err = bt_mesh_dev_key(link.dhkey, link.prov_salt, - link.provisioner->node->dev_key); - if (err) { - BT_ERR("Unable to generate device key"); - prov_send_fail_msg(PROV_ERR_UNEXP_ERR); - goto done; - } - - BT_DBG("DevKey: %s", bt_hex(link.provisioner->node->dev_key, 16)); - - sub = bt_mesh_subnet_get(link.provisioner->node->net_idx); - if (sub == NULL) { - BT_ERR("No subnet with net_idx %u", - link.provisioner->node->net_idx); - prov_send_fail_msg(PROV_ERR_UNEXP_ERR); - goto done; - } - - prov_buf_init(pdu, PROV_DATA); - net_buf_simple_add_mem(pdu, sub->keys[sub->kr_flag].net, 16); - net_buf_simple_add_be16(pdu, link.provisioner->node->net_idx); - net_buf_simple_add_u8(pdu, bt_mesh_net_flags(sub)); - net_buf_simple_add_be32(pdu, bt_mesh.iv_index); - net_buf_simple_add_be16(pdu, link.provisioner->node->addr); - net_buf_simple_add(pdu, 8); /* For MIC */ - - BT_DBG("net_idx %u, iv_index 0x%08x, addr 0x%04x", - link.provisioner->node->net_idx, bt_mesh.iv_index, - link.provisioner->node->addr); - - err = bt_mesh_prov_encrypt(session_key, nonce, &pdu->om_data[1], - &pdu->om_data[1]); - if (err) { - BT_ERR("Unable to encrypt provisioning data"); - prov_send_fail_msg(PROV_ERR_DECRYPT); - goto done; - } - - if (prov_send(pdu)) { - BT_ERR("Failed to send Provisioning Data"); - goto done; - } - - link.expect = PROV_COMPLETE; - -done: - os_mbuf_free_chain(pdu); -} - -static void prov_complete(const u8_t *data) -{ - if (!IS_ENABLED(CONFIG_BT_MESH_PROVISIONER)) { - return; - } - - struct bt_mesh_node *node = link.provisioner->node; -#if MYNEWT_VAL(BLE_MESH_PB_ADV) - u8_t reason = CLOSE_REASON_SUCCESS; -#endif - - BT_DBG("key %s, net_idx %u, num_elem %u, addr 0x%04x", - bt_hex(node->dev_key, 16), node->net_idx, node->num_elem, - node->addr); - - if (IS_ENABLED(CONFIG_BT_SETTINGS)) { - bt_mesh_store_node(node); - } - - link.provisioner->node = NULL; - link.expect = PROV_NO_PDU; - atomic_set_bit(link.flags, LINK_CLOSING); - -#if MYNEWT_VAL(BLE_MESH_PB_ADV) - bearer_ctl_send(LINK_CLOSE, &reason, sizeof(reason)); -#endif - - bt_mesh_prov_node_added(node->net_idx, node->addr, node->num_elem); - - /* - * According to mesh profile spec (5.3.1.4.3), the close message should - * be restransmitted at least three times. Retransmit the LINK_CLOSE - * message until CLOSING_TIMEOUT has elapsed instead of resetting the - * link here. - */ -} - -static void send_random(void) -{ - struct os_mbuf *rnd = PROV_BUF(17); - - prov_buf_init(rnd, PROV_RANDOM); - net_buf_simple_add_mem(rnd, link.rand, 16); - - if (prov_send(rnd)) { - BT_ERR("Failed to send Provisioning Random"); - goto done; - } - - if (atomic_test_bit(link.flags, PROVISIONER)) { - link.expect = PROV_RANDOM; - } else { - link.expect = PROV_DATA; - } - -done: - os_mbuf_free_chain(rnd); -} - -static void prov_random(const u8_t *data) -{ - u8_t conf_verify[16]; - const u8_t *prov_rand, *dev_rand; - - BT_DBG("Remote Random: %s", bt_hex(data, 16)); - - if (bt_mesh_prov_conf(link.conf_key, data, link.auth, conf_verify)) { - BT_ERR("Unable to calculate confirmation verification"); - prov_send_fail_msg(PROV_ERR_UNEXP_ERR); - return; - } - - if (memcmp(conf_verify, link.conf, 16)) { - BT_ERR("Invalid confirmation value"); - BT_DBG("Received: %s", bt_hex(link.conf, 16)); - BT_DBG("Calculated: %s", bt_hex(conf_verify, 16)); - prov_send_fail_msg(PROV_ERR_CFM_FAILED); - return; - } - - if (atomic_test_bit(link.flags, PROVISIONER)) { - prov_rand = link.rand; - dev_rand = data; - } else { - prov_rand = data; - dev_rand = link.rand; - } - - if (bt_mesh_prov_salt(link.conf_salt, prov_rand, dev_rand, - link.prov_salt)) { - BT_ERR("Failed to generate provisioning salt"); - prov_send_fail_msg(PROV_ERR_UNEXP_ERR); - return; - } - - BT_DBG("ProvisioningSalt: %s", bt_hex(link.prov_salt, 16)); - - if (IS_ENABLED(CONFIG_BT_MESH_PROVISIONER) && - atomic_test_bit(link.flags, PROVISIONER)) { - send_prov_data(); - } else { - send_random(); - } -} - -static void prov_confirm(const u8_t *data) -{ - BT_DBG("Remote Confirm: %s", bt_hex(data, 16)); - - memcpy(link.conf, data, 16); - - notify_input_complete(); - - if (atomic_test_bit(link.flags, PROVISIONER)) { - send_random(); - } else { - send_confirm(); - } -} - -static inline bool is_pb_gatt(void) -{ -#if MYNEWT_VAL(BLE_MESH_PB_GATT) - return (link.conn_handle != BLE_HS_CONN_HANDLE_NONE); -#else - return false; -#endif -} - -static void prov_data(const u8_t *data) -{ - struct os_mbuf *msg = PROV_BUF(1); - u8_t session_key[16]; - u8_t nonce[13]; - u8_t dev_key[16]; - u8_t pdu[25]; - u8_t flags; - u32_t iv_index; - u16_t addr; - u16_t net_idx; - int err; - bool identity_enable; - - BT_DBG(""); - - err = bt_mesh_session_key(link.dhkey, link.prov_salt, session_key); - if (err) { - BT_ERR("Unable to generate session key"); - prov_send_fail_msg(PROV_ERR_UNEXP_ERR); - goto done; - } - - BT_DBG("SessionKey: %s", bt_hex(session_key, 16)); - - err = bt_mesh_prov_nonce(link.dhkey, link.prov_salt, nonce); - if (err) { - BT_ERR("Unable to generate session nonce"); - prov_send_fail_msg(PROV_ERR_UNEXP_ERR); - goto done; - } - - BT_DBG("Nonce: %s", bt_hex(nonce, 13)); - - err = bt_mesh_prov_decrypt(session_key, nonce, data, pdu); - if (err) { - BT_ERR("Unable to decrypt provisioning data"); - prov_send_fail_msg(PROV_ERR_DECRYPT); - goto done; - } - - err = bt_mesh_dev_key(link.dhkey, link.prov_salt, dev_key); - if (err) { - BT_ERR("Unable to generate device key"); - prov_send_fail_msg(PROV_ERR_UNEXP_ERR); - goto done; - } - - BT_DBG("DevKey: %s", bt_hex(dev_key, 16)); - - net_idx = sys_get_be16(&pdu[16]); - flags = pdu[18]; - iv_index = sys_get_be32(&pdu[19]); - addr = sys_get_be16(&pdu[23]); - - BT_DBG("net_idx %u iv_index 0x%08x, addr 0x%04x", - net_idx, (unsigned) iv_index, addr); - - prov_buf_init(msg, PROV_COMPLETE); - if (prov_send(msg)) { - BT_ERR("Failed to send Provisioning Complete"); - goto done; - } - - /* Ignore any further PDUs on this link */ - link.expect = PROV_NO_PDU; - - /* Store info, since bt_mesh_provision() will end up clearing it */ - if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) { - identity_enable = is_pb_gatt(); - } else { - identity_enable = false; - } - - err = bt_mesh_provision(pdu, net_idx, flags, iv_index, addr, dev_key); - if (err) { - BT_ERR("Failed to provision (err %d)", err); - goto done; - } - - /* After PB-GATT provisioning we should start advertising - * using Node Identity. - */ - if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) && identity_enable) { - bt_mesh_proxy_identity_enable(); - } - -done: - os_mbuf_free_chain(msg); -} - -static void prov_failed(const u8_t *data) -{ - BT_WARN("Error: 0x%02x", data[0]); -} - -static const struct { - void (*func)(const u8_t *data); - u16_t len; -} prov_handlers[] = { - { prov_invite, 1 }, - { prov_capabilities, 11 }, - { prov_start, 5, }, - { prov_pub_key, 64 }, - { prov_input_complete, 0 }, - { prov_confirm, 16 }, - { prov_random, 16 }, - { prov_data, 33 }, - { prov_complete, 0 }, - { prov_failed, 1 }, -}; - -#if (MYNEWT_VAL(BLE_MESH_PB_ADV)) -static void prov_retransmit(struct ble_npl_event *work) -{ - int i, timeout; - - BT_DBG(""); - - if (!atomic_test_bit(link.flags, LINK_ACTIVE)) { - BT_WARN("Link not active"); - return; - } - - if (atomic_test_bit(link.flags, LINK_CLOSING)) { - timeout = CLOSING_TIMEOUT; - } else { - timeout = TRANSACTION_TIMEOUT; - } - - if (k_uptime_get() - link.tx.start > timeout) { - BT_WARN("Giving up transaction"); - reset_adv_link(); - return; - } - - for (i = 0; i < ARRAY_SIZE(link.tx.buf); i++) { - struct os_mbuf *buf = link.tx.buf[i]; - - if (!buf) { - break; - } - - if (BT_MESH_ADV(buf)->busy) { - continue; - } - - BT_DBG("%u bytes: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len)); - - if (i + 1 < ARRAY_SIZE(link.tx.buf) && link.tx.buf[i + 1]) { - bt_mesh_adv_send(buf, NULL, NULL); - } else { - bt_mesh_adv_send(buf, &buf_sent_cb, NULL); - } - - } -} - -static void link_open(struct prov_rx *rx, struct os_mbuf *buf) -{ - BT_DBG("link open: len %u", buf->om_len); - - if (buf->om_len < 16) { - BT_ERR("Too short bearer open message (len %u)", buf->om_len); - return; - } - - if (atomic_test_bit(link.flags, LINK_ACTIVE)) { - /* Send another link ack if the provisioner missed the last */ - if (link.id == rx->link_id && link.expect == PROV_INVITE) { - BT_DBG("Resending link ack"); - bearer_ctl_send(LINK_ACK, NULL, 0); - } else { - BT_WARN("Ignoring bearer open: link already active"); - } - - return; - } - - if (memcmp(buf->om_data, prov->uuid, 16)) { - BT_DBG("Bearer open message not for us"); - return; - } - - if (prov->link_open) { - prov->link_open(BT_MESH_PROV_ADV); - } - - link.id = rx->link_id; - atomic_set_bit(link.flags, LINK_ACTIVE); - net_buf_simple_init(link.rx.buf, 0); - - bearer_ctl_send(LINK_ACK, NULL, 0); - - link.expect = PROV_INVITE; -} - -static void link_ack(struct prov_rx *rx, struct os_mbuf *buf) -{ - BT_DBG("Link ack: len %u", buf->om_len); - - if (IS_ENABLED(CONFIG_BT_MESH_PROVISIONER) && - atomic_test_bit(link.flags, PROVISIONER)) { - if (atomic_test_and_set_bit(link.flags, LINK_ACK_RECVD)) { - return; - } - - prov_clear_tx(); - - if (prov->link_open) { - prov->link_open(BT_MESH_PROV_ADV); - } - - send_invite(); - } -} - -static void link_close(struct prov_rx *rx, struct os_mbuf *buf) -{ - BT_DBG("Link close: len %u", buf->om_len); - - reset_adv_link(); -} - -static void gen_prov_ctl(struct prov_rx *rx, struct os_mbuf *buf) -{ - BT_DBG("op 0x%02x len %u", BEARER_CTL(rx->gpc), buf->om_len); - - switch (BEARER_CTL(rx->gpc)) { - case LINK_OPEN: - link_open(rx, buf); - break; - case LINK_ACK: - if (!atomic_test_bit(link.flags, LINK_ACTIVE)) { - return; - } - - link_ack(rx, buf); - break; - case LINK_CLOSE: - if (!atomic_test_bit(link.flags, LINK_ACTIVE)) { - return; - } - - link_close(rx, buf); - break; - default: - BT_ERR("Unknown bearer opcode: 0x%02x", BEARER_CTL(rx->gpc)); - - if (IS_ENABLED(CONFIG_BT_TESTING)) { - bt_test_mesh_prov_invalid_bearer(BEARER_CTL(rx->gpc)); - } - - return; - } -} - -static void prov_msg_recv(void) -{ - u8_t type = link.rx.buf->om_data[0]; - - BT_DBG("type 0x%02x len %u", type, link.rx.buf->om_len); - - k_delayed_work_submit(&link.prot_timer, PROTOCOL_TIMEOUT); - - if (!bt_mesh_fcs_check(link.rx.buf, link.rx.fcs)) { - BT_ERR("Incorrect FCS"); - return; - } - - gen_prov_ack_send(link.rx.id); - link.rx.prev_id = link.rx.id; - link.rx.id = 0; - - if (atomic_test_bit(link.flags, LINK_INVALID)) { - BT_WARN("Unexpected msg 0x%02x on invalidated link", type); - prov_send_fail_msg(PROV_ERR_UNEXP_PDU); - return; - } - - if (type != PROV_FAILED && type != link.expect) { - BT_WARN("Unexpected msg 0x%02x != 0x%02x", type, link.expect); - prov_send_fail_msg(PROV_ERR_UNEXP_PDU); - return; - } - - if (type >= ARRAY_SIZE(prov_handlers)) { - BT_ERR("Unknown provisioning PDU type 0x%02x", type); - prov_send_fail_msg(PROV_ERR_NVAL_PDU); - return; - } - - if (1 + prov_handlers[type].len != link.rx.buf->om_len) { - BT_ERR("Invalid length %u for type 0x%02x", - link.rx.buf->om_len, type); - prov_send_fail_msg(PROV_ERR_NVAL_FMT); - return; - } - - prov_handlers[type].func(&link.rx.buf->om_data[1]); -} - -static void gen_prov_cont(struct prov_rx *rx, struct os_mbuf *buf) -{ - u8_t seg = CONT_SEG_INDEX(rx->gpc); - - BT_DBG("len %u, seg_index %u", buf->om_len, seg); - - if (!link.rx.seg && link.rx.prev_id == rx->xact_id) { - BT_WARN("Resending ack"); - gen_prov_ack_send(rx->xact_id); - return; - } - - if (rx->xact_id != link.rx.id) { - BT_WARN("Data for unknown transaction (%u != %u)", - rx->xact_id, link.rx.id); - return; - } - - if (seg > link.rx.last_seg) { - BT_ERR("Invalid segment index %u", seg); - prov_send_fail_msg(PROV_ERR_NVAL_FMT); - return; - } else if (seg == link.rx.last_seg) { - u8_t expect_len; - - expect_len = (link.rx.buf->om_len - 20 - - ((link.rx.last_seg - 1) * 23)); - if (expect_len != buf->om_len) { - BT_ERR("Incorrect last seg len: %u != %u", - expect_len, buf->om_len); - prov_send_fail_msg(PROV_ERR_NVAL_FMT); - return; - } - } - - if (!(link.rx.seg & BIT(seg))) { - BT_WARN("Ignoring already received segment"); - return; - } - - memcpy(XACT_SEG_DATA(seg), buf->om_data, buf->om_len); - XACT_SEG_RECV(seg); - - if (!link.rx.seg) { - prov_msg_recv(); - } -} - -static void gen_prov_ack(struct prov_rx *rx, struct os_mbuf *buf) -{ - BT_DBG("len %u", buf->om_len); - - if (!link.tx.buf[0]) { - return; - } - - if (rx->xact_id == link.tx.id) { - /* Don't clear resending of LINK_CLOSE messages */ - if (!atomic_test_bit(link.flags, LINK_CLOSING)) { - prov_clear_tx(); - } - - /* Send the PubKey when the the Start message is ACK'ed */ - if (IS_ENABLED(CONFIG_BT_MESH_PROVISIONER) && - atomic_test_and_clear_bit(link.flags, SEND_PUB_KEY)) { - if (!bt_pub_key_get()) { - atomic_set_bit(link.flags, WAIT_PUB_KEY); - BT_WARN("Waiting for local public key"); - } else { - send_pub_key(); - } - } - } -} - -static void gen_prov_start(struct prov_rx *rx, struct os_mbuf *buf) -{ - u16_t trailing_space = 0; - - if (link.rx.seg) { - BT_WARN("Got Start while there are unreceived segments"); - return; - } - - if (link.rx.prev_id == rx->xact_id) { - BT_WARN("Resending ack"); - gen_prov_ack_send(rx->xact_id); - return; - } - - trailing_space = OS_MBUF_TRAILINGSPACE(link.rx.buf); - - link.rx.buf->om_len = net_buf_simple_pull_be16(buf); - link.rx.id = rx->xact_id; - link.rx.fcs = net_buf_simple_pull_u8(buf); - - BT_DBG("len %u last_seg %u total_len %u fcs 0x%02x", buf->om_len, - START_LAST_SEG(rx->gpc), link.rx.buf->om_len, link.rx.fcs); - - if (link.rx.buf->om_len < 1) { - BT_ERR("Ignoring zero-length provisioning PDU"); - prov_send_fail_msg(PROV_ERR_NVAL_FMT); - return; - } - - if (link.rx.buf->om_len > trailing_space) { - BT_ERR("Too large provisioning PDU (%u bytes)", - link.rx.buf->om_len); - prov_send_fail_msg(PROV_ERR_NVAL_FMT); - return; - } - - if (START_LAST_SEG(rx->gpc) > 0 && link.rx.buf->om_len <= 20) { - BT_ERR("Too small total length for multi-segment PDU"); - prov_send_fail_msg(PROV_ERR_NVAL_FMT); - return; - } - - link.rx.seg = (1 << (START_LAST_SEG(rx->gpc) + 1)) - 1; - link.rx.last_seg = START_LAST_SEG(rx->gpc); - memcpy(link.rx.buf->om_data, buf->om_data, buf->om_len); - XACT_SEG_RECV(0); - - if (!link.rx.seg) { - prov_msg_recv(); - } -} - -static const struct { - void (*func)(struct prov_rx *rx, struct os_mbuf *buf); - bool require_link; - u8_t min_len; -} gen_prov[] = { - { gen_prov_start, true, 3 }, - { gen_prov_ack, true, 0 }, - { gen_prov_cont, true, 0 }, - { gen_prov_ctl, false, 0 }, -}; - -static void gen_prov_recv(struct prov_rx *rx, struct os_mbuf *buf) -{ - if (buf->om_len < gen_prov[GPCF(rx->gpc)].min_len) { - BT_ERR("Too short GPC message type %u", GPCF(rx->gpc)); - return; - } - - if (!atomic_test_bit(link.flags, LINK_ACTIVE) && - gen_prov[GPCF(rx->gpc)].require_link) { - BT_DBG("Ignoring message that requires active link"); - return; - } - - BT_DBG("prov_action: %d", GPCF(rx->gpc)); - gen_prov[GPCF(rx->gpc)].func(rx, buf); -} - -void bt_mesh_pb_adv_recv(struct os_mbuf *buf) -{ - struct prov_rx rx; - - if (!bt_prov_active() && bt_mesh_is_provisioned()) { - BT_DBG("Ignoring provisioning PDU - already provisioned"); - return; - } - - if (buf->om_len < 6) { - BT_WARN("Too short provisioning packet (len %u)", buf->om_len); - return; - } - - rx.link_id = net_buf_simple_pull_be32(buf); - rx.xact_id = net_buf_simple_pull_u8(buf); - rx.gpc = net_buf_simple_pull_u8(buf); - - BT_DBG("link_id 0x%08x xact_id %u", (unsigned) rx.link_id, rx.xact_id); - - if (atomic_test_bit(link.flags, LINK_ACTIVE) && link.id != rx.link_id) { - BT_DBG("Ignoring mesh beacon for unknown link"); - return; - } - - gen_prov_recv(&rx, buf); -} - -int bt_mesh_pb_adv_open(const u8_t uuid[16], u16_t net_idx, u16_t addr, - u8_t attention_duration) -{ - BT_DBG("uuid %s", bt_hex(uuid, 16)); - - if (atomic_test_and_set_bit(link.flags, LINK_ACTIVE)) { - return -EBUSY; - } - - atomic_set_bit(link.flags, PROVISIONER); - - bt_rand(&link.id, sizeof(link.id)); - link.tx.id = 0x7F; - link.provisioner->addr = addr; - link.provisioner->net_idx = net_idx; - link.provisioner->attention_duration = attention_duration; - - net_buf_simple_init(link.rx.buf, 0); - - bearer_ctl_send(LINK_OPEN, uuid, 16); - - return 0; -} - -#endif /* MYNEWT_VAL(BLE_MESH_PB_ADV) */ - -#if (MYNEWT_VAL(BLE_MESH_PB_GATT)) -int bt_mesh_pb_gatt_recv(uint16_t conn_handle, struct os_mbuf *buf) -{ - u8_t type; - - BT_DBG("%u bytes: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len)); - - if (link.conn_handle != conn_handle) { - BT_WARN("Data for unexpected connection"); - return -ENOTCONN; - } - - if (buf->om_len < 1) { - BT_WARN("Too short provisioning packet (len %u)", buf->om_len); - return -EINVAL; - } - - type = net_buf_simple_pull_u8(buf); - if (type != PROV_FAILED && type != link.expect) { - BT_WARN("Unexpected msg 0x%02x != 0x%02x", type, link.expect); - prov_send_fail_msg(PROV_ERR_UNEXP_PDU); - return -EINVAL; - } - - if (type >= ARRAY_SIZE(prov_handlers)) { - BT_ERR("Unknown provisioning PDU type 0x%02x", type); - return -EINVAL; - } - - if (prov_handlers[type].len != buf->om_len) { - BT_ERR("Invalid length %u for type 0x%02x", buf->om_len, type); - return -EINVAL; - } - - prov_handlers[type].func(buf->om_data); - - return 0; -} - -int bt_mesh_pb_gatt_open(uint16_t conn_handle) -{ - BT_DBG("conn_handle %d", conn_handle); - - if (atomic_test_and_set_bit(link.flags, LINK_ACTIVE)) { - BT_ERR("Link already opened?"); - return -EBUSY; - } - - link.conn_handle = conn_handle; - link.expect = PROV_INVITE; - - if (prov->link_open) { - prov->link_open(BT_MESH_PROV_GATT); - } - - return 0; -} - -int bt_mesh_pb_gatt_close(uint16_t conn_handle) -{ - BT_DBG("conn_handle %d", conn_handle); - - if (link.conn_handle != conn_handle) { - BT_ERR("Not connected"); - return -ENOTCONN; - } - - if (prov->link_close) { - prov->link_close(BT_MESH_PROV_GATT); - } - - return reset_state(); -} -#endif /* MYNEWT_VAL(BLE_MESH_PB_GATT) */ - const struct bt_mesh_prov *bt_mesh_prov_get(void) { - return prov; + return bt_mesh_prov; } -bool bt_prov_active(void) +bool bt_mesh_prov_active(void) { - return atomic_test_bit(link.flags, LINK_ACTIVE); + return atomic_test_bit(bt_mesh_prov_link.flags, LINK_ACTIVE); } -static void protocol_timeout(struct ble_npl_event *work) +static void prov_recv(const struct prov_bearer *bearer, void *cb_data, + struct os_mbuf *buf) { - BT_DBG("Protocol timeout"); + static const uint8_t op_len[10] = { + [PROV_INVITE] = 1, + [PROV_CAPABILITIES] = 11, + [PROV_START] = 5, + [PROV_PUB_KEY] = 64, + [PROV_INPUT_COMPLETE] = 0, + [PROV_CONFIRM] = 16, + [PROV_RANDOM] = 16, + [PROV_DATA] = 33, + [PROV_COMPLETE] = 0, + [PROV_FAILED] = 1, + }; -#if MYNEWT_VAL(BLE_MESH_PB_GATT) - if (link.conn_handle != BLE_HS_CONN_HANDLE_NONE) { - bt_mesh_pb_gatt_close(link.conn_handle); + uint8_t type = buf->om_data[0]; + BT_DBG("type 0x%02x len %u", type, buf->om_len); + + if (type >= ARRAY_SIZE(bt_mesh_prov_link.role->op)) { + BT_ERR("Unknown provisioning PDU type 0x%02x", type); + bt_mesh_prov_link.role->error(PROV_ERR_NVAL_FMT); return; } -#endif -#if MYNEWT_VAL(BLE_MESH_PB_ADV) - u8_t reason = CLOSE_REASON_TIMEOUT; + if ((type != PROV_FAILED && type != bt_mesh_prov_link.expect) || + !bt_mesh_prov_link.role->op[type]) { + BT_WARN("Unexpected msg 0x%02x != 0x%02x", type, bt_mesh_prov_link.expect); + bt_mesh_prov_link.role->error(PROV_ERR_UNEXP_PDU); + return; + } - link.rx.seg = 0U; - bearer_ctl_send(LINK_CLOSE, &reason, sizeof(reason)); + if (1 + op_len[type] != buf->om_len) { + BT_ERR("Invalid length %u for type 0x%02x", buf->om_len, type); + bt_mesh_prov_link.role->error(PROV_ERR_NVAL_FMT); + return; + } - reset_state(); -#endif + bt_mesh_prov_link.role->op[type](&buf->om_data[1]); +} + +static void prov_link_opened(const struct prov_bearer *bearer, void *cb_data) +{ + atomic_set_bit(bt_mesh_prov_link.flags, LINK_ACTIVE); + + BT_ERR("bt_mesh_prov->link_open"); + if (bt_mesh_prov->link_open) { + bt_mesh_prov->link_open(bearer->type); + } + + BT_ERR("bt_mesh_prov_link.bearer"); + bt_mesh_prov_link.bearer = bearer; + + BT_ERR("bt_mesh_prov_link.role->link_opened"); + BT_ERR("%p", bt_mesh_prov_link.role); + BT_ERR("%p", bt_mesh_prov_link.role->link_opened); + if (bt_mesh_prov_link.role->link_opened) { + bt_mesh_prov_link.role->link_opened(); + } + BT_ERR("done"); +} + +static void prov_link_closed(const struct prov_bearer *bearer, void *cb_data, + enum prov_bearer_link_status reason) +{ + if (bt_mesh_prov_link.role->link_closed) { + bt_mesh_prov_link.role->link_closed(); + } + + if (bt_mesh_prov->link_close) { + bt_mesh_prov->link_close(bearer->type); + } +} + +static void prov_bearer_error(const struct prov_bearer *bearer, void *cb_data, + uint8_t err) +{ + if (bt_mesh_prov_link.role->error) { + bt_mesh_prov_link.role->error(err); + } +} + +static const struct prov_bearer_cb prov_bearer_cb = { + .link_opened = prov_link_opened, + .link_closed = prov_link_closed, + .error = prov_bearer_error, + .recv = prov_recv, +}; + +const struct prov_bearer_cb *bt_mesh_prov_bearer_cb_get(void) +{ + return &prov_bearer_cb; +} + +void bt_mesh_prov_complete(uint16_t net_idx, uint16_t addr) +{ + if (bt_mesh_prov->complete) { + bt_mesh_prov->complete(net_idx, addr); + } +} + +void bt_mesh_prov_reset(void) +{ + BT_DBG("bt_mesh_prov_reset"); + + if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV)) { + pb_adv_reset(); + } + + if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT)) { + pb_gatt_reset(); + } + + bt_mesh_prov_reset_state(NULL); + + if (bt_mesh_prov->reset) { + bt_mesh_prov->reset(); + } } int bt_mesh_prov_init(const struct bt_mesh_prov *prov_info) @@ -1961,48 +363,14 @@ int bt_mesh_prov_init(const struct bt_mesh_prov *prov_info) return -EINVAL; } - k_delayed_work_init(&link.prot_timer, protocol_timeout); + bt_mesh_prov = prov_info; - prov = prov_info; - -#if MYNEWT_VAL(BLE_MESH_PB_ADV) - k_delayed_work_init(&link.tx.retransmit, prov_retransmit); -#endif - - return reset_state(); -} - -void bt_mesh_prov_reset_link(void) -{ -#if (MYNEWT_VAL(BLE_MESH_PB_ADV)) -#if (MYNEWT_VAL(BLE_MESH_PB_GATT)) - link.rx.buf = bt_mesh_proxy_get_buf(); -#else - net_buf_simple_init(rx_buf, 0); - link.rx.buf = rx_buf; -#endif -#endif -} - -void bt_mesh_prov_complete(u16_t net_idx, u16_t addr) -{ - if (prov->complete) { - prov->complete(net_idx, addr); + if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV)) { + pb_adv_init(); } -} - -void bt_mesh_prov_node_added(u16_t net_idx, u16_t addr, u8_t num_elem) -{ - if (prov->node_added) { - prov->node_added(net_idx, addr, num_elem); + if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT)) { + pb_gatt_init(); } -} -void bt_mesh_prov_reset(void) -{ - if (prov->reset) { - prov->reset(); - } + return bt_mesh_prov_reset_state(NULL); } - -#endif /* MYNEWT_VAL(BLE_MESH_PROV) */ diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/prov.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/prov.h index 96e5a447..89f02725 100644 --- a/src/libs/mynewt-nimble/nimble/host/mesh/src/prov.h +++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/prov.h @@ -9,16 +9,131 @@ #ifndef __PROV_H__ #define __PROV_H__ +#include "prov_bearer.h" #include "os/os_mbuf.h" #include "mesh/mesh.h" #include "../src/ble_hs_conn_priv.h" -int bt_mesh_pb_adv_open(const u8_t uuid[16], u16_t net_idx, u16_t addr, - u8_t attention_duration); +#define PROV_ERR_NONE 0x00 +#define PROV_ERR_NVAL_PDU 0x01 +#define PROV_ERR_NVAL_FMT 0x02 +#define PROV_ERR_UNEXP_PDU 0x03 +#define PROV_ERR_CFM_FAILED 0x04 +#define PROV_ERR_RESOURCES 0x05 +#define PROV_ERR_DECRYPT 0x06 +#define PROV_ERR_UNEXP_ERR 0x07 +#define PROV_ERR_ADDR 0x08 -void bt_mesh_pb_adv_recv(struct os_mbuf *buf); +#define AUTH_METHOD_NO_OOB 0x00 +#define AUTH_METHOD_STATIC 0x01 +#define AUTH_METHOD_OUTPUT 0x02 +#define AUTH_METHOD_INPUT 0x03 -bool bt_prov_active(void); +#define OUTPUT_OOB_BLINK 0x00 +#define OUTPUT_OOB_BEEP 0x01 +#define OUTPUT_OOB_VIBRATE 0x02 +#define OUTPUT_OOB_NUMBER 0x03 +#define OUTPUT_OOB_STRING 0x04 + +#define INPUT_OOB_PUSH 0x00 +#define INPUT_OOB_TWIST 0x01 +#define INPUT_OOB_NUMBER 0x02 +#define INPUT_OOB_STRING 0x03 + +#define PUB_KEY_NO_OOB 0x00 +#define PUB_KEY_OOB 0x01 + +#define PROV_INVITE 0x00 +#define PROV_CAPABILITIES 0x01 +#define PROV_START 0x02 +#define PROV_PUB_KEY 0x03 +#define PROV_INPUT_COMPLETE 0x04 +#define PROV_CONFIRM 0x05 +#define PROV_RANDOM 0x06 +#define PROV_DATA 0x07 +#define PROV_COMPLETE 0x08 +#define PROV_FAILED 0x09 + +#define PROV_NO_PDU 0xff + +#define PROV_ALG_P256 0x00 + +#define PROV_BUF(len) \ + NET_BUF_SIMPLE(PROV_BEARER_BUF_HEADROOM + len) + +enum { + WAIT_PUB_KEY, /* Waiting for local PubKey to be generated */ + LINK_ACTIVE, /* Link has been opened */ + WAIT_NUMBER, /* Waiting for number input from user */ + WAIT_STRING, /* Waiting for string input from user */ + NOTIFY_INPUT_COMPLETE, /* Notify that input has been completed. */ + PROVISIONER, /* The link was opened as provisioner */ + OOB_PUB_KEY, /* OOB Public key used */ + PUB_KEY_SENT, /* Public key has been sent */ + REMOTE_PUB_KEY, /* Remote key has been received */ + INPUT_COMPLETE, /* Device input completed */ + WAIT_CONFIRM, /* Wait for send confirm */ + WAIT_AUTH, /* Wait for auth response */ + OOB_STATIC_KEY, /* OOB Static Authentication */ + + NUM_FLAGS, +}; + +/** Provisioning role */ +struct bt_mesh_prov_role { + void (*link_opened)(void); + + void (*link_closed)(void); + + void (*error)(uint8_t reason); + + void (*input_complete)(void); + + void (*op[10])(const uint8_t *data); +}; + +struct bt_mesh_prov_link { + ATOMIC_DEFINE(flags, NUM_FLAGS); + + const struct prov_bearer *bearer; + const struct bt_mesh_prov_role *role; + + uint8_t oob_method; /* Authen method */ + uint8_t oob_action; /* Authen action */ + uint8_t oob_size; /* Authen size */ + uint8_t auth[16]; /* Authen value */ + + uint8_t dhkey[32]; /* Calculated DHKey */ + uint8_t expect; /* Next expected PDU */ + uint8_t conf[16]; /* Remote Confirmation */ + uint8_t rand[16]; /* Local Random */ + + uint8_t conf_salt[16]; /* ConfirmationSalt */ + uint8_t conf_key[16]; /* ConfirmationKey */ + uint8_t conf_inputs[145]; /* ConfirmationInputs */ + uint8_t prov_salt[16]; /* Provisioning Salt */ +}; + +extern struct bt_mesh_prov_link bt_mesh_prov_link; +extern const struct bt_mesh_prov *bt_mesh_prov; + +static inline int bt_mesh_prov_send(struct os_mbuf *buf, + prov_bearer_send_complete_t cb) +{ + return bt_mesh_prov_link.bearer->send(buf, cb, NULL); +} + +static inline void bt_mesh_prov_buf_init(struct os_mbuf *buf, uint8_t type) +{ + net_buf_reserve(buf, PROV_BEARER_BUF_HEADROOM); + net_buf_simple_add_u8(buf, type); +} + +int bt_mesh_prov_reset_state(void (*func)(const uint8_t key[64])); + +bool bt_mesh_prov_active(void); + +int bt_mesh_prov_auth(uint8_t method, uint8_t action, uint8_t size); int bt_mesh_pb_gatt_open(uint16_t conn_handle); int bt_mesh_pb_gatt_close(uint16_t conn_handle); @@ -26,12 +141,14 @@ int bt_mesh_pb_gatt_recv(uint16_t conn_handle, struct os_mbuf *buf); const struct bt_mesh_prov *bt_mesh_prov_get(void); -int bt_mesh_prov_init(const struct bt_mesh_prov *prov); - void bt_mesh_prov_reset_link(void); -void bt_mesh_prov_complete(u16_t net_idx, u16_t addr); -void bt_mesh_prov_node_added(u16_t net_idx, u16_t addr, u8_t num_elem); +void bt_mesh_prov_complete(uint16_t net_idx, uint16_t addr); void bt_mesh_prov_reset(void); +const struct prov_bearer_cb *bt_mesh_prov_bearer_cb_get(void); + +void bt_mesh_pb_adv_recv(struct os_mbuf *buf); + +int bt_mesh_prov_init(const struct bt_mesh_prov *prov); #endif diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/prov_bearer.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/prov_bearer.h new file mode 100644 index 00000000..3e526831 --- /dev/null +++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/prov_bearer.h @@ -0,0 +1,116 @@ +/* Bluetooth Mesh */ + +/* + * Copyright (c) 2020 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define PROTOCOL_TIMEOUT K_SECONDS(60) + +/** @def PROV_BEARER_BUF_HEADROOM + * + * @brief Required headroom for the bearer packet buffers. + */ +#if MYNEWT_VAL(BLE_MESH_PB_GATT) +#define PROV_BEARER_BUF_HEADROOM 5 +#else +#define PROV_BEARER_BUF_HEADROOM 0 +#endif + +enum prov_bearer_link_status { + PROV_BEARER_LINK_STATUS_SUCCESS, + PROV_BEARER_LINK_STATUS_TIMEOUT, + PROV_BEARER_LINK_STATUS_FAIL, +}; + +struct prov_bearer; + +/** Callbacks from bearer to host */ +struct prov_bearer_cb { + + void (*link_opened)(const struct prov_bearer *bearer, void *cb_data); + + void (*link_closed)(const struct prov_bearer *bearer, void *cb_data, + enum prov_bearer_link_status reason); + + void (*error)(const struct prov_bearer *bearer, void *cb_data, + uint8_t err); + + void (*recv)(const struct prov_bearer *bearer, void *cb_data, + struct os_mbuf *buf); +}; + +typedef void (*prov_bearer_send_complete_t)(int err, void *cb_data); + +/** Provisioning bearer API */ +struct prov_bearer { + /** Provisioning bearer type. */ + bt_mesh_prov_bearer_t type; + + /** @brief Enable link establishment as a provisionee. + * + * Prompts the bearer to make itself visible to provisioners, and + * start accepting link open messages. + * + * @param cb Bearer event callbacks used for the duration of the link. + * @param cb_data Context parameter to pass to the bearer callbacks. + * + * @return Zero on success, or (negative) error code otherwise. + */ + int (*link_accept)(const struct prov_bearer_cb *cb, void *cb_data); + + /** @brief Send a packet on an established link. + * + * @param buf Payload buffer. Requires @ref + * PROV_BEARER_BUF_HEADROOM bytes of headroom. + * @param cb Callback to call when sending is complete. + * @param cb_data Callback data. + * + * @return Zero on success, or (negative) error code otherwise. + */ + int (*send)(struct os_mbuf *buf, prov_bearer_send_complete_t cb, + void *cb_data); + + /** @brief Clear any ongoing transmissions, if possible. + * + * Bearers that don't support tx clearing must implement this callback + * and leave it empty. + */ + void (*clear_tx)(void); + + /* Only available in provisioners: */ + + /** @brief Open a new link as a provisioner. + * + * Only available in provisioners. Bearers that don't support the + * provisioner role should leave this as NULL. + * + * @param uuid UUID of the node to establish a link to. + * @param timeout Protocol timeout. + * @param cb Bearer event callbacks used for the duration of the link. + * @param cb_data Context parameter to pass to the bearer callbacks. + * + * @return Zero on success, or (negative) error code otherwise. + */ + int (*link_open)(const uint8_t uuid[16], int32_t timeout, + const struct prov_bearer_cb *cb, void *cb_data); + + /** @brief Close the current link. + * + * Only available in provisioners. Bearers that don't support the + * provisioner role should leave this as NULL. + * + * @param status Link status for the link close message. + */ + void (*link_close)(enum prov_bearer_link_status status); +}; + +extern const struct prov_bearer pb_adv; +extern const struct prov_bearer pb_gatt; + +void pb_adv_init(void); +void pb_gatt_init(void); + +void pb_adv_reset(void); +void pb_gatt_reset(void); diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/prov_device.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/prov_device.c new file mode 100644 index 00000000..38a96e7a --- /dev/null +++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/prov_device.c @@ -0,0 +1,569 @@ +/* Bluetooth Mesh */ + +/* + * Copyright (c) 2017 Intel Corporation + * Copyright (c) 2020 Lingao Meng + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define MESH_LOG_MODULE BLE_MESH_PROV_LOG + +#include "testing.h" +#include "crypto.h" +#include "adv.h" +#include "mesh/mesh.h" +#include "net.h" +#include "rpl.h" +#include "beacon.h" +#include "access.h" +#include "foundation.h" +#include "proxy.h" +#include "prov.h" +#include "settings.h" + +static void send_pub_key(void); +static void pub_key_ready(const uint8_t *pkey); + +static int reset_state(void) +{ + return bt_mesh_prov_reset_state(pub_key_ready); +} + +static void prov_send_fail_msg(uint8_t err) +{ + struct os_mbuf *buf = PROV_BUF(2); + + BT_DBG("%u", err); + + bt_mesh_prov_link.expect = PROV_NO_PDU; + + bt_mesh_prov_buf_init(buf, PROV_FAILED); + net_buf_simple_add_u8(buf, err); + + if (bt_mesh_prov_send(buf, NULL)) { + BT_ERR("Failed to send Provisioning Failed message"); + } +} + +static void prov_fail(uint8_t reason) +{ + /* According to Bluetooth Mesh Specification v1.0.1, Section 5.4.4, the + * provisioner just closes the link when something fails, while the + * provisionee sends the fail message, and waits for the provisioner to + * close the link. + */ + prov_send_fail_msg(reason); +} + +static void prov_invite(const uint8_t *data) +{ + struct os_mbuf *buf = PROV_BUF(12); + + BT_DBG("Attention Duration: %u seconds", data[0]); + + if (data[0]) { + bt_mesh_attention(NULL, data[0]); + } + + bt_mesh_prov_link.conf_inputs[0] = data[0]; + + bt_mesh_prov_buf_init(buf, PROV_CAPABILITIES); + + /* Number of Elements supported */ + net_buf_simple_add_u8(buf, bt_mesh_elem_count()); + + /* Supported algorithms - FIPS P-256 Eliptic Curve */ + net_buf_simple_add_be16(buf, BIT(PROV_ALG_P256)); + + /* Public Key Type, Only "No OOB" Public Key is supported */ + net_buf_simple_add_u8(buf, PUB_KEY_NO_OOB); + + /* Static OOB Type */ + net_buf_simple_add_u8(buf, bt_mesh_prov->static_val ? BIT(0) : 0x00); + + /* Output OOB Size */ + net_buf_simple_add_u8(buf, bt_mesh_prov->output_size); + + /* Output OOB Action */ + net_buf_simple_add_be16(buf, bt_mesh_prov->output_actions); + + /* Input OOB Size */ + net_buf_simple_add_u8(buf, bt_mesh_prov->input_size); + + /* Input OOB Action */ + net_buf_simple_add_be16(buf, bt_mesh_prov->input_actions); + + memcpy(&bt_mesh_prov_link.conf_inputs[1], &buf->om_data[1], 11); + + if (bt_mesh_prov_send(buf, NULL)) { + BT_ERR("Failed to send capabilities"); + return; + } + + bt_mesh_prov_link.expect = PROV_START; +} + +static void prov_start(const uint8_t *data) +{ + BT_DBG("Algorithm: 0x%02x", data[0]); + BT_DBG("Public Key: 0x%02x", data[1]); + BT_DBG("Auth Method: 0x%02x", data[2]); + BT_DBG("Auth Action: 0x%02x", data[3]); + BT_DBG("Auth Size: 0x%02x", data[4]); + + if (data[0] != PROV_ALG_P256) { + BT_ERR("Unknown algorithm 0x%02x", data[0]); + prov_fail(PROV_ERR_NVAL_FMT); + return; + } + + if (data[1] != PUB_KEY_NO_OOB) { + BT_ERR("Invalid public key type: 0x%02x", data[1]); + prov_fail(PROV_ERR_NVAL_FMT); + return; + } + + memcpy(&bt_mesh_prov_link.conf_inputs[12], data, 5); + + bt_mesh_prov_link.expect = PROV_PUB_KEY; + + if (bt_mesh_prov_auth(data[2], data[3], data[4]) < 0) { + BT_ERR("Invalid authentication method: 0x%02x; " + "action: 0x%02x; size: 0x%02x", data[2], data[3], + data[4]); + prov_fail(PROV_ERR_NVAL_FMT); + } + + if (atomic_test_bit(bt_mesh_prov_link.flags, OOB_STATIC_KEY)) { + memcpy(bt_mesh_prov_link.auth + 16 - bt_mesh_prov->static_val_len, + bt_mesh_prov->static_val, bt_mesh_prov->static_val_len); + (void)memset(bt_mesh_prov_link.auth, 0, + sizeof(bt_mesh_prov_link.auth) - bt_mesh_prov->static_val_len); + } +} + +static void send_confirm(void) +{ + struct os_mbuf *cfm = PROV_BUF(17); + + BT_DBG("ConfInputs[0] %s", bt_hex(bt_mesh_prov_link.conf_inputs, 64)); + BT_DBG("ConfInputs[64] %s", bt_hex(&bt_mesh_prov_link.conf_inputs[64], 64)); + BT_DBG("ConfInputs[128] %s", bt_hex(&bt_mesh_prov_link.conf_inputs[128], 17)); + + if (bt_mesh_prov_conf_salt(bt_mesh_prov_link.conf_inputs, + bt_mesh_prov_link.conf_salt)) { + BT_ERR("Unable to generate confirmation salt"); + prov_fail(PROV_ERR_UNEXP_ERR); + return; + } + + BT_DBG("ConfirmationSalt: %s", bt_hex(bt_mesh_prov_link.conf_salt, 16)); + + if (bt_mesh_prov_conf_key(bt_mesh_prov_link.dhkey, bt_mesh_prov_link.conf_salt, + bt_mesh_prov_link.conf_key)) { + BT_ERR("Unable to generate confirmation key"); + prov_fail(PROV_ERR_UNEXP_ERR); + return; + } + + BT_DBG("ConfirmationKey: %s", bt_hex(bt_mesh_prov_link.conf_key, 16)); + + if (bt_rand(bt_mesh_prov_link.rand, 16)) { + BT_ERR("Unable to generate random number"); + prov_fail(PROV_ERR_UNEXP_ERR); + return; + } + + BT_DBG("LocalRandom: %s", bt_hex(bt_mesh_prov_link.rand, 16)); + + bt_mesh_prov_buf_init(cfm, PROV_CONFIRM); + + if (bt_mesh_prov_conf(bt_mesh_prov_link.conf_key, bt_mesh_prov_link.rand, + bt_mesh_prov_link.auth, net_buf_simple_add(cfm, 16))) { + BT_ERR("Unable to generate confirmation value"); + prov_fail(PROV_ERR_UNEXP_ERR); + return; + } + + if (bt_mesh_prov_send(cfm, NULL)) { + BT_ERR("Failed to send Provisioning Confirm"); + return; + } + + bt_mesh_prov_link.expect = PROV_RANDOM; + +} + +static void send_input_complete(void) +{ + struct os_mbuf *buf = PROV_BUF(1); + + bt_mesh_prov_buf_init(buf, PROV_INPUT_COMPLETE); + if (bt_mesh_prov_send(buf, NULL)) { + BT_ERR("Failed to send Provisioning Input Complete"); + } + bt_mesh_prov_link.expect = PROV_CONFIRM; +} + +static void public_key_sent(int err, void *cb_data) +{ + atomic_set_bit(bt_mesh_prov_link.flags, PUB_KEY_SENT); + + if (atomic_test_bit(bt_mesh_prov_link.flags, INPUT_COMPLETE)) { + send_input_complete(); + return; + } +} + +static void send_pub_key(void) +{ + struct os_mbuf *buf = PROV_BUF(65); + const uint8_t *key; + + key = bt_pub_key_get(); + if (!key) { + BT_ERR("No public key available"); + prov_fail(PROV_ERR_UNEXP_ERR); + return; + } + + BT_DBG("Local Public Key: %s", bt_hex(key, 64)); + + bt_mesh_prov_buf_init(buf, PROV_PUB_KEY); + + /* Swap X and Y halves independently to big-endian */ + sys_memcpy_swap(net_buf_simple_add(buf, 32), key, 32); + sys_memcpy_swap(net_buf_simple_add(buf, 32), &key[32], 32); + + /* PublicKeyRemote */ + memcpy(&bt_mesh_prov_link.conf_inputs[81], &buf->om_data[1], 64); + + if (bt_mesh_prov_send(buf, public_key_sent)) { + BT_ERR("Failed to send Public Key"); + return; + } + + if (atomic_test_bit(bt_mesh_prov_link.flags, WAIT_NUMBER) || + atomic_test_bit(bt_mesh_prov_link.flags, WAIT_STRING)) { + bt_mesh_prov_link.expect = PROV_NO_PDU; /* Wait for input */ + } else { + bt_mesh_prov_link.expect = PROV_CONFIRM; + } +} + +static void prov_dh_key_cb(const uint8_t dhkey[32]) +{ + BT_DBG("%p", dhkey); + + if (!dhkey) { + BT_ERR("DHKey generation failed"); + prov_fail(PROV_ERR_UNEXP_ERR); + return; + } + + sys_memcpy_swap(bt_mesh_prov_link.dhkey, dhkey, 32); + + BT_DBG("DHkey: %s", bt_hex(bt_mesh_prov_link.dhkey, 32)); + + send_pub_key(); +} + +static void prov_dh_key_gen(void) +{ + uint8_t remote_pk_le[64], *remote_pk; + + remote_pk = &bt_mesh_prov_link.conf_inputs[17]; + + /* Copy remote key in little-endian for bt_dh_key_gen(). + * X and Y halves are swapped independently. The bt_dh_key_gen() + * will also take care of validating the remote public key. + */ + sys_memcpy_swap(remote_pk_le, remote_pk, 32); + sys_memcpy_swap(&remote_pk_le[32], &remote_pk[32], 32); + + if (bt_dh_key_gen(remote_pk_le, prov_dh_key_cb)) { + BT_ERR("Failed to generate DHKey"); + prov_fail(PROV_ERR_UNEXP_ERR); + } +} + +static void prov_pub_key(const uint8_t *data) +{ + BT_DBG("Remote Public Key: %s", bt_hex(data, 64)); + + /* PublicKeyProvisioner */ + memcpy(&bt_mesh_prov_link.conf_inputs[17], data, 64); + + if (!bt_pub_key_get()) { + /* Clear retransmit timer */ + bt_mesh_prov_link.bearer->clear_tx(); + atomic_set_bit(bt_mesh_prov_link.flags, WAIT_PUB_KEY); + BT_WARN("Waiting for local public key"); + return; + } + + prov_dh_key_gen(); +} + +static void pub_key_ready(const uint8_t *pkey) +{ + if (!pkey) { + BT_WARN("Public key not available"); + return; + } + + BT_DBG("Local public key ready"); + + if (atomic_test_and_clear_bit(bt_mesh_prov_link.flags, WAIT_PUB_KEY)) { + prov_dh_key_gen(); + } +} + +static void notify_input_complete(void) +{ + if (atomic_test_and_clear_bit(bt_mesh_prov_link.flags, + NOTIFY_INPUT_COMPLETE) && + bt_mesh_prov->input_complete) { + bt_mesh_prov->input_complete(); + } +} + +static void send_random(void) +{ + struct os_mbuf *rnd = PROV_BUF(17); + + bt_mesh_prov_buf_init(rnd, PROV_RANDOM); + net_buf_simple_add_mem(rnd, bt_mesh_prov_link.rand, 16); + + if (bt_mesh_prov_send(rnd, NULL)) { + BT_ERR("Failed to send Provisioning Random"); + return; + } + + bt_mesh_prov_link.expect = PROV_DATA; +} + +static void prov_random(const uint8_t *data) +{ + uint8_t conf_verify[16]; + + BT_DBG("Remote Random: %s", bt_hex(data, 16)); + if (!memcmp(data, bt_mesh_prov_link.rand, 16)) { + BT_ERR("Random value is identical to ours, rejecting."); + prov_fail(PROV_ERR_CFM_FAILED); + return; + } + + if (bt_mesh_prov_conf(bt_mesh_prov_link.conf_key, data, + bt_mesh_prov_link.auth, conf_verify)) { + BT_ERR("Unable to calculate confirmation verification"); + prov_fail(PROV_ERR_UNEXP_ERR); + return; + } + + if (memcmp(conf_verify, bt_mesh_prov_link.conf, 16)) { + BT_ERR("Invalid confirmation value"); + BT_DBG("Received: %s", bt_hex(bt_mesh_prov_link.conf, 16)); + BT_DBG("Calculated: %s", bt_hex(conf_verify, 16)); + prov_fail(PROV_ERR_CFM_FAILED); + return; + } + + if (bt_mesh_prov_salt(bt_mesh_prov_link.conf_salt, data, + bt_mesh_prov_link.rand, bt_mesh_prov_link.prov_salt)) { + BT_ERR("Failed to generate provisioning salt"); + prov_fail(PROV_ERR_UNEXP_ERR); + return; + } + + BT_DBG("ProvisioningSalt: %s", bt_hex(bt_mesh_prov_link.prov_salt, 16)); + + send_random(); +} + +static void prov_confirm(const uint8_t *data) +{ + BT_DBG("Remote Confirm: %s", bt_hex(data, 16)); + + memcpy(bt_mesh_prov_link.conf, data, 16); + + notify_input_complete(); + + send_confirm(); +} + +static inline bool is_pb_gatt(void) +{ + return bt_mesh_prov_link.bearer && + bt_mesh_prov_link.bearer->type == BT_MESH_PROV_GATT; +} + +static void prov_data(const uint8_t *data) +{ + struct os_mbuf *msg = PROV_BUF(1); + uint8_t session_key[16]; + uint8_t nonce[13]; + uint8_t dev_key[16]; + uint8_t pdu[25]; + uint8_t flags; + uint32_t iv_index; + uint16_t addr; + uint16_t net_idx; + int err; + bool identity_enable; + + BT_DBG(""); + + err = bt_mesh_session_key(bt_mesh_prov_link.dhkey, + bt_mesh_prov_link.prov_salt, session_key); + if (err) { + BT_ERR("Unable to generate session key"); + prov_fail(PROV_ERR_UNEXP_ERR); + return; + } + + BT_DBG("SessionKey: %s", bt_hex(session_key, 16)); + + err = bt_mesh_prov_nonce(bt_mesh_prov_link.dhkey, + bt_mesh_prov_link.prov_salt, nonce); + if (err) { + BT_ERR("Unable to generate session nonce"); + prov_fail(PROV_ERR_UNEXP_ERR); + return; + } + + BT_DBG("Nonce: %s", bt_hex(nonce, 13)); + + err = bt_mesh_prov_decrypt(session_key, nonce, data, pdu); + if (err) { + BT_ERR("Unable to decrypt provisioning data"); + prov_fail(PROV_ERR_DECRYPT); + return; + } + + err = bt_mesh_dev_key(bt_mesh_prov_link.dhkey, + bt_mesh_prov_link.prov_salt, dev_key); + if (err) { + BT_ERR("Unable to generate device key"); + prov_fail(PROV_ERR_UNEXP_ERR); + return; + } + + BT_DBG("DevKey: %s", bt_hex(dev_key, 16)); + + net_idx = sys_get_be16(&pdu[16]); + flags = pdu[18]; + iv_index = sys_get_be32(&pdu[19]); + addr = sys_get_be16(&pdu[23]); + + BT_DBG("net_idx %u iv_index 0x%08x, addr 0x%04x", + net_idx, iv_index, addr); + + bt_mesh_prov_buf_init(msg, PROV_COMPLETE); + if (bt_mesh_prov_send(msg, NULL)) { + BT_ERR("Failed to send Provisioning Complete"); + return; + } + + /* Ignore any further PDUs on this link */ + bt_mesh_prov_link.expect = PROV_NO_PDU; + + /* Store info, since bt_mesh_provision() will end up clearing it */ + if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) { + identity_enable = is_pb_gatt(); + } else { + identity_enable = false; + } + + err = bt_mesh_provision(pdu, net_idx, flags, iv_index, addr, dev_key); + if (err) { + BT_ERR("Failed to provision (err %d)", err); + return; + } + + /* After PB-GATT provisioning we should start advertising + * using Node Identity. + */ + if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY) && identity_enable) { + bt_mesh_proxy_identity_enable(); + } +} + +static void local_input_complete(void) +{ + if (atomic_test_bit(bt_mesh_prov_link.flags, PUB_KEY_SENT)) { + send_input_complete(); + } else { + atomic_set_bit(bt_mesh_prov_link.flags, INPUT_COMPLETE); + } +} + +static void prov_link_closed(void) +{ + reset_state(); +} + +static void prov_link_opened(void) +{ + bt_mesh_prov_link.expect = PROV_INVITE; +} + +static const struct bt_mesh_prov_role role_device = { + .input_complete = local_input_complete, + .link_opened = prov_link_opened, + .link_closed = prov_link_closed, + .error = prov_fail, + .op = { + [PROV_INVITE] = prov_invite, + [PROV_START] = prov_start, + [PROV_PUB_KEY] = prov_pub_key, + [PROV_CONFIRM] = prov_confirm, + [PROV_RANDOM] = prov_random, + [PROV_DATA] = prov_data, + }, +}; + +int bt_mesh_prov_enable(bt_mesh_prov_bearer_t bearers) +{ + BT_DBG("bt_mesh_prov_enable"); + + if (bt_mesh_is_provisioned()) { + return -EALREADY; + } + + if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV) && + (bearers & BT_MESH_PROV_ADV)) { + pb_adv.link_accept(bt_mesh_prov_bearer_cb_get(), NULL); + } + + if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT) && + (bearers & BT_MESH_PROV_GATT)) { + pb_gatt.link_accept(bt_mesh_prov_bearer_cb_get(), NULL); + } + + BT_DBG("bt_mesh_prov_link.role = &role_device"); + bt_mesh_prov_link.role = &role_device; + + return 0; +} + +int bt_mesh_prov_disable(bt_mesh_prov_bearer_t bearers) +{ + if (bt_mesh_is_provisioned()) { + return -EALREADY; + } + + if (IS_ENABLED(CONFIG_BT_MESH_PB_ADV) && + (bearers & BT_MESH_PROV_ADV)) { + bt_mesh_beacon_disable(); + bt_mesh_scan_disable(); + } + + if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT) && + (bearers & BT_MESH_PROV_GATT)) { + bt_mesh_proxy_prov_disable(true); + } + + return 0; +} diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/provisioner.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/provisioner.c new file mode 100644 index 00000000..371c1f6c --- /dev/null +++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/provisioner.c @@ -0,0 +1,746 @@ +/* Bluetooth Mesh */ + +/* + * Copyright (c) 2017 Intel Corporation + * Copyright (c) 2020 Lingao Meng + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define MESH_LOG_MODULE BLE_MESH_PROV_LOG + +#include "testing.h" + +#include "crypto.h" +#include "adv.h" +#include "mesh/mesh.h" +#include "net.h" +#include "rpl.h" +#include "beacon.h" +#include "access.h" +#include "foundation.h" +#include "proxy.h" +#include "prov.h" +#include "settings.h" + +static struct { + struct bt_mesh_cdb_node *node; + uint16_t addr; + uint16_t net_idx; + uint8_t attention_duration; + uint8_t uuid[16]; +} prov_device; + +static void send_pub_key(void); +static void prov_dh_key_gen(void); +static void pub_key_ready(const uint8_t *pkey); + +static int reset_state(void) +{ +#if BLE_MESH_CDB + if (prov_device.node != NULL) { + bt_mesh_cdb_node_del(prov_device.node, false); + } +#endif + return bt_mesh_prov_reset_state(pub_key_ready); +} + +static void prov_link_close(enum prov_bearer_link_status status) +{ + BT_DBG("%u", status); + bt_mesh_prov_link.expect = PROV_NO_PDU; + + bt_mesh_prov_link.bearer->link_close(status); +} + +static void prov_fail(uint8_t reason) +{ + /* According to Bluetooth Mesh Specification v1.0.1, Section 5.4.4, the + * provisioner just closes the link when something fails, while the + * provisionee sends the fail message, and waits for the provisioner to + * close the link. + */ + prov_link_close(PROV_BEARER_LINK_STATUS_FAIL); +} + +static void send_invite(void) +{ + struct os_mbuf *inv = PROV_BUF(2); + + BT_DBG(""); + + bt_mesh_prov_buf_init(inv, PROV_INVITE); + net_buf_simple_add_u8(inv, prov_device.attention_duration); + + bt_mesh_prov_link.conf_inputs[0] = prov_device.attention_duration; + + if (bt_mesh_prov_send(inv, NULL)) { + BT_ERR("Failed to send invite"); + return; + } + + bt_mesh_prov_link.expect = PROV_CAPABILITIES; +} + +static void start_sent(int err, void *cb_data) +{ + if (!bt_pub_key_get()) { + atomic_set_bit(bt_mesh_prov_link.flags, WAIT_PUB_KEY); + BT_WARN("Waiting for local public key"); + } else { + send_pub_key(); + } +} + +static void send_start(void) +{ + BT_DBG(""); + uint8_t method, action; + struct os_mbuf *start = PROV_BUF(6); + + const uint8_t *data = &bt_mesh_prov_link.conf_inputs[1 + 3]; + + bt_mesh_prov_buf_init(start, PROV_START); + net_buf_simple_add_u8(start, PROV_ALG_P256); + + if (atomic_test_bit(bt_mesh_prov_link.flags, REMOTE_PUB_KEY) && + *data == PUB_KEY_OOB) { + net_buf_simple_add_u8(start, PUB_KEY_OOB); + atomic_set_bit(bt_mesh_prov_link.flags, OOB_PUB_KEY); + } else { + net_buf_simple_add_u8(start, PUB_KEY_NO_OOB); + } + + if (bt_mesh_prov_link.oob_method == AUTH_METHOD_INPUT) { + method = AUTH_METHOD_OUTPUT; + if (bt_mesh_prov_link.oob_action == INPUT_OOB_STRING) { + action = OUTPUT_OOB_STRING; + } else { + action = OUTPUT_OOB_NUMBER; + } + + } else if (bt_mesh_prov_link.oob_method == AUTH_METHOD_OUTPUT) { + method = AUTH_METHOD_INPUT; + if (bt_mesh_prov_link.oob_action == OUTPUT_OOB_STRING) { + action = INPUT_OOB_STRING; + } else { + action = INPUT_OOB_NUMBER; + } + } else { + method = bt_mesh_prov_link.oob_method; + action = 0x00; + } + + net_buf_simple_add_u8(start, bt_mesh_prov_link.oob_method); + + net_buf_simple_add_u8(start, bt_mesh_prov_link.oob_action); + + net_buf_simple_add_u8(start, bt_mesh_prov_link.oob_size); + + memcpy(&bt_mesh_prov_link.conf_inputs[12], &start->om_data[1], 5); + + if (bt_mesh_prov_auth(method, action, bt_mesh_prov_link.oob_size) < 0) { + BT_ERR("Invalid authentication method: 0x%02x; " + "action: 0x%02x; size: 0x%02x", method, + action, bt_mesh_prov_link.oob_size); + return; + } + + if (bt_mesh_prov_send(start, start_sent)) { + BT_ERR("Failed to send Provisioning Start"); + return; + } +} + +static bool prov_check_method(struct bt_mesh_dev_capabilities *caps) +{ + if (bt_mesh_prov_link.oob_method == AUTH_METHOD_STATIC) { + if (!caps->static_oob) { + BT_WARN("Device not support OOB static authentication provisioning"); + return false; + } + } else if (bt_mesh_prov_link.oob_method == AUTH_METHOD_INPUT) { + if (bt_mesh_prov_link.oob_size > caps->input_size) { + BT_WARN("The required input length (0x%02x) " + "exceeds the device capacity (0x%02x)", + bt_mesh_prov_link.oob_size, caps->input_size); + return false; + } + + if (!(BIT(bt_mesh_prov_link.oob_action) & caps->input_actions)) { + BT_WARN("The required input action (0x%02x) " + "not supported by the device (0x%02x)", + bt_mesh_prov_link.oob_action, caps->input_actions); + return false; + } + + if (bt_mesh_prov_link.oob_action == INPUT_OOB_STRING) { + if (!bt_mesh_prov->output_string) { + BT_WARN("Not support output string"); + return false; + } + } else { + if (!bt_mesh_prov->output_number) { + BT_WARN("Not support output number"); + return false; + } + } + } else if (bt_mesh_prov_link.oob_method == AUTH_METHOD_OUTPUT) { + if (bt_mesh_prov_link.oob_size > caps->output_size) { + BT_WARN("The required output length (0x%02x) " + "exceeds the device capacity (0x%02x)", + bt_mesh_prov_link.oob_size, caps->output_size); + return false; + } + + if (!(BIT(bt_mesh_prov_link.oob_action) & caps->output_actions)) { + BT_WARN("The required output action (0x%02x) " + "not supported by the device (0x%02x)", + bt_mesh_prov_link.oob_action, caps->output_actions); + return false; + } + + if (!bt_mesh_prov->input) { + BT_WARN("Not support input"); + return false; + } + } + + return true; +} + +static void prov_capabilities(const uint8_t *data) +{ + struct bt_mesh_dev_capabilities caps; + + caps.elem_count = data[0]; + BT_DBG("Elements: %u", caps.elem_count); + + caps.algorithms = sys_get_be16(&data[1]); + BT_DBG("Algorithms: %u", caps.algorithms); + + caps.pub_key_type = data[3]; + caps.static_oob = data[4]; + caps.output_size = data[5]; + BT_DBG("Public Key Type: 0x%02x", caps.pub_key_type); + BT_DBG("Static OOB Type: 0x%02x", caps.static_oob); + BT_DBG("Output OOB Size: %u", caps.output_size); + + caps.output_actions = (bt_mesh_output_action_t)data[6]; + caps.input_size = data[8]; + caps.input_actions = (bt_mesh_input_action_t)data[9]; + BT_DBG("Output OOB Action: 0x%04x", caps.output_actions); + BT_DBG("Input OOB Size: %u", caps.input_size); + BT_DBG("Input OOB Action: 0x%04x", caps.input_actions); + + if (data[0] == 0) { + BT_ERR("Invalid number of elements"); + prov_fail(PROV_ERR_NVAL_FMT); + return; + } +#if BLE_MESH_CDB + prov_device.node = + bt_mesh_cdb_node_alloc(prov_device.uuid, + prov_device.addr, data[0], + prov_device.net_idx); + if (prov_device.node == NULL) { + BT_ERR("Failed allocating node 0x%04x", prov_device.addr); + prov_fail(PROV_ERR_RESOURCES); + return; + } +#endif + memcpy(&bt_mesh_prov_link.conf_inputs[1], data, 11); + + if (bt_mesh_prov->capabilities) { + bt_mesh_prov->capabilities(&caps); + } + + if (!prov_check_method(&caps)) { + prov_fail(PROV_ERR_UNEXP_ERR); + return; + } + + send_start(); +} + +static void send_confirm(void) +{ + struct os_mbuf *cfm = PROV_BUF(17); + + BT_DBG("ConfInputs[0] %s", bt_hex(bt_mesh_prov_link.conf_inputs, 64)); + BT_DBG("ConfInputs[64] %s", bt_hex(&bt_mesh_prov_link.conf_inputs[64], 64)); + BT_DBG("ConfInputs[128] %s", bt_hex(&bt_mesh_prov_link.conf_inputs[128], 17)); + + if (bt_mesh_prov_conf_salt(bt_mesh_prov_link.conf_inputs, + bt_mesh_prov_link.conf_salt)) { + BT_ERR("Unable to generate confirmation salt"); + prov_fail(PROV_ERR_UNEXP_ERR); + return; + } + + BT_DBG("ConfirmationSalt: %s", bt_hex(bt_mesh_prov_link.conf_salt, 16)); + + if (bt_mesh_prov_conf_key(bt_mesh_prov_link.dhkey, + bt_mesh_prov_link.conf_salt, bt_mesh_prov_link.conf_key)) { + BT_ERR("Unable to generate confirmation key"); + prov_fail(PROV_ERR_UNEXP_ERR); + return; + } + + BT_DBG("ConfirmationKey: %s", bt_hex(bt_mesh_prov_link.conf_key, 16)); + + if (bt_rand(bt_mesh_prov_link.rand, 16)) { + BT_ERR("Unable to generate random number"); + prov_fail(PROV_ERR_UNEXP_ERR); + return; + } + + BT_DBG("LocalRandom: %s", bt_hex(bt_mesh_prov_link.rand, 16)); + + bt_mesh_prov_buf_init(cfm, PROV_CONFIRM); + + if (bt_mesh_prov_conf(bt_mesh_prov_link.conf_key, + bt_mesh_prov_link.rand, bt_mesh_prov_link.auth, + net_buf_simple_add(cfm, 16))) { + BT_ERR("Unable to generate confirmation value"); + prov_fail(PROV_ERR_UNEXP_ERR); + return; + } + + if (bt_mesh_prov_send(cfm, NULL)) { + BT_ERR("Failed to send Provisioning Confirm"); + return; + } + + bt_mesh_prov_link.expect = PROV_CONFIRM; +} + +static void public_key_sent(int err, void *cb_data) +{ + atomic_set_bit(bt_mesh_prov_link.flags, PUB_KEY_SENT); + + if (atomic_test_bit(bt_mesh_prov_link.flags, OOB_PUB_KEY) && + atomic_test_bit(bt_mesh_prov_link.flags, REMOTE_PUB_KEY)) { + prov_dh_key_gen(); + return; + } + + bt_mesh_prov_link.expect = PROV_PUB_KEY; +} + +static void send_pub_key(void) +{ + struct os_mbuf *buf = PROV_BUF(65); + const uint8_t *key; + + key = bt_pub_key_get(); + if (!key) { + BT_ERR("No public key available"); + prov_fail(PROV_ERR_UNEXP_ERR); + return; + } + + BT_DBG("Local Public Key: %s", bt_hex(key, 64)); + + bt_mesh_prov_buf_init(buf, PROV_PUB_KEY); + + /* Swap X and Y halves independently to big-endian */ + sys_memcpy_swap(net_buf_simple_add(buf, 32), key, 32); + sys_memcpy_swap(net_buf_simple_add(buf, 32), &key[32], 32); + + /* PublicKeyProvisioner */ + memcpy(&bt_mesh_prov_link.conf_inputs[17], &buf->om_databuf[1], 64); + + if (bt_mesh_prov_send(buf, public_key_sent)) { + BT_ERR("Failed to send Public Key"); + return; + } +} + +static void prov_dh_key_cb(const uint8_t dhkey[32]) +{ + BT_DBG("%p", dhkey); + + if (!dhkey) { + BT_ERR("DHKey generation failed"); + prov_fail(PROV_ERR_UNEXP_ERR); + return; + } + + sys_memcpy_swap(bt_mesh_prov_link.dhkey, dhkey, 32); + + BT_DBG("DHkey: %s", bt_hex(bt_mesh_prov_link.dhkey, 32)); + + if (atomic_test_bit(bt_mesh_prov_link.flags, WAIT_STRING) || + atomic_test_bit(bt_mesh_prov_link.flags, WAIT_NUMBER) || + atomic_test_bit(bt_mesh_prov_link.flags, NOTIFY_INPUT_COMPLETE)) { + atomic_set_bit(bt_mesh_prov_link.flags, WAIT_CONFIRM); + return; + } + + send_confirm(); +} + +static void prov_dh_key_gen(void) +{ + uint8_t remote_pk_le[64], *remote_pk; + + remote_pk = &bt_mesh_prov_link.conf_inputs[81]; + + /* Copy remote key in little-endian for bt_dh_key_gen(). + * X and Y halves are swapped independently. The bt_dh_key_gen() + * will also take care of validating the remote public key. + */ + sys_memcpy_swap(remote_pk_le, remote_pk, 32); + sys_memcpy_swap(&remote_pk_le[32], &remote_pk[32], 32); + + if (bt_dh_key_gen(remote_pk_le, prov_dh_key_cb)) { + BT_ERR("Failed to generate DHKey"); + prov_fail(PROV_ERR_UNEXP_ERR); + } + + if (atomic_test_bit(bt_mesh_prov_link.flags, NOTIFY_INPUT_COMPLETE)) { + bt_mesh_prov_link.expect = PROV_INPUT_COMPLETE; + } +} + +static void prov_pub_key(const uint8_t *data) +{ + BT_DBG("Remote Public Key: %s", bt_hex(data, 64)); + + atomic_set_bit(bt_mesh_prov_link.flags, REMOTE_PUB_KEY); + + /* PublicKeyDevice */ + memcpy(&bt_mesh_prov_link.conf_inputs[81], data, 64); + bt_mesh_prov_link.bearer->clear_tx(); + + prov_dh_key_gen(); +} + +static void pub_key_ready(const uint8_t *pkey) +{ + if (!pkey) { + BT_WARN("Public key not available"); + return; + } + + BT_DBG("Local public key ready"); + + if (atomic_test_and_clear_bit(bt_mesh_prov_link.flags, WAIT_PUB_KEY)) { + send_pub_key(); + } +} + +static void notify_input_complete(void) +{ + if (atomic_test_and_clear_bit(bt_mesh_prov_link.flags, + NOTIFY_INPUT_COMPLETE) && + bt_mesh_prov->input_complete) { + bt_mesh_prov->input_complete(); + } +} + +static void prov_input_complete(const uint8_t *data) +{ + BT_DBG(""); + + notify_input_complete(); + + if (atomic_test_and_clear_bit(bt_mesh_prov_link.flags, WAIT_CONFIRM)) { + send_confirm(); + } +} + +static void send_prov_data(void) +{ + struct os_mbuf *pdu = PROV_BUF(34); +#if BLE_MESH_CDB + struct bt_mesh_cdb_subnet *sub; +#endif + uint8_t session_key[16]; + uint8_t nonce[13]; + int err; + + err = bt_mesh_session_key(bt_mesh_prov_link.dhkey, + bt_mesh_prov_link.prov_salt, session_key); + if (err) { + BT_ERR("Unable to generate session key"); + prov_fail(PROV_ERR_UNEXP_ERR); + return; + } + + BT_DBG("SessionKey: %s", bt_hex(session_key, 16)); + + err = bt_mesh_prov_nonce(bt_mesh_prov_link.dhkey, + bt_mesh_prov_link.prov_salt, nonce); + if (err) { + BT_ERR("Unable to generate session nonce"); + prov_fail(PROV_ERR_UNEXP_ERR); + return; + } + + BT_DBG("Nonce: %s", bt_hex(nonce, 13)); + + err = bt_mesh_dev_key(bt_mesh_prov_link.dhkey, + bt_mesh_prov_link.prov_salt, prov_device.node->dev_key); + if (err) { + BT_ERR("Unable to generate device key"); + prov_fail(PROV_ERR_UNEXP_ERR); + return; + } + + BT_DBG("DevKey: %s", bt_hex(prov_device.node->dev_key, 16)); +#if BLE_MESH_CDB + sub = bt_mesh_cdb_subnet_get(prov_device.node->net_idx); + if (sub == NULL) { + BT_ERR("No subnet with net_idx %u", + prov_device.node->net_idx); + prov_fail(PROV_ERR_UNEXP_ERR); + return; + } +#endif + bt_mesh_prov_buf_init(pdu, PROV_DATA); +#if BLE_MESH_CDB + net_buf_simple_add_mem(pdu, sub->keys[sub->kr_flag].net_key, 16); + net_buf_simple_add_be16(pdu, prov_device.node->net_idx); + net_buf_simple_add_u8(pdu, bt_mesh_cdb_subnet_flags(sub)); + net_buf_simple_add_be32(pdu, bt_mesh_cdb.iv_index); +#endif + net_buf_simple_add_be16(pdu, prov_device.node->addr); + net_buf_simple_add(pdu, 8); /* For MIC */ + + BT_DBG("net_idx %u, iv_index 0x%08x, addr 0x%04x", + prov_device.node->net_idx, bt_mesh.iv_index, + prov_device.node->addr); + + err = bt_mesh_prov_encrypt(session_key, nonce, &pdu->om_data[1], + &pdu->om_data[1]); + if (err) { + BT_ERR("Unable to encrypt provisioning data"); + prov_fail(PROV_ERR_DECRYPT); + return; + } + + if (bt_mesh_prov_send(pdu, NULL)) { + BT_ERR("Failed to send Provisioning Data"); + return; + } + + bt_mesh_prov_link.expect = PROV_COMPLETE; +} + +static void prov_complete(const uint8_t *data) +{ + struct bt_mesh_cdb_node *node = prov_device.node; + + BT_DBG("key %s, net_idx %u, num_elem %u, addr 0x%04x", + bt_hex(node->dev_key, 16), node->net_idx, node->num_elem, + node->addr); + + if (IS_ENABLED(CONFIG_BT_SETTINGS)) { + bt_mesh_store_cdb_node(node); + } + + prov_device.node = NULL; + prov_link_close(PROV_BEARER_LINK_STATUS_SUCCESS); + + if (bt_mesh_prov->node_added) { + bt_mesh_prov->node_added(node->net_idx, node->uuid, node->addr, + node->num_elem); + } +} + +static void send_random(void) +{ + struct os_mbuf *rnd = PROV_BUF(17); + + bt_mesh_prov_buf_init(rnd, PROV_RANDOM); + net_buf_simple_add_mem(rnd, bt_mesh_prov_link.rand, 16); + + if (bt_mesh_prov_send(rnd, NULL)) { + BT_ERR("Failed to send Provisioning Random"); + return; + } + + bt_mesh_prov_link.expect = PROV_RANDOM; +} + +static void prov_random(const uint8_t *data) +{ + uint8_t conf_verify[16]; + + BT_DBG("Remote Random: %s", bt_hex(data, 16)); + if (!memcmp(data, bt_mesh_prov_link.rand, 16)) { + BT_ERR("Random value is identical to ours, rejecting."); + prov_fail(PROV_ERR_CFM_FAILED); + return; + } + + if (bt_mesh_prov_conf(bt_mesh_prov_link.conf_key, + data, bt_mesh_prov_link.auth, conf_verify)) { + BT_ERR("Unable to calculate confirmation verification"); + prov_fail(PROV_ERR_UNEXP_ERR); + return; + } + + if (memcmp(conf_verify, bt_mesh_prov_link.conf, 16)) { + BT_ERR("Invalid confirmation value"); + BT_DBG("Received: %s", bt_hex(bt_mesh_prov_link.conf, 16)); + BT_DBG("Calculated: %s", bt_hex(conf_verify, 16)); + prov_fail(PROV_ERR_CFM_FAILED); + return; + } + + if (bt_mesh_prov_salt(bt_mesh_prov_link.conf_salt, + bt_mesh_prov_link.rand, data, bt_mesh_prov_link.prov_salt)) { + BT_ERR("Failed to generate provisioning salt"); + prov_fail(PROV_ERR_UNEXP_ERR); + return; + } + + BT_DBG("ProvisioningSalt: %s", bt_hex(bt_mesh_prov_link.prov_salt, 16)); + + send_prov_data(); +} + +static void prov_confirm(const uint8_t *data) +{ + BT_DBG("Remote Confirm: %s", bt_hex(data, 16)); + + memcpy(bt_mesh_prov_link.conf, data, 16); + + send_random(); +} + +static void prov_failed(const uint8_t *data) +{ + BT_WARN("Error: 0x%02x", data[0]); + reset_state(); +} + +static void local_input_complete(void) +{ + if (atomic_test_and_clear_bit(bt_mesh_prov_link.flags, WAIT_CONFIRM)) { + send_confirm(); + } +} + +static void prov_link_closed(void) +{ + reset_state(); +} + +static void prov_link_opened(void) +{ + send_invite(); +} + +static const struct bt_mesh_prov_role role_provisioner = { + .input_complete = local_input_complete, + .link_opened = prov_link_opened, + .link_closed = prov_link_closed, + .error = prov_fail, + .op = { + [PROV_CAPABILITIES] = prov_capabilities, + [PROV_PUB_KEY] = prov_pub_key, + [PROV_INPUT_COMPLETE] = prov_input_complete, + [PROV_CONFIRM] = prov_confirm, + [PROV_RANDOM] = prov_random, + [PROV_COMPLETE] = prov_complete, + [PROV_FAILED] = prov_failed, + }, +}; + +static void prov_set_method(uint8_t method, uint8_t action, uint8_t size) +{ + bt_mesh_prov_link.oob_method = method; + bt_mesh_prov_link.oob_action = action; + bt_mesh_prov_link.oob_size = size; +} + +int bt_mesh_auth_method_set_input(bt_mesh_input_action_t action, uint8_t size) +{ + if (!action || !size || size > 8) { + return -EINVAL; + } + + prov_set_method(AUTH_METHOD_INPUT, find_msb_set(action) - 1, size); + return 0; +} + +int bt_mesh_auth_method_set_output(bt_mesh_output_action_t action, uint8_t size) +{ + if (!action || !size || size > 8) { + return -EINVAL; + } + + prov_set_method(AUTH_METHOD_OUTPUT, find_msb_set(action) - 1, size); + return 0; +} + +int bt_mesh_auth_method_set_static(const uint8_t *static_val, uint8_t size) +{ + if (!size || !static_val || size > 16) { + return -EINVAL; + } + + prov_set_method(AUTH_METHOD_STATIC, 0, 0); + + memcpy(bt_mesh_prov_link.auth + 16 - size, static_val, size); + if (size < 16) { + (void)memset(bt_mesh_prov_link.auth, 0, + sizeof(bt_mesh_prov_link.auth) - size); + } + return 0; +} + +int bt_mesh_auth_method_set_none(void) +{ + prov_set_method(AUTH_METHOD_NO_OOB, 0, 0); + return 0; +} + +int bt_mesh_prov_remote_pub_key_set(const uint8_t public_key[64]) +{ + if (public_key == NULL) { + return -EINVAL; + } + + if (atomic_test_and_set_bit(bt_mesh_prov_link.flags, REMOTE_PUB_KEY)) { + return -EALREADY; + } + + /* Swap X and Y halves independently to big-endian */ + memcpy(&bt_mesh_prov_link.conf_inputs[81], public_key, 32); + memcpy(&bt_mesh_prov_link.conf_inputs[81 + 32], &public_key[32], 32); + + return 0; +} + +#if defined(CONFIG_BT_MESH_PB_ADV) +int bt_mesh_pb_adv_open(const uint8_t uuid[16], uint16_t net_idx, uint16_t addr, + uint8_t attention_duration) +{ + int err; + + if (atomic_test_and_set_bit(bt_mesh_prov_link.flags, LINK_ACTIVE)) { + return -EBUSY; + } + + atomic_set_bit(bt_mesh_prov_link.flags, PROVISIONER); + memcpy(prov_device.uuid, uuid, 16); + prov_device.addr = addr; + prov_device.net_idx = net_idx; + prov_device.attention_duration = attention_duration; + bt_mesh_prov_link.bearer = &pb_adv; + bt_mesh_prov_link.role = &role_provisioner; + + err = bt_mesh_prov_link.bearer->link_open(prov_device.uuid, PROTOCOL_TIMEOUT, + bt_mesh_prov_bearer_cb_get(), NULL); + if (err) { + atomic_clear_bit(bt_mesh_prov_link.flags, LINK_ACTIVE); + } + + return err; +} +#endif \ No newline at end of file diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/provisioner.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/provisioner.h new file mode 100644 index 00000000..ccda47ef --- /dev/null +++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/provisioner.h @@ -0,0 +1,10 @@ +/* Bluetooth Mesh */ + +/* + * Copyright (c) 2017 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +int bt_mesh_pb_adv_open(const uint8_t uuid[16], uint16_t net_idx, uint16_t addr, + uint8_t attention_duration); \ No newline at end of file diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/proxy.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/proxy.c index 134a36dd..6d631b72 100644 --- a/src/libs/mynewt-nimble/nimble/host/mesh/src/proxy.c +++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/proxy.c @@ -19,6 +19,7 @@ #include "mesh_priv.h" #include "adv.h" #include "net.h" +#include "rpl.h" #include "prov.h" #include "beacon.h" #include "foundation.h" @@ -28,6 +29,9 @@ #define PDU_TYPE(data) (data[0] & BIT_MASK(6)) #define PDU_SAR(data) (data[0] >> 6) +#define BT_UUID_16_ENCODE(w16) \ + (((w16) >> 0) & 0xFF), \ + (((w16) >> 8) & 0xFF) /* Mesh Profile 1.0 Section 6.6: * "The timeout for the SAR transfer is 20 seconds. When the timeout * expires, the Proxy Server shall disconnect." @@ -110,14 +114,14 @@ static bool prov_fast_adv; static struct bt_mesh_proxy_client { uint16_t conn_handle; - u16_t filter[MYNEWT_VAL(BLE_MESH_PROXY_FILTER_SIZE)]; + uint16_t filter[MYNEWT_VAL(BLE_MESH_PROXY_FILTER_SIZE)]; enum __packed { NONE, WHITELIST, BLACKLIST, PROV, } filter_type; - u8_t msg_type; + uint8_t msg_type; #if (MYNEWT_VAL(BLE_MESH_GATT_PROXY)) struct ble_npl_callout send_beacons; #endif @@ -127,6 +131,9 @@ static struct bt_mesh_proxy_client { [0 ... (MYNEWT_VAL(BLE_MAX_CONNECTIONS) - 1)] = { 0 }, }; +static sys_slist_t idle_waiters; +static atomic_t pending_notifications; + /* Track which service is enabled */ static enum { MESH_GATT_NONE, @@ -195,15 +202,15 @@ static struct bt_mesh_proxy_client *find_client(uint16_t conn_handle) #if (MYNEWT_VAL(BLE_MESH_GATT_PROXY)) /* Next subnet in queue to be advertised */ -static int next_idx; +static struct bt_mesh_subnet *beacon_sub; -static int proxy_segment_and_send(uint16_t conn_handle, u8_t type, +static int proxy_segment_and_send(uint16_t conn_handle, uint8_t type, struct os_mbuf *msg); static int filter_set(struct bt_mesh_proxy_client *client, struct os_mbuf *buf) { - u8_t type; + uint8_t type; if (buf->om_len < 1) { BT_WARN("Too short Filter Set message"); @@ -230,7 +237,7 @@ static int filter_set(struct bt_mesh_proxy_client *client, return 0; } -static void filter_add(struct bt_mesh_proxy_client *client, u16_t addr) +static void filter_add(struct bt_mesh_proxy_client *client, uint16_t addr) { int i; @@ -254,7 +261,7 @@ static void filter_add(struct bt_mesh_proxy_client *client, u16_t addr) } } -static void filter_remove(struct bt_mesh_proxy_client *client, u16_t addr) +static void filter_remove(struct bt_mesh_proxy_client *client, uint16_t addr) { int i; @@ -281,7 +288,7 @@ static void send_filter_status(struct bt_mesh_proxy_client *client, .ctx = &rx->ctx, .src = bt_mesh_primary_addr(), }; - u16_t filter_size; + uint16_t filter_size; int i, err; /* Configuration messages always have dst unassigned */ @@ -323,7 +330,7 @@ static void proxy_cfg(struct bt_mesh_proxy_client *client) { struct os_mbuf *buf = NET_BUF_SIMPLE(29); struct bt_mesh_net_rx rx; - u8_t opcode; + uint8_t opcode; int err; err = bt_mesh_net_decode(client->buf, BT_MESH_NET_IF_PROXY_CFG, @@ -333,8 +340,16 @@ static void proxy_cfg(struct bt_mesh_proxy_client *client) goto done; } + rx.local_match = 1U; + + if (bt_mesh_rpl_check(&rx, NULL)) { + BT_WARN("Replay: src 0x%04x dst 0x%04x seq 0x%06x", + rx.ctx.addr, rx.ctx.recv_dst, rx.seq); + goto done; + } + /* Remove network headers */ - net_buf_simple_pull(buf, BT_MESH_NET_HDR_LEN); + net_buf_simple_pull_mem(buf, BT_MESH_NET_HDR_LEN); BT_DBG("%u bytes: %s", buf->om_len, bt_hex(buf->om_data, buf->om_len)); @@ -351,7 +366,7 @@ static void proxy_cfg(struct bt_mesh_proxy_client *client) break; case CFG_FILTER_ADD: while (buf->om_len >= 2) { - u16_t addr; + uint16_t addr; addr = net_buf_simple_pull_be16(buf); filter_add(client, addr); @@ -360,7 +375,7 @@ static void proxy_cfg(struct bt_mesh_proxy_client *client) break; case CFG_FILTER_REMOVE: while (buf->om_len >= 2) { - u16_t addr; + uint16_t addr; addr = net_buf_simple_pull_be16(buf); filter_remove(client, addr); @@ -389,21 +404,20 @@ static int beacon_send(uint16_t conn_handle, struct bt_mesh_subnet *sub) return rc; } +static int send_beacon_cb(struct bt_mesh_subnet *sub, void *cb_data) +{ + struct bt_mesh_proxy_client *client = cb_data; + + return beacon_send(client->conn_handle, sub); +} + static void proxy_send_beacons(struct ble_npl_event *work) { struct bt_mesh_proxy_client *client; - int i; - client = ble_npl_event_get_arg(work); - for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) { - struct bt_mesh_subnet *sub = &bt_mesh.sub[i]; - - if (sub->net_idx != BT_MESH_KEY_UNUSED) { - beacon_send(client->conn_handle, sub); - } - } + (void)bt_mesh_subnet_find(send_beacon_cb, client); } static void proxy_sar_timeout(struct ble_npl_event *work) @@ -429,12 +443,7 @@ void bt_mesh_proxy_beacon_send(struct bt_mesh_subnet *sub) if (!sub) { /* NULL means we send on all subnets */ - for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) { - if (bt_mesh.sub[i].net_idx != BT_MESH_KEY_UNUSED) { - bt_mesh_proxy_beacon_send(&bt_mesh.sub[i]); - } - } - + bt_mesh_subnet_foreach(bt_mesh_proxy_beacon_send); return; } @@ -445,13 +454,17 @@ void bt_mesh_proxy_beacon_send(struct bt_mesh_subnet *sub) } } -void bt_mesh_proxy_identity_start(struct bt_mesh_subnet *sub) +static void node_id_start(struct bt_mesh_subnet *sub) { sub->node_id = BT_MESH_NODE_IDENTITY_RUNNING; sub->node_id_start = k_uptime_get_32(); +} +void bt_mesh_proxy_identity_start(struct bt_mesh_subnet *sub) +{ + node_id_start(sub); /* Prioritize the recently enabled subnet */ - next_idx = sub - bt_mesh.sub; + beacon_sub = sub; } void bt_mesh_proxy_identity_stop(struct bt_mesh_subnet *sub) @@ -462,30 +475,13 @@ void bt_mesh_proxy_identity_stop(struct bt_mesh_subnet *sub) int bt_mesh_proxy_identity_enable(void) { - int i, count = 0; - BT_DBG(""); if (!bt_mesh_is_provisioned()) { return -EAGAIN; } - for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) { - struct bt_mesh_subnet *sub = &bt_mesh.sub[i]; - - if (sub->net_idx == BT_MESH_KEY_UNUSED) { - continue; - } - - if (sub->node_id == BT_MESH_NODE_IDENTITY_NOT_SUPPORTED) { - continue; - } - - bt_mesh_proxy_identity_start(sub); - count++; - } - - if (count) { + if (bt_mesh_subnet_foreach(node_id_start)) { bt_mesh_adv_update(); } @@ -528,9 +524,9 @@ static void proxy_complete_pdu(struct bt_mesh_proxy_client *client) static int proxy_recv(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) { - struct bt_mesh_proxy_client *client; - const u8_t *data = ctxt->om->om_data; - u16_t len = ctxt->om->om_len; + struct bt_mesh_proxy_client *client = find_client(conn_handle); + const uint8_t *data = ctxt->om->om_data; + uint16_t len = ctxt->om->om_len; client = find_client(conn_handle); @@ -652,7 +648,9 @@ static void proxy_connected(uint16_t conn_handle) static void proxy_disconnected(uint16_t conn_handle, int reason) { int i; - bool disconnected = false; + + BT_DBG("conn handle %u reason 0x%02x", conn_handle, reason); + conn_count--; for (i = 0; i < ARRAY_SIZE(clients); i++) { struct bt_mesh_proxy_client *client = &clients[i]; @@ -665,16 +663,11 @@ static void proxy_disconnected(uint16_t conn_handle, int reason) k_delayed_work_cancel(&client->sar_timer); client->conn_handle = BLE_HS_CONN_HANDLE_NONE; - conn_count--; - disconnected = true; break; } } - if (disconnected) { - BT_INFO("conn_handle %d reason %d", conn_handle, reason); - bt_mesh_adv_update(); - } + bt_mesh_adv_update(); } struct os_mbuf *bt_mesh_proxy_get_buf(void) @@ -887,7 +880,7 @@ int bt_mesh_proxy_gatt_disable(void) return 0; } -void bt_mesh_proxy_addr_add(struct os_mbuf *buf, u16_t addr) +void bt_mesh_proxy_addr_add(struct os_mbuf *buf, uint16_t addr) { struct bt_mesh_proxy_client *client = NULL; int i; @@ -911,7 +904,7 @@ void bt_mesh_proxy_addr_add(struct os_mbuf *buf, u16_t addr) } static bool client_filter_match(struct bt_mesh_proxy_client *client, - u16_t addr) + uint16_t addr) { int i; @@ -942,7 +935,7 @@ static bool client_filter_match(struct bt_mesh_proxy_client *client, return false; } -bool bt_mesh_proxy_relay(struct os_mbuf *buf, u16_t dst) +bool bt_mesh_proxy_relay(struct os_mbuf *buf, uint16_t dst) { bool relayed = false; int i; @@ -978,9 +971,25 @@ bool bt_mesh_proxy_relay(struct os_mbuf *buf, u16_t dst) #endif /* MYNEWT_VAL(BLE_MESH_GATT_PROXY) */ -static int proxy_send(uint16_t conn_handle, const void *data, u16_t len) +static void notify_complete(void) +{ + sys_snode_t *n; + + if (atomic_dec(&pending_notifications) > 1) { + return; + } + + BT_DBG(""); + + while ((n = sys_slist_get(&idle_waiters))) { + CONTAINER_OF(n, struct bt_mesh_proxy_idle_cb, n)->cb(); + } +} + +static int proxy_send(uint16_t conn_handle, const void *data, uint16_t len) { struct os_mbuf *om; + int err = 0; BT_DBG("%u bytes: %s", len, bt_hex(data, len)); @@ -988,7 +997,8 @@ static int proxy_send(uint16_t conn_handle, const void *data, u16_t len) if (gatt_svc == MESH_GATT_PROXY) { om = ble_hs_mbuf_from_flat(data, len); assert(om); - ble_gattc_notify_custom(conn_handle, svc_handles.proxy_data_out_h, om); + err = ble_gattc_notify_custom(conn_handle, svc_handles.proxy_data_out_h, om); + notify_complete(); } #endif @@ -996,17 +1006,22 @@ static int proxy_send(uint16_t conn_handle, const void *data, u16_t len) if (gatt_svc == MESH_GATT_PROV) { om = ble_hs_mbuf_from_flat(data, len); assert(om); - ble_gattc_notify_custom(conn_handle, svc_handles.prov_data_out_h, om); + err = ble_gattc_notify_custom(conn_handle, svc_handles.prov_data_out_h, om); + notify_complete(); } #endif - return 0; + if (!err) { + atomic_inc(&pending_notifications); + } + + return err; } -static int proxy_segment_and_send(uint16_t conn_handle, u8_t type, +static int proxy_segment_and_send(uint16_t conn_handle, uint8_t type, struct os_mbuf *msg) { - u16_t mtu; + uint16_t mtu; BT_DBG("conn_handle %d type 0x%02x len %u: %s", conn_handle, type, msg->om_len, bt_hex(msg->om_data, msg->om_len)); @@ -1020,7 +1035,7 @@ static int proxy_segment_and_send(uint16_t conn_handle, u8_t type, net_buf_simple_push_u8(msg, PDU_HDR(SAR_FIRST, type)); proxy_send(conn_handle, msg->om_data, mtu); - net_buf_simple_pull(msg, mtu); + net_buf_simple_pull_mem(msg, mtu); while (msg->om_len) { if (msg->om_len + 1 < mtu) { @@ -1031,13 +1046,13 @@ static int proxy_segment_and_send(uint16_t conn_handle, u8_t type, net_buf_simple_push_u8(msg, PDU_HDR(SAR_CONT, type)); proxy_send(conn_handle, msg->om_data, mtu); - net_buf_simple_pull(msg, mtu); + net_buf_simple_pull_mem(msg, mtu); } return 0; } -int bt_mesh_proxy_send(uint16_t conn_handle, u8_t type, +int bt_mesh_proxy_send(uint16_t conn_handle, uint8_t type, struct os_mbuf *msg) { struct bt_mesh_proxy_client *client = find_client(conn_handle); @@ -1056,11 +1071,14 @@ int bt_mesh_proxy_send(uint16_t conn_handle, u8_t type, } #if (MYNEWT_VAL(BLE_MESH_PB_GATT)) -static u8_t prov_svc_data[20] = { 0x27, 0x18, }; +static uint8_t prov_svc_data[20] = { + BT_UUID_16_ENCODE(BT_UUID_MESH_PROV_VAL), +}; static const struct bt_data prov_ad[] = { BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)), - BT_DATA_BYTES(BT_DATA_UUID16_ALL, 0x27, 0x18), + BT_DATA_BYTES(BT_DATA_UUID16_ALL, + BT_UUID_16_ENCODE(BT_UUID_MESH_PROV_VAL)), BT_DATA(BT_DATA_SVC_DATA16, prov_svc_data, sizeof(prov_svc_data)), }; #endif /* PB_GATT */ @@ -1075,23 +1093,27 @@ static const struct bt_data prov_ad[] = { #define NODE_ID_TIMEOUT K_SECONDS(CONFIG_BT_MESH_NODE_ID_TIMEOUT) -static u8_t proxy_svc_data[NODE_ID_LEN] = { 0x28, 0x18, }; +static uint8_t proxy_svc_data[NODE_ID_LEN] = { + BT_UUID_16_ENCODE(BT_UUID_MESH_PROXY_VAL), +}; static const struct bt_data node_id_ad[] = { BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)), - BT_DATA_BYTES(BT_DATA_UUID16_ALL, 0x28, 0x18), + BT_DATA_BYTES(BT_DATA_UUID16_ALL, + BT_UUID_16_ENCODE(BT_UUID_MESH_PROXY_VAL)), BT_DATA(BT_DATA_SVC_DATA16, proxy_svc_data, NODE_ID_LEN), }; static const struct bt_data net_id_ad[] = { BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)), - BT_DATA_BYTES(BT_DATA_UUID16_ALL, 0x28, 0x18), + BT_DATA_BYTES(BT_DATA_UUID16_ALL, + BT_UUID_16_ENCODE(BT_UUID_MESH_PROXY_VAL)), BT_DATA(BT_DATA_SVC_DATA16, proxy_svc_data, NET_ID_LEN), }; static int node_id_adv(struct bt_mesh_subnet *sub) { - u8_t tmp[16]; + uint8_t tmp[16]; int err; BT_DBG(""); @@ -1107,7 +1129,8 @@ static int node_id_adv(struct bt_mesh_subnet *sub) memcpy(tmp + 6, proxy_svc_data + 11, 8); sys_put_be16(bt_mesh_primary_addr(), tmp + 14); - err = bt_encrypt_be(sub->keys[sub->kr_flag].identity, tmp, tmp); + err = bt_encrypt_be(sub->keys[SUBNET_KEY_TX_IDX(sub)].identity, tmp, + tmp); if (err) { return err; } @@ -1135,9 +1158,9 @@ static int net_id_adv(struct bt_mesh_subnet *sub) proxy_svc_data[2] = ID_TYPE_NET; BT_DBG("Advertising with NetId %s", - bt_hex(sub->keys[sub->kr_flag].net_id, 8)); + bt_hex(sub->keys[SUBNET_KEY_TX_IDX(sub)].net_id, 8)); - memcpy(proxy_svc_data + 3, sub->keys[sub->kr_flag].net_id, 8); + memcpy(proxy_svc_data + 3, sub->keys[SUBNET_KEY_TX_IDX(sub)].net_id, 8); err = bt_le_adv_start(&slow_adv_param, net_id_ad, ARRAY_SIZE(net_id_ad), NULL, 0); @@ -1158,60 +1181,75 @@ static bool advertise_subnet(struct bt_mesh_subnet *sub) } return (sub->node_id == BT_MESH_NODE_IDENTITY_RUNNING || - bt_mesh_gatt_proxy_get() != BT_MESH_GATT_PROXY_NOT_SUPPORTED); + bt_mesh_gatt_proxy_get() == BT_MESH_GATT_PROXY_ENABLED); } static struct bt_mesh_subnet *next_sub(void) { - int i; + struct bt_mesh_subnet *sub = NULL; - for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) { - struct bt_mesh_subnet *sub; - - sub = &bt_mesh.sub[(i + next_idx) % ARRAY_SIZE(bt_mesh.sub)]; - if (advertise_subnet(sub)) { - next_idx = (next_idx + 1) % ARRAY_SIZE(bt_mesh.sub); - return sub; + if (!beacon_sub) { + beacon_sub = bt_mesh_subnet_next(NULL); + if (!beacon_sub) { + /* No valid subnets */ + return NULL; } } + sub = beacon_sub; + do { + if (advertise_subnet(sub)) { + beacon_sub = sub; + return sub; + } + + sub = bt_mesh_subnet_next(sub); + } while (sub != beacon_sub); + + /* No subnets to advertise on */ + return NULL; } -static int sub_count(void) +static int sub_count_cb(struct bt_mesh_subnet *sub, void *cb_data) { - int i, count = 0; + int *count = cb_data; - for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) { - struct bt_mesh_subnet *sub = &bt_mesh.sub[i]; - - if (advertise_subnet(sub)) { - count++; - } + if (advertise_subnet(sub)) { + (*count)++; } + return 0; +} + +static int sub_count(void) +{ + int count = 0; + + (void)bt_mesh_subnet_find(sub_count_cb, &count); return count; } -static s32_t gatt_proxy_advertise(struct bt_mesh_subnet *sub) +static int32_t gatt_proxy_advertise(struct bt_mesh_subnet *sub) { - s32_t remaining = K_FOREVER; + int32_t remaining = K_FOREVER; int subnet_count; BT_DBG(""); if (conn_count == CONFIG_BT_MAX_CONN) { - BT_DBG("Connectable advertising deferred (max connections)"); - return remaining; + BT_DBG("Connectable advertising deferred (max connections %d)", conn_count); + return -ENOMEM; } + sub = beacon_sub ? beacon_sub : bt_mesh_subnet_next(beacon_sub); if (!sub) { BT_WARN("No subnets to advertise on"); - return remaining; + return -ENOENT; } if (sub->node_id == BT_MESH_NODE_IDENTITY_RUNNING) { - u32_t active = k_uptime_get_32() - sub->node_id_start; + uint32_t active = k_uptime_get_32() - sub->node_id_start; if (active < NODE_ID_TIMEOUT) { remaining = NODE_ID_TIMEOUT - active; @@ -1231,7 +1269,7 @@ static s32_t gatt_proxy_advertise(struct bt_mesh_subnet *sub) subnet_count = sub_count(); BT_DBG("sub_count %u", subnet_count); if (subnet_count > 1) { - s32_t max_timeout; + int32_t max_timeout; /* We use NODE_ID_TIMEOUT as a starting point since it may * be less than 60 seconds. Divide this period into at least @@ -1249,6 +1287,8 @@ static s32_t gatt_proxy_advertise(struct bt_mesh_subnet *sub) BT_DBG("Advertising %d ms for net_idx 0x%04x", (int) remaining, sub->net_idx); + beacon_sub = bt_mesh_subnet_next(beacon_sub); + return remaining; } #endif /* GATT_PROXY */ @@ -1299,7 +1339,7 @@ static size_t gatt_prov_adv_create(struct bt_data prov_sd[2]) } #endif /* PB_GATT */ -s32_t bt_mesh_proxy_adv_start(void) +int32_t bt_mesh_proxy_adv_start(void) { BT_DBG(""); @@ -1361,6 +1401,19 @@ void bt_mesh_proxy_adv_stop(void) } } +#if defined(CONFIG_BT_MESH_GATT_PROXY) +static void subnet_evt(struct bt_mesh_subnet *sub, enum bt_mesh_key_evt evt) +{ + if (evt == BT_MESH_KEY_DELETED) { + if (sub == beacon_sub) { + beacon_sub = NULL; + } + } else { + bt_mesh_proxy_beacon_send(sub); + } +} +#endif + static void ble_mesh_handle_connect(struct ble_gap_event *event, void *arg) { #if MYNEWT_VAL(BLE_EXT_ADV) @@ -1477,6 +1530,12 @@ int bt_mesh_proxy_init(void) { int i; +#if (MYNEWT_VAL(BLE_MESH_GATT_PROXY)) + if (!bt_mesh_subnet_cb_list[4]) { + bt_mesh_subnet_cb_list[4] = subnet_evt; + } +#endif + for (i = 0; i < MYNEWT_VAL(BLE_MAX_CONNECTIONS); ++i) { #if (MYNEWT_VAL(BLE_MESH_GATT_PROXY)) k_work_init(&clients[i].send_beacons, proxy_send_beacons); @@ -1496,4 +1555,14 @@ int bt_mesh_proxy_init(void) return 0; } +void bt_mesh_proxy_on_idle(struct bt_mesh_proxy_idle_cb *cb) +{ + if (!atomic_get(&pending_notifications)) { + cb->cb(); + return; + } + + sys_slist_append(&idle_waiters, &cb->n); +} + #endif /* MYNEWT_VAL(BLE_MESH_PROXY) */ diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/proxy.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/proxy.h index 64338a0a..ebade45a 100644 --- a/src/libs/mynewt-nimble/nimble/host/mesh/src/proxy.h +++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/proxy.h @@ -15,8 +15,14 @@ #define BT_MESH_PROXY_PROV 0x03 #include "mesh/mesh.h" +#include "mesh/slist.h" -int bt_mesh_proxy_send(uint16_t conn_handle, u8_t type, struct os_mbuf *msg); +struct bt_mesh_proxy_idle_cb { + sys_snode_t n; + void (*cb)(void); +}; + +int bt_mesh_proxy_send(uint16_t conn_handle, uint8_t type, struct os_mbuf *msg); int bt_mesh_proxy_prov_enable(void); int bt_mesh_proxy_prov_disable(bool disconnect); @@ -29,16 +35,17 @@ void bt_mesh_proxy_beacon_send(struct bt_mesh_subnet *sub); struct os_mbuf *bt_mesh_proxy_get_buf(void); -s32_t bt_mesh_proxy_adv_start(void); +int32_t bt_mesh_proxy_adv_start(void); void bt_mesh_proxy_adv_stop(void); void bt_mesh_proxy_identity_start(struct bt_mesh_subnet *sub); void bt_mesh_proxy_identity_stop(struct bt_mesh_subnet *sub); -bool bt_mesh_proxy_relay(struct os_mbuf *buf, u16_t dst); -void bt_mesh_proxy_addr_add(struct os_mbuf *buf, u16_t addr); +bool bt_mesh_proxy_relay(struct os_mbuf *buf, uint16_t dst); +void bt_mesh_proxy_addr_add(struct os_mbuf *buf, uint16_t addr); int bt_mesh_proxy_init(void); +void bt_mesh_proxy_on_idle(struct bt_mesh_proxy_idle_cb *cb); int ble_mesh_proxy_gap_event(struct ble_gap_event *event, void *arg); diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/rpl.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/rpl.c new file mode 100644 index 00000000..93c2e1a8 --- /dev/null +++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/rpl.c @@ -0,0 +1,162 @@ +/* Bluetooth Mesh */ + +/* + * Copyright (c) 2017 Intel Corporation + * Copyright (c) 2020 Lingao Meng + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define MESH_LOG_MODULE BLE_MESH_RPL_LOG + +#include "log/log.h" + +#include "mesh_priv.h" +#include "adv.h" +#include "net.h" +#include "rpl.h" +#include "settings.h" + +static struct bt_mesh_rpl replay_list[MYNEWT_VAL(BLE_MESH_CRPL)]; + +void bt_mesh_rpl_update(struct bt_mesh_rpl *rpl, + struct bt_mesh_net_rx *rx) +{ + rpl->src = rx->ctx.addr; + rpl->seq = rx->seq; + rpl->old_iv = rx->old_iv; + + if (IS_ENABLED(CONFIG_BT_SETTINGS)) { + bt_mesh_store_rpl(rpl); + } +} + +/* Check the Replay Protection List for a replay attempt. If non-NULL match + * parameter is given the RPL slot is returned but it is not immediately + * updated (needed for segmented messages), whereas if a NULL match is given + * the RPL is immediately updated (used for unsegmented messages). + */ +bool bt_mesh_rpl_check(struct bt_mesh_net_rx *rx, + struct bt_mesh_rpl **match) +{ + int i; + + /* Don't bother checking messages from ourselves */ + if (rx->net_if == BT_MESH_NET_IF_LOCAL) { + return false; + } + + /* The RPL is used only for the local node */ + if (!rx->local_match) { + return false; + } + + for (i = 0; i < ARRAY_SIZE(replay_list); i++) { + struct bt_mesh_rpl *rpl = &replay_list[i]; + + /* Empty slot */ + if (!rpl->src) { + if (match) { + *match = rpl; + } else { + bt_mesh_rpl_update(rpl, rx); + } + + return false; + } + + /* Existing slot for given address */ + if (rpl->src == rx->ctx.addr) { + if (rx->old_iv && !rpl->old_iv) { + return true; + } + + if ((!rx->old_iv && rpl->old_iv) || + rpl->seq < rx->seq) { + if (match) { + *match = rpl; + } else { + bt_mesh_rpl_update(rpl, rx); + } + + return false; + } else { + return true; + } + } + } + + BT_ERR("RPL is full!"); + return true; +} + +void bt_mesh_rpl_clear(void) +{ + BT_DBG(""); + + if (IS_ENABLED(CONFIG_BT_SETTINGS)) { + bt_mesh_clear_rpl(); + } else { + (void)memset(replay_list, 0, sizeof(replay_list)); + } +} + +struct bt_mesh_rpl *bt_mesh_rpl_find(uint16_t src) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(replay_list); i++) { + if (replay_list[i].src == src) { + return &replay_list[i]; + } + } + + return NULL; +} + +struct bt_mesh_rpl *bt_mesh_rpl_alloc(uint16_t src) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(replay_list); i++) { + if (!replay_list[i].src) { + replay_list[i].src = src; + return &replay_list[i]; + } + } + + return NULL; +} + +void bt_mesh_rpl_foreach(bt_mesh_rpl_func_t func, void *user_data) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(replay_list); i++) { + func(&replay_list[i], user_data); + } +} + +void bt_mesh_rpl_reset(void) +{ + int i; + + /* Discard "old old" IV Index entries from RPL and flag + * any other ones (which are valid) as old. + */ + for (i = 0; i < ARRAY_SIZE(replay_list); i++) { + struct bt_mesh_rpl *rpl = &replay_list[i]; + + if (rpl->src) { + if (rpl->old_iv) { + (void)memset(rpl, 0, sizeof(*rpl)); + } else { + rpl->old_iv = true; + } + + if (IS_ENABLED(CONFIG_BT_SETTINGS)) { + bt_mesh_store_rpl(rpl); + } + } + } +} \ No newline at end of file diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/rpl.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/rpl.h new file mode 100644 index 00000000..0592712f --- /dev/null +++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/rpl.h @@ -0,0 +1,30 @@ +/* Bluetooth Mesh */ + +/* + * Copyright (c) 2017 Intel Corporation + * Copyright (c) 2020 Lingao Meng + * + * SPDX-License-Identifier: Apache-2.0 + */ + +struct bt_mesh_rpl { + uint16_t src; + bool old_iv; +#if defined(CONFIG_BT_SETTINGS) + bool store; +#endif + uint32_t seq; +}; + +typedef void (*bt_mesh_rpl_func_t)(struct bt_mesh_rpl *rpl, + void *user_data); + +void bt_mesh_rpl_reset(void); +bool bt_mesh_rpl_check(struct bt_mesh_net_rx *rx, + struct bt_mesh_rpl **match); +void bt_mesh_rpl_clear(void); +struct bt_mesh_rpl *bt_mesh_rpl_find(uint16_t src); +struct bt_mesh_rpl *bt_mesh_rpl_alloc(uint16_t src); +void bt_mesh_rpl_foreach(bt_mesh_rpl_func_t func, void *user_data); +void bt_mesh_rpl_update(struct bt_mesh_rpl *rpl, + struct bt_mesh_net_rx *rx); \ No newline at end of file diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/settings.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/settings.c index 88d9b302..537bd785 100644 --- a/src/libs/mynewt-nimble/nimble/host/mesh/src/settings.c +++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/settings.c @@ -9,16 +9,23 @@ #if MYNEWT_VAL(BLE_MESH_SETTINGS) +#include "mesh_priv.h" #include "mesh/mesh.h" #include "mesh/glue.h" +#include "subnet.h" +#include "app_keys.h" #include "net.h" +#include "rpl.h" #include "crypto.h" #include "transport.h" +#include "heartbeat.h" #include "access.h" #include "foundation.h" #include "proxy.h" #include "settings.h" -#include "nodes.h" +#include "lpn.h" +#include "cfg.h" + #include "config/config.h" @@ -27,116 +34,155 @@ * bt_mesh_app_key and bt_mesh_subnet structs themselves, since once a key * gets deleted its struct becomes invalid and may be reused for other keys. */ -static struct key_update { - u16_t key_idx:12, /* AppKey or NetKey Index */ +struct key_update { + uint16_t key_idx:12, /* AppKey or NetKey Index */ valid:1, /* 1 if this entry is valid, 0 if not */ app_key:1, /* 1 if this is an AppKey, 0 if a NetKey */ clear:1; /* 1 if key needs clearing, 0 if storing */ -} key_updates[CONFIG_BT_MESH_APP_KEY_COUNT + CONFIG_BT_MESH_SUBNET_COUNT]; +}; + +static struct key_update key_updates[CONFIG_BT_MESH_APP_KEY_COUNT + + CONFIG_BT_MESH_SUBNET_COUNT]; static struct k_delayed_work pending_store; /* Mesh network storage information */ struct net_val { - u16_t primary_addr; - u8_t dev_key[16]; + uint16_t primary_addr; + uint8_t dev_key[16]; } __packed; /* Sequence number storage */ struct seq_val { - u8_t val[3]; + uint8_t val[3]; } __packed; /* Heartbeat Publication storage */ struct hb_pub_val { - u16_t dst; - u8_t period; - u8_t ttl; - u16_t feat; - u16_t net_idx:12, + uint16_t dst; + uint8_t period; + uint8_t ttl; + uint16_t feat; + uint16_t net_idx:12, indefinite:1; }; /* Miscelaneous configuration server model states */ struct cfg_val { - u8_t net_transmit; - u8_t relay; - u8_t relay_retransmit; - u8_t beacon; - u8_t gatt_proxy; - u8_t frnd; - u8_t default_ttl; + uint8_t net_transmit; + uint8_t relay; + uint8_t relay_retransmit; + uint8_t beacon; + uint8_t gatt_proxy; + uint8_t frnd; + uint8_t default_ttl; }; /* IV Index & IV Update storage */ struct iv_val { - u32_t iv_index; - u8_t iv_update:1, + uint32_t iv_index; + uint8_t iv_update:1, iv_duration:7; } __packed; /* Replay Protection List storage */ struct rpl_val { - u32_t seq:24, + uint32_t seq:24, old_iv:1; }; /* NetKey storage information */ struct net_key_val { - u8_t kr_flag:1, + uint8_t kr_flag:1, kr_phase:7; - u8_t val[2][16]; + uint8_t val[2][16]; } __packed; /* AppKey storage information */ struct app_key_val { - u16_t net_idx; + uint16_t net_idx; bool updated; - u8_t val[2][16]; + uint8_t val[2][16]; } __packed; struct mod_pub_val { - u16_t addr; - u16_t key; - u8_t ttl; - u8_t retransmit; - u8_t period; - u8_t period_div:4, + uint16_t addr; + uint16_t key; + uint8_t ttl; + uint8_t retransmit; + uint8_t period; + uint8_t period_div:4, cred:1; }; /* Virtual Address information */ struct va_val { - u16_t ref; - u16_t addr; - u8_t uuid[16]; + uint16_t ref; + uint16_t addr; + uint8_t uuid[16]; +} __packed; + +struct cdb_net_val { + uint32_t iv_index; + bool iv_update; } __packed; /* Node storage information */ struct node_val { - u16_t net_idx; - u8_t dev_key[16]; - u8_t num_elem; + uint16_t net_idx; + uint8_t num_elem; + uint8_t flags; +#define F_NODE_CONFIGURED 0x01 + uint8_t uuid[16]; + uint8_t dev_key[16]; } __packed; struct node_update { - u16_t addr; + uint16_t addr; bool clear; }; -#if MYNEWT_VAL(BLE_MESH_PROVISIONER) -static struct node_update node_updates[CONFIG_BT_MESH_NODE_COUNT]; +#if MYNEWT_VAL(BLE_MESH_CDB) +static struct node_update cdb_node_updates[MYNEWT_VAL(BLE_MESH_CDB_NODE_COUNT)]; +static struct key_update cdb_key_updates[ + MYNEWT_VAL(BLE_MESH_CDB_SUBNET_COUNT) + + MYNEWT_VAL(BLE_MESH_CDB_APP_KEY_COUNT)]; #else -static struct node_update node_updates[0]; +static struct node_update cdb_node_updates[0]; +static struct key_update cdb_key_updates[0]; #endif -/* We need this so we don't overwrite app-hardcoded values in case FCB - * contains a history of changes but then has a NULL at the end. - */ -static struct { - bool valid; - struct cfg_val cfg; -} stored_cfg; +int settings_name_next(char *name, char **next) +{ + int rc = 0; + + if (next) { + *next = NULL; + } + + if (!name) { + return 0; + } + + /* name might come from flash directly, in flash the name would end + * with '=' or '\0' depending how storage is done. Flash reading is + * limited to what can be read + */ + while ((*name != '\0') && (*name != '=') && + (*name != '/')) { + rc++; + name++; + } + + if (*name == '/') { + if (next) { + *next = name + 1; + } + return rc; + } + + return rc; +} static int net_set(int argc, char **argv, char *val) { @@ -231,8 +277,7 @@ static int seq_set(int argc, char **argv, char *val) return -EINVAL; } - bt_mesh.seq = ((u32_t)seq.val[0] | ((u32_t)seq.val[1] << 8) | - ((u32_t)seq.val[2] << 16)); + bt_mesh.seq = sys_get_le24(seq.val); if (CONFIG_BT_MESH_SEQ_STORE_RATE > 0) { /* Make sure we have a large enough sequence number. We @@ -249,39 +294,12 @@ static int seq_set(int argc, char **argv, char *val) return 0; } -static struct bt_mesh_rpl *rpl_find(u16_t src) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(bt_mesh.rpl); i++) { - if (bt_mesh.rpl[i].src == src) { - return &bt_mesh.rpl[i]; - } - } - - return NULL; -} - -static struct bt_mesh_rpl *rpl_alloc(u16_t src) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(bt_mesh.rpl); i++) { - if (!bt_mesh.rpl[i].src) { - bt_mesh.rpl[i].src = src; - return &bt_mesh.rpl[i]; - } - } - - return NULL; -} - static int rpl_set(int argc, char **argv, char *val) { struct bt_mesh_rpl *entry; struct rpl_val rpl; int len, err; - u16_t src; + uint16_t src; if (argc < 1) { BT_ERR("Invalid argc (%d)", argc); @@ -291,7 +309,7 @@ static int rpl_set(int argc, char **argv, char *val) BT_DBG("argv[0] %s val %s", argv[0], val ? val : "(null)"); src = strtol(argv[0], NULL, 16); - entry = rpl_find(src); + entry = bt_mesh_rpl_find(src); if (!val) { if (entry) { @@ -304,7 +322,7 @@ static int rpl_set(int argc, char **argv, char *val) } if (!entry) { - entry = rpl_alloc(src); + entry = bt_mesh_rpl_alloc(src); if (!entry) { BT_ERR("Unable to allocate RPL entry for 0x%04x", src); return -ENOMEM; @@ -334,26 +352,13 @@ static int rpl_set(int argc, char **argv, char *val) static int net_key_set(int argc, char **argv, char *val) { - struct bt_mesh_subnet *sub; struct net_key_val key; - int len, i, err; - u16_t net_idx; + int len, err; + uint16_t net_idx; BT_DBG("argv[0] %s val %s", argv[0], val ? val : "(null)"); net_idx = strtol(argv[0], NULL, 16); - sub = bt_mesh_subnet_get(net_idx); - - if (!val) { - if (!sub) { - BT_ERR("No subnet with NetKeyIndex 0x%03x", net_idx); - return -ENOENT; - } - - BT_DBG("Deleting NetKeyIndex 0x%03x", net_idx); - bt_mesh_subnet_del(sub, false); - return 0; - } len = sizeof(key); err = settings_bytes_from_str(val, &key, &len); @@ -367,93 +372,41 @@ static int net_key_set(int argc, char **argv, char *val) return -EINVAL; } - if (sub) { - BT_DBG("Updating existing NetKeyIndex 0x%03x", net_idx); - - sub->kr_flag = key.kr_flag; - sub->kr_phase = key.kr_phase; - memcpy(sub->keys[0].net, &key.val[0], 16); - memcpy(sub->keys[1].net, &key.val[1], 16); - - return 0; - } - - for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) { - if (bt_mesh.sub[i].net_idx == BT_MESH_KEY_UNUSED) { - sub = &bt_mesh.sub[i]; - break; - } - } - - if (!sub) { - BT_ERR("No space to allocate a new subnet"); - return -ENOMEM; - } - - sub->net_idx = net_idx; - sub->kr_flag = key.kr_flag; - sub->kr_phase = key.kr_phase; - memcpy(sub->keys[0].net, &key.val[0], 16); - memcpy(sub->keys[1].net, &key.val[1], 16); - BT_DBG("NetKeyIndex 0x%03x recovered from storage", net_idx); - return 0; + return bt_mesh_subnet_set( + net_idx, key.kr_phase, key.val[0], + (key.kr_phase != BT_MESH_KR_NORMAL) ? key.val[1] : NULL); } static int app_key_set(int argc, char **argv, char *val) { - struct bt_mesh_app_key *app; struct app_key_val key; - u16_t app_idx; - int len, err; + uint16_t app_idx; + int len_rd, err; BT_DBG("argv[0] %s val %s", argv[0], val ? val : "(null)"); app_idx = strtol(argv[0], NULL, 16); + len_rd = strtol(argv[1], NULL, 16); - if (!val) { - BT_DBG("Deleting AppKeyIndex 0x%03x", app_idx); - - app = bt_mesh_app_key_find(app_idx); - if (app) { - bt_mesh_app_key_del(app, false); - } - + if (!len_rd) { return 0; } - len = sizeof(key); - err = settings_bytes_from_str(val, &key, &len); + err = settings_bytes_from_str(val, &key, &len_rd); if (err) { BT_ERR("Failed to decode value %s (err %d)", val, err); return err; } - if (len != sizeof(key)) { - BT_ERR("Unexpected value length (%d != %zu)", len, sizeof(key)); - return -EINVAL; + err = bt_mesh_app_key_set(app_idx, key.net_idx, key.val[0], + key.updated ? key.val[1] : NULL); + if (err) { + BT_ERR("Failed to set \'app-key\'"); + return err; } - app = bt_mesh_app_key_find(app_idx); - if (!app) { - app = bt_mesh_app_key_alloc(app_idx); - } - - if (!app) { - BT_ERR("No space for a new app key"); - return -ENOMEM; - } - - app->net_idx = key.net_idx; - app->app_idx = app_idx; - app->updated = key.updated; - memcpy(app->keys[0].val, key.val[0], 16); - memcpy(app->keys[1].val, key.val[1], 16); - - bt_mesh_app_id(app->keys[0].val, &app->keys[0].id); - bt_mesh_app_id(app->keys[1].val, &app->keys[1].id); - BT_DBG("AppKeyIndex 0x%03x recovered from storage", app_idx); return 0; @@ -461,27 +414,12 @@ static int app_key_set(int argc, char **argv, char *val) static int hb_pub_set(int argc, char **argv, char *val) { - struct bt_mesh_hb_pub *pub = bt_mesh_hb_pub_get(); + struct bt_mesh_hb_pub pub; struct hb_pub_val hb_val; int len, err; BT_DBG("val %s", val ? val : "(null)"); - if (!pub) { - return -ENOENT; - } - - if (!val) { - pub->dst = BT_MESH_ADDR_UNASSIGNED; - pub->count = 0; - pub->ttl = 0; - pub->period = 0; - pub->feat = 0; - - BT_DBG("Cleared heartbeat publication"); - return 0; - } - len = sizeof(hb_val); err = settings_bytes_from_str(val, &hb_val, &len); if (err) { @@ -495,18 +433,20 @@ static int hb_pub_set(int argc, char **argv, char *val) return -EINVAL; } - pub->dst = hb_val.dst; - pub->period = hb_val.period; - pub->ttl = hb_val.ttl; - pub->feat = hb_val.feat; - pub->net_idx = hb_val.net_idx; + pub.dst = hb_val.dst; + pub.period = bt_mesh_hb_pwr2(hb_val.period); + pub.ttl = hb_val.ttl; + pub.feat = hb_val.feat; + pub.net_idx = hb_val.net_idx; if (hb_val.indefinite) { - pub->count = 0xffff; + pub.count = 0xffff; } else { - pub->count = 0; + pub.count = 0; } + (void)bt_mesh_hb_pub_set(&pub); + BT_DBG("Restored heartbeat publication"); return 0; @@ -514,35 +454,36 @@ static int hb_pub_set(int argc, char **argv, char *val) static int cfg_set(int argc, char **argv, char *val) { - struct bt_mesh_cfg_srv *cfg = bt_mesh_cfg_get(); + struct cfg_val cfg; int len, err; BT_DBG("val %s", val ? val : "(null)"); - if (!cfg) { - return -ENOENT; - } - if (!val) { - stored_cfg.valid = false; BT_DBG("Cleared configuration state"); return 0; } - len = sizeof(stored_cfg.cfg); - err = settings_bytes_from_str(val, &stored_cfg.cfg, &len); + len = sizeof(cfg); + err = settings_bytes_from_str(val, &cfg, &len); if (err) { BT_ERR("Failed to decode value %s (err %d)", val, err); return err; } - if (len != sizeof(stored_cfg.cfg)) { + if (len != sizeof(cfg)) { BT_ERR("Unexpected value length (%d != %zu)", len, - sizeof(stored_cfg.cfg)); + sizeof(cfg)); return -EINVAL; } - stored_cfg.valid = true; + bt_mesh_net_transmit_set(cfg.net_transmit); + bt_mesh_relay_set(cfg.relay, cfg.relay_retransmit); + bt_mesh_beacon_set(cfg.beacon); + bt_mesh_gatt_proxy_set(cfg.gatt_proxy); + bt_mesh_friend_set(cfg.frnd); + bt_mesh_default_ttl_set(cfg.default_ttl); + BT_DBG("Restored configuration state"); return 0; @@ -646,11 +587,25 @@ static int mod_set_pub(struct bt_mesh_model *mod, char *val) return 0; } +static int mod_data_set(struct bt_mesh_model *mod, + char *name, char *len_rd) +{ + char *next; + + settings_name_next(name, &next); + + if (mod->cb && mod->cb->settings_set) { + return mod->cb->settings_set(mod, next, len_rd); + } + + return 0; +} + static int mod_set(bool vnd, int argc, char **argv, char *val) { struct bt_mesh_model *mod; - u8_t elem_idx, mod_idx; - u16_t mod_key; + uint8_t elem_idx, mod_idx; + uint16_t mod_key; if (argc < 2) { BT_ERR("Too small argc (%d)", argc); @@ -684,11 +639,7 @@ static int mod_set(bool vnd, int argc, char **argv, char *val) } if (!strcmp(argv[1], "data")) { - mod->flags |= BT_MESH_MOD_DATA_PRESENT; - - if (mod->cb && mod->cb->settings_set) { - return mod->cb->settings_set(mod, val); - } + return mod_data_set(mod, argv[1], val); } BT_WARN("Unknown module key %s", argv[1]); @@ -709,8 +660,8 @@ static int vnd_mod_set(int argc, char **argv, char *val) static int va_set(int argc, char **argv, char *val) { struct va_val va; - struct label *lab; - u16_t index; + struct bt_mesh_va *lab; + uint16_t index; int len, err; if (argc < 1) { @@ -741,7 +692,7 @@ static int va_set(int argc, char **argv, char *val) return 0; } - lab = get_label(index); + lab = bt_mesh_va_get(index); if (lab == NULL) { BT_WARN("Out of labels buffers"); return -ENOBUFS; @@ -758,12 +709,35 @@ static int va_set(int argc, char **argv, char *val) } #endif -#if MYNEWT_VAL(BLE_MESH_PROVISIONER) -static int node_set(int argc, char **argv, char *str) +#if MYNEWT_VAL(BLE_MESH_CDB) +static int cdb_net_set(int argc, char *val) { - struct bt_mesh_node *node; + struct cdb_net_val net; + int len, err; + + len = sizeof(net); + err = settings_bytes_from_str(val, &net, &len); + if (err) { + BT_ERR("Failed to set \'cdb_net\'"); + return err; + } + + bt_mesh_cdb.iv_index = net.iv_index; + + if (net.iv_update) { + atomic_set_bit(bt_mesh_cdb.flags, BT_MESH_CDB_IVU_IN_PROGRESS); + } + + atomic_set_bit(bt_mesh_cdb.flags, BT_MESH_CDB_VALID); + + return 0; +} + +static int cdb_node_set(int argc, char *str) +{ + struct bt_mesh_cdb_node *node; struct node_val val; - u16_t addr; + uint16_t addr; int len, err; if (argc < 1) { @@ -771,15 +745,16 @@ static int node_set(int argc, char **argv, char *str) return -ENOENT; } - addr = strtol(argv[0], NULL, 16); + addr = strtol(str, NULL, 16); + len = sizeof(str); - if (str == NULL) { + if (argc < 1) { BT_DBG("val (null)"); BT_DBG("Deleting node 0x%04x", addr); - node = bt_mesh_node_find(addr); + node = bt_mesh_cdb_node_get(addr); if (node) { - bt_mesh_node_del(node, false); + bt_mesh_cdb_node_del(node, false); } return 0; @@ -796,9 +771,10 @@ static int node_set(int argc, char **argv, char *str) return -EINVAL; } - node = bt_mesh_node_find(addr); + node = bt_mesh_cdb_node_get(addr); if (!node) { - node = bt_mesh_node_alloc(addr, val.num_elem, val.net_idx); + node = bt_mesh_cdb_node_alloc(val.uuid, addr, val.num_elem, + val.net_idx); } if (!node) { @@ -806,12 +782,163 @@ static int node_set(int argc, char **argv, char *str) return -ENOMEM; } - memcpy(node->dev_key, &val.dev_key, 16); + if (val.flags & F_NODE_CONFIGURED) { + atomic_set_bit(node->flags, BT_MESH_CDB_NODE_CONFIGURED); + } + + memcpy(node->uuid, val.uuid, 16); + memcpy(node->dev_key, val.dev_key, 16); BT_DBG("Node 0x%04x recovered from storage", addr); return 0; } + +static int cdb_subnet_set(int argc, char *name) +{ + struct bt_mesh_cdb_subnet *sub; + struct net_key_val key; + uint16_t net_idx; + int len, len_rd, err; + + if (!name) { + BT_ERR("Insufficient number of arguments"); + return -ENOENT; + } + + len_rd = sizeof(sub); + net_idx = strtol(name, NULL, 16); + sub = bt_mesh_cdb_subnet_get(net_idx); + + if (len_rd == 0) { + BT_DBG("val (null)"); + if (!sub) { + BT_ERR("No subnet with NetKeyIndex 0x%03x", net_idx); + return -ENOENT; + } + + BT_DBG("Deleting NetKeyIndex 0x%03x", net_idx); + bt_mesh_cdb_subnet_del(sub, false); + return 0; + } + + len = sizeof(key); + err = settings_bytes_from_str(name, &key, &len); + if (err) { + BT_ERR("Failed to set \'net-key\'"); + return err; + } + + if (sub) { + BT_DBG("Updating existing NetKeyIndex 0x%03x", net_idx); + + sub->kr_flag = key.kr_flag; + sub->kr_phase = key.kr_phase; + memcpy(sub->keys[0].net_key, &key.val[0], 16); + memcpy(sub->keys[1].net_key, &key.val[1], 16); + + return 0; + } + + sub = bt_mesh_cdb_subnet_alloc(net_idx); + if (!sub) { + BT_ERR("No space to allocate a new subnet"); + return -ENOMEM; + } + + sub->kr_flag = key.kr_flag; + sub->kr_phase = key.kr_phase; + memcpy(sub->keys[0].net_key, &key.val[0], 16); + memcpy(sub->keys[1].net_key, &key.val[1], 16); + + BT_DBG("NetKeyIndex 0x%03x recovered from storage", net_idx); + + return 0; +} + +static int cdb_app_key_set(int argc, char *name) +{ + struct bt_mesh_cdb_app_key *app; + struct app_key_val key; + uint16_t app_idx; + int len_rd, err; + + app_idx = strtol(name, NULL, 16); + len_rd = sizeof(key); + + if (len_rd == 0) { + BT_DBG("val (null)"); + BT_DBG("Deleting AppKeyIndex 0x%03x", app_idx); + + app = bt_mesh_cdb_app_key_get(app_idx); + if (app) { + bt_mesh_cdb_app_key_del(app, false); + } + + return 0; + } + + err = settings_bytes_from_str(name, &key, &len_rd); + if (err) { + BT_ERR("Failed to set \'app-key\'"); + return err; + } + + app = bt_mesh_cdb_app_key_get(app_idx); + if (!app) { + app = bt_mesh_cdb_app_key_alloc(key.net_idx, app_idx); + } + + if (!app) { + BT_ERR("No space for a new app key"); + return -ENOMEM; + } + + memcpy(app->keys[0].app_key, key.val[0], 16); + memcpy(app->keys[1].app_key, key.val[1], 16); + + BT_DBG("AppKeyIndex 0x%03x recovered from storage", app_idx); + + return 0; +} + +static int cdb_set(int argc, char **argv, char *name) +{ + int len; + char *next; + + if (argc < 1) { + BT_ERR("Insufficient number of arguments"); + return -ENOENT; + } + + if (!strcmp(name, "Net")) { + return cdb_net_set(1, name); + } + + + len = settings_name_next(name, &next); + + if (!next) { + BT_ERR("Insufficient number of arguments"); + return -ENOENT; + } + + if (!strncmp(name, "Node", len)) { + return cdb_node_set(1, next); + } + + if (!strncmp(name, "Subnet", len)) { + return cdb_subnet_set(1, next); + } + + if (!strncmp(name, "AppKey", len)) { + return cdb_app_key_set(1, next); + } + + BT_WARN("Unknown module key %s", name); + return -ENOENT; +} #endif const struct mesh_setting { @@ -831,8 +958,8 @@ const struct mesh_setting { #if CONFIG_BT_MESH_LABEL_COUNT > 0 { "Va", va_set }, #endif -#if MYNEWT_VAL(BLE_MESH_PROVISIONER) - { "Node", node_set }, +#if MYNEWT_VAL(BLE_MESH_CDB) + { "cdb", cdb_set }, #endif }; @@ -861,43 +988,12 @@ static int mesh_set(int argc, char **argv, char *val) return -ENOENT; } -static int subnet_init(struct bt_mesh_subnet *sub) -{ - int err; - - err = bt_mesh_net_keys_create(&sub->keys[0], sub->keys[0].net); - if (err) { - BT_ERR("Unable to generate keys for subnet"); - return -EIO; - } - - if (sub->kr_phase != BT_MESH_KR_NORMAL) { - err = bt_mesh_net_keys_create(&sub->keys[1], sub->keys[1].net); - if (err) { - BT_ERR("Unable to generate keys for subnet"); - memset(&sub->keys[0], 0, sizeof(sub->keys[0])); - return -EIO; - } - } - - if (IS_ENABLED(CONFIG_BT_MESH_GATT_PROXY)) { - sub->node_id = BT_MESH_NODE_IDENTITY_STOPPED; - } else { - sub->node_id = BT_MESH_NODE_IDENTITY_NOT_SUPPORTED; - } - - /* Make sure we have valid beacon data to be sent */ - bt_mesh_net_beacon_update(sub); - - return 0; -} - static void commit_mod(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, bool vnd, bool primary, void *user_data) { if (mod->pub && mod->pub->update && mod->pub->addr != BT_MESH_ADDR_UNASSIGNED) { - s32_t ms = bt_mesh_model_pub_period_get(mod); + int32_t ms = bt_mesh_model_pub_period_get(mod); if (ms) { BT_DBG("Starting publish timer (period %u ms)", (unsigned) ms); @@ -905,20 +1001,20 @@ static void commit_mod(struct bt_mesh_model *mod, struct bt_mesh_elem *elem, } } - if (mod->cb && mod->cb->settings_commit) { - mod->cb->settings_commit(mod); + if (!IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) { + return; + } + + for (int i = 0; i < ARRAY_SIZE(mod->groups); i++) { + if (mod->groups[i] != BT_MESH_ADDR_UNASSIGNED) { + bt_mesh_lpn_group_add(mod->groups[i]); + } } } static int mesh_commit(void) { - struct bt_mesh_hb_pub *hb_pub; - struct bt_mesh_cfg_srv *cfg; - int i; - - BT_DBG("sub[0].net_idx 0x%03x", bt_mesh.sub[0].net_idx); - - if (bt_mesh.sub[0].net_idx == BT_MESH_KEY_UNUSED) { + if (!bt_mesh_subnet_next(NULL)) { /* Nothing to do since we're not yet provisioned */ return 0; } @@ -927,47 +1023,15 @@ static int mesh_commit(void) bt_mesh_proxy_prov_disable(true); } - for (i = 0; i < ARRAY_SIZE(bt_mesh.sub); i++) { - struct bt_mesh_subnet *sub = &bt_mesh.sub[i]; - int err; - - if (sub->net_idx == BT_MESH_KEY_UNUSED) { - continue; - } - - err = subnet_init(sub); - if (err) { - BT_ERR("Failed to init subnet 0x%03x", sub->net_idx); - } - } - if (bt_mesh.ivu_duration < BT_MESH_IVU_MIN_HOURS) { k_delayed_work_submit(&bt_mesh.ivu_timer, BT_MESH_IVU_TIMEOUT); } bt_mesh_model_foreach(commit_mod, NULL); - hb_pub = bt_mesh_hb_pub_get(); - if (hb_pub && hb_pub->dst != BT_MESH_ADDR_UNASSIGNED && - hb_pub->count && hb_pub->period) { - BT_DBG("Starting heartbeat publication"); - k_work_submit(&hb_pub->timer.work); - } - - cfg = bt_mesh_cfg_get(); - if (cfg && stored_cfg.valid) { - cfg->net_transmit = stored_cfg.cfg.net_transmit; - cfg->relay = stored_cfg.cfg.relay; - cfg->relay_retransmit = stored_cfg.cfg.relay_retransmit; - cfg->beacon = stored_cfg.cfg.beacon; - cfg->gatt_proxy = stored_cfg.cfg.gatt_proxy; - cfg->frnd = stored_cfg.cfg.frnd; - cfg->default_ttl = stored_cfg.cfg.default_ttl; - } - atomic_set_bit(bt_mesh.flags, BT_MESH_VALID); - bt_mesh_net_start(); + bt_mesh_start(); return 0; } @@ -981,12 +1045,11 @@ static int mesh_commit(void) #define GENERIC_PENDING_BITS (BIT(BT_MESH_KEYS_PENDING) | \ BIT(BT_MESH_HB_PUB_PENDING) | \ BIT(BT_MESH_CFG_PENDING) | \ - BIT(BT_MESH_MOD_PENDING) | \ - BIT(BT_MESH_NODES_PENDING)) + BIT(BT_MESH_MOD_PENDING)) static void schedule_store(int flag) { - s32_t timeout, remaining; + int32_t timeout, remaining; atomic_set_bit(bt_mesh.flags, flag); @@ -1112,9 +1175,7 @@ static void store_pending_seq(void) char *str; int err; - seq.val[0] = bt_mesh.seq; - seq.val[1] = bt_mesh.seq >> 8; - seq.val[2] = bt_mesh.seq >> 16; + sys_put_le24(bt_mesh.seq, seq.val); str = settings_str_from_bytes(&seq, sizeof(seq), buf, sizeof(buf)); if (!str) { @@ -1172,69 +1233,54 @@ static void store_rpl(struct bt_mesh_rpl *entry) } } -static void clear_rpl(void) +static void clear_rpl(struct bt_mesh_rpl *rpl, void *user_data) { - int i, err; + int err; + char path[18]; - BT_DBG(""); - - for (i = 0; i < ARRAY_SIZE(bt_mesh.rpl); i++) { - struct bt_mesh_rpl *rpl = &bt_mesh.rpl[i]; - char path[18]; - - if (!rpl->src) { - continue; - } - - snprintk(path, sizeof(path), "bt_mesh/RPL/%x", rpl->src); - err = settings_save_one(path, NULL); - if (err) { - BT_ERR("Failed to clear RPL"); - } else { - BT_DBG("Cleared RPL"); - } - - memset(rpl, 0, sizeof(*rpl)); + if (!rpl->src) { + return; } + + snprintk(path, sizeof(path), "bt/mesh/RPL/%x", rpl->src); + err = settings_save_one(path, NULL); + if (err) { + BT_ERR("Failed to clear RPL"); + } else { + BT_DBG("Cleared RPL"); + } + + (void)memset(rpl, 0, sizeof(*rpl)); } -static void store_pending_rpl(void) +static void store_pending_rpl(struct bt_mesh_rpl *rpl, void *user_data) { - int i; - BT_DBG(""); - for (i = 0; i < ARRAY_SIZE(bt_mesh.rpl); i++) { - struct bt_mesh_rpl *rpl = &bt_mesh.rpl[i]; - - if (rpl->store) { - rpl->store = false; - store_rpl(rpl); - } + if (rpl->store) { + rpl->store = false; + store_rpl(rpl); } } static void store_pending_hb_pub(void) { char buf[BT_SETTINGS_SIZE(sizeof(struct hb_pub_val))]; - struct bt_mesh_hb_pub *pub = bt_mesh_hb_pub_get(); + struct bt_mesh_hb_pub pub; struct hb_pub_val val; char *str; int err; - if (!pub) { - return; - } - - if (pub->dst == BT_MESH_ADDR_UNASSIGNED) { + bt_mesh_hb_pub_get(&pub); + if (pub.dst == BT_MESH_ADDR_UNASSIGNED) { str = NULL; } else { - val.indefinite = (pub->count == 0xffff); - val.dst = pub->dst; - val.period = pub->period; - val.ttl = pub->ttl; - val.feat = pub->feat; - val.net_idx = pub->net_idx; + val.indefinite = (pub.count == 0xffff); + val.dst = pub.dst; + val.period = bt_mesh_hb_log(pub.period); + val.ttl = pub.ttl; + val.feat = pub.feat; + val.net_idx = pub.net_idx; str = settings_str_from_bytes(&val, sizeof(val), buf, sizeof(buf)); @@ -1257,22 +1303,17 @@ static void store_pending_hb_pub(void) static void store_pending_cfg(void) { char buf[BT_SETTINGS_SIZE(sizeof(struct cfg_val))]; - struct bt_mesh_cfg_srv *cfg = bt_mesh_cfg_get(); struct cfg_val val; char *str; int err; - if (!cfg) { - return; - } - - val.net_transmit = cfg->net_transmit; - val.relay = cfg->relay; - val.relay_retransmit = cfg->relay_retransmit; - val.beacon = cfg->beacon; - val.gatt_proxy = cfg->gatt_proxy; - val.frnd = cfg->frnd; - val.default_ttl = cfg->default_ttl; + val.net_transmit = bt_mesh_net_transmit_get(); + val.relay = bt_mesh_relay_get(); + val.relay_retransmit = bt_mesh_relay_retransmit_get(); + val.beacon = bt_mesh_beacon_enabled(); + val.gatt_proxy = bt_mesh_gatt_proxy_get(); + val.frnd = bt_mesh_friend_get(); + val.default_ttl = bt_mesh_default_ttl_get(); str = settings_str_from_bytes(&val, sizeof(val), buf, sizeof(buf)); if (!str) { @@ -1301,7 +1342,7 @@ static void clear_cfg(void) } } -static void clear_app_key(u16_t app_idx) +static void clear_app_key(uint16_t app_idx) { char path[20]; int err; @@ -1317,7 +1358,7 @@ static void clear_app_key(u16_t app_idx) } } -static void clear_net_key(u16_t net_idx) +static void clear_net_key(uint16_t net_idx) { char path[20]; int err; @@ -1333,31 +1374,36 @@ static void clear_net_key(u16_t net_idx) } } -static void store_net_key(struct bt_mesh_subnet *sub) +static void store_subnet(uint16_t net_idx) { - char buf[BT_SETTINGS_SIZE(sizeof(struct net_key_val))]; + const struct bt_mesh_subnet *sub; struct net_key_val key; + char buf[BT_SETTINGS_SIZE(sizeof(struct app_key_val))]; char path[20]; char *str; int err; - BT_DBG("NetKeyIndex 0x%03x NetKey %s", sub->net_idx, - bt_hex(sub->keys[0].net, 16)); + sub = bt_mesh_subnet_get(net_idx); + if (!sub) { + BT_WARN("NetKeyIndex 0x%03x not found", net_idx); + return; + } + + BT_DBG("NetKeyIndex 0x%03x", net_idx); + + snprintk(path, sizeof(path), "bt/mesh/NetKey/%x", net_idx); memcpy(&key.val[0], sub->keys[0].net, 16); memcpy(&key.val[1], sub->keys[1].net, 16); - key.kr_flag = sub->kr_flag; + key.kr_flag = 0U; /* Deprecated */ key.kr_phase = sub->kr_phase; str = settings_str_from_bytes(&key, sizeof(key), buf, sizeof(buf)); if (!str) { - BT_ERR("Unable to encode NetKey as value"); + BT_ERR("Unable to encode AppKey as value"); return; } - snprintk(path, sizeof(path), "bt_mesh/NetKey/%x", sub->net_idx); - - BT_DBG("Saving NetKey %s as value %s", path, str); err = settings_save_one(path, str); if (err) { BT_ERR("Failed to store NetKey"); @@ -1366,16 +1412,26 @@ static void store_net_key(struct bt_mesh_subnet *sub) } } -static void store_app_key(struct bt_mesh_app_key *app) +static void store_app(uint16_t app_idx) { + const struct bt_mesh_app_key *app; char buf[BT_SETTINGS_SIZE(sizeof(struct app_key_val))]; struct app_key_val key; char path[20]; char *str; int err; - key.net_idx = app->net_idx; - key.updated = app->updated; + snprintk(path, sizeof(path), "bt/mesh/AppKey/%x", app_idx); + + app = bt_mesh_app_key_get(app_idx); + if (!app) { + BT_WARN("ApKeyIndex 0x%03x not found", app_idx); + return; + } + + key.net_idx = app->net_idx, + key.updated = app->updated, + memcpy(key.val[0], app->keys[0].val, 16); memcpy(key.val[1], app->keys[1].val, 16); @@ -1414,47 +1470,71 @@ static void store_pending_keys(void) clear_net_key(update->key_idx); } } else { - if (update->app_key) { - struct bt_mesh_app_key *key; - - key = bt_mesh_app_key_find(update->key_idx); - if (key) { - store_app_key(key); - } else { - BT_WARN("AppKeyIndex 0x%03x not found", - update->key_idx); - } - - } else { - struct bt_mesh_subnet *sub; - - sub = bt_mesh_subnet_get(update->key_idx); - if (sub) { - store_net_key(sub); - } else { - BT_WARN("NetKeyIndex 0x%03x not found", - update->key_idx); - } - } + store_subnet(update->key_idx); } update->valid = 0; } } -static void store_node(struct bt_mesh_node *node) +static void clear_cdb(void) +{ + int err; + + err = settings_save_one("bt/mesh/cdb/Net", NULL); + if (err) { + BT_ERR("Failed to clear Network"); + } else { + BT_DBG("Cleared Network"); + } +} + +static void store_pending_cdb(void) +{ + char buf[BT_SETTINGS_SIZE(sizeof(struct cdb_net_val))]; + struct cdb_net_val net; + int err; + char *str; + + BT_DBG(""); + + net.iv_index = bt_mesh_cdb.iv_index; + net.iv_update = atomic_test_bit(bt_mesh_cdb.flags, + BT_MESH_CDB_IVU_IN_PROGRESS); + + str = settings_str_from_bytes(&net, sizeof(net), buf, sizeof(buf)); + if (!str) { + BT_ERR("Unable to encode Network as value"); + return; + } + err = settings_save_one("bt/mesh/cdb/Net", str); + if (err) { + BT_ERR("Failed to store Network value"); + } else { + BT_DBG("Stored Network value"); + } +} + +static void store_cdb_node(const struct bt_mesh_cdb_node *node) { char buf[BT_SETTINGS_SIZE(sizeof(struct node_val))]; struct node_val val; - char path[20]; + char path[30]; char *str; int err; val.net_idx = node->net_idx; val.num_elem = node->num_elem; + val.flags = 0; + + if (atomic_test_bit(node->flags, BT_MESH_CDB_NODE_CONFIGURED)) { + val.flags |= F_NODE_CONFIGURED; + } + + memcpy(val.uuid, node->uuid, 16); memcpy(val.dev_key, node->dev_key, 16); - snprintk(path, sizeof(path), "bt_mesh/Node/%x", node->addr); + snprintk(path, sizeof(path), "bt/mesh/cdb/Node/%x", node->addr); str = settings_str_from_bytes(&val, sizeof(val), buf, sizeof(buf)); if (!str) { @@ -1471,14 +1551,14 @@ static void store_node(struct bt_mesh_node *node) } } -static void clear_node(u16_t addr) +static void clear_cdb_node(uint16_t addr) { - char path[20]; + char path[30]; int err; BT_DBG("Node 0x%04x", addr); - snprintk(path, sizeof(path), "bt_mesh/Node/%x", addr); + snprintk(path, sizeof(path), "bt/mesh/cdb/Node/%x", addr); err = settings_save_one(path, NULL); if (err) { BT_ERR("Failed to clear Node 0x%04x", addr); @@ -1487,25 +1567,27 @@ static void clear_node(u16_t addr) } } -static void store_pending_nodes(void) +static void store_pending_cdb_nodes(void) { int i; - for (i = 0; i < ARRAY_SIZE(node_updates); ++i) { - struct node_update *update = &node_updates[i]; + for (i = 0; i < ARRAY_SIZE(cdb_node_updates); ++i) { + struct node_update *update = &cdb_node_updates[i]; if (update->addr == BT_MESH_ADDR_UNASSIGNED) { continue; } - if (update->clear) { - clear_node(update->addr); - } else { - struct bt_mesh_node *node; + BT_DBG("addr: 0x%04x, clear: %d", update->addr, update->clear); - node = bt_mesh_node_find(update->addr); + if (update->clear) { + clear_cdb_node(update->addr); + } else { + struct bt_mesh_cdb_node *node; + + node = bt_mesh_cdb_node_get(update->addr); if (node) { - store_node(node); + store_cdb_node(node); } else { BT_WARN("Node 0x%04x not found", update->addr); } @@ -1515,8 +1597,139 @@ static void store_pending_nodes(void) } } -static struct node_update *node_update_find(u16_t addr, - struct node_update **free_slot) +static void store_cdb_subnet(const struct bt_mesh_cdb_subnet *sub) +{ + char buf[BT_SETTINGS_SIZE(sizeof(struct net_key_val))]; + struct net_key_val key; + char path[30]; + int err; + char *str; + + BT_DBG("NetKeyIndex 0x%03x NetKey %s", sub->net_idx, + bt_hex(sub->keys[0].net_key, 16)); + + memcpy(&key.val[0], sub->keys[0].net_key, 16); + memcpy(&key.val[1], sub->keys[1].net_key, 16); + key.kr_flag = sub->kr_flag; + key.kr_phase = sub->kr_phase; + + snprintk(path, sizeof(path), "bt/mesh/cdb/Subnet/%x", sub->net_idx); + + + str = settings_str_from_bytes(&key, sizeof(key), buf, sizeof(buf)); + if (!str) { + BT_ERR("Unable to encode Subnet as value"); + return; + } + err = settings_save_one(path, str); + if (err) { + BT_ERR("Failed to store Subnet value"); + } else { + BT_DBG("Stored Subnet value"); + } +} + +static void clear_cdb_subnet(uint16_t net_idx) +{ + char path[30]; + int err; + + BT_DBG("NetKeyIndex 0x%03x", net_idx); + + snprintk(path, sizeof(path), "bt/mesh/cdb/Subnet/%x", net_idx); + err = settings_save_one(path, NULL); + if (err) { + BT_ERR("Failed to clear NetKeyIndex 0x%03x", net_idx); + } else { + BT_DBG("Cleared NetKeyIndex 0x%03x", net_idx); + } +} + +static void store_cdb_app_key(const struct bt_mesh_cdb_app_key *app) +{ + char buf[BT_SETTINGS_SIZE(sizeof(struct app_key_val))]; + struct app_key_val key; + char path[30]; + int err; + char *str; + + key.net_idx = app->net_idx; + key.updated = false; + memcpy(key.val[0], app->keys[0].app_key, 16); + memcpy(key.val[1], app->keys[1].app_key, 16); + + snprintk(path, sizeof(path), "bt/mesh/cdb/AppKey/%x", app->app_idx); + + str = settings_str_from_bytes(&key, sizeof(key), buf, sizeof(buf)); + err = settings_save_one(path, str); + if (err) { + BT_ERR("Failed to store AppKey"); + } else { + BT_DBG("Stored AppKey"); + } +} + +static void clear_cdb_app_key(uint16_t app_idx) +{ + char path[30]; + int err; + + snprintk(path, sizeof(path), "bt/mesh/cdb/AppKey/%x", app_idx); + err = settings_save_one(path, NULL); + if (err) { + BT_ERR("Failed to clear AppKeyIndex 0x%03x", app_idx); + } else { + BT_DBG("Cleared AppKeyIndex 0x%03x", app_idx); + } +} + +static void store_pending_cdb_keys(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(cdb_key_updates); i++) { + struct key_update *update = &cdb_key_updates[i]; + + if (!update->valid) { + continue; + } + + if (update->clear) { + if (update->app_key) { + clear_cdb_app_key(update->key_idx); + } else { + clear_cdb_subnet(update->key_idx); + } + } else { + if (update->app_key) { + struct bt_mesh_cdb_app_key *key; + + key = bt_mesh_cdb_app_key_get(update->key_idx); + if (key) { + store_cdb_app_key(key); + } else { + BT_WARN("AppKeyIndex 0x%03x not found", + update->key_idx); + } + } else { + struct bt_mesh_cdb_subnet *sub; + + sub = bt_mesh_cdb_subnet_get(update->key_idx); + if (sub) { + store_cdb_subnet(sub); + } else { + BT_WARN("NetKeyIndex 0x%03x not found", + update->key_idx); + } + } + } + + update->valid = 0U; + } +} + +static struct node_update *cdb_node_update_find(uint16_t addr, + struct node_update **free_slot) { struct node_update *match; int i; @@ -1524,8 +1737,8 @@ static struct node_update *node_update_find(u16_t addr, match = NULL; *free_slot = NULL; - for (i = 0; i < ARRAY_SIZE(node_updates); i++) { - struct node_update *update = &node_updates[i]; + for (i = 0; i < ARRAY_SIZE(cdb_node_updates); i++) { + struct node_update *update = &cdb_node_updates[i]; if (update->addr == BT_MESH_ADDR_UNASSIGNED) { *free_slot = update; @@ -1543,7 +1756,7 @@ static struct node_update *node_update_find(u16_t addr, static void encode_mod_path(struct bt_mesh_model *mod, bool vnd, const char *key, char *path, size_t path_len) { - u16_t mod_key = (((u16_t)mod->elem_idx << 8) | mod->mod_idx); + uint16_t mod_key = (((uint16_t)mod->elem_idx << 8) | mod->mod_idx); if (vnd) { snprintk(path, path_len, "bt_mesh/v/%x/%s", mod_key, key); @@ -1554,7 +1767,7 @@ static void encode_mod_path(struct bt_mesh_model *mod, bool vnd, static void store_pending_mod_bind(struct bt_mesh_model *mod, bool vnd) { - u16_t keys[CONFIG_BT_MESH_MODEL_KEY_COUNT]; + uint16_t keys[CONFIG_BT_MESH_MODEL_KEY_COUNT]; char buf[BT_SETTINGS_SIZE(sizeof(keys))]; char path[20]; int i, count, err; @@ -1590,7 +1803,7 @@ static void store_pending_mod_bind(struct bt_mesh_model *mod, bool vnd) static void store_pending_mod_sub(struct bt_mesh_model *mod, bool vnd) { - u16_t groups[CONFIG_BT_MESH_MODEL_GROUP_COUNT]; + uint16_t groups[CONFIG_BT_MESH_MODEL_GROUP_COUNT]; char buf[BT_SETTINGS_SIZE(sizeof(groups))]; char path[20]; int i, count, err; @@ -1690,19 +1903,20 @@ static void store_pending_mod(struct bt_mesh_model *mod, static void store_pending_va(void) { char buf[BT_SETTINGS_SIZE(sizeof(struct va_val))]; - struct label *lab; + struct bt_mesh_va *lab; struct va_val va; char path[18]; char *val; - u16_t i; + uint16_t i; int err = 0; - for (i = 0; (lab = get_label(i)) != NULL; i++) { - if (!atomic_test_and_clear_bit(lab->flags, - BT_MESH_VA_CHANGED)) { + for (i = 0; (lab = bt_mesh_va_get(i)) != NULL; i++) { + if (!lab->changed) { continue; } + lab->changed = 0U; + snprintk(path, sizeof(path), "bt_mesh/Va/%x", i); if (IS_VA_DEL(lab)) { @@ -1738,9 +1952,9 @@ static void store_pending(struct ble_npl_event *work) if (atomic_test_and_clear_bit(bt_mesh.flags, BT_MESH_RPL_PENDING)) { if (atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) { - store_pending_rpl(); + bt_mesh_rpl_foreach(store_pending_rpl, NULL); } else { - clear_rpl(); + bt_mesh_rpl_foreach(clear_rpl, NULL); } } @@ -1788,9 +2002,26 @@ static void store_pending(struct ble_npl_event *work) store_pending_va(); } - if (IS_ENABLED(CONFIG_BT_MESH_PROVISIONER) && - atomic_test_and_clear_bit(bt_mesh.flags, BT_MESH_NODES_PENDING)) { - store_pending_nodes(); + if (IS_ENABLED(CONFIG_BT_MESH_CDB)) { + if (atomic_test_and_clear_bit(bt_mesh_cdb.flags, + BT_MESH_CDB_SUBNET_PENDING)) { + if (atomic_test_bit(bt_mesh_cdb.flags, + BT_MESH_CDB_VALID)) { + store_pending_cdb(); + } else { + clear_cdb(); + } + } + + if (atomic_test_and_clear_bit(bt_mesh_cdb.flags, + BT_MESH_CDB_NODES_PENDING)) { + store_pending_cdb_nodes(); + } + + if (atomic_test_and_clear_bit(bt_mesh_cdb.flags, + BT_MESH_CDB_KEYS_PENDING)) { + store_pending_cdb_keys(); + } } } @@ -1800,7 +2031,7 @@ void bt_mesh_store_rpl(struct bt_mesh_rpl *entry) schedule_store(BT_MESH_RPL_PENDING); } -static struct key_update *key_update_find(bool app_key, u16_t key_idx, +static struct key_update *key_update_find(bool app_key, uint16_t key_idx, struct key_update **free_slot) { struct key_update *match; @@ -1829,13 +2060,13 @@ static struct key_update *key_update_find(bool app_key, u16_t key_idx, return match; } -void bt_mesh_store_subnet(struct bt_mesh_subnet *sub) +void bt_mesh_store_subnet(uint16_t net_idx) { struct key_update *update, *free_slot; - BT_DBG("NetKeyIndex 0x%03x", sub->net_idx); + BT_DBG("NetKeyIndex 0x%03x", net_idx); - update = key_update_find(false, sub->net_idx, &free_slot); + update = key_update_find(false, net_idx, &free_slot); if (update) { update->clear = 0; schedule_store(BT_MESH_KEYS_PENDING); @@ -1843,25 +2074,25 @@ void bt_mesh_store_subnet(struct bt_mesh_subnet *sub) } if (!free_slot) { - store_net_key(sub); + store_subnet(net_idx); return; } free_slot->valid = 1; - free_slot->key_idx = sub->net_idx; + free_slot->key_idx = net_idx; free_slot->app_key = 0; free_slot->clear = 0; schedule_store(BT_MESH_KEYS_PENDING); } -void bt_mesh_store_app_key(struct bt_mesh_app_key *key) +void bt_mesh_store_app_key(uint16_t app_idx) { struct key_update *update, *free_slot; - BT_DBG("AppKeyIndex 0x%03x", key->app_idx); + BT_DBG("AppKeyIndex 0x%03x", app_idx); - update = key_update_find(true, key->app_idx, &free_slot); + update = key_update_find(true, app_idx, &free_slot); if (update) { update->clear = 0; schedule_store(BT_MESH_KEYS_PENDING); @@ -1869,12 +2100,12 @@ void bt_mesh_store_app_key(struct bt_mesh_app_key *key) } if (!free_slot) { - store_app_key(key); + store_app(app_idx); return; } free_slot->valid = 1; - free_slot->key_idx = key->app_idx; + free_slot->key_idx = app_idx; free_slot->app_key = 1; free_slot->clear = 0; @@ -1898,13 +2129,13 @@ void bt_mesh_clear_net(void) schedule_store(BT_MESH_CFG_PENDING); } -void bt_mesh_clear_subnet(struct bt_mesh_subnet *sub) +void bt_mesh_clear_subnet(uint16_t net_idx) { struct key_update *update, *free_slot; - BT_DBG("NetKeyIndex 0x%03x", sub->net_idx); + BT_DBG("NetKeyIndex 0x%03x", net_idx); - update = key_update_find(false, sub->net_idx, &free_slot); + update = key_update_find(false, net_idx, &free_slot); if (update) { update->clear = 1; schedule_store(BT_MESH_KEYS_PENDING); @@ -1912,25 +2143,25 @@ void bt_mesh_clear_subnet(struct bt_mesh_subnet *sub) } if (!free_slot) { - clear_net_key(sub->net_idx); + clear_net_key(net_idx); return; } free_slot->valid = 1; - free_slot->key_idx = sub->net_idx; + free_slot->key_idx = net_idx; free_slot->app_key = 0; free_slot->clear = 1; schedule_store(BT_MESH_KEYS_PENDING); } -void bt_mesh_clear_app_key(struct bt_mesh_app_key *key) +void bt_mesh_clear_app_key(uint16_t app_idx) { struct key_update *update, *free_slot; - BT_DBG("AppKeyIndex 0x%03x", key->app_idx); + BT_DBG("AppKeyIndex 0x%03x", app_idx); - update = key_update_find(true, key->app_idx, &free_slot); + update = key_update_find(true, app_idx, &free_slot); if (update) { update->clear = 1; schedule_store(BT_MESH_KEYS_PENDING); @@ -1938,12 +2169,12 @@ void bt_mesh_clear_app_key(struct bt_mesh_app_key *key) } if (!free_slot) { - clear_app_key(key->app_idx); + clear_app_key(app_idx); return; } free_slot->valid = 1; - free_slot->key_idx = key->app_idx; + free_slot->key_idx = app_idx; free_slot->app_key = 1; free_slot->clear = 1; @@ -1979,64 +2210,215 @@ void bt_mesh_store_label(void) schedule_store(BT_MESH_VA_PENDING); } -void bt_mesh_store_node(struct bt_mesh_node *node) +static void schedule_cdb_store(int flag) { - struct node_update *update, *free_slot; - - BT_DBG("Node 0x%04x", node->addr); - - update = node_update_find(node->addr, &free_slot); - if (update) { - update->clear = false; - schedule_store(BT_MESH_NODES_PENDING); - return; - } - - if (!free_slot) { - store_node(node); - return; - } - - free_slot->addr = node->addr; - - schedule_store(BT_MESH_NODES_PENDING); + atomic_set_bit(bt_mesh_cdb.flags, flag); + k_delayed_work_submit(&pending_store, K_NO_WAIT); } -void bt_mesh_clear_node(struct bt_mesh_node *node) +void bt_mesh_store_cdb(void) +{ + schedule_cdb_store(BT_MESH_CDB_SUBNET_PENDING); +} + +void bt_mesh_store_cdb_node(const struct bt_mesh_cdb_node *node) { struct node_update *update, *free_slot; BT_DBG("Node 0x%04x", node->addr); - update = node_update_find(node->addr, &free_slot); + update = cdb_node_update_find(node->addr, &free_slot); if (update) { - update->clear = true; - schedule_store(BT_MESH_NODES_PENDING); + update->clear = false; + schedule_cdb_store(BT_MESH_CDB_NODES_PENDING); return; } if (!free_slot) { - clear_node(node->addr); + store_cdb_node(node); return; } free_slot->addr = node->addr; + free_slot->clear = false; - schedule_store(BT_MESH_NODES_PENDING); + schedule_cdb_store(BT_MESH_CDB_NODES_PENDING); +} + +void bt_mesh_clear_cdb_node(struct bt_mesh_cdb_node *node) +{ + struct node_update *update, *free_slot; + + BT_DBG("Node 0x%04x", node->addr); + + update = cdb_node_update_find(node->addr, &free_slot); + if (update) { + update->clear = true; + schedule_cdb_store(BT_MESH_CDB_NODES_PENDING); + return; + } + + if (!free_slot) { + clear_cdb_node(node->addr); + return; + } + + free_slot->addr = node->addr; + free_slot->clear = true; + + schedule_cdb_store(BT_MESH_CDB_NODES_PENDING); +} + +/* TODO: Could be shared with key_update_find? */ +static struct key_update *cdb_key_update_find(bool app_key, uint16_t key_idx, + struct key_update **free_slot) +{ + struct key_update *match; + int i; + + match = NULL; + *free_slot = NULL; + + for (i = 0; i < ARRAY_SIZE(cdb_key_updates); i++) { + struct key_update *update = &cdb_key_updates[i]; + + if (!update->valid) { + *free_slot = update; + continue; + } + + if (update->app_key != app_key) { + continue; + } + + if (update->key_idx == key_idx) { + match = update; + } + } + + return match; +} + +void bt_mesh_store_cdb_subnet(const struct bt_mesh_cdb_subnet *sub) +{ + struct key_update *update, *free_slot; + + BT_DBG("NetKeyIndex 0x%03x", sub->net_idx); + + update = cdb_key_update_find(false, sub->net_idx, &free_slot); + if (update) { + update->clear = 0U; + schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING); + return; + } + + if (!free_slot) { + store_cdb_subnet(sub); + return; + } + + free_slot->valid = 1U; + free_slot->key_idx = sub->net_idx; + free_slot->app_key = 0U; + free_slot->clear = 0U; + + schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING); +} + +void bt_mesh_clear_cdb_subnet(struct bt_mesh_cdb_subnet *sub) +{ + struct key_update *update, *free_slot; + + BT_DBG("NetKeyIndex 0x%03x", sub->net_idx); + + update = cdb_key_update_find(false, sub->net_idx, &free_slot); + if (update) { + update->clear = 1U; + schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING); + return; + } + + if (!free_slot) { + clear_cdb_subnet(sub->net_idx); + return; + } + + free_slot->valid = 1U; + free_slot->key_idx = sub->net_idx; + free_slot->app_key = 0U; + free_slot->clear = 1U; + + schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING); +} + +void bt_mesh_store_cdb_app_key(const struct bt_mesh_cdb_app_key *key) +{ + struct key_update *update, *free_slot; + + BT_DBG("AppKeyIndex 0x%03x", key->app_idx); + + update = cdb_key_update_find(true, key->app_idx, &free_slot); + if (update) { + update->clear = 0U; + schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING); + return; + } + + if (!free_slot) { + store_cdb_app_key(key); + return; + } + + free_slot->valid = 1U; + free_slot->key_idx = key->app_idx; + free_slot->app_key = 1U; + free_slot->clear = 0U; + + schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING); +} + +void bt_mesh_clear_cdb_app_key(struct bt_mesh_cdb_app_key *key) +{ + struct key_update *update, *free_slot; + + BT_DBG("AppKeyIndex 0x%03x", key->app_idx); + + update = cdb_key_update_find(true, key->app_idx, &free_slot); + if (update) { + update->clear = 1U; + schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING); + return; + } + + if (!free_slot) { + clear_cdb_app_key(key->app_idx); + return; + } + + free_slot->valid = 1U; + free_slot->key_idx = key->app_idx; + free_slot->app_key = 1U; + free_slot->clear = 1U; + + schedule_cdb_store(BT_MESH_CDB_KEYS_PENDING); } 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) { - char path[20]; + char path[30]; char buf[BT_SETTINGS_SIZE(sizeof(struct mod_pub_val))]; char *val; int err; encode_mod_path(mod, vnd, "data", path, sizeof(path)); + if (name) { + strcat(path, "/"); + strncat(path, name, 8); + } if (data_len) { - mod->flags |= BT_MESH_MOD_DATA_PRESENT; val = settings_str_from_bytes(data, data_len, buf, sizeof(buf)); if (!val) { @@ -2044,12 +2426,8 @@ int bt_mesh_model_data_store(struct bt_mesh_model *mod, bool vnd, return -EINVAL; } err = settings_save_one(path, val); - } else if (mod->flags & BT_MESH_MOD_DATA_PRESENT) { - mod->flags &= ~BT_MESH_MOD_DATA_PRESENT; - err = settings_save_one(path, NULL); } else { - /* Nothing to delete */ - err = 0; + err = settings_save_one(path, NULL); } if (err) { diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/settings.h b/src/libs/mynewt-nimble/nimble/host/mesh/src/settings.h index c630814e..9060a14a 100644 --- a/src/libs/mynewt-nimble/nimble/host/mesh/src/settings.h +++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/settings.h @@ -8,20 +8,25 @@ void bt_mesh_store_net(void); void bt_mesh_store_iv(bool only_duration); void bt_mesh_store_seq(void); void bt_mesh_store_rpl(struct bt_mesh_rpl *rpl); -void bt_mesh_store_subnet(struct bt_mesh_subnet *sub); -void bt_mesh_store_app_key(struct bt_mesh_app_key *key); +void bt_mesh_store_subnet(uint16_t net_idx); +void bt_mesh_store_app_key(uint16_t app_idx); void bt_mesh_store_hb_pub(void); void bt_mesh_store_cfg(void); void bt_mesh_store_mod_bind(struct bt_mesh_model *mod); void bt_mesh_store_mod_sub(struct bt_mesh_model *mod); void bt_mesh_store_mod_pub(struct bt_mesh_model *mod); void bt_mesh_store_label(void); -void bt_mesh_store_node(struct bt_mesh_node *node); +void bt_mesh_store_cdb(void); +void bt_mesh_store_cdb_node(const struct bt_mesh_cdb_node *node); +void bt_mesh_store_cdb_subnet(const struct bt_mesh_cdb_subnet *sub); +void bt_mesh_store_cdb_app_key(const struct bt_mesh_cdb_app_key *app); void bt_mesh_clear_net(void); -void bt_mesh_clear_subnet(struct bt_mesh_subnet *sub); -void bt_mesh_clear_app_key(struct bt_mesh_app_key *key); +void bt_mesh_clear_subnet(uint16_t net_idx); +void bt_mesh_clear_app_key(uint16_t app_idx); void bt_mesh_clear_rpl(void); -void bt_mesh_clear_node(struct bt_mesh_node *node); +void bt_mesh_clear_cdb_node(struct bt_mesh_cdb_node *node); +void bt_mesh_clear_cdb_subnet(struct bt_mesh_cdb_subnet *sub); +void bt_mesh_clear_cdb_app_key(struct bt_mesh_cdb_app_key *app); void bt_mesh_settings_init(void); diff --git a/src/libs/mynewt-nimble/nimble/host/mesh/src/shell.c b/src/libs/mynewt-nimble/nimble/host/mesh/src/shell.c index 91fbd978..d597ed6d 100644 --- a/src/libs/mynewt-nimble/nimble/host/mesh/src/shell.c +++ b/src/libs/mynewt-nimble/nimble/host/mesh/src/shell.c @@ -25,6 +25,7 @@ /* Private includes for raw Network & Transport layer access */ #include "net.h" +#include "rpl.h" #include "access.h" #include "mesh_priv.h" #include "lpn.h" @@ -55,50 +56,29 @@ static struct os_eventq mesh_shell_queue; #define VND_MODEL_ID_1 0x1234 /* Default net, app & dev key values, unless otherwise specified */ -static const u8_t default_key[16] = { +static const uint8_t default_key[16] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, }; static struct { - u16_t local; - u16_t dst; - u16_t net_idx; - u16_t app_idx; + uint16_t local; + uint16_t dst; + uint16_t net_idx; + uint16_t app_idx; } net = { .local = BT_MESH_ADDR_UNASSIGNED, .dst = BT_MESH_ADDR_UNASSIGNED, }; -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_DISABLED, -#else - .frnd = BT_MESH_FRIEND_NOT_SUPPORTED, -#endif -#if MYNEWT_VAL(BLE_MESH_GATT_PROXY) - .gatt_proxy = BT_MESH_GATT_PROXY_DISABLED, -#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), -}; - #define CUR_FAULTS_MAX 4 -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]; -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]) { @@ -108,8 +88,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) { printk("Sending current faults\n"); @@ -121,8 +101,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 cid, - u8_t *test_id, u8_t *faults, u8_t *fault_count) +static int fault_get_reg(struct bt_mesh_model *model, uint16_t cid, + uint8_t *test_id, uint8_t *faults, uint8_t *fault_count) { if (cid != CID_VENDOR) { printk("Faults requested for unknown Company ID 0x%04x\n", cid); @@ -189,7 +169,7 @@ static struct bt_mesh_cfg_cli cfg_cli = { #endif /* MYNEWT_VAL(BLE_MESH_CFG_CLI) */ #if MYNEWT_VAL(BLE_MESH_HEALTH_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; @@ -207,8 +187,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) { printk("Health Current Status from 0x%04x\n", addr); @@ -242,22 +222,22 @@ static struct bt_mesh_light_lightness_srv light_lightness_srv = { .set = light_model_light_lightness_set, }; -void bt_mesh_set_gen_onoff_srv_cb(int (*get)(struct bt_mesh_model *model, u8_t *state), - int (*set)(struct bt_mesh_model *model, u8_t state)) +void bt_mesh_set_gen_onoff_srv_cb(int (*get)(struct bt_mesh_model *model, uint8_t *state), + int (*set)(struct bt_mesh_model *model, uint8_t state)) { gen_onoff_srv.get = get; gen_onoff_srv.set = set; } -void bt_mesh_set_gen_level_srv_cb(int (*get)(struct bt_mesh_model *model, s16_t *level), - int (*set)(struct bt_mesh_model *model, s16_t level)) +void bt_mesh_set_gen_level_srv_cb(int (*get)(struct bt_mesh_model *model, int16_t *level), + int (*set)(struct bt_mesh_model *model, int16_t level)) { gen_level_srv.get = get; gen_level_srv.set = set; } -void bt_mesh_set_light_lightness_srv_cb(int (*get)(struct bt_mesh_model *model, s16_t *level), - int (*set)(struct bt_mesh_model *model, s16_t level)) +void bt_mesh_set_light_lightness_srv_cb(int (*get)(struct bt_mesh_model *model, int16_t *level), + int (*set)(struct bt_mesh_model *model, int16_t level)) { light_lightness_srv.get = get; light_lightness_srv.set = set; @@ -265,7 +245,7 @@ void bt_mesh_set_light_lightness_srv_cb(int (*get)(struct bt_mesh_model *model, #endif 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), #if MYNEWT_VAL(BLE_MESH_CFG_CLI) BT_MESH_MODEL_CFG_CLI(&cfg_cli), @@ -297,7 +277,7 @@ static const struct bt_mesh_comp comp = { .elem_count = ARRAY_SIZE(elements), }; -static u8_t hex2val(char c) +static uint8_t hex2val(char c) { if (c >= '0' && c <= '9') { return c - '0'; @@ -310,7 +290,54 @@ static u8_t hex2val(char c) } } -static size_t hex2bin(const char *hex, u8_t *bin, size_t bin_len) +int char2hex(char c, uint8_t *x) +{ + if (c >= '0' && c <= '9') { + *x = c - '0'; + } else if (c >= 'a' && c <= 'f') { + *x = c - 'a' + 10; + } else if (c >= 'A' && c <= 'F') { + *x = c - 'A' + 10; + } else { + return -EINVAL; + } + + return 0; +} + +int hex2char(uint8_t x, char *c) +{ + if (x <= 9) { + *c = x + '0'; + } else if (x <= 15) { + *c = x - 10 + 'a'; + } else { + return -EINVAL; + } + + return 0; +} + +size_t bin2hex(const uint8_t *buf, size_t buflen, char *hex, size_t hexlen) +{ + if ((hexlen + 1) < buflen * 2) { + return 0; + } + + for (size_t i = 0; i < buflen; i++) { + if (hex2char(buf[i] >> 4, &hex[2 * i]) < 0) { + return 0; + } + if (hex2char(buf[i] & 0xf, &hex[2 * i + 1]) < 0) { + return 0; + } + } + + hex[2 * buflen] = '\0'; + return 2 * buflen; +} + +static size_t hex2bin(const char *hex, uint8_t *bin, size_t bin_len) { size_t len = 0; @@ -328,7 +355,7 @@ static size_t hex2bin(const char *hex, u8_t *bin, size_t bin_len) return len; } -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, net_idx 0x%04x address 0x%04x\n", net_idx, addr); @@ -337,7 +364,8 @@ static void prov_complete(u16_t net_idx, u16_t addr) net.dst = addr; } -static void prov_node_added(u16_t net_idx, u16_t addr, u8_t num_elem) +static void prov_node_added(uint16_t net_idx, uint8_t uuid[16], uint16_t addr, + uint8_t num_elem) { printk("Node provisioned, net_idx 0x%04x address " "0x%04x elements %d", net_idx, addr, num_elem); @@ -369,7 +397,7 @@ static int output_string(const char *str) } static bt_mesh_input_action_t input_act; -static u8_t input_size; +static uint8_t input_size; static int cmd_input_num(int argc, char *argv[]) { @@ -437,7 +465,7 @@ struct shell_cmd_help cmd_input_str_help = { NULL, "", NULL }; -static int input(bt_mesh_input_action_t act, u8_t size) +static int input(bt_mesh_input_action_t act, uint8_t size) { switch (act) { case BT_MESH_ENTER_NUMBER: @@ -481,9 +509,9 @@ static void link_close(bt_mesh_prov_bearer_t bearer) printk("Provisioning link closed on %s\n", bearer2str(bearer)); } -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 u8_t static_val[16]; +static uint8_t static_val[16]; static struct bt_mesh_prov prov = { .uuid = dev_uuid, @@ -534,7 +562,7 @@ struct shell_cmd_help cmd_static_oob_help = { static int cmd_uuid(int argc, char *argv[]) { - u8_t uuid[16]; + uint8_t uuid[16]; size_t len; if (argc < 2) { @@ -560,12 +588,38 @@ struct shell_cmd_help cmd_uuid_help = { static int cmd_reset(int argc, char *argv[]) { - bt_mesh_reset(); - printk("Local node reset complete\n"); + uint16_t addr; + if (argc < 2) { + return -EINVAL; + } + + addr = strtoul(argv[1], NULL, 0); + + if (addr == net.local) { + bt_mesh_reset(); + printk("Local node reset complete"); + } else { + int err; + bool reset = false; + + err = bt_mesh_cfg_node_reset(net.net_idx, net.dst, &reset); + if (err) { + printk("Unable to send " + "Remote Node Reset (err %d)", err); + return 0; + } + + printk("Remote node reset complete"); + } + return 0; } -static u8_t str2u8(const char *str) +struct shell_cmd_help cmd_reset_help = { + NULL, "", NULL +}; + +static uint8_t str2u8(const char *str) { if (isdigit(str[0])) { return strtoul(str, NULL, 0); @@ -631,7 +685,7 @@ static int cmd_poll(int argc, char *argv[]) return 0; } -static void lpn_cb(u16_t friend_addr, bool established) +static void lpn_cb(uint16_t friend_addr, bool established) { if (established) { printk("Friendship (as LPN) established to Friend 0x%04x\n", @@ -784,8 +838,6 @@ static int cmd_net_send(int argc, char *argv[]) struct bt_mesh_net_tx tx = { .ctx = &ctx, .src = net.local, - .xmit = bt_mesh_net_transmit_get(), - .sub = bt_mesh_subnet_get(net.net_idx), }; size_t len; int err = 0; @@ -795,12 +847,6 @@ static int cmd_net_send(int argc, char *argv[]) goto done; } - if (!tx.sub) { - printk("No matching subnet for NetKey Index 0x%04x\n", - net.net_idx); - goto done; - } - net_buf_simple_init(msg, 0); len = hex2bin(argv[1], msg->om_data, net_buf_simple_tailroom(msg) - 4); net_buf_simple_add(msg, len); @@ -828,7 +874,7 @@ static int cmd_rpl_clear(int argc, char *argv[]) #if MYNEWT_VAL(BLE_MESH_LOW_POWER) static int cmd_lpn_subscribe(int argc, char *argv[]) { - u16_t address; + uint16_t address; if (argc < 2) { return -EINVAL; @@ -849,7 +895,7 @@ struct shell_cmd_help cmd_lpn_subscribe_help = { static int cmd_lpn_unsubscribe(int argc, char *argv[]) { - u16_t address; + uint16_t address; if (argc < 2) { return -EINVAL; @@ -912,7 +958,7 @@ struct shell_cmd_help cmd_iv_update_test_help = { int cmd_timeout(int argc, char *argv[]) { - s32_t timeout; + int32_t timeout; if (argc < 2) { timeout = bt_mesh_cfg_cli_timeout_get(); @@ -952,7 +998,7 @@ struct shell_cmd_help cmd_timeout_help = { static int cmd_get_comp(int argc, char *argv[]) { struct os_mbuf *comp = NET_BUF_SIMPLE(32); - u8_t status, page = 0x00; + uint8_t status, page = 0x00; int err = 0; if (argc > 1) { @@ -980,8 +1026,8 @@ static int cmd_get_comp(int argc, char *argv[]) printk("\tFeatures 0x%04x\n", net_buf_simple_pull_le16(comp)); while (comp->om_len > 4) { - u8_t sig, vnd; - u16_t loc; + uint8_t sig, vnd; + uint16_t loc; int i; loc = net_buf_simple_pull_le16(comp); @@ -1002,7 +1048,7 @@ static int cmd_get_comp(int argc, char *argv[]) } for (i = 0; i < sig; i++) { - u16_t mod_id = net_buf_simple_pull_le16(comp); + uint16_t mod_id = net_buf_simple_pull_le16(comp); printk("\t\t\t0x%04x\n", mod_id); } @@ -1014,8 +1060,8 @@ static int cmd_get_comp(int argc, char *argv[]) } for (i = 0; i < vnd; i++) { - u16_t cid = net_buf_simple_pull_le16(comp); - u16_t mod_id = net_buf_simple_pull_le16(comp); + uint16_t cid = net_buf_simple_pull_le16(comp); + uint16_t mod_id = net_buf_simple_pull_le16(comp); printk("\t\t\tCompany 0x%04x: 0x%04x\n", cid, mod_id); } @@ -1032,13 +1078,13 @@ struct shell_cmd_help cmd_get_comp_help = { static int cmd_beacon(int argc, char *argv[]) { - u8_t status; + uint8_t status; int err; if (argc < 2) { err = bt_mesh_cfg_beacon_get(net.net_idx, net.dst, &status); } else { - u8_t val = str2u8(argv[1]); + uint8_t val = str2u8(argv[1]); err = bt_mesh_cfg_beacon_set(net.net_idx, net.dst, val, &status); @@ -1054,19 +1100,49 @@ static int cmd_beacon(int argc, char *argv[]) return 0; } +static void print_unprovisioned_beacon(uint8_t uuid[16], + bt_mesh_prov_oob_info_t oob_info, + uint32_t *uri_hash) +{ + char uuid_hex_str[32 + 1]; + + bin2hex(uuid, 16, uuid_hex_str, sizeof(uuid_hex_str)); + + printk("UUID %s, OOB Info 0x%04x, URI Hash 0x%lx", + uuid_hex_str, oob_info, + (uri_hash == NULL ? 0 : *uri_hash)); +} + +static int cmd_beacon_listen(int argc, char *argv[]) +{ + uint8_t val = str2u8(argv[1]); + + if (val) { + prov.unprovisioned_beacon = print_unprovisioned_beacon; + } else { + prov.unprovisioned_beacon = NULL; + } + + return 0; +} + struct shell_cmd_help cmd_beacon_help = { NULL, "[val: off, on]", NULL }; +struct shell_cmd_help cmd_beacon_listen_help = { + NULL, "[val: off, on]", NULL +}; + static int cmd_ttl(int argc, char *argv[]) { - u8_t ttl; + uint8_t ttl; int err; if (argc < 2) { err = bt_mesh_cfg_ttl_get(net.net_idx, net.dst, &ttl); } else { - u8_t val = strtoul(argv[1], NULL, 0); + uint8_t val = strtoul(argv[1], NULL, 0); err = bt_mesh_cfg_ttl_set(net.net_idx, net.dst, val, &ttl); } @@ -1087,13 +1163,13 @@ struct shell_cmd_help cmd_ttl_help = { static int cmd_friend(int argc, char *argv[]) { - u8_t frnd; + uint8_t frnd; int err; if (argc < 2) { err = bt_mesh_cfg_friend_get(net.net_idx, net.dst, &frnd); } else { - u8_t val = str2u8(argv[1]); + uint8_t val = str2u8(argv[1]); err = bt_mesh_cfg_friend_set(net.net_idx, net.dst, val, &frnd); } @@ -1114,13 +1190,13 @@ struct shell_cmd_help cmd_friend_help = { static int cmd_gatt_proxy(int argc, char *argv[]) { - u8_t proxy; + uint8_t proxy; int err; if (argc < 2) { err = bt_mesh_cfg_gatt_proxy_get(net.net_idx, net.dst, &proxy); } else { - u8_t val = str2u8(argv[1]); + uint8_t val = str2u8(argv[1]); err = bt_mesh_cfg_gatt_proxy_set(net.net_idx, net.dst, val, &proxy); @@ -1140,17 +1216,60 @@ struct shell_cmd_help cmd_gatt_proxy_help = { NULL, "[val: off, on]", NULL }; +static int cmd_net_transmit(int argc, char *argv[]) +{ + uint8_t transmit; + int err; + + if (argc < 2) { + err = bt_mesh_cfg_net_transmit_get(net.net_idx, + net.dst, &transmit); + } else { + if (argc != 3) { + printk("Wrong number of input arguments" + "(2 arguments are required)"); + return -EINVAL; + } + + uint8_t count, interval, new_transmit; + + count = strtoul(argv[1], NULL, 0); + interval = strtoul(argv[2], NULL, 0); + + new_transmit = BT_MESH_TRANSMIT(count, interval); + + err = bt_mesh_cfg_net_transmit_set(net.net_idx, net.dst, + new_transmit, &transmit); + } + + if (err) { + printk("Unable to send network transmit" + " Get/Set (err %d)", err); + return 0; + } + + printk("Transmit 0x%02x (count %u interval %ums)", + transmit, BT_MESH_TRANSMIT_COUNT(transmit), + BT_MESH_TRANSMIT_INT(transmit)); + + return 0; +} + +struct shell_cmd_help cmd_net_transmit_help = { + NULL, "[ ]", NULL +}; + static int cmd_relay(int argc, char *argv[]) { - u8_t relay, transmit; + uint8_t relay, transmit; int err; if (argc < 2) { err = bt_mesh_cfg_relay_get(net.net_idx, net.dst, &relay, &transmit); } else { - u8_t val = str2u8(argv[1]); - u8_t count, interval, new_transmit; + uint8_t val = str2u8(argv[1]); + uint8_t count, interval, new_transmit; if (val) { if (argc > 2) { @@ -1192,9 +1311,10 @@ struct shell_cmd_help cmd_relay_help = { static int cmd_net_key_add(int argc, char *argv[]) { - u8_t key_val[16]; - u16_t key_net_idx; - u8_t status; + bool has_key_val = (argc > 2); + uint8_t key_val[16]; + uint16_t key_net_idx; + uint8_t status; int err; if (argc < 2) { @@ -1203,7 +1323,7 @@ static int cmd_net_key_add(int argc, char *argv[]) key_net_idx = strtoul(argv[1], NULL, 0); - if (argc > 2) { + if (has_key_val) { size_t len; len = hex2bin(argv[3], key_val, sizeof(key_val)); @@ -1212,6 +1332,29 @@ static int cmd_net_key_add(int argc, char *argv[]) memcpy(key_val, default_key, sizeof(key_val)); } + if (IS_ENABLED(CONFIG_BT_MESH_CDB)) { + struct bt_mesh_cdb_subnet *subnet; + + subnet = bt_mesh_cdb_subnet_get(key_net_idx); + if (subnet) { + if (has_key_val) { + printk("Subnet 0x%03x already has a value", key_net_idx); + return 0; + } + + memcpy(key_val, subnet->keys[0].net_key, 16); + } else { + subnet = bt_mesh_cdb_subnet_alloc(key_net_idx); + if (!subnet) { + printk("No space for subnet in cdb"); + return 0; + } + + memcpy(subnet->keys[0].net_key, key_val, 16); + bt_mesh_cdb_subnet_store(subnet); + } + } + err = bt_mesh_cfg_net_key_add(net.net_idx, net.dst, key_net_idx, key_val, &status); if (err) { @@ -1232,11 +1375,67 @@ struct shell_cmd_help cmd_net_key_add_help = { NULL, " [val]", NULL }; +static int cmd_net_key_get(int argc, char *argv[]) +{ + uint16_t keys[16]; + size_t cnt; + int err, i; + + cnt = ARRAY_SIZE(keys); + + err = bt_mesh_cfg_net_key_get(net.net_idx, net.dst, keys, &cnt); + if (err) { + printk("Unable to send NetKeyGet (err %d)", err); + return 0; + } + + printk("NetKeys known by 0x%04x:", net.dst); + for (i = 0; i < cnt; i++) { + printk("\t0x%03x", keys[i]); + } + + return 0; +} + +struct shell_cmd_help cmd_net_key_get_help = { + NULL, NULL, NULL +}; + +static int cmd_net_key_del(int argc, char *argv[]) +{ + uint16_t key_net_idx; + uint8_t status; + int err; + + key_net_idx = strtoul(argv[1], NULL, 0); + + err = bt_mesh_cfg_net_key_del(net.net_idx, net.dst, key_net_idx, + &status); + if (err) { + printk("Unable to send NetKeyDel (err %d)", err); + return 0; + } + + if (status) { + printk("NetKeyDel failed with status 0x%02x", + status); + } else { + printk("NetKey 0x%03x deleted", key_net_idx); + } + + return 0; +} + +struct shell_cmd_help cmd_net_key_del_help = { + NULL, "", NULL +}; + static int cmd_app_key_add(int argc, char *argv[]) { - u8_t key_val[16]; - u16_t key_net_idx, key_app_idx; - u8_t status; + uint8_t key_val[16]; + uint16_t key_net_idx, key_app_idx; + bool has_key_val = (argc > 3); + uint8_t status; int err; if (argc < 3) { @@ -1246,7 +1445,7 @@ static int cmd_app_key_add(int argc, char *argv[]) key_net_idx = strtoul(argv[1], NULL, 0); key_app_idx = strtoul(argv[2], NULL, 0); - if (argc > 3) { + if (has_key_val) { size_t len; len = hex2bin(argv[3], key_val, sizeof(key_val)); @@ -1255,6 +1454,30 @@ static int cmd_app_key_add(int argc, char *argv[]) memcpy(key_val, default_key, sizeof(key_val)); } + if (IS_ENABLED(CONFIG_BT_MESH_CDB)) { + struct bt_mesh_cdb_app_key *app_key; + + app_key = bt_mesh_cdb_app_key_get(key_app_idx); + if (app_key) { + if (has_key_val) { + printk("App key 0x%03x already has a value", key_app_idx); + return 0; + } + + memcpy(key_val, app_key->keys[0].app_key, 16); + } else { + app_key = bt_mesh_cdb_app_key_alloc(key_net_idx, + key_app_idx); + if (!app_key) { + printk("No space for app key in cdb"); + return 0; + } + + memcpy(app_key->keys[0].app_key, key_val, 16); + bt_mesh_cdb_app_key_store(app_key); + } + } + err = bt_mesh_cfg_app_key_add(net.net_idx, net.dst, key_net_idx, key_app_idx, key_val, &status); if (err) { @@ -1276,10 +1499,83 @@ struct shell_cmd_help cmd_app_key_add_help = { NULL, " [val]", NULL }; +static int cmd_app_key_get(int argc, char *argv[]) +{ + uint16_t net_idx; + uint16_t keys[16]; + size_t cnt; + uint8_t status; + int err, i; + + net_idx = strtoul(argv[1], NULL, 0); + cnt = ARRAY_SIZE(keys); + + err = bt_mesh_cfg_app_key_get(net.net_idx, net.dst, net_idx, &status, + keys, &cnt); + if (err) { + printk("Unable to send AppKeyGet (err %d)", err); + return 0; + } + + if (status) { + printk("AppKeyGet failed with status 0x%02x", + status); + return 0; + } + + printk( + "AppKeys for NetKey 0x%03x known by 0x%04x:", net_idx, + net.dst); + for (i = 0; i < cnt; i++) { + printk("\t0x%03x", keys[i]); + } + + return 0; +} + +struct shell_cmd_help cmd_app_key_get_help = { + NULL, "", NULL +}; + +static int cmd_app_key_del(int argc, char *argv[]) +{ + uint16_t key_net_idx, key_app_idx; + uint8_t status; + int err; + + if (argc < 3) { + return -EINVAL; + } + + key_net_idx = strtoul(argv[1], NULL, 0); + key_app_idx = strtoul(argv[2], NULL, 0); + + err = bt_mesh_cfg_app_key_del(net.net_idx, net.dst, key_net_idx, + key_app_idx, &status); + if (err) { + printk("Unable to send App Key del(err %d)", err); + return 0; + } + + if (status) { + printk("AppKeyDel failed with status 0x%02x", + status); + } else { + printk("AppKey deleted, NetKeyIndex 0x%04x " + "AppKeyIndex 0x%04x", key_net_idx, key_app_idx); + } + + return 0; +} + +struct shell_cmd_help cmd_app_key_del_help = { + NULL, " ", NULL +}; + static int cmd_mod_app_bind(int argc, char *argv[]) { - u16_t elem_addr, mod_app_idx, mod_id, cid; - u8_t status; + uint16_t elem_addr, mod_app_idx, mod_id, cid; + uint8_t status; int err; if (argc < 4) { @@ -1318,10 +1614,107 @@ struct shell_cmd_help cmd_mod_app_bind_help = { NULL, " [Company ID]", NULL }; +static int cmd_mod_app_unbind(int argc, char *argv[]) +{ + uint16_t elem_addr, mod_app_idx, mod_id, cid; + uint8_t status; + int err; + + if (argc < 4) { + return -EINVAL; + } + + elem_addr = strtoul(argv[1], NULL, 0); + mod_app_idx = strtoul(argv[2], NULL, 0); + mod_id = strtoul(argv[3], NULL, 0); + + if (argc > 4) { + cid = strtoul(argv[4], NULL, 0); + err = bt_mesh_cfg_mod_app_unbind_vnd(net.net_idx, net.dst, + elem_addr, mod_app_idx, + mod_id, cid, &status); + } else { + err = bt_mesh_cfg_mod_app_unbind(net.net_idx, net.dst, + elem_addr, mod_app_idx, mod_id, &status); + } + + if (err) { + printk("Unable to send Model App Unbind (err %d)", + err); + return 0; + } + + if (status) { + printk("Model App Unbind failed with status 0x%02x", + status); + } else { + printk("AppKey successfully unbound"); + } + + return 0; +} + +struct shell_cmd_help cmd_mod_app_unbind_help = { + NULL, " [Company ID]", NULL +}; + +static int cmd_mod_app_get(int argc, + char *argv[]) +{ + uint16_t elem_addr, mod_id, cid; + uint16_t apps[16]; + uint8_t status; + size_t cnt; + int err, i; + + elem_addr = strtoul(argv[1], NULL, 0); + mod_id = strtoul(argv[2], NULL, 0); + cnt = ARRAY_SIZE(apps); + + if (argc > 3) { + cid = strtoul(argv[3], NULL, 0); + err = bt_mesh_cfg_mod_app_get_vnd(net.net_idx, net.dst, + elem_addr, mod_id, cid, + &status, apps, &cnt); + } else { + err = bt_mesh_cfg_mod_app_get(net.net_idx, net.dst, elem_addr, + mod_id, &status, apps, &cnt); + } + + if (err) { + printk("Unable to send Model App Get (err %d)", + err); + return 0; + } + + if (status) { + printk("Model App Get failed with status 0x%02x", + status); + } else { + printk( + "Apps bound to Element 0x%04x, Model 0x%04x %s:", + elem_addr, mod_id, argc > 3 ? argv[3] : "(SIG)"); + + if (!cnt) { + printk("\tNone."); + } + + for (i = 0; i < cnt; i++) { + printk("\t0x%04x", apps[i]); + } + } + + return 0; +} + +struct shell_cmd_help cmd_mod_app_get_help = { + NULL, " [Company ID]", NULL +}; + static int cmd_mod_sub_add(int argc, char *argv[]) { - u16_t elem_addr, sub_addr, mod_id, cid; - u8_t status; + uint16_t elem_addr, sub_addr, mod_id, cid; + uint8_t status; int err; if (argc < 4) { @@ -1363,8 +1756,8 @@ struct shell_cmd_help cmd_mod_sub_add_help = { static int cmd_mod_sub_del(int argc, char *argv[]) { - u16_t elem_addr, sub_addr, mod_id, cid; - u8_t status; + uint16_t elem_addr, sub_addr, mod_id, cid; + uint8_t status; int err; if (argc < 4) { @@ -1407,9 +1800,9 @@ struct shell_cmd_help cmd_mod_sub_del_help = { static int cmd_mod_sub_add_va(int argc, char *argv[]) { - u16_t elem_addr, sub_addr, mod_id, cid; - u8_t label[16]; - u8_t status; + uint16_t elem_addr, sub_addr, mod_id, cid; + uint8_t label[16]; + uint8_t status; size_t len; int err; @@ -1457,9 +1850,9 @@ struct shell_cmd_help cmd_mod_sub_add_va_help = { static int cmd_mod_sub_del_va(int argc, char *argv[]) { - u16_t elem_addr, sub_addr, mod_id, cid; - u8_t label[16]; - u8_t status; + uint16_t elem_addr, sub_addr, mod_id, cid; + uint8_t label[16]; + uint8_t status; size_t len; int err; @@ -1506,10 +1899,64 @@ struct shell_cmd_help cmd_mod_sub_del_va_help = { NULL, "