diff --git a/nimble/host/mesh/include/mesh/glue.h b/nimble/host/mesh/include/mesh/glue.h index 926cbfb93..4cb61c5bc 100644 --- a/nimble/host/mesh/include/mesh/glue.h +++ b/nimble/host/mesh/include/mesh/glue.h @@ -373,7 +373,10 @@ static inline void k_sem_init(struct k_sem *sem, unsigned int initial_count, static inline int k_sem_take(struct k_sem *sem, s32_t timeout) { - return - os_sem_pend(sem, timeout); + uint32_t ticks; + + os_time_ms_to_ticks(timeout, &ticks); + return - os_sem_pend(sem, ticks); } static inline void k_sem_give(struct k_sem *sem) diff --git a/nimble/host/mesh/pkg.yml b/nimble/host/mesh/pkg.yml index d3c36be1d..3e1be0e0c 100644 --- a/nimble/host/mesh/pkg.yml +++ b/nimble/host/mesh/pkg.yml @@ -39,3 +39,6 @@ pkg.deps.BLE_MESH_SHELL: pkg.req_apis: - log - stats + +pkg.init: + ble_mesh_shell_init: 1000 diff --git a/nimble/host/mesh/src/cfg_cli.c b/nimble/host/mesh/src/cfg_cli.c index 2ec090549..05c302bd1 100644 --- a/nimble/host/mesh/src/cfg_cli.c +++ b/nimble/host/mesh/src/cfg_cli.c @@ -25,7 +25,7 @@ struct comp_data { struct os_mbuf *comp; }; -static s32_t msg_timeout = K_SECONDS(2); +static s32_t msg_timeout = K_SECONDS(5); static struct bt_mesh_cfg_cli *cli; diff --git a/nimble/host/mesh/src/friend.c b/nimble/host/mesh/src/friend.c index 50d65e6a5..9969737e9 100644 --- a/nimble/host/mesh/src/friend.c +++ b/nimble/host/mesh/src/friend.c @@ -28,8 +28,6 @@ #include "foundation.h" #include "friend.h" -#define FRIEND_BUF_SIZE (BT_MESH_ADV_DATA_SIZE - BT_MESH_NET_HDR_LEN) - /* 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. */ @@ -37,7 +35,7 @@ static os_membuf_t friend_buf_mem[OS_MEMPOOL_SIZE( FRIEND_BUF_COUNT, - BT_MESH_ADV_DATA_SIZE + BT_MESH_ADV_USER_DATA_SIZE)]; + BT_MESH_ADV_DATA_SIZE + BT_MESH_MBUF_HEADER_SIZE)]; struct os_mbuf_pool friend_os_mbuf_pool; static struct os_mempool friend_buf_mempool; diff --git a/nimble/host/mesh/src/glue.c b/nimble/host/mesh/src/glue.c index a4ab5a85e..086edaf8c 100644 --- a/nimble/host/mesh/src/glue.c +++ b/nimble/host/mesh/src/glue.c @@ -340,7 +340,9 @@ k_delayed_work_submit(struct k_delayed_work *w, uint32_t ms) { uint32_t ticks; - os_time_ms_to_ticks(ms, &ticks); + if (os_time_ms_to_ticks(ms, &ticks) != 0) { + assert(0); + } os_callout_reset(&w->work, ticks); } @@ -370,12 +372,12 @@ k_delayed_work_remaining_get (struct k_delayed_work *w) OS_ENTER_CRITICAL(sr); - t = os_callout_remaining_ticks(&w->work, os_cputime_get32()); + t = os_callout_remaining_ticks(&w->work, os_time_get()); OS_EXIT_CRITICAL(sr); /* We should return ms */ - return os_cputime_ticks_to_usecs(t) / 1000; + return t / OS_TICKS_PER_SEC * 1000; } int64_t k_uptime_get(void) diff --git a/nimble/host/mesh/src/health_cli.c b/nimble/host/mesh/src/health_cli.c index 35affba79..b94e6c29c 100644 --- a/nimble/host/mesh/src/health_cli.c +++ b/nimble/host/mesh/src/health_cli.c @@ -23,7 +23,7 @@ #include "foundation.h" #include "mesh/health_cli.h" -static s32_t msg_timeout = K_SECONDS(2); +static s32_t msg_timeout = K_SECONDS(5); static struct bt_mesh_health_cli *health_cli; diff --git a/nimble/host/mesh/src/mesh.c b/nimble/host/mesh/src/mesh.c index 04712f78e..b0b685abf 100644 --- a/nimble/host/mesh/src/mesh.c +++ b/nimble/host/mesh/src/mesh.c @@ -246,10 +246,6 @@ int bt_mesh_init(uint8_t own_addr_type, const struct bt_mesh_prov *prov, bt_mesh_beacon_enable(); #endif -#if (MYNEWT_VAL(BLE_MESH_SHELL)) - mesh_shell_init(); -#endif - #if (MYNEWT_VAL(BLE_MESH_PB_GATT)) bt_mesh_proxy_prov_enable(); #endif diff --git a/nimble/host/mesh/src/shell.c b/nimble/host/mesh/src/shell.c index 303f13ccc..686c12ac2 100644 --- a/nimble/host/mesh/src/shell.c +++ b/nimble/host/mesh/src/shell.c @@ -21,15 +21,29 @@ #include "mesh/mesh.h" #include "mesh/main.h" #include "mesh/glue.h" +#include "mesh/testing.h" /* Private includes for raw Network & Transport layer access */ #include "net.h" +#include "access.h" #include "mesh_priv.h" +#include "lpn.h" #include "transport.h" #include "foundation.h" +#include "testing.h" + +/* This should be higher priority (lower value) than main task priority */ +#define BLE_MESH_SHELL_TASK_PRIO 126 +#define BLE_MESH_SHELL_STACK_SIZE 768 + +struct os_task mesh_shell_task; +static struct os_eventq mesh_shell_queue; #define CID_NVAL 0xffff -#define CID_LOCAL 0x0002 +#define CID_VENDOR 0x05C3 + +/* Vendor Model data */ +#define VND_MODEL_ID_1 0x1234 /* Default net, app & dev key values, unless otherwise specified */ static const u8_t default_key[16] = { @@ -91,7 +105,7 @@ static int fault_get_cur(struct bt_mesh_model *model, u8_t *test_id, printk("Sending current faults\n"); *test_id = 0x00; - *company_id = CID_LOCAL; + *company_id = CID_VENDOR; get_faults(cur_faults, sizeof(cur_faults), faults, fault_count); @@ -101,7 +115,7 @@ static int fault_get_cur(struct bt_mesh_model *model, u8_t *test_id, static int fault_get_reg(struct bt_mesh_model *model, u16_t cid, u8_t *test_id, u8_t *faults, u8_t *fault_count) { - if (cid != CID_LOCAL) { + if (cid != CID_VENDOR) { printk("Faults requested for unknown Company ID 0x%04x\n", cid); return -EINVAL; } @@ -117,7 +131,7 @@ static int fault_get_reg(struct bt_mesh_model *model, u16_t cid, static int fault_clear(struct bt_mesh_model *model, uint16_t cid) { - if (cid != CID_LOCAL) { + if (cid != CID_VENDOR) { return -EINVAL; } @@ -129,7 +143,7 @@ static int fault_clear(struct bt_mesh_model *model, uint16_t cid) static int fault_test(struct bt_mesh_model *model, uint8_t test_id, uint16_t cid) { - if (cid != CID_LOCAL) { + if (cid != CID_VENDOR) { return -EINVAL; } @@ -193,7 +207,7 @@ static struct bt_mesh_health_cli health_cli = { .current_status = health_current_status, }; -static u8_t dev_uuid[16] = { 0xdd, 0xdd }; +static u8_t dev_uuid[16] = MYNEWT_VAL(BLE_MESH_DEV_UUID); static struct bt_mesh_model root_models[] = { BT_MESH_MODEL_CFG_SRV(&cfg_srv), @@ -202,12 +216,17 @@ static struct bt_mesh_model root_models[] = { BT_MESH_MODEL_HEALTH_CLI(&health_cli), }; +static struct bt_mesh_model vnd_models[] = { + BT_MESH_MODEL_VND(CID_VENDOR, VND_MODEL_ID_1, BT_MESH_MODEL_NO_OPS, NULL, + NULL), +}; + static struct bt_mesh_elem elements[] = { - BT_MESH_ELEM(0, root_models, BT_MESH_MODEL_NONE), + BT_MESH_ELEM(0, root_models, vnd_models), }; static const struct bt_mesh_comp comp = { - .cid = CID_LOCAL, + .cid = CID_VENDOR, .elem = elements, .elem_count = ARRAY_SIZE(elements), }; @@ -545,18 +564,30 @@ struct shell_cmd_help cmd_lpn_help = { #endif /* MESH_LOW_POWER */ +static int check_addr_unassigned(uint8_t addr[BLE_DEV_ADDR_LEN]) +{ + return memcmp(addr, (uint8_t[BLE_DEV_ADDR_LEN]){0, 0, 0, 0, 0, 0}, + BLE_DEV_ADDR_LEN) == 0; +} + static int cmd_init(int argc, char *argv[]) { 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); + if (check_addr_unassigned(MYNEWT_VAL(BLE_PUBLIC_DEV_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); + + err = bt_mesh_init(addr.type, &prov, &comp); + } + else { + err = bt_mesh_init(0, &prov, &comp); + } - err = bt_mesh_init(addr.type, &prov, &comp); if (err) { printk("Mesh initialization failed (err %d)\n", err); } @@ -783,6 +814,50 @@ static int cmd_rpl_clear(int argc, char *argv[]) return 0; } +#if MYNEWT_VAL(BLE_MESH_LOW_POWER) +static int cmd_lpn_subscribe(int argc, char *argv[]) +{ + u16_t address; + + if (argc < 2) { + return -EINVAL; + } + + address = strtoul(argv[1], NULL, 0); + + printk("address 0x%04x", address); + + bt_mesh_lpn_group_add(address); + + return 0; +} + +struct shell_cmd_help cmd_lpn_subscribe_help = { + NULL, "", NULL +}; + +static int cmd_lpn_unsubscribe(int argc, char *argv[]) +{ + u16_t address; + + if (argc < 2) { + return -EINVAL; + } + + address = strtoul(argv[1], NULL, 0); + + printk("address 0x%04x", address); + + bt_mesh_lpn_group_del(&address, 1); + + return 0; +} + +struct shell_cmd_help cmd_lpn_unsubscribe_help = { + NULL, "", NULL +}; +#endif + static int cmd_iv_update_test(int argc, char *argv[]) { bool enable; @@ -2039,6 +2114,56 @@ struct shell_cmd_help cmd_del_fault_help = { NULL, "[Fault ID]", NULL }; +static int cmd_print_credentials(int argc, char *argv[]) +{ + bt_test_print_credentials(); + return 0; +} + +static void print_comp_elem(struct bt_mesh_elem *elem, + bool primary) +{ + struct bt_mesh_model *mod; + int i; + + printk("Loc: %u\n", elem->loc); + printk("Model count: %u\n", elem->model_count); + printk("Vnd model count: %u\n", elem->vnd_model_count); + + for (i = 0; i < elem->model_count; i++) { + mod = &elem->models[i]; + printk(" Model: %u\n", i); + printk(" ID: 0x%04x\n", mod->id); + printk(" Opcode: 0x%08lx\n", mod->op->opcode); + } + + for (i = 0; i < elem->vnd_model_count; i++) { + mod = &elem->vnd_models[i]; + printk(" Vendor model: %u\n", i); + printk(" Company: 0x%04x\n", mod->vnd.company); + printk(" ID: 0x%04x\n", mod->vnd.id); + printk(" Opcode: 0x%08lx\n", mod->op->opcode); + } +} + +static int cmd_print_composition_data(int argc, char *argv[]) +{ + const struct bt_mesh_comp *comp; + int i; + + comp = bt_mesh_comp_get(); + + printk("CID: %u\n", comp->cid); + printk("PID: %u\n", comp->pid); + printk("VID: %u\n", comp->vid); + + for (i = 0; i < comp->elem_count; i++) { + print_comp_elem(&comp->elem[i], i == 0); + } + + return 0; +} + static const struct shell_cmd mesh_commands[] = { { "init", cmd_init, NULL }, { "timeout", cmd_timeout, &cmd_timeout_help }, @@ -2070,6 +2195,12 @@ static const struct shell_cmd mesh_commands[] = { { "iv-update", cmd_iv_update, NULL }, { "iv-update-test", cmd_iv_update_test, &cmd_iv_update_test_help }, { "rpl-clear", cmd_rpl_clear, NULL }, +#if MYNEWT_VAL(BLE_MESH_LOW_POWER) + { "lpn-subscribe", cmd_lpn_subscribe, &cmd_lpn_subscribe_help }, + { "lpn-unsubscribe", cmd_lpn_unsubscribe, &cmd_lpn_unsubscribe_help }, +#endif + { "print-credentials", cmd_print_credentials, NULL }, + { "print-composition-data", cmd_print_composition_data, NULL }, /* Configuration Client Model operations */ { "get-comp", cmd_get_comp, &cmd_get_comp_help }, @@ -2109,10 +2240,38 @@ static const struct shell_cmd mesh_commands[] = { { NULL, NULL, NULL} }; -void mesh_shell_init(void) +static void mesh_shell_thread(void *args) { - health_pub_init(); - shell_register("mesh", mesh_commands); + while (1) { + os_eventq_run(&mesh_shell_queue); + } } +static void bt_mesh_shell_task_init(void) +{ + os_stack_t *pstack; + + pstack = malloc(sizeof(os_stack_t) * BLE_MESH_SHELL_STACK_SIZE); + os_eventq_init(&mesh_shell_queue); + + os_task_init(&mesh_shell_task, "mesh_sh", mesh_shell_thread, NULL, + BLE_MESH_SHELL_TASK_PRIO, OS_WAIT_FOREVER, pstack, + BLE_MESH_SHELL_STACK_SIZE); +} #endif + +void ble_mesh_shell_init(void) +{ +#if !(MYNEWT_VAL(BLE_MESH_SHELL)) + return; +#endif + + /* Initialize health pub message */ + health_pub_init(); + + /* Shell and other mesh clients should use separate task to + avoid deadlocks with mesh message processing queue */ + bt_mesh_shell_task_init(); + shell_evq_set(&mesh_shell_queue); + shell_register("mesh", mesh_commands); +} diff --git a/nimble/host/mesh/src/shell.h b/nimble/host/mesh/src/shell.h index edd85a1f7..53cc83a27 100644 --- a/nimble/host/mesh/src/shell.h +++ b/nimble/host/mesh/src/shell.h @@ -1,6 +1,6 @@ #ifndef __SHELL_H__ #define __SHELL_H__ -void mesh_shell_init(void); +void ble_mesh_shell_init(void); #endif diff --git a/nimble/host/mesh/src/testing.c b/nimble/host/mesh/src/testing.c index 4a41978cd..16db07558 100644 --- a/nimble/host/mesh/src/testing.c +++ b/nimble/host/mesh/src/testing.c @@ -6,6 +6,7 @@ #include +#include "console/console.h" #include "mesh/testing.h" #include "mesh/slist.h" #include "mesh/glue.h" @@ -84,3 +85,70 @@ void bt_test_mesh_trans_incomp_timer_exp(void) } } } + +void bt_test_print_credentials(void) +{ + int i; + u8_t nid; + const u8_t *enc; + const u8_t *priv; + struct bt_mesh_subnet *sub; + struct bt_mesh_app_key *app_key; + + console_printf("IV Index: %08lx\n", bt_mesh.iv_index); + console_printf("Dev key: %s\n", bt_hex(bt_mesh.dev_key, 16)); + + for (i = 0; i < MYNEWT_VAL(BLE_MESH_SUBNET_COUNT); ++i) + { + if (bt_mesh.app_keys[i].net_idx == BT_MESH_KEY_UNUSED) { + continue; + } + + sub = &bt_mesh.sub[i]; + + console_printf("Subnet: %d\n", i); + console_printf("\tNetKeyIdx: %04x\n", + sub->net_idx); + console_printf("\tNetKey: %s\n", + bt_hex(sub->keys[sub->kr_flag].net, 16)); + } + + for (i = 0; i < MYNEWT_VAL(BLE_MESH_APP_KEY_COUNT); ++i) + { + if (bt_mesh.app_keys[i].net_idx == BT_MESH_KEY_UNUSED) { + continue; + } + + sub = &bt_mesh.sub[i]; + app_key = &bt_mesh.app_keys[i]; + + console_printf("AppKey: %d\n", i); + console_printf("\tNetKeyIdx: %04x\n", + app_key->net_idx); + console_printf("\tAppKeyIdx: %04x\n", + app_key->app_idx); + console_printf("\tAppKey: %s\n", + bt_hex(app_key->keys[sub->kr_flag].val, 16)); + } + + for (i = 0; i < MYNEWT_VAL(BLE_MESH_SUBNET_COUNT); ++i) + { + if (bt_mesh.app_keys[i].net_idx == BT_MESH_KEY_UNUSED) { + continue; + } + + if (friend_cred_get(&bt_mesh.sub[i], BT_MESH_ADDR_UNASSIGNED, + &nid, &enc, &priv)) { + return; + } + + console_printf("Friend cred: %d\n", i); + console_printf("\tNetKeyIdx: %04x\n", + bt_mesh.sub[i].net_idx); + console_printf("\tNID: %02x\n", nid); + console_printf("\tEncKey: %s\n", + bt_hex(enc, 16)); + console_printf("\tPrivKey: %s\n", + bt_hex(priv, 16)); + } +} diff --git a/nimble/host/mesh/src/testing.h b/nimble/host/mesh/src/testing.h index 9a1df6f0e..166a9eea6 100644 --- a/nimble/host/mesh/src/testing.h +++ b/nimble/host/mesh/src/testing.h @@ -20,3 +20,4 @@ void bt_test_mesh_prov_invalid_bearer(u8_t opcode); void bt_test_mesh_net_recv(u8_t ttl, u8_t ctl, u16_t src, u16_t dst, const void *payload, size_t payload_len); void bt_test_mesh_trans_incomp_timer_exp(void); +void bt_test_print_credentials(void);