From 95c4d0c1f38b73599e2b5be6ce1b55abfff03b6e Mon Sep 17 00:00:00 2001 From: Sathish Narasimman Date: Wed, 8 Mar 2017 14:18:16 +0530 Subject: [PATCH 01/41] Bluetooth: AT: Unit test application init AT Module unit testing application to verify at_parse_input, at_parse_cmd_input, at_get_number. Change-Id: I256c0f9b62c13bc6f22eac4b94118b5fc7643462 Signed-off-by: Sathish Narasimman --- tests/unit/bluetooth/at/Makefile | 4 ++ tests/unit/bluetooth/at/prj.conf | 5 ++ tests/unit/bluetooth/at/src/Makefile | 4 ++ tests/unit/bluetooth/at/src/main.c | 76 ++++++++++++++++++++++++++++ tests/unit/bluetooth/at/testcase.ini | 4 ++ 5 files changed, 93 insertions(+) create mode 100644 tests/unit/bluetooth/at/Makefile create mode 100644 tests/unit/bluetooth/at/prj.conf create mode 100644 tests/unit/bluetooth/at/src/Makefile create mode 100644 tests/unit/bluetooth/at/src/main.c create mode 100644 tests/unit/bluetooth/at/testcase.ini diff --git a/tests/unit/bluetooth/at/Makefile b/tests/unit/bluetooth/at/Makefile new file mode 100644 index 00000000000..4b05dca8edb --- /dev/null +++ b/tests/unit/bluetooth/at/Makefile @@ -0,0 +1,4 @@ +BOARD ?= qemu_x86 +CONF_FILE = prj.conf + +include $(ZEPHYR_BASE)/Makefile.test diff --git a/tests/unit/bluetooth/at/prj.conf b/tests/unit/bluetooth/at/prj.conf new file mode 100644 index 00000000000..8d1867a407a --- /dev/null +++ b/tests/unit/bluetooth/at/prj.conf @@ -0,0 +1,5 @@ +CONFIG_BLUETOOTH=y +CONFIG_BLUETOOTH_BREDR=y +CONFIG_BLUETOOTH_HFP_HF=y +CONFIG_NET_BUF=y +CONFIG_ZTEST=y diff --git a/tests/unit/bluetooth/at/src/Makefile b/tests/unit/bluetooth/at/src/Makefile new file mode 100644 index 00000000000..243f22f31d0 --- /dev/null +++ b/tests/unit/bluetooth/at/src/Makefile @@ -0,0 +1,4 @@ +obj-y = main.o +ccflags-y += -I${ZEPHYR_BASE}/subsys + +include $(ZEPHYR_BASE)/tests/Makefile.test diff --git a/tests/unit/bluetooth/at/src/main.c b/tests/unit/bluetooth/at/src/main.c new file mode 100644 index 00000000000..0bc3608f032 --- /dev/null +++ b/tests/unit/bluetooth/at/src/main.c @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2017 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include + +#include "../../../../subsys/bluetooth/host/at.h" + +#include + +static struct at_client at; +static char buffer[140]; + +NET_BUF_POOL_DEFINE(at_pool, 1, 140, 0, NULL); + +static const char example_data[] = "\r\n+ABCD:999\r\n"; + +int at_handle(struct at_client *hf_at) +{ + uint32_t val; + + assert_equal(at_get_number(hf_at, &val), 0, "Error getting value"); + + assert_equal(val, 999, "Invalid value parsed"); + + return 0; +} + +int at_resp(struct at_client *hf_at, struct net_buf *buf) +{ + int err; + + err = at_parse_cmd_input(hf_at, buf, "ABCD", at_handle, + AT_CMD_TYPE_NORMAL); + assert_equal(err, 0, "Error parsing CMD input"); + + return 0; +} + + +static void at_test1(void) +{ + struct net_buf *buf; + int len; + + at.buf_max_len = 140; + at.buf = buffer; + + buf = net_buf_alloc(&at_pool, K_FOREVER); + assert_not_null(buf, "Failed to get buffer"); + + at_register(&at, at_resp, NULL); + len = strlen(example_data); + + assert_true(net_buf_tailroom(buf) >= len, + "Allocated buffer is too small"); + strncpy((char *)buf->data, example_data, len); + net_buf_add(buf, len); + + assert_equal(at_parse_input(&at, buf), 0, "Parsing failed"); +} + +void test_main(void) +{ + ztest_test_suite(at_tests, + ztest_unit_test(at_test1) + ); + + ztest_run_test_suite(at_tests); +} diff --git a/tests/unit/bluetooth/at/testcase.ini b/tests/unit/bluetooth/at/testcase.ini new file mode 100644 index 00000000000..c1a502f4f2a --- /dev/null +++ b/tests/unit/bluetooth/at/testcase.ini @@ -0,0 +1,4 @@ +[test] +tags = bluetooth +build_only = true +filter = ( CONFIG_SRAM_SIZE > 16 or CONFIG_DCCM_SIZE > 16 or CONFIG_RAM_SIZE > 16 ) From 86d64b4f92c14cca23cd4d409aad9e1b27990d37 Mon Sep 17 00:00:00 2001 From: Sathish Narasimman Date: Wed, 22 Mar 2017 19:09:14 +0530 Subject: [PATCH 02/41] Bluetooth: HFP HF: Lookup table for unsolicited commands Using lookup table to search for unsolicted command and its handler function. Change-Id: Id677dad3918d7187e0065ada2985ec12a97f8ed9 Signed-off-by: Sathish Narasimman --- subsys/bluetooth/host/hfp_hf.c | 36 +++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/subsys/bluetooth/host/hfp_hf.c b/subsys/bluetooth/host/hfp_hf.c index 7ac89e1c8d7..12adc334868 100644 --- a/subsys/bluetooth/host/hfp_hf.c +++ b/subsys/bluetooth/host/hfp_hf.c @@ -342,14 +342,44 @@ int ciev_handle(struct at_client *hf_at) return 0; } +static const struct unsolicited { + const char *cmd; + enum at_cmd_type type; + int (*func)(struct at_client *hf_at); +} handlers[] = { + { "CIEV", AT_CMD_TYPE_UNSOLICITED, ciev_handle } +}; + +static const struct unsolicited *hfp_hf_unsol_lookup(struct at_client *hf_at) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(handlers); i++) { + if (!strncmp(hf_at->buf, handlers[i].cmd, + strlen(handlers[i].cmd))) { + return &handlers[i]; + } + } + + return NULL; +} + int unsolicited_cb(struct at_client *hf_at, struct net_buf *buf) { - if (!at_parse_cmd_input(hf_at, buf, "CIEV", ciev_handle, - AT_CMD_TYPE_UNSOLICITED)) { + const struct unsolicited *handler; + + handler = hfp_hf_unsol_lookup(hf_at); + if (!handler) { + BT_ERR("Unhandled unsolicited response"); + return -ENOMSG; + } + + if (!at_parse_cmd_input(hf_at, buf, handler->cmd, handler->func, + handler->type)) { return 0; } - return -EINVAL; + return -ENOMSG; } int cmee_finish(struct at_client *hf_at, enum at_result result, From 19d740c162b319298882a006ca50019d15843166 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Tue, 28 Mar 2017 12:59:22 +0300 Subject: [PATCH 03/41] Bluetooth: monitor: Drop data instead of holding IRQ lock for long The IRQ lock should never be held for long periods of time. Instead of using the IRQ lock to prevent monitor protocol corruption simply drop the data. Follow-up patches will add additional drop count tracking so that these get reported properly over the protocol. Change-Id: If498125b29f1b58bed676c78ad2062e2aa206318 Signed-off-by: Johan Hedberg --- subsys/bluetooth/host/monitor.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/subsys/bluetooth/host/monitor.c b/subsys/bluetooth/host/monitor.c index e1e040b7038..52022eb7b82 100644 --- a/subsys/bluetooth/host/monitor.c +++ b/subsys/bluetooth/host/monitor.c @@ -31,6 +31,12 @@ static struct device *monitor_dev; +enum { + BT_LOG_BUSY, +}; + +static atomic_t flags; + extern int _prf(int (*func)(), void *dest, const char *format, va_list vargs); @@ -71,7 +77,7 @@ void bt_log(int prio, const char *fmt, ...) struct bt_monitor_hdr hdr; const char id[] = "bt"; va_list ap; - int len, key; + int len; va_start(ap, fmt); len = vsnprintk(NULL, 0, fmt, ap); @@ -87,7 +93,9 @@ void bt_log(int prio, const char *fmt, ...) encode_hdr(&hdr, BT_MONITOR_USER_LOGGING, sizeof(log) + sizeof(id) + len + 1); - key = irq_lock(); + if (atomic_test_and_set_bit(&flags, BT_LOG_BUSY)) { + return; + } monitor_send(&hdr, sizeof(hdr)); monitor_send(&log, sizeof(log)); @@ -100,22 +108,23 @@ void bt_log(int prio, const char *fmt, ...) /* Terminate the string with null */ uart_poll_out(monitor_dev, '\0'); - irq_unlock(key); + atomic_clear_bit(&flags, BT_LOG_BUSY); } void bt_monitor_send(uint16_t opcode, const void *data, size_t len) { struct bt_monitor_hdr hdr; - int key; encode_hdr(&hdr, opcode, len); - key = irq_lock(); + if (atomic_test_and_set_bit(&flags, BT_LOG_BUSY)) { + return; + } monitor_send(&hdr, sizeof(hdr)); monitor_send(data, len); - irq_unlock(key); + atomic_clear_bit(&flags, BT_LOG_BUSY); } void bt_monitor_new_index(uint8_t type, uint8_t bus, bt_addr_t *addr, From 1f5a809178e5e99b63d039047e1658de0c89e2ac Mon Sep 17 00:00:00 2001 From: Sathish Narasimman Date: Mon, 20 Feb 2017 17:24:41 +0530 Subject: [PATCH 04/41] Bluetooth: HFP HF: Add support for RING indication cb This patch adds support for incoming RING indication callback to notify application. > ACL Data RX: Handle 256 flags 0x02 dlen 16 [hci0] 167174.600312 Channel: 65 len 12 [PSM 3 mode 0] {chan 1} RFCOMM: Unnumbered Info with Header Check (UIH) (0xef) Address: 0x0b cr 1 dlci 0x02 Control: 0xef poll/final 0 Length: 8 FCS: 0x9a 0d 0a 52 49 4e 47 0d 0a 9a ..RING... Change-Id: I0469590a77d619f2a842df647d84f4d56dbd4883 Signed-off-by: Sathish Narasimman --- include/bluetooth/hfp_hf.h | 8 ++++++++ samples/bluetooth/handsfree/src/main.c | 6 ++++++ subsys/bluetooth/host/at.c | 27 ++++++++++++++++++++++++-- subsys/bluetooth/host/at.h | 3 ++- subsys/bluetooth/host/hfp_hf.c | 15 +++++++++++++- 5 files changed, 55 insertions(+), 4 deletions(-) diff --git a/include/bluetooth/hfp_hf.h b/include/bluetooth/hfp_hf.h index 81420d97097..48dc710c5f8 100644 --- a/include/bluetooth/hfp_hf.h +++ b/include/bluetooth/hfp_hf.h @@ -98,6 +98,14 @@ struct bt_hfp_hf_cb { * @param value battery indicator value received from the AG. */ void (*battery)(struct bt_conn *conn, uint32_t value); + /** HF incoming call Ring indication callback to application + * + * If this callback is provided it will be called whenever there + * is an incoming call. + * + * @param conn Connection object. + */ + void (*ring_indication)(struct bt_conn *conn); }; /** @brief Register HFP HF profile diff --git a/samples/bluetooth/handsfree/src/main.c b/samples/bluetooth/handsfree/src/main.c index 5fe1a80d529..d0a8abcbc3a 100644 --- a/samples/bluetooth/handsfree/src/main.c +++ b/samples/bluetooth/handsfree/src/main.c @@ -63,6 +63,11 @@ static void battery(struct bt_conn *conn, uint32_t value) printk("Battery indicator value: %u\n", value); } +static void ring_cb(struct bt_conn *conn) +{ + printk("Incoming Call...\n"); +} + static struct bt_hfp_hf_cb hf_cb = { .connected = connected, .disconnected = disconnected, @@ -73,6 +78,7 @@ static struct bt_hfp_hf_cb hf_cb = { .signal = signal, .roam = roam, .battery = battery, + .ring_indication = ring_cb, }; static void bt_ready(int err) diff --git a/subsys/bluetooth/host/at.c b/subsys/bluetooth/host/at.c index 28963e950ba..e184f93364e 100644 --- a/subsys/bluetooth/host/at.c +++ b/subsys/bluetooth/host/at.c @@ -227,11 +227,25 @@ static int at_state_get_result_string(struct at_client *at, struct net_buf *buf) return get_response_string(at, buf, '\r', AT_STATE_PROCESS_RESULT); } +static bool is_ring(struct at_client *at) +{ + if (strncmp(at->buf, "RING", 4) == 0) { + return true; + } + + return false; +} + static int at_state_process_result(struct at_client *at, struct net_buf *buf) { enum at_cme cme_err; enum at_result result; + if (is_ring(at)) { + at->state = AT_STATE_UNSOLICITED_CMD; + return 0; + } + if (at_parse_result(at->buf, buf, &result) == 0) { if (at->finish) { /* cme_err is 0 - Is invalid until result is @@ -327,8 +341,15 @@ static int at_cmd_start(struct at_client *at, struct net_buf *buf, return -ENODATA; } - reset_buffer(at); - at->cmd_state = AT_CMD_GET_VALUE; + if (type == AT_CMD_TYPE_OTHER) { + /* Skip for Other type such as ..RING.. which does not have + * values to get processed. + */ + at->cmd_state = AT_CMD_PROCESS_VALUE; + } else { + at->cmd_state = AT_CMD_GET_VALUE; + } + return 0; } @@ -336,6 +357,8 @@ static int at_cmd_get_value(struct at_client *at, struct net_buf *buf, const char *prefix, parse_val_t func, enum at_cmd_type type) { + /* Reset buffer before getting the values */ + reset_buffer(at); return get_cmd_value(at, buf, '\r', AT_CMD_PROCESS_VALUE); } diff --git a/subsys/bluetooth/host/at.h b/subsys/bluetooth/host/at.h index 914dcbddb1f..ae2c7f95d80 100644 --- a/subsys/bluetooth/host/at.h +++ b/subsys/bluetooth/host/at.h @@ -64,7 +64,8 @@ enum at_cmd_state { enum at_cmd_type { AT_CMD_TYPE_NORMAL, - AT_CMD_TYPE_UNSOLICITED + AT_CMD_TYPE_UNSOLICITED, + AT_CMD_TYPE_OTHER }; struct at_client; diff --git a/subsys/bluetooth/host/hfp_hf.c b/subsys/bluetooth/host/hfp_hf.c index 12adc334868..f058cfdec29 100644 --- a/subsys/bluetooth/host/hfp_hf.c +++ b/subsys/bluetooth/host/hfp_hf.c @@ -342,12 +342,25 @@ int ciev_handle(struct at_client *hf_at) return 0; } +int ring_handle(struct at_client *hf_at) +{ + struct bt_hfp_hf *hf = CONTAINER_OF(hf_at, struct bt_hfp_hf, at); + struct bt_conn *conn = hf->rfcomm_dlc.session->br_chan.chan.conn; + + if (bt_hf->ring_indication) { + bt_hf->ring_indication(conn); + } + + return 0; +} + static const struct unsolicited { const char *cmd; enum at_cmd_type type; int (*func)(struct at_client *hf_at); } handlers[] = { - { "CIEV", AT_CMD_TYPE_UNSOLICITED, ciev_handle } + { "CIEV", AT_CMD_TYPE_UNSOLICITED, ciev_handle }, + { "RING", AT_CMD_TYPE_OTHER, ring_handle } }; static const struct unsolicited *hfp_hf_unsol_lookup(struct at_client *hf_at) From 46e649c536c1987a82c2d67928f4ead4c8c9507b Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Tue, 28 Mar 2017 13:58:05 +0300 Subject: [PATCH 05/41] Bluetooth: monitor: Add support for logging packet drops The monitor protocol provides support for logging packet drops with the help of the extended monitor header. Implement support for this. Change-Id: I7ef7894816cb8d1bd876842d0253ef0980471e69 Signed-off-by: Johan Hedberg --- subsys/bluetooth/host/monitor.c | 93 ++++++++++++++++++++++++++++----- subsys/bluetooth/host/monitor.h | 13 ++++- 2 files changed, 91 insertions(+), 15 deletions(-) diff --git a/subsys/bluetooth/host/monitor.c b/subsys/bluetooth/host/monitor.c index 52022eb7b82..ee075756b3b 100644 --- a/subsys/bluetooth/host/monitor.c +++ b/subsys/bluetooth/host/monitor.c @@ -37,6 +37,18 @@ enum { static atomic_t flags; +static struct { + atomic_t cmd; + atomic_t evt; + atomic_t acl_tx; + atomic_t acl_rx; +#if defined(CONFIG_BLUETOOTH_BREDR) + atomic_t sco_tx; + atomic_t sco_rx; +#endif + atomic_t other; +} drops; + extern int _prf(int (*func)(), void *dest, const char *format, va_list vargs); @@ -49,20 +61,42 @@ static void monitor_send(const void *data, size_t len) } } +static void encode_drops(struct bt_monitor_hdr *hdr, uint8_t type, + atomic_t *val) +{ + atomic_val_t count; + + count = atomic_set(val, 0); + if (count) { + hdr->ext[hdr->hdr_len++] = type; + hdr->ext[hdr->hdr_len++] = min(count, 255); + } +} + static inline void encode_hdr(struct bt_monitor_hdr *hdr, uint16_t opcode, uint16_t len) { - uint32_t ts32; + struct bt_monitor_ts32 *ts; - hdr->hdr_len = sizeof(hdr->type) + sizeof(hdr->ts32); - hdr->data_len = sys_cpu_to_le16(4 + hdr->hdr_len + len); hdr->opcode = sys_cpu_to_le16(opcode); hdr->flags = 0; - /* Extended header */ - hdr->type = BT_MONITOR_TS32; - ts32 = k_uptime_get() * 10; - hdr->ts32 = sys_cpu_to_le32(ts32); + ts = (void *)hdr->ext; + ts->type = BT_MONITOR_TS32; + ts->ts32 = sys_cpu_to_le32(k_uptime_get() * 10); + hdr->hdr_len = sizeof(*ts); + + encode_drops(hdr, BT_MONITOR_COMMAND_DROPS, &drops.cmd); + encode_drops(hdr, BT_MONITOR_EVENT_DROPS, &drops.evt); + encode_drops(hdr, BT_MONITOR_ACL_TX_DROPS, &drops.acl_tx); + encode_drops(hdr, BT_MONITOR_ACL_RX_DROPS, &drops.acl_rx); +#if defined(CONFIG_BLUETOOTH_BREDR) + encode_drops(hdr, BT_MONITOR_SCO_TX_DROPS, &drops.sco_tx); + encode_drops(hdr, BT_MONITOR_SCO_RX_DROPS, &drops.sco_rx); +#endif + encode_drops(hdr, BT_MONITOR_OTHER_DROPS, &drops.other); + + hdr->data_len = sys_cpu_to_le16(4 + hdr->hdr_len + len); } static int log_out(int c, void *unused) @@ -71,6 +105,35 @@ static int log_out(int c, void *unused) return 0; } +static void drop_add(uint16_t opcode) +{ + switch (opcode) { + case BT_MONITOR_COMMAND_PKT: + atomic_inc(&drops.cmd); + break; + case BT_MONITOR_EVENT_PKT: + atomic_inc(&drops.evt); + break; + case BT_MONITOR_ACL_TX_PKT: + atomic_inc(&drops.acl_tx); + break; + case BT_MONITOR_ACL_RX_PKT: + atomic_inc(&drops.acl_rx); + break; +#if defined(CONFIG_BLUETOOTH_BREDR) + case BT_MONITOR_SCO_TX_PKT: + atomic_inc(&drops.sco_tx); + break; + case BT_MONITOR_SCO_RX_PKT: + atomic_inc(&drops.sco_rx); + break; +#endif + default: + atomic_inc(&drops.other); + break; + } +} + void bt_log(int prio, const char *fmt, ...) { struct bt_monitor_user_logging log; @@ -90,14 +153,15 @@ void bt_log(int prio, const char *fmt, ...) log.priority = prio; log.ident_len = sizeof(id); - encode_hdr(&hdr, BT_MONITOR_USER_LOGGING, - sizeof(log) + sizeof(id) + len + 1); - if (atomic_test_and_set_bit(&flags, BT_LOG_BUSY)) { + drop_add(BT_MONITOR_USER_LOGGING); return; } - monitor_send(&hdr, sizeof(hdr)); + encode_hdr(&hdr, BT_MONITOR_USER_LOGGING, + sizeof(log) + sizeof(id) + len + 1); + + monitor_send(&hdr, BT_MONITOR_BASE_HDR_LEN + hdr.hdr_len); monitor_send(&log, sizeof(log)); monitor_send(id, sizeof(id)); @@ -115,13 +179,14 @@ void bt_monitor_send(uint16_t opcode, const void *data, size_t len) { struct bt_monitor_hdr hdr; - encode_hdr(&hdr, opcode, len); - if (atomic_test_and_set_bit(&flags, BT_LOG_BUSY)) { + drop_add(opcode); return; } - monitor_send(&hdr, sizeof(hdr)); + encode_hdr(&hdr, opcode, len); + + monitor_send(&hdr, BT_MONITOR_BASE_HDR_LEN + hdr.hdr_len); monitor_send(data, len); atomic_clear_bit(&flags, BT_LOG_BUSY); diff --git a/subsys/bluetooth/host/monitor.h b/subsys/bluetooth/host/monitor.h index 9faaee2d07d..a52aa915a19 100644 --- a/subsys/bluetooth/host/monitor.h +++ b/subsys/bluetooth/host/monitor.h @@ -39,13 +39,24 @@ #define BT_MONITOR_OTHER_DROPS 7 #define BT_MONITOR_TS32 8 +#define BT_MONITOR_BASE_HDR_LEN 6 + +#if defined(CONFIG_BLUETOOTH_BREDR) +#define BT_MONITOR_EXT_HDR_MAX 19 +#else +#define BT_MONITOR_EXT_HDR_MAX 15 +#endif + struct bt_monitor_hdr { uint16_t data_len; uint16_t opcode; uint8_t flags; uint8_t hdr_len; - /* Extended header */ + uint8_t ext[BT_MONITOR_EXT_HDR_MAX]; +} __packed; + +struct bt_monitor_ts32 { uint8_t type; uint32_t ts32; } __packed; From 646726518f9d9229c7fce5409eaec34967158196 Mon Sep 17 00:00:00 2001 From: Vinayak Chettimada Date: Mon, 27 Mar 2017 11:21:56 +0200 Subject: [PATCH 06/41] Bluetooth: controller: Kconfig for advanced event preparation Added Kconfig option to enable advanced event preparation feature. Enables advanced event preparation offset ahead of radio tx/rx, taking into account predictive processing time requirements in preparation to the event, like control procedure handling and CPU execution speeds. Crystal oscillator is retained between closely spaced consecutive radio events to reduce the overall number of crystal settling current consumptions. This feature maximizes radio utilization in an average role event timeslice when they are closely spaced by using a reduced offset between preparation and radio event. By disabling this feature, the controller will use a constant offset between the preparation and radio event. The controller will toggle crystal oscillator between two closely spaced radio events leading to higher average current due to increased number of crystal settling current consumptions. Change-id: I19e640f7395ac7938873ef4bfac38acf8d6f7e0e Signed-off-by: Vinayak Chettimada --- subsys/bluetooth/controller/Kconfig | 32 +++++++++++++++++ subsys/bluetooth/controller/ll_sw/ctrl.c | 36 ++++++++++---------- tests/bluetooth/init/prj_controller.conf | 1 + tests/bluetooth/init/prj_controller_4_0.conf | 1 + tests/bluetooth/init/prj_controller_dbg.conf | 1 + 5 files changed, 53 insertions(+), 18 deletions(-) diff --git a/subsys/bluetooth/controller/Kconfig b/subsys/bluetooth/controller/Kconfig index d98f2ead0f6..e0ea66e6046 100644 --- a/subsys/bluetooth/controller/Kconfig +++ b/subsys/bluetooth/controller/Kconfig @@ -91,6 +91,38 @@ config BLUETOOTH_CONTROLLER_DATA_LENGTH_MAX help Set the maximum data length of PDU supported in the Controller. +config BLUETOOTH_CONTROLLER_XTAL_ADVANCED + bool "Advanced event preparation" + default y + help + Enables advanced event preparation offset ahead of radio tx/rx, taking + into account predictive processing time requirements in preparation to + the event, like control procedure handling and CPU execution speeds. + Crystal oscillator is retained between closely spaced consecutive + radio events to reduce the overall number of crystal settling current + consumptions. + + This feature maximizes radio utilization in an average role event + timeslice when they are closely spaced by using a reduced offset + between preparation and radio event. + + By disabling this feature, the controller will use a constant offset + between the preparation and radio event. The controller will toggle + crystal oscillator between two closely spaced radio events leading to + higher average current due to increased number of crystal settling + current consumptions. + +config BLUETOOTH_CONTROLLER_XTAL_THRESHOLD + prompt "Crystal shutdown threshold in uS" + depends on BLUETOOTH_CONTROLLER_XTAL_ADVANCED + int + default 5168 + help + Configure the optimal delta in micro seconds between two consecutive + radio events below which (active clock) crystal will be retained. This + value is board dependent. The value 5168 is based on crude calculation + for nRF51 current versus startup time of high frequency crystal. + config BLUETOOTH_CONTROLLER_FAST_ENC bool "Fast Encryption Setup" help diff --git a/subsys/bluetooth/controller/ll_sw/ctrl.c b/subsys/bluetooth/controller/ll_sw/ctrl.c index 2495e33a64d..c0e2fc9f602 100644 --- a/subsys/bluetooth/controller/ll_sw/ctrl.c +++ b/subsys/bluetooth/controller/ll_sw/ctrl.c @@ -56,7 +56,6 @@ #define RADIO_IRK_COUNT_MAX 8 -#define XTAL_ADVANCED 1 #define SCHED_ADVANCED 1 #define SILENT_CONNECTION 0 @@ -2999,7 +2998,7 @@ static void mayfly_xtal_stop(void *params) DEBUG_RADIO_CLOSE(0); } -#if XTAL_ADVANCED +#if CONFIG_BLUETOOTH_CONTROLLER_XTAL_ADVANCED static void mayfly_xtal_retain(uint8_t caller_id, uint8_t retain) { static uint8_t s_xtal_retained; @@ -3165,7 +3164,8 @@ static void mayfly_xtal_stop_calc(void *params) LL_ASSERT(ret_cb == TICKER_STATUS_SUCCESS); if ((ticker_id != 0xff) && - (ticks_to_expire < TICKER_US_TO_TICKS(10000))) { + (ticks_to_expire < + TICKER_US_TO_TICKS(CONFIG_BLUETOOTH_CONTROLLER_XTAL_THRESHOLD))) { mayfly_xtal_retain(RADIO_TICKER_USER_ID_JOB, 1); if (ticker_id >= RADIO_TICKER_ID_ADV) { @@ -3333,7 +3333,7 @@ static void mayfly_xtal_stop_calc(void *params) } } } -#endif /* XTAL_ADVANCED */ +#endif /* CONFIG_BLUETOOTH_CONTROLLER_XTAL_ADVANCED */ #if SCHED_ADVANCED static void sched_after_mstr_free_slot_get(uint8_t user_id, @@ -3929,8 +3929,8 @@ static void event_common_prepare(uint32_t ticks_at_expire, /* route all packets queued for connections */ packet_tx_enqueue(0xFF); +#if CONFIG_BLUETOOTH_CONTROLLER_XTAL_ADVANCED /* calc whether xtal needs to be retained after this event */ -#if XTAL_ADVANCED { static void *s_link[2]; static struct mayfly s_mfy_xtal_stop_calc = {0, 0, s_link, NULL, @@ -3944,7 +3944,7 @@ static void event_common_prepare(uint32_t ticks_at_expire, &s_mfy_xtal_stop_calc); LL_ASSERT(!retval); } -#endif +#endif /* CONFIG_BLUETOOTH_CONTROLLER_XTAL_ADVANCED */ } static uint8_t channel_calc(uint8_t *channel_use, uint8_t hop, @@ -4213,15 +4213,15 @@ static void event_adv(uint32_t ticks_at_expire, uint32_t remainder, _radio.remainder_anchor); radio_tmr_end_capture(); -#if (XTAL_ADVANCED && (RADIO_TICKER_PREEMPT_PART_US \ - <= RADIO_TICKER_PREEMPT_PART_MIN_US)) +#if (CONFIG_BLUETOOTH_CONTROLLER_XTAL_ADVANCED && \ + (RADIO_TICKER_PREEMPT_PART_US <= RADIO_TICKER_PREEMPT_PART_MIN_US)) /* check if preempt to start has changed */ if (preempt_calc(&_radio.advertiser.hdr, RADIO_TICKER_ID_ADV, ticks_at_expire) != 0) { _radio.state = STATE_STOP; radio_disable(); } else -#endif +#endif /* CONFIG_BLUETOOTH_CONTROLLER_XTAL_ADVANCED */ /* Ticker Job Silence */ #if (RADIO_TICKER_USER_ID_WORKER_PRIO == RADIO_TICKER_USER_ID_JOB_PRIO) @@ -4402,15 +4402,15 @@ static void event_obs(uint32_t ticks_at_expire, uint32_t remainder, _radio.remainder_anchor); radio_tmr_end_capture(); -#if (XTAL_ADVANCED && (RADIO_TICKER_PREEMPT_PART_US\ - <= RADIO_TICKER_PREEMPT_PART_MIN_US)) +#if (CONFIG_BLUETOOTH_CONTROLLER_XTAL_ADVANCED && \ + (RADIO_TICKER_PREEMPT_PART_US <= RADIO_TICKER_PREEMPT_PART_MIN_US)) /* check if preempt to start has changed */ if (preempt_calc(&_radio.observer.hdr, RADIO_TICKER_ID_OBS, ticks_at_expire) != 0) { _radio.state = STATE_STOP; radio_disable(); } else -#endif +#endif /* CONFIG_BLUETOOTH_CONTROLLER_XTAL_ADVANCED */ { /* start window close timeout */ ticker_status = @@ -5717,15 +5717,15 @@ static void event_slave(uint32_t ticks_at_expire, uint32_t remainder, conn->role.slave.window_size_event_us); radio_tmr_end_capture(); -#if (XTAL_ADVANCED && (RADIO_TICKER_PREEMPT_PART_US \ - <= RADIO_TICKER_PREEMPT_PART_MIN_US)) +#if (CONFIG_BLUETOOTH_CONTROLLER_XTAL_ADVANCED && \ + (RADIO_TICKER_PREEMPT_PART_US <= RADIO_TICKER_PREEMPT_PART_MIN_US)) /* check if preempt to start has changed */ if (preempt_calc(&conn->hdr, (RADIO_TICKER_ID_FIRST_CONNECTION + conn->handle), ticks_at_expire) != 0) { _radio.state = STATE_STOP; radio_disable(); } else -#endif +#endif /* CONFIG_BLUETOOTH_CONTROLLER_XTAL_ADVANCED */ /* Ticker Job Silence */ #if (RADIO_TICKER_USER_ID_WORKER_PRIO == RADIO_TICKER_USER_ID_JOB_PRIO) @@ -5853,8 +5853,8 @@ static void event_master(uint32_t ticks_at_expire, uint32_t remainder, } #endif -#if (XTAL_ADVANCED && (RADIO_TICKER_PREEMPT_PART_US \ - <= RADIO_TICKER_PREEMPT_PART_MIN_US)) +#if (CONFIG_BLUETOOTH_CONTROLLER_XTAL_ADVANCED && \ + (RADIO_TICKER_PREEMPT_PART_US <= RADIO_TICKER_PREEMPT_PART_MIN_US)) /* check if preempt to start has changed */ if (0 != preempt_calc(&conn->hdr, (RADIO_TICKER_ID_FIRST_CONNECTION + @@ -5862,7 +5862,7 @@ static void event_master(uint32_t ticks_at_expire, uint32_t remainder, _radio.state = STATE_STOP; radio_disable(); } else -#endif +#endif /* CONFIG_BLUETOOTH_CONTROLLER_XTAL_ADVANCED */ /* Ticker Job Silence */ #if (RADIO_TICKER_USER_ID_WORKER_PRIO == RADIO_TICKER_USER_ID_JOB_PRIO) diff --git a/tests/bluetooth/init/prj_controller.conf b/tests/bluetooth/init/prj_controller.conf index fcade189e21..1f8c7f79f17 100644 --- a/tests/bluetooth/init/prj_controller.conf +++ b/tests/bluetooth/init/prj_controller.conf @@ -1,5 +1,6 @@ CONFIG_BLUETOOTH=y CONFIG_BLUETOOTH_CONTROLLER=y +CONFIG_BLUETOOTH_CONTROLLER_XTAL_ADVANCED=y CONFIG_BLUETOOTH_PERIPHERAL=y CONFIG_BLUETOOTH_CENTRAL=y CONFIG_BLUETOOTH_SMP=y diff --git a/tests/bluetooth/init/prj_controller_4_0.conf b/tests/bluetooth/init/prj_controller_4_0.conf index b6bcadafb0a..dc12481b9ed 100644 --- a/tests/bluetooth/init/prj_controller_4_0.conf +++ b/tests/bluetooth/init/prj_controller_4_0.conf @@ -1,5 +1,6 @@ CONFIG_BLUETOOTH=y CONFIG_BLUETOOTH_CONTROLLER=y +CONFIG_BLUETOOTH_CONTROLLER_XTAL_ADVANCED=y CONFIG_BLUETOOTH_CONTROLLER_LE_PING=n CONFIG_BLUETOOTH_CONTROLLER_DATA_LENGTH=n CONFIG_BLUETOOTH_CONTROLLER_CONN_RSSI=n diff --git a/tests/bluetooth/init/prj_controller_dbg.conf b/tests/bluetooth/init/prj_controller_dbg.conf index 2208928743c..97226696e5b 100644 --- a/tests/bluetooth/init/prj_controller_dbg.conf +++ b/tests/bluetooth/init/prj_controller_dbg.conf @@ -1,5 +1,6 @@ CONFIG_BLUETOOTH=y CONFIG_BLUETOOTH_CONTROLLER=y +CONFIG_BLUETOOTH_CONTROLLER_XTAL_ADVANCED=n CONFIG_BLUETOOTH_CONTROLLER_CONN_RSSI=y CONFIG_BLUETOOTH_CONTROLLER_ADV_INDICATION=y CONFIG_BLUETOOTH_CONTROLLER_PROFILE_ISR=y From 60e44f6956c3521ec4f7bb57d6ce1981ce0f8add Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Tue, 28 Mar 2017 22:00:04 +0300 Subject: [PATCH 07/41] Bluetooth: HCI: Add define for success status Change-Id: I048318094f3eac3e5e705ccc2d3c53512430e960 Signed-off-by: Johan Hedberg --- include/bluetooth/hci.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/bluetooth/hci.h b/include/bluetooth/hci.h index fe7a3762287..b74fb972613 100644 --- a/include/bluetooth/hci.h +++ b/include/bluetooth/hci.h @@ -88,6 +88,7 @@ static inline bool bt_addr_le_is_identity(const bt_addr_le_t *addr) } /* HCI Error Codes */ +#define BT_HCI_ERR_SUCCESS 0x00 #define BT_HCI_ERR_UNKNOWN_CMD 0x01 #define BT_HCI_ERR_UNKNOWN_CONN_ID 0x02 #define BT_HCI_ERR_AUTHENTICATION_FAIL 0x05 From 9028e8e75b8ca238c9967667d5c0536ca749d668 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Tue, 28 Mar 2017 22:00:20 +0300 Subject: [PATCH 08/41] Bluetooth: ECC: Fix command status emission from wrong thread HCI drivers are obliged to send HCI Command Status/Complete events from a separate context than all other data, however the ECC wrapper was violating this rule (sending everything from the same ECC thread). This could lead to a deadlock if e.g. the ECC API user decides to generate a DHKey from the same callback that it got notified of local key-pair generation. The obvious solution is to emit the Command Status directly from the send function, before passing the command to be processed by the ECC therad (through a k_fifo). However, this is not quite so simple since bt_buf_get_cmd_complete() reuses the original command buffer, meaning we'd loose the original parameters after sending a Command Status. To work around this limitation with bt_buf_get_cmd_complete() we stop passing the command buffer to the thread and instead store the parameters in static variables and do the thread communication using flags and a semaphore. One side effect is that only one command can be pending at a time, however that works out fine for all of the users of ECC. A nice side effect of moving some things to static variables is that we end up reducing call stack usage in the ECC thread, allowing it to be shrunk by 180 bytes (verified to be sufficient for both ARM and x86 boards). Change-Id: Ic41f0316d3fe4d14b64fd3d0a549b221d168411a Signed-off-by: Johan Hedberg --- subsys/bluetooth/host/hci_ecc.c | 142 +++++++++++++++++++------------- 1 file changed, 87 insertions(+), 55 deletions(-) diff --git a/subsys/bluetooth/host/hci_ecc.c b/subsys/bluetooth/host/hci_ecc.c index 5473c1b59e8..5d3b824c33f 100644 --- a/subsys/bluetooth/host/hci_ecc.c +++ b/subsys/bluetooth/host/hci_ecc.c @@ -33,7 +33,7 @@ #include "hci_core.h" #endif -static BT_STACK_NOINIT(ecc_thread_stack, 1280); +static BT_STACK_NOINIT(ecc_thread_stack, 1100); /* based on Core Specification 4.2 Vol 3. Part H 2.3.5.6.1 */ static const uint32_t debug_private_key[8] = { @@ -52,9 +52,22 @@ static const uint8_t debug_public_key[64] = { }; #endif -static K_FIFO_DEFINE(ecc_queue); +enum { + PENDING_PUB_KEY, + PENDING_DHKEY, +}; + +static atomic_t flags; + +static K_SEM_DEFINE(cmd_sem, 0, 1); + static uint32_t private_key[8]; +static union { + EccPoint pk; + uint32_t dhkey[8]; +} ecc; + static void send_cmd_status(uint16_t opcode, uint8_t status) { struct bt_hci_evt_cmd_status *evt; @@ -105,21 +118,17 @@ static uint8_t generate_keys(EccPoint *pkey, uint32_t private_key[8]) return 0; } -static void emulate_le_p256_public_key_cmd(struct net_buf *buf) +static void emulate_le_p256_public_key_cmd(void) { struct bt_hci_evt_le_p256_public_key_complete *evt; struct bt_hci_evt_le_meta_event *meta; struct bt_hci_evt_hdr *hdr; + struct net_buf *buf; uint8_t status; - EccPoint pkey; BT_DBG(""); - net_buf_unref(buf); - - send_cmd_status(BT_HCI_OP_LE_P256_PUBLIC_KEY, 0); - - status = generate_keys(&pkey, private_key); + status = generate_keys(&ecc.pk, private_key); buf = bt_buf_get_rx(K_FOREVER); bt_buf_set_type(buf, BT_BUF_EVT); @@ -137,42 +146,22 @@ static void emulate_le_p256_public_key_cmd(struct net_buf *buf) if (status) { memset(evt->key, 0, sizeof(evt->key)); } else { - memcpy(evt->key, pkey.x, 32); - memcpy(&evt->key[32], pkey.y, 32); + memcpy(evt->key, ecc.pk.x, 32); + memcpy(&evt->key[32], ecc.pk.y, 32); } + atomic_clear_bit(&flags, PENDING_PUB_KEY); + bt_recv(buf); } -static void emulate_le_generate_dhkey(struct net_buf *buf) +static void emulate_le_generate_dhkey(void) { struct bt_hci_evt_le_generate_dhkey_complete *evt; - struct bt_hci_cp_le_generate_dhkey *cmd; struct bt_hci_evt_le_meta_event *meta; struct bt_hci_evt_hdr *hdr; + struct net_buf *buf; int32_t ret; - /* The following large stack variables are never needed at the same - * time, so we save some stack space by putting them in a union. - */ - union { - EccPoint pk; - uint32_t dhkey[8]; - } ecc; - - if (buf->len < sizeof(*cmd)) { - send_cmd_status(BT_HCI_OP_LE_GENERATE_DHKEY, - BT_HCI_ERR_INVALID_PARAMS); - return; - } - - cmd = (void *)buf->data + sizeof(struct bt_hci_cmd_hdr); - - memcpy(ecc.pk.x, cmd->key, 32); - memcpy(ecc.pk.y, &cmd->key[32], 32); - - send_cmd_status(BT_HCI_OP_LE_GENERATE_DHKEY, 0); - - net_buf_unref(buf); if (ecc_valid_public_key(&ecc.pk) < 0) { ret = TC_CRYPTO_FAIL; @@ -200,31 +189,22 @@ static void emulate_le_generate_dhkey(struct net_buf *buf) memcpy(evt->dhkey, ecc.dhkey, sizeof(ecc.dhkey)); } + atomic_clear_bit(&flags, PENDING_DHKEY); + bt_recv(buf); } static void ecc_thread(void *p1, void *p2, void *p3) { while (true) { - struct net_buf *buf; - struct bt_hci_cmd_hdr *chdr; - uint16_t opcode; + k_sem_take(&cmd_sem, K_FOREVER); - buf = k_fifo_get(&ecc_queue, K_FOREVER); - chdr = (void *)buf->data; - opcode = sys_le16_to_cpu(chdr->opcode); - switch (opcode) { - case BT_HCI_OP_LE_P256_PUBLIC_KEY: - emulate_le_p256_public_key_cmd(buf); - break; - case BT_HCI_OP_LE_GENERATE_DHKEY: - emulate_le_generate_dhkey(buf); - break; - default: - BT_ERR("Unhandled command for ECC task (opcode %x)", - opcode); - net_buf_unref(buf); - break; + if (atomic_test_bit(&flags, PENDING_PUB_KEY)) { + emulate_le_p256_public_key_cmd(); + } else if (atomic_test_bit(&flags, PENDING_DHKEY)) { + emulate_le_generate_dhkey(); + } else { + __ASSERT(0, "Unhandled ECC command"); } stack_analyze("ecc stack", ecc_thread_stack, @@ -246,16 +226,68 @@ static void clear_ecc_events(struct net_buf *buf) cmd->events[1] &= ~0x01; /* LE Generate DHKey Compl Event */ } +static void le_gen_dhkey(struct net_buf *buf) +{ + struct bt_hci_cp_le_generate_dhkey *cmd; + uint8_t status; + + if (atomic_test_bit(&flags, PENDING_PUB_KEY)) { + status = BT_HCI_ERR_CMD_DISALLOWED; + goto send_status; + } + + if (buf->len < sizeof(struct bt_hci_cp_le_generate_dhkey)) { + status = BT_HCI_ERR_INVALID_PARAMS; + goto send_status; + } + + if (atomic_test_and_set_bit(&flags, PENDING_DHKEY)) { + status = BT_HCI_ERR_CMD_DISALLOWED; + goto send_status; + } + + cmd = (void *)buf->data; + memcpy(ecc.pk.x, cmd->key, 32); + memcpy(ecc.pk.y, &cmd->key[32], 32); + k_sem_give(&cmd_sem); + status = BT_HCI_ERR_SUCCESS; + +send_status: + net_buf_unref(buf); + send_cmd_status(BT_HCI_OP_LE_GENERATE_DHKEY, status); +} + +static void le_p256_pub_key(struct net_buf *buf) +{ + uint8_t status; + + net_buf_unref(buf); + + if (atomic_test_bit(&flags, PENDING_DHKEY)) { + status = BT_HCI_ERR_CMD_DISALLOWED; + } else if (atomic_test_and_set_bit(&flags, PENDING_PUB_KEY)) { + status = BT_HCI_ERR_CMD_DISALLOWED; + } else { + k_sem_give(&cmd_sem); + status = BT_HCI_ERR_SUCCESS; + } + + send_cmd_status(BT_HCI_OP_LE_P256_PUBLIC_KEY, status); +} + int bt_hci_ecc_send(struct net_buf *buf) { if (bt_buf_get_type(buf) == BT_BUF_CMD) { - struct bt_hci_cmd_hdr *chdr = (void *)buf->data; switch (sys_le16_to_cpu(chdr->opcode)) { case BT_HCI_OP_LE_P256_PUBLIC_KEY: + net_buf_pull(buf, sizeof(*chdr)); + le_p256_pub_key(buf); + return 0; case BT_HCI_OP_LE_GENERATE_DHKEY: - net_buf_put(&ecc_queue, buf); + net_buf_pull(buf, sizeof(*chdr)); + le_gen_dhkey(buf); return 0; case BT_HCI_OP_LE_SET_EVENT_MASK: clear_ecc_events(buf); From f38d57cba31fe6ff17c3558e2008f2a5b309410e Mon Sep 17 00:00:00 2001 From: Vinayak Chettimada Date: Mon, 27 Mar 2017 10:44:06 +0200 Subject: [PATCH 09/41] Bluetooth: controller: Kconfig option for advanced scheduling Add Kconfig option to enable advanced scheduling in the controller. Enable non-overlapping placement of observer, initiator and master roles in timespace. Uses window offset in connection updates and uses connection parameter request in slave role to negotiate non-overlapping placement with active master roles to avoid slave roles drifting into active master roles in the local controller. This feature maximizes the average data transmission amongst active concurrent master and slave connections while other observer, initiator, master or slave roles are active in the local controller. Disabling this feature will lead to overlapping role in timespace leading to skipped events amongst active roles. Change-id: I16e4e6c3ca99f93987ab86924af0cb9d76bdbc7e Signed-off-by: Vinayak Chettimada --- subsys/bluetooth/controller/Kconfig | 19 +++++++ subsys/bluetooth/controller/ll_sw/ctrl.c | 60 ++++++++++---------- tests/bluetooth/init/prj_controller.conf | 1 + tests/bluetooth/init/prj_controller_4_0.conf | 1 + tests/bluetooth/init/prj_controller_dbg.conf | 1 + 5 files changed, 52 insertions(+), 30 deletions(-) diff --git a/subsys/bluetooth/controller/Kconfig b/subsys/bluetooth/controller/Kconfig index e0ea66e6046..2113f1abe84 100644 --- a/subsys/bluetooth/controller/Kconfig +++ b/subsys/bluetooth/controller/Kconfig @@ -123,6 +123,25 @@ config BLUETOOTH_CONTROLLER_XTAL_THRESHOLD value is board dependent. The value 5168 is based on crude calculation for nRF51 current versus startup time of high frequency crystal. +config BLUETOOTH_CONTROLLER_SCHED_ADVANCED + bool "Advanced scheduling" + depends on (BLUETOOTH_MAX_CONN != 0) + default y + default n if BLUETOOTH_PERIPHERAL && !BLUETOOTH_CENTRAL + help + Enable non-overlapping placement of observer, initiator and master + roles in timespace. Uses window offset in connection updates and uses + connection parameter request in slave role to negotiate + non-overlapping placement with active master roles to avoid slave + roles drifting into active master roles in the local controller. + + This feature maximizes the average data transmission amongst active + concurrent master and slave connections while other observer, + initiator, master or slave roles are active in the local controller. + + Disabling this feature will lead to overlapping role in timespace + leading to skipped events amongst active roles. + config BLUETOOTH_CONTROLLER_FAST_ENC bool "Fast Encryption Setup" help diff --git a/subsys/bluetooth/controller/ll_sw/ctrl.c b/subsys/bluetooth/controller/ll_sw/ctrl.c index c0e2fc9f602..e185e92b2d1 100644 --- a/subsys/bluetooth/controller/ll_sw/ctrl.c +++ b/subsys/bluetooth/controller/ll_sw/ctrl.c @@ -56,7 +56,6 @@ #define RADIO_IRK_COUNT_MAX 8 -#define SCHED_ADVANCED 1 #define SILENT_CONNECTION 0 #define RADIO_PHY_ADV 0 @@ -3169,10 +3168,10 @@ static void mayfly_xtal_stop_calc(void *params) mayfly_xtal_retain(RADIO_TICKER_USER_ID_JOB, 1); if (ticker_id >= RADIO_TICKER_ID_ADV) { -#if SCHED_ADVANCED +#if CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED uint8_t ticker_id_current = ((uint32_t)params & 0xff); struct connection *conn_curr = NULL; -#endif +#endif /* CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED */ uint32_t ticks_prepare_to_start; struct connection *conn = NULL; struct shdr *hdr = NULL; @@ -3232,7 +3231,7 @@ static void mayfly_xtal_stop_calc(void *params) } } -#if SCHED_ADVANCED +#if CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED if (ticker_id_current >= RADIO_TICKER_ID_FIRST_CONNECTION) { /* compensate the current ticker for reduced * prepare. @@ -3302,7 +3301,7 @@ static void mayfly_xtal_stop_calc(void *params) } } } -#endif /* SCHED_ADVANCED */ +#endif /* CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED */ } } else { mayfly_xtal_retain(RADIO_TICKER_USER_ID_JOB, 0); @@ -3335,7 +3334,7 @@ static void mayfly_xtal_stop_calc(void *params) } #endif /* CONFIG_BLUETOOTH_CONTROLLER_XTAL_ADVANCED */ -#if SCHED_ADVANCED +#if CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED static void sched_after_mstr_free_slot_get(uint8_t user_id, uint32_t ticks_slot_abs, uint32_t *ticks_anchor, @@ -3743,7 +3742,7 @@ static void mayfly_sched_win_offset_select(void *params) error_code = 0x20; /* Unsupported parameter value */ } } -#endif /* SCHED_ADVANCED */ +#endif /* CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED */ static void mayfly_radio_stop(void *params) { @@ -4312,7 +4311,7 @@ static void event_obs_prepare(uint32_t ticks_at_expire, uint32_t remainder, _radio.observer.hdr.ticks_preempt_to_start, RADIO_TICKER_ID_OBS, event_obs, NULL); -#if SCHED_ADVANCED +#if CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED /* calc next group in us for the anchor where first connection event * to be placed */ @@ -4345,7 +4344,7 @@ static void event_obs_prepare(uint32_t ticks_at_expire, uint32_t remainder, &s_mfy_sched_after_mstr_free_offset_get); LL_ASSERT(!retval); } -#endif +#endif /* CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED */ DEBUG_RADIO_PREPARE_O(0); } @@ -4480,7 +4479,7 @@ event_conn_update_st_init(struct connection *conn, pdu_ctrl_tx->payload.llctrl.ctrldata.conn_update_ind.instant = conn->llcp.connection_update.instant; -#if SCHED_ADVANCED +#if CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED { uint32_t retval; @@ -4512,11 +4511,11 @@ event_conn_update_st_init(struct connection *conn, mayfly_sched_offset); LL_ASSERT(!retval); } -#else +#else /* !CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED */ ARG_UNUSED(ticks_at_expire); ARG_UNUSED(mayfly_sched_offset); ARG_UNUSED(fp_mayfly_select_or_use); -#endif +#endif /* !CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED */ } static inline void event_conn_update_st_req(struct connection *conn, @@ -4554,7 +4553,7 @@ static inline void event_conn_update_st_req(struct connection *conn, /* Start Procedure Timeout */ conn->procedure_expire = conn->procedure_reload; -#if SCHED_ADVANCED +#if CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED { uint32_t retval; @@ -4583,10 +4582,10 @@ static inline void event_conn_update_st_req(struct connection *conn, mayfly_sched_offset); LL_ASSERT(!retval); } -#else +#else /* !CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED */ ARG_UNUSED(ticks_at_expire); ARG_UNUSED(mayfly_sched_offset); -#endif +#endif /* !CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED */ } static inline void event_conn_update_st_rsp(struct connection *conn, @@ -4655,12 +4654,12 @@ static inline uint32_t event_conn_update_prep(struct connection *conn, LLCP_CONN_STATE_APP_WAIT) && (conn->llcp.connection_update.state != LLCP_CONN_STATE_RSP_WAIT)) { -#if SCHED_ADVANCED +#if CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED static void *s_link[2]; static struct mayfly s_mfy_sched_offset = {0, 0, s_link, NULL, NULL }; void (*fp_mayfly_select_or_use)(void *); -#endif +#endif /* CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED */ struct radio_pdu_node_tx *node_tx; struct pdu_data *pdu_ctrl_tx; uint8_t state; @@ -4672,55 +4671,55 @@ static inline uint32_t event_conn_update_prep(struct connection *conn, pdu_ctrl_tx = (struct pdu_data *)node_tx->pdu_data; -#if SCHED_ADVANCED +#if CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED fp_mayfly_select_or_use = mayfly_sched_win_offset_use; -#endif +#endif /* CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED */ state = conn->llcp.connection_update.state; if ((state == LLCP_CONN_STATE_RSP) && (conn->role.master.role == 0)) { state = LLCP_CONN_STATE_INITIATE; -#if SCHED_ADVANCED +#if CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED fp_mayfly_select_or_use = mayfly_sched_win_offset_select; -#endif +#endif /* CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED */ } switch (state) { case LLCP_CONN_STATE_INITIATE: if (conn->role.master.role == 0) { -#if SCHED_ADVANCED +#if CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED event_conn_update_st_init(conn, event_counter, pdu_ctrl_tx, ticks_at_expire, &s_mfy_sched_offset, fp_mayfly_select_or_use); -#else +#else /* !CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED */ event_conn_update_st_init(conn, event_counter, pdu_ctrl_tx, ticks_at_expire, NULL, NULL); -#endif +#endif /* !CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED */ break; } /* fall thru if slave */ case LLCP_CONN_STATE_REQ: -#if SCHED_ADVANCED +#if CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED event_conn_update_st_req(conn, event_counter, pdu_ctrl_tx, ticks_at_expire, &s_mfy_sched_offset); -#else +#else /* !CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED */ event_conn_update_st_req(conn, event_counter, pdu_ctrl_tx, ticks_at_expire, NULL); -#endif +#endif /* !CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED */ break; case LLCP_CONN_STATE_RSP: @@ -7363,17 +7362,18 @@ uint32_t radio_scan_enable(uint8_t scan_type, uint8_t init_addr_type, ticks_anchor = ticker_ticks_now_get(); - if ((_radio.observer.conn) || !SCHED_ADVANCED) { + if ((_radio.observer.conn) || + !IS_ENABLED(CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED)) { us_offset = 0; } -#if SCHED_ADVANCED +#if CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED else { sched_after_mstr_free_slot_get(RADIO_TICKER_USER_ID_APP, (ticks_slot_offset + _radio.observer.hdr.ticks_slot), &ticks_anchor, &us_offset); } -#endif +#endif /* CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED */ ret = ticker_start(RADIO_TICKER_INSTANCE_ID_RADIO, RADIO_TICKER_USER_ID_APP, RADIO_TICKER_ID_OBS, diff --git a/tests/bluetooth/init/prj_controller.conf b/tests/bluetooth/init/prj_controller.conf index 1f8c7f79f17..7d679719992 100644 --- a/tests/bluetooth/init/prj_controller.conf +++ b/tests/bluetooth/init/prj_controller.conf @@ -1,6 +1,7 @@ CONFIG_BLUETOOTH=y CONFIG_BLUETOOTH_CONTROLLER=y CONFIG_BLUETOOTH_CONTROLLER_XTAL_ADVANCED=y +CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED=y CONFIG_BLUETOOTH_PERIPHERAL=y CONFIG_BLUETOOTH_CENTRAL=y CONFIG_BLUETOOTH_SMP=y diff --git a/tests/bluetooth/init/prj_controller_4_0.conf b/tests/bluetooth/init/prj_controller_4_0.conf index dc12481b9ed..f5cad448610 100644 --- a/tests/bluetooth/init/prj_controller_4_0.conf +++ b/tests/bluetooth/init/prj_controller_4_0.conf @@ -1,6 +1,7 @@ CONFIG_BLUETOOTH=y CONFIG_BLUETOOTH_CONTROLLER=y CONFIG_BLUETOOTH_CONTROLLER_XTAL_ADVANCED=y +CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED=y CONFIG_BLUETOOTH_CONTROLLER_LE_PING=n CONFIG_BLUETOOTH_CONTROLLER_DATA_LENGTH=n CONFIG_BLUETOOTH_CONTROLLER_CONN_RSSI=n diff --git a/tests/bluetooth/init/prj_controller_dbg.conf b/tests/bluetooth/init/prj_controller_dbg.conf index 97226696e5b..b9128fa73d1 100644 --- a/tests/bluetooth/init/prj_controller_dbg.conf +++ b/tests/bluetooth/init/prj_controller_dbg.conf @@ -1,6 +1,7 @@ CONFIG_BLUETOOTH=y CONFIG_BLUETOOTH_CONTROLLER=y CONFIG_BLUETOOTH_CONTROLLER_XTAL_ADVANCED=n +CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED=n CONFIG_BLUETOOTH_CONTROLLER_CONN_RSSI=y CONFIG_BLUETOOTH_CONTROLLER_ADV_INDICATION=y CONFIG_BLUETOOTH_CONTROLLER_PROFILE_ISR=y From 16bd3d48db068293c9ed1eed51d2250df7e8fc04 Mon Sep 17 00:00:00 2001 From: Vinayak Chettimada Date: Tue, 28 Mar 2017 00:25:14 +0200 Subject: [PATCH 10/41] Bluetooth: controller: Hide advance features in Kconfig Added a explicit Kconfig option to show the Controller's advanced feature configurations. These feature configurations need specific in-depth Controller implementation knowledge and should not overwhelm normal users of the Controller. Change-id: Iae764f2b266b199cf180936c51c7a4ea089ee510 Signed-off-by: Vinayak Chettimada --- subsys/bluetooth/controller/Kconfig | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/subsys/bluetooth/controller/Kconfig b/subsys/bluetooth/controller/Kconfig index 2113f1abe84..7225920bc2f 100644 --- a/subsys/bluetooth/controller/Kconfig +++ b/subsys/bluetooth/controller/Kconfig @@ -91,6 +91,14 @@ config BLUETOOTH_CONTROLLER_DATA_LENGTH_MAX help Set the maximum data length of PDU supported in the Controller. +config BLUETOOTH_CONTROLLER_ADVANCED_FEATURES + bool "Show advanced features" + help + Makes advanced features visible to controller developers. + +menu "Advanced features" + visible if BLUETOOTH_CONTROLLER_ADVANCED_FEATURES + config BLUETOOTH_CONTROLLER_XTAL_ADVANCED bool "Advanced event preparation" default y @@ -165,6 +173,8 @@ config BLUETOOTH_CONTROLLER_ADV_INDICATION help Generate events indicating on air advertisement events. +endmenu + comment "BLE Controller debug configuration" config BLUETOOTH_CONTROLLER_ASSERT_HANDLER From b593e44da6d08b83ab83059b382f7a82093dc586 Mon Sep 17 00:00:00 2001 From: Vinayak Chettimada Date: Tue, 28 Mar 2017 00:37:05 +0200 Subject: [PATCH 11/41] Bluetooth: controller: Move comp id and subver to configuration Move company id and subversion number Kconfig to the Controller configuration section from the features section. Change-id: Ic4deb8b24d84d9b1817ba542705eebd612f0e020 Signed-off-by: Vinayak Chettimada --- subsys/bluetooth/controller/Kconfig | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/subsys/bluetooth/controller/Kconfig b/subsys/bluetooth/controller/Kconfig index 7225920bc2f..c212381762d 100644 --- a/subsys/bluetooth/controller/Kconfig +++ b/subsys/bluetooth/controller/Kconfig @@ -47,12 +47,6 @@ config BLUETOOTH_CONTROLLER_TX_BUFFER_SIZE Maximum is set to 16384 due to implementation limitations (use of uint16_t for size/length variables). -config BLUETOOTH_CONTROLLER_RX_PRIO_STACK_SIZE - int - default 320 - -comment "BLE Controller features" - config BLUETOOTH_CONTROLLER_COMPANY_ID prompt "Company Id" hex @@ -69,6 +63,12 @@ config BLUETOOTH_CONTROLLER_SUBVERSION_NUMBER help Set the Subversion Number that will be used in VERSION_IND PDU. +config BLUETOOTH_CONTROLLER_RX_PRIO_STACK_SIZE + int + default 320 + +comment "BLE Controller features" + config BLUETOOTH_CONTROLLER_LE_PING bool "LE Ping" default y From dd1ba2872654d1bb7a45344d97171d3d9fd3e411 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Wed, 29 Mar 2017 13:41:49 +0300 Subject: [PATCH 12/41] Bluetooth: Controller: Introduce rate-limiting on stack analysis In case the controller is receiving PDUs very rapidly, prevent it from spamming the logs by limiting its stack analysis to at most once every 5 seconds. Change-Id: I31c70d28e8af62b27172a4a77bf6e614ea3e20eb Signed-off-by: Johan Hedberg --- subsys/bluetooth/controller/hci/hci_driver.c | 24 ++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/subsys/bluetooth/controller/hci/hci_driver.c b/subsys/bluetooth/controller/hci/hci_driver.c index e4cae0ffd44..25ced39f0dc 100644 --- a/subsys/bluetooth/controller/hci/hci_driver.c +++ b/subsys/bluetooth/controller/hci/hci_driver.c @@ -46,6 +46,11 @@ static BT_STACK_NOINIT(prio_recv_thread_stack, CONFIG_BLUETOOTH_CONTROLLER_RX_PRIO_STACK_SIZE); static BT_STACK_NOINIT(recv_thread_stack, CONFIG_BLUETOOTH_RX_STACK_SIZE); +#if defined(CONFIG_INIT_STACKS) +static uint32_t prio_ts; +static uint32_t rx_ts; +#endif + static void prio_recv_thread(void *p1, void *p2, void *p3) { while (1) { @@ -79,8 +84,14 @@ static void prio_recv_thread(void *p1, void *p2, void *p3) k_sem_take(&sem_prio_recv, K_FOREVER); BT_DBG("sem taken"); - stack_analyze("prio recv thread stack", prio_recv_thread_stack, - sizeof(prio_recv_thread_stack)); +#if defined(CONFIG_INIT_STACKS) + if (k_uptime_get_32() - prio_ts > K_SECONDS(5)) { + stack_analyze("prio recv thread stack", + prio_recv_thread_stack, + sizeof(prio_recv_thread_stack)); + prio_ts = k_uptime_get_32(); + } +#endif } } @@ -135,8 +146,13 @@ static void recv_thread(void *p1, void *p2, void *p3) k_yield(); - stack_analyze("recv thread stack", recv_thread_stack, - sizeof(recv_thread_stack)); +#if defined(CONFIG_INIT_STACKS) + if (k_uptime_get_32() - rx_ts > K_SECONDS(5)) { + stack_analyze("recv thread stack", recv_thread_stack, + sizeof(recv_thread_stack)); + rx_ts = k_uptime_get_32(); + } +#endif } } From 3136aa2ced9a0d0acdad3ff8c6d88366132b2782 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Thu, 30 Mar 2017 15:01:59 +0300 Subject: [PATCH 13/41] Bluetooth: GATT: Fix using write command when signing was requested Checking both if signing has been requested _and_ conn->encrypt can bypass signing leading to the caller to assume that a proper signature was send in when fact it was not. To fix now the code explicitly checks if SMP is enabled and in case it is and signing was requested fails. Change-Id: Ie17df4a4c2191f2da0172c687db7999395839a97 Signed-off-by: Luiz Augusto von Dentz --- subsys/bluetooth/host/gatt.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/subsys/bluetooth/host/gatt.c b/subsys/bluetooth/host/gatt.c index 2b0ebacfe60..71263f917c2 100644 --- a/subsys/bluetooth/host/gatt.c +++ b/subsys/bluetooth/host/gatt.c @@ -1481,15 +1481,6 @@ static void gatt_write_rsp(struct bt_conn *conn, uint8_t err, const void *pdu, params->func(conn, err, params); } -static bool write_signed_allowed(struct bt_conn *conn) -{ -#if defined(CONFIG_BLUETOOTH_SMP) - return conn->encrypt == 0; -#else - return false; -#endif /* CONFIG_BLUETOOTH_SMP */ -} - int bt_gatt_write_without_response(struct bt_conn *conn, uint16_t handle, const void *data, uint16_t length, bool sign) { @@ -1503,7 +1494,18 @@ int bt_gatt_write_without_response(struct bt_conn *conn, uint16_t handle, return -ENOTCONN; } - if (sign && write_signed_allowed(conn)) { +#if defined(CONFIG_BLUETOOTH_SMP) + if (conn->encrypt) { + /* Don't need to sign if already encrypted */ + sign = false; + } +#else + if (sign) { + return -EOPNOTSUPP; + } +#endif + + if (sign) { buf = bt_att_create_pdu(conn, BT_ATT_OP_SIGNED_WRITE_CMD, sizeof(*cmd) + length + 12); } else { From 757fd755a6b645d0c85cfaaf4fa1d301410a4a19 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sun, 19 Mar 2017 13:35:09 +0200 Subject: [PATCH 14/41] Bluetooth: Remove unnecessary controller-side buffers tracking When there's no support for connections there's also no need to track the controller side buffers. Change-Id: I7eac3af486f139f1ab32efda8ccfa188ed8359eb Signed-off-by: Johan Hedberg --- subsys/bluetooth/host/conn.c | 11 +++++++++++ subsys/bluetooth/host/conn_internal.h | 11 +---------- subsys/bluetooth/host/hci_core.c | 11 +++++++++-- subsys/bluetooth/host/hci_core.h | 2 ++ 4 files changed, 23 insertions(+), 12 deletions(-) diff --git a/subsys/bluetooth/host/conn.c b/subsys/bluetooth/host/conn.c index 86add72b4f4..bf8b67094f3 100644 --- a/subsys/bluetooth/host/conn.c +++ b/subsys/bluetooth/host/conn.c @@ -64,6 +64,17 @@ static const uint8_t ssp_method[4 /* remote */][4 /* local */] = { }; #endif /* CONFIG_BLUETOOTH_BREDR */ +struct k_sem *bt_conn_get_pkts(struct bt_conn *conn) +{ +#if defined(CONFIG_BLUETOOTH_BREDR) + if (conn->type == BT_CONN_TYPE_BR || !bt_dev.le.mtu) { + return &bt_dev.br.pkts; + } +#endif /* CONFIG_BLUETOOTH_BREDR */ + + return &bt_dev.le.pkts; +} + static inline const char *state2str(bt_conn_state_t state) { switch (state) { diff --git a/subsys/bluetooth/host/conn_internal.h b/subsys/bluetooth/host/conn_internal.h index 0d9ca5221c2..a224da7be41 100644 --- a/subsys/bluetooth/host/conn_internal.h +++ b/subsys/bluetooth/host/conn_internal.h @@ -186,16 +186,7 @@ struct net_buf *bt_conn_create_pdu(struct net_buf_pool *pool, size_t reserve); int bt_conn_init(void); /* Selects based on connecton type right semaphore for ACL packets */ -static inline struct k_sem *bt_conn_get_pkts(struct bt_conn *conn) -{ -#if defined(CONFIG_BLUETOOTH_BREDR) - if (conn->type == BT_CONN_TYPE_BR || !bt_dev.le.mtu) { - return &bt_dev.br.pkts; - } -#endif /* CONFIG_BLUETOOTH_BREDR */ - - return &bt_dev.le.pkts; -} +struct k_sem *bt_conn_get_pkts(struct bt_conn *conn); /* k_poll related helpers for the TX thread */ int bt_conn_prepare_events(struct k_poll_event events[]); diff --git a/subsys/bluetooth/host/hci_core.c b/subsys/bluetooth/host/hci_core.c index c006a694016..1c97c6f5693 100644 --- a/subsys/bluetooth/host/hci_core.c +++ b/subsys/bluetooth/host/hci_core.c @@ -2836,7 +2836,7 @@ static void read_buffer_size_complete(struct net_buf *buf) k_sem_init(&bt_dev.br.pkts, pkts, pkts); } -#else +#elif defined(CONFIG_BLUETOOTH_CONN) static void read_buffer_size_complete(struct net_buf *buf) { struct bt_hci_rp_read_buffer_size *rp = (void *)buf->data; @@ -2858,6 +2858,7 @@ static void read_buffer_size_complete(struct net_buf *buf) } #endif +#if defined(CONFIG_BLUETOOTH_CONN) static void le_read_buffer_size_complete(struct net_buf *buf) { struct bt_hci_rp_le_read_buffer_size *rp = (void *)buf->data; @@ -2872,6 +2873,7 @@ static void le_read_buffer_size_complete(struct net_buf *buf) bt_dev.le.mtu); } } +#endif static void read_supported_commands_complete(struct net_buf *buf) { @@ -2994,13 +2996,16 @@ static int le_init(void) read_le_features_complete(rsp); net_buf_unref(rsp); +#if defined(CONFIG_BLUETOOTH_CONN) /* Read LE Buffer Size */ - err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_READ_BUFFER_SIZE, NULL, &rsp); + err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_READ_BUFFER_SIZE, + NULL, &rsp); if (err) { return err; } le_read_buffer_size_complete(rsp); net_buf_unref(rsp); +#endif if (BT_FEAT_BREDR(bt_dev.features)) { buf = bt_hci_cmd_create(BT_HCI_OP_LE_WRITE_LE_HOST_SUPP, @@ -3262,6 +3267,7 @@ static int br_init(void) #else static int br_init(void) { +#if defined(CONFIG_BLUETOOTH_CONN) struct net_buf *rsp; int err; @@ -3277,6 +3283,7 @@ static int br_init(void) read_buffer_size_complete(rsp); net_buf_unref(rsp); +#endif /* CONFIG_BLUETOOTH_CONN */ return 0; } diff --git a/subsys/bluetooth/host/hci_core.h b/subsys/bluetooth/host/hci_core.h index a63c8fce57c..abf4405da7c 100644 --- a/subsys/bluetooth/host/hci_core.h +++ b/subsys/bluetooth/host/hci_core.h @@ -57,9 +57,11 @@ struct bt_dev_le { /* LE states */ uint64_t states; +#if defined(CONFIG_BLUETOOTH_CONN) /* Controller buffer information */ uint16_t mtu; struct k_sem pkts; +#endif /* CONFIG_BLUETOOTH_CONN */ }; #if defined(CONFIG_BLUETOOTH_BREDR) From 57a99f6b7a9e62ddb40eb9840d8b9ff976424bc4 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Fri, 31 Mar 2017 10:56:11 +0300 Subject: [PATCH 15/41] Bluetooth: GATT: Be consistent with error in case SMP is disabled This makes the code consistent with respect of errors, so instead of checking directly on bt_gatt_write_without_response let this up to bt_smp_sign. Change-Id: Iea8d0bd2020df427b7542e2878ce8d9fd8b94170 Signed-off-by: Luiz Augusto von Dentz --- subsys/bluetooth/host/gatt.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/subsys/bluetooth/host/gatt.c b/subsys/bluetooth/host/gatt.c index 71263f917c2..63839d15bc1 100644 --- a/subsys/bluetooth/host/gatt.c +++ b/subsys/bluetooth/host/gatt.c @@ -1499,10 +1499,6 @@ int bt_gatt_write_without_response(struct bt_conn *conn, uint16_t handle, /* Don't need to sign if already encrypted */ sign = false; } -#else - if (sign) { - return -EOPNOTSUPP; - } #endif if (sign) { From ddba873aae636922b3cef83b7548310a912c600d Mon Sep 17 00:00:00 2001 From: Vinayak Chettimada Date: Fri, 31 Mar 2017 03:50:49 +0200 Subject: [PATCH 16/41] Bluetooth: Kconfig: Move BLUETOOTH_CONTROLLER to Controller file Move the Kconfig BLUETOOTH_CONTROLLER switch from top-level Bluetooth Kconfig to Bluetooth Controller Kconfig. Change-id: Iead760c22a0fbbda11e4558c4943b3366ecc8769 Signed-off-by: Vinayak Chettimada --- subsys/bluetooth/Kconfig | 12 +----------- subsys/bluetooth/controller/Kconfig | 19 +++++++++++++++++-- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/subsys/bluetooth/Kconfig b/subsys/bluetooth/Kconfig index c34a9f3066a..4f847f6f8ac 100644 --- a/subsys/bluetooth/Kconfig +++ b/subsys/bluetooth/Kconfig @@ -34,18 +34,8 @@ config BLUETOOTH_CUSTOM endchoice if BLUETOOTH_HCI - -config BLUETOOTH_CONTROLLER - bool "Bluetooth Controller" - select BLUETOOTH_RECV_IS_RX_THREAD - help - Enables support for SoC native controller implementations. - source "subsys/bluetooth/host/Kconfig" - -if BLUETOOTH_CONTROLLER source "subsys/bluetooth/controller/Kconfig" -endif - endif # BLUETOOTH_HCI + endif # BLUETOOTH diff --git a/subsys/bluetooth/controller/Kconfig b/subsys/bluetooth/controller/Kconfig index c212381762d..6ba10166862 100644 --- a/subsys/bluetooth/controller/Kconfig +++ b/subsys/bluetooth/controller/Kconfig @@ -1,6 +1,19 @@ -if BLUETOOTH_CONTROLLER +# Kconfig - Bluetooth Controller configuration options +# +# Copyright (c) 2016-2017 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# -comment "BLE Controller configuration" +comment "BLE Controller support" + +config BLUETOOTH_CONTROLLER + bool "Bluetooth Controller" + select BLUETOOTH_RECV_IS_RX_THREAD + help + Enables support for SoC native controller implementations. + +if BLUETOOTH_CONTROLLER choice prompt "Bluetooth Link Layer Selection" @@ -15,6 +28,8 @@ config BLUETOOTH_LL_SW endchoice +comment "BLE Controller configuration" + config BLUETOOTH_CONTROLLER_RX_BUFFERS prompt "Number of Rx buffers" int From 74cddf93930217b8a017e28a61cf15a8111e49bf Mon Sep 17 00:00:00 2001 From: Vinayak Chettimada Date: Fri, 31 Mar 2017 08:38:55 +0200 Subject: [PATCH 17/41] Bluetooth: Kconfig: Group stack size related options Group the stack size related options together to represent a better order when using menuconfig. Change-id: Id2968607e5054e30029c42987b3e70cb8cbfc74d Signed-off-by: Vinayak Chettimada --- subsys/bluetooth/host/Kconfig | 38 +++++++++++++++++------------------ 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/subsys/bluetooth/host/Kconfig b/subsys/bluetooth/host/Kconfig index 804387b732d..d8ed4bfedb0 100644 --- a/subsys/bluetooth/host/Kconfig +++ b/subsys/bluetooth/host/Kconfig @@ -8,17 +8,6 @@ comment "Host Stack Configuration" -# Stack size needed for executing bt_send with specified driver -config BLUETOOTH_HCI_TX_STACK_SIZE - int - # Even if no driver is selected the following default is still - # needed e.g. for unit tests. - default 256 - default 256 if BLUETOOTH_H4 - default 256 if BLUETOOTH_H5 - default 256 if BLUETOOTH_SPI - default 640 if BLUETOOTH_CONTROLLER - config BLUETOOTH_HCI_RAW bool "RAW HCI access" help @@ -32,14 +21,6 @@ config BLUETOOTH_HCI_HOST depends on !BLUETOOTH_HCI_RAW select POLL -config BLUETOOTH_RECV_IS_RX_THREAD - # Virtual option set by the HCI driver to indicate that there's - # no need for the host to have its own RX thread, rather the - # context that bt_recv() gets called in is already good enough. - # If this is set, the driver RX thread is required as the first - # thing to make a call to bt_rx_thread_ready(). - bool - config BLUETOOTH_HCI_CMD_COUNT int "Number of HCI command buffers" default 2 @@ -79,6 +60,25 @@ config BLUETOOTH_UART_TO_HOST_DEV_NAME to connect to an external Bluetooth Host when Zephyr is acting as a Bluetooth Controller. +config BLUETOOTH_HCI_TX_STACK_SIZE + # Stack size needed for executing bt_send with specified driver + int + # Even if no driver is selected the following default is still + # needed e.g. for unit tests. + default 256 + default 256 if BLUETOOTH_H4 + default 256 if BLUETOOTH_H5 + default 256 if BLUETOOTH_SPI + default 640 if BLUETOOTH_CONTROLLER + +config BLUETOOTH_RECV_IS_RX_THREAD + # Virtual option set by the HCI driver to indicate that there's + # no need for the host to have its own RX thread, rather the + # context that bt_recv() gets called in is already good enough. + # If this is set, the driver RX thread is required as the first + # thing to make a call to bt_rx_thread_ready(). + bool + config BLUETOOTH_RX_STACK_SIZE int "Size of the receiving thread stack" depends on BLUETOOTH_HCI_HOST || BLUETOOTH_RECV_IS_RX_THREAD From 2d6b82d44d7d495ee319a6ef182b480ec962a864 Mon Sep 17 00:00:00 2001 From: Vinayak Chettimada Date: Fri, 31 Mar 2017 08:52:28 +0200 Subject: [PATCH 18/41] Bluetooth: Kconfig: Group HCI_RAW related options Move the BLUETOOTH_UART_TO_HOST_DEV_NAME options to after BLUETOOTH_HCI_RAW option to group it together in the Kconfig while using menuconfig. Change-id: I21da080a5ffa30a08b1a1aa148ce8116e63a3c18 Signed-off-by: Vinayak Chettimada --- subsys/bluetooth/host/Kconfig | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/subsys/bluetooth/host/Kconfig b/subsys/bluetooth/host/Kconfig index d8ed4bfedb0..1c5c1e80ad4 100644 --- a/subsys/bluetooth/host/Kconfig +++ b/subsys/bluetooth/host/Kconfig @@ -14,6 +14,15 @@ config BLUETOOTH_HCI_RAW This option allows to access Bluetooth controller from the application with the RAW HCI protocol. +config BLUETOOTH_UART_TO_HOST_DEV_NAME + string "Device Name of UART Device to an external Bluetooth Host" + default "UART_0" + depends on BLUETOOTH_HCI_RAW + help + This option specifies the name of UART device to be used + to connect to an external Bluetooth Host when Zephyr is + acting as a Bluetooth Controller. + # Virtual/hidden option to make the conditions more intuitive config BLUETOOTH_HCI_HOST bool @@ -51,15 +60,6 @@ config BLUETOOTH_RX_BUF_LEN an L2CAP MTU of 65 bytes. On top of this there's the L2CAP header (4 bytes) and the ACL header (also 4 bytes) which yields 73 bytes. -config BLUETOOTH_UART_TO_HOST_DEV_NAME - string "Device Name of UART Device to an external Bluetooth Host" - default "UART_0" - depends on BLUETOOTH_HCI_RAW - help - This option specifies the name of UART device to be used - to connect to an external Bluetooth Host when Zephyr is - acting as a Bluetooth Controller. - config BLUETOOTH_HCI_TX_STACK_SIZE # Stack size needed for executing bt_send with specified driver int From 5f69bde72b5a1d2324bcef24b116cb0298da1ee2 Mon Sep 17 00:00:00 2001 From: Vinayak Chettimada Date: Fri, 31 Mar 2017 11:39:41 +0200 Subject: [PATCH 19/41] Bluetooth: Kconfig: Move BLUETOOTH_MAX_SCO_CONN to BR/EDR Move the Kconfig option BLUETOOTH_MAX_SCO_CONN to BR/EDR if clause. Change-id: Iead2bc5a70a9499125f9edf22e85ade4dda8f5ac Signed-off-by: Vinayak Chettimada --- subsys/bluetooth/host/Kconfig | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/subsys/bluetooth/host/Kconfig b/subsys/bluetooth/host/Kconfig index 1c5c1e80ad4..ca1fb63ca83 100644 --- a/subsys/bluetooth/host/Kconfig +++ b/subsys/bluetooth/host/Kconfig @@ -268,15 +268,6 @@ config BLUETOOTH_TINYCRYPT_ECC option injects support for the 2 HCI commands required for LE Secure Connections so that Hosts can make use of those. -config BLUETOOTH_MAX_SCO_CONN - int "Maximum number of simultaneous SCO connections" - depends on BLUETOOTH_CONN || BLUETOOTH_CONTROLLER - default 1 - range 1 3 - help - Maximum number of simultaneous Bluetooth synchronous connections - supported. The minimum (and default) number is 1. - config BLUETOOTH_MAX_CONN int "Maximum number of simultaneous connections" depends on BLUETOOTH_CONN || BLUETOOTH_CONTROLLER @@ -456,6 +447,14 @@ config BLUETOOTH_BREDR This option enables Bluetooth BR/EDR support" if BLUETOOTH_BREDR +config BLUETOOTH_MAX_SCO_CONN + int "Maximum number of simultaneous SCO connections" + default 1 + range 1 3 + help + Maximum number of simultaneous Bluetooth synchronous connections + supported. The minimum (and default) number is 1. + config BLUETOOTH_RFCOMM bool "Bluetooth RFCOMM protocol support [EXPERIMENTAL]" help From a91238aca671c3ef0c71a09adfdf168214347b24 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Fri, 31 Mar 2017 14:51:53 +0300 Subject: [PATCH 20/41] Bluetooth: L2CAP: Fix accounting SDU header len as data This cause packets that are up to 2 bytes off segment maximum length to be considered transmitted when in fact that could be some bytes left to be transmitted which cause any subsequent packet to trigger invalid SDU on the remote end: [ 3612.376068] l2cap_le_data_rcv:6757: SDU fragment. chan->sdu->len 66 skb->len 68 chan->sdu_len 67 [ 3612.376073] Bluetooth: Too much LE L2CAP data received Change-Id: Id2f3469ce1c0b27bb87c4d5bc18e6ede9d93dbde Signed-off-by: Luiz Augusto von Dentz --- subsys/bluetooth/host/l2cap.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/subsys/bluetooth/host/l2cap.c b/subsys/bluetooth/host/l2cap.c index caad67a98d2..c7d21239998 100644 --- a/subsys/bluetooth/host/l2cap.c +++ b/subsys/bluetooth/host/l2cap.c @@ -1063,7 +1063,7 @@ static int l2cap_chan_le_send(struct bt_l2cap_le_chan *ch, struct net_buf *buf, BT_DBG("ch %p cid 0x%04x len %u credits %u", ch, ch->tx.cid, buf->len, k_sem_count_get(&ch->tx.credits)); - len = buf->len; + len = buf->len - sdu_hdr_len; bt_l2cap_send(ch->chan.conn, ch->tx.cid, buf); @@ -1119,7 +1119,8 @@ static int l2cap_chan_le_send_sdu(struct bt_l2cap_le_chan *ch, } } - BT_DBG("ch %p cid 0x%04x sent %u", ch, ch->tx.cid, sent); + BT_DBG("ch %p cid 0x%04x sent %u total_len %u", ch, ch->tx.cid, sent, + total_len); net_buf_unref(buf); @@ -1640,7 +1641,7 @@ int bt_l2cap_chan_send(struct bt_l2cap_chan *chan, struct net_buf *buf) return -EINVAL; } - BT_DBG("chan %p buf %p len %u", chan, buf, buf->len); + BT_DBG("chan %p buf %p len %zu", chan, buf, net_buf_frags_len(buf)); if (!chan->conn || chan->conn->state != BT_CONN_CONNECTED) { return -ENOTCONN; From 9319e441b8e01c798455e1b2cbe54c5c999488d2 Mon Sep 17 00:00:00 2001 From: Sathish Narasimman Date: Mon, 27 Feb 2017 17:30:24 +0530 Subject: [PATCH 21/41] Bluetooth: HFP HF: Support to send hf AT command A initiation to send AT commands is given in the application with prefered AT command as the argument. This patch supports to send the command within the profile stack. Change-Id: Id5caa3ce64070fc17e60f4ea61a8c83a961099ba Signed-off-by: Sathish Narasimman --- include/bluetooth/hfp_hf.h | 42 ++++++++++++++++ subsys/bluetooth/host/hfp_hf.c | 89 ++++++++++++++++++++++++++++++++++ 2 files changed, 131 insertions(+) diff --git a/include/bluetooth/hfp_hf.h b/include/bluetooth/hfp_hf.h index 48dc710c5f8..5ddc645e304 100644 --- a/include/bluetooth/hfp_hf.h +++ b/include/bluetooth/hfp_hf.h @@ -23,6 +23,28 @@ extern "C" { #endif +/* AT Commands */ +enum bt_hfp_hf_at_cmd { + BT_HFP_HF_ATA, + BT_HFP_HF_AT_CHUP, +}; + +/* + * Command complete types for the application + */ +#define HFP_HF_CMD_OK 0 +#define HFP_HF_CMD_ERROR 1 +#define HFP_HF_CMD_CME_ERROR 2 +#define HFP_HF_CMD_UNKNOWN_ERROR 4 + +/** @brief HFP HF Command completion field */ +struct bt_hfp_hf_cmd_complete { + /* Command complete status */ + uint8_t type; + /* CME error number to be added */ + uint8_t cme; +}; + /** @brief HFP profile application callback */ struct bt_hfp_hf_cb { /** HF connected callback to application @@ -106,6 +128,15 @@ struct bt_hfp_hf_cb { * @param conn Connection object. */ void (*ring_indication)(struct bt_conn *conn); + /** HF notify command completed callback to application + * + * The command sent from the application is notified about its status + * + * @param conn Connection object. + * @param cmd structure contains status of the command including cme. + */ + void (*cmd_complete_cb)(struct bt_conn *conn, + struct bt_hfp_hf_cmd_complete *cmd); }; /** @brief Register HFP HF profile @@ -119,6 +150,17 @@ struct bt_hfp_hf_cb { */ int bt_hfp_hf_register(struct bt_hfp_hf_cb *cb); +/** @brief Handsfree client Send AT + * + * Send specific AT commands to handsfree client profile. + * + * @param conn Connection object. + * @param cmd AT command to be sent. + * + * @return 0 in case of success or negative value in case of error. + */ +int bt_hfp_hf_send_cmd(struct bt_conn *conn, enum bt_hfp_hf_at_cmd cmd); + #ifdef __cplusplus } #endif diff --git a/subsys/bluetooth/host/hfp_hf.c b/subsys/bluetooth/host/hfp_hf.c index f058cfdec29..fc5c7b260fd 100644 --- a/subsys/bluetooth/host/hfp_hf.c +++ b/subsys/bluetooth/host/hfp_hf.c @@ -395,6 +395,39 @@ int unsolicited_cb(struct at_client *hf_at, struct net_buf *buf) return -ENOMSG; } +int cmd_complete(struct at_client *hf_at, enum at_result result, + enum at_cme cme_err) +{ + struct bt_hfp_hf *hf = CONTAINER_OF(hf_at, struct bt_hfp_hf, at); + struct bt_conn *conn = hf->rfcomm_dlc.session->br_chan.chan.conn; + struct bt_hfp_hf_cmd_complete cmd = { 0 }; + + BT_DBG(""); + + switch (result) { + case AT_RESULT_OK: + cmd.type = HFP_HF_CMD_OK; + break; + case AT_RESULT_ERROR: + cmd.type = HFP_HF_CMD_ERROR; + break; + case AT_RESULT_CME_ERROR: + cmd.type = HFP_HF_CMD_CME_ERROR; + cmd.cme = cme_err; + break; + default: + BT_ERR("Unknown error code"); + cmd.type = HFP_HF_CMD_UNKNOWN_ERROR; + break; + } + + if (bt_hf->cmd_complete_cb) { + bt_hf->cmd_complete_cb(conn, &cmd); + } + + return 0; +} + int cmee_finish(struct at_client *hf_at, enum at_result result, enum at_cme cme_err) { @@ -515,6 +548,62 @@ int hf_slc_establish(struct bt_hfp_hf *hf) return 0; } +static struct bt_hfp_hf *bt_hfp_hf_lookup_bt_conn(struct bt_conn *conn) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(bt_hfp_hf_pool); i++) { + struct bt_hfp_hf *hf = &bt_hfp_hf_pool[i]; + + if (hf->rfcomm_dlc.session->br_chan.chan.conn == conn) { + return hf; + } + } + + return NULL; +} + +int bt_hfp_hf_send_cmd(struct bt_conn *conn, enum bt_hfp_hf_at_cmd cmd) +{ + struct bt_hfp_hf *hf; + int err; + + BT_DBG(""); + + if (!conn) { + BT_ERR("Invalid connection"); + return -ENOTCONN; + } + + hf = bt_hfp_hf_lookup_bt_conn(conn); + if (!hf) { + BT_ERR("No HF connection found"); + return -ENOTCONN; + } + + switch (cmd) { + case BT_HFP_HF_ATA: + err = hfp_hf_send_cmd(hf, NULL, cmd_complete, "ATA"); + if (err < 0) { + BT_ERR("Failed ATA"); + return err; + } + break; + case BT_HFP_HF_AT_CHUP: + err = hfp_hf_send_cmd(hf, NULL, cmd_complete, "AT+CHUP"); + if (err < 0) { + BT_ERR("Failed AT+CHUP"); + return err; + } + break; + default: + BT_ERR("Invalid AT Command"); + return -EINVAL; + } + + return 0; +} + static void hfp_hf_connected(struct bt_rfcomm_dlc *dlc) { struct bt_hfp_hf *hf = CONTAINER_OF(dlc, struct bt_hfp_hf, rfcomm_dlc); From 9d7552f8f6c37053b126d6298e6cc0c400486f6c Mon Sep 17 00:00:00 2001 From: Sathish Narasimman Date: Thu, 30 Mar 2017 17:57:09 +0530 Subject: [PATCH 22/41] Bluetooth: AT: Fix - chance of missing UNSOLICITED state If during hfp_hf_send response callback is not filled with NULL and you receive unsolicited callback. which will not be taken care. This patch fixes this issue. Change-Id: I04007059d62273b9cdddf29e2d4a9086b07a01e5 Signed-off-by: Sathish Narasimman --- subsys/bluetooth/host/at.c | 1 + 1 file changed, 1 insertion(+) diff --git a/subsys/bluetooth/host/at.c b/subsys/bluetooth/host/at.c index e184f93364e..17a9963e66c 100644 --- a/subsys/bluetooth/host/at.c +++ b/subsys/bluetooth/host/at.c @@ -216,6 +216,7 @@ static int at_state_process_cmd(struct at_client *at, struct net_buf *buf) if (at->resp) { at->resp(at, buf); + at->resp = NULL; return 0; } at->state = AT_STATE_UNSOLICITED_CMD; From 563fdd784b4d819e1d9b9e584814e552e493d2a7 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Fri, 31 Mar 2017 12:17:51 +0300 Subject: [PATCH 23/41] Bluetooth: SMP: Remove redundant ';' Change-Id: I889b1768c40b630e00c9856630001dbf7557abba Signed-off-by: Johan Hedberg --- subsys/bluetooth/host/smp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subsys/bluetooth/host/smp.c b/subsys/bluetooth/host/smp.c index 523de28e2b6..a3e45dcb962 100644 --- a/subsys/bluetooth/host/smp.c +++ b/subsys/bluetooth/host/smp.c @@ -3720,7 +3720,7 @@ int bt_smp_sign(struct bt_conn *conn, struct net_buf *buf) BT_ERR("Unable to create signature for %s", bt_addr_le_str(&conn->le.dst)); return -EIO; - }; + } keys->local_csrk.cnt++; From 981f2d3fdb99eb978dd17ef0e6e40150820e2bc0 Mon Sep 17 00:00:00 2001 From: Vinayak Chettimada Date: Fri, 31 Mar 2017 21:12:37 +0200 Subject: [PATCH 24/41] Bluetooth: Compile BR/EDR independent of BLUETOOTH_CONN check BR/EDR sources that was compiled under BLUETOOTH_CONN if-clause is moved out as independent conditional compilation based on selected BR/EDR feature support. Change-id: Iedfafc6056132654a9150ed235b245f8be62b4b1 Signed-off-by: Vinayak Chettimada --- subsys/bluetooth/host/Makefile | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/subsys/bluetooth/host/Makefile b/subsys/bluetooth/host/Makefile index 6f4c0bb0d41..0be479f8f21 100644 --- a/subsys/bluetooth/host/Makefile +++ b/subsys/bluetooth/host/Makefile @@ -20,16 +20,16 @@ ifeq ($(CONFIG_BLUETOOTH_CONN),y) else obj-y += smp_null.o endif - - obj-$(CONFIG_BLUETOOTH_BREDR) += keys_br.o l2cap_br.o avdtp.o sdp.o - - obj-$(CONFIG_BLUETOOTH_RFCOMM) += rfcomm.o - - obj-$(CONFIG_BLUETOOTH_HFP_HF) += at.o hfp_hf.o - - obj-$(CONFIG_BLUETOOTH_AVDTP) += avdtp.o - - obj-$(CONFIG_BLUETOOTH_A2DP) += a2dp.o endif obj-$(CONFIG_BLUETOOTH_HOST_CRYPTO) += crypto.o + +obj-$(CONFIG_BLUETOOTH_BREDR) += keys_br.o l2cap_br.o sdp.o + +obj-$(CONFIG_BLUETOOTH_RFCOMM) += rfcomm.o + +obj-$(CONFIG_BLUETOOTH_HFP_HF) += at.o hfp_hf.o + +obj-$(CONFIG_BLUETOOTH_AVDTP) += avdtp.o + +obj-$(CONFIG_BLUETOOTH_A2DP) += a2dp.o From cced2aea30b11e369b1c652efb7a7624d1130faf Mon Sep 17 00:00:00 2001 From: Vinayak Chettimada Date: Mon, 27 Mar 2017 16:04:42 +0200 Subject: [PATCH 25/41] Bluetooth: Permit connectionless host-controller combined build In a host plus controller combined build, if no connection is required, deselect CONFIG_BLUETOOTH_MAX_CONN. This will reduce RAM and ROM usage in the controller. Also, make BLUETOOTH_PERIPHERAL, BLUETOOTH_CENTRAL and BLUETOOTH_CONN switches accessible by the controller kconfig to select the right roles to enable. Change-id: I164cf696ab2a6f4859086d2cb18f6d3f2b1399d3 Signed-off-by: Vinayak Chettimada --- subsys/bluetooth/host/Kconfig | 53 ++++++++++++++++++---------------- subsys/bluetooth/host/Makefile | 22 +++++++------- 2 files changed, 40 insertions(+), 35 deletions(-) diff --git a/subsys/bluetooth/host/Kconfig b/subsys/bluetooth/host/Kconfig index ca1fb63ca83..b2e3775f4f0 100644 --- a/subsys/bluetooth/host/Kconfig +++ b/subsys/bluetooth/host/Kconfig @@ -1,6 +1,7 @@ # Kconfig - Bluetooth LE stack configuration options # +# Copyright (c) 2016-2017 Nordic Semiconductor ASA # Copyright (c) 2015-2016 Intel Corporation # # SPDX-License-Identifier: Apache-2.0 @@ -23,13 +24,39 @@ config BLUETOOTH_UART_TO_HOST_DEV_NAME to connect to an external Bluetooth Host when Zephyr is acting as a Bluetooth Controller. -# Virtual/hidden option to make the conditions more intuitive config BLUETOOTH_HCI_HOST + # Virtual/hidden option to make the conditions more intuitive bool default y depends on !BLUETOOTH_HCI_RAW select POLL +config BLUETOOTH_PERIPHERAL + bool "Peripheral Role support" + select BLUETOOTH_CONN + default y if BLUETOOTH_HCI_RAW + help + Select this for LE Peripheral role support. + +config BLUETOOTH_CENTRAL + bool "Central Role support" + select BLUETOOTH_CONN + default y if BLUETOOTH_HCI_RAW + help + Select this for LE Central role support. + +config BLUETOOTH_CONN + bool + +config BLUETOOTH_MAX_CONN + int "Maximum number of simultaneous connections" + depends on BLUETOOTH_CONN + range 1 64 + default 1 + help + Maximum number of simultaneous Bluetooth connections + supported. + config BLUETOOTH_HCI_CMD_COUNT int "Number of HCI command buffers" default 2 @@ -116,21 +143,6 @@ config BLUETOOTH_INTERNAL_STORAGE persistent storage handlers through the bt_storage API, rather an internal default handler is used for this. -config BLUETOOTH_PERIPHERAL - bool "Peripheral Role support" - select BLUETOOTH_CONN - help - Select this for LE Peripheral role support. - -config BLUETOOTH_CENTRAL - bool "Central Role support" - select BLUETOOTH_CONN - help - Select this for LE Central role support. - -config BLUETOOTH_CONN - bool - if BLUETOOTH_CONN config BLUETOOTH_L2CAP_TX_BUF_COUNT int "Number of L2CAP TX buffers" @@ -268,15 +280,6 @@ config BLUETOOTH_TINYCRYPT_ECC option injects support for the 2 HCI commands required for LE Secure Connections so that Hosts can make use of those. -config BLUETOOTH_MAX_CONN - int "Maximum number of simultaneous connections" - depends on BLUETOOTH_CONN || BLUETOOTH_CONTROLLER - default 1 - range 1 64 - help - Maximum number of simultaneous Bluetooth connections - supported. The minimum (and default) number is 1. - config BLUETOOTH_DEBUG bool diff --git a/subsys/bluetooth/host/Makefile b/subsys/bluetooth/host/Makefile index 0be479f8f21..2db461c4466 100644 --- a/subsys/bluetooth/host/Makefile +++ b/subsys/bluetooth/host/Makefile @@ -1,7 +1,5 @@ ccflags-y +=-I$(srctree)/include/drivers -obj-$(CONFIG_BLUETOOTH_HCI_HOST) += uuid.o hci_core.o - obj-$(CONFIG_BLUETOOTH_HCI_RAW) += hci_raw.o obj-$(CONFIG_BLUETOOTH_DEBUG) += log.o @@ -12,17 +10,21 @@ obj-$(CONFIG_BLUETOOTH_TINYCRYPT_ECC) += hci_ecc.o obj-$(CONFIG_BLUETOOTH_INTERNAL_STORAGE) += storage.o -ifeq ($(CONFIG_BLUETOOTH_CONN),y) - obj-y += conn.o l2cap.o att.o gatt.o +ifeq ($(CONFIG_BLUETOOTH_HCI_HOST),y) + obj-y += uuid.o hci_core.o - ifeq ($(CONFIG_BLUETOOTH_SMP),y) - obj-y += smp.o keys.o - else - obj-y += smp_null.o + ifeq ($(CONFIG_BLUETOOTH_CONN),y) + obj-y += conn.o l2cap.o att.o gatt.o + + ifeq ($(CONFIG_BLUETOOTH_SMP),y) + obj-y += smp.o keys.o + else + obj-y += smp_null.o + endif endif -endif -obj-$(CONFIG_BLUETOOTH_HOST_CRYPTO) += crypto.o + obj-$(CONFIG_BLUETOOTH_HOST_CRYPTO) += crypto.o +endif obj-$(CONFIG_BLUETOOTH_BREDR) += keys_br.o l2cap_br.o sdp.o From 698de8891660c00d669ad1d0aa519f14b489fb23 Mon Sep 17 00:00:00 2001 From: Vinayak Chettimada Date: Thu, 30 Mar 2017 08:17:53 +0200 Subject: [PATCH 26/41] Bluetooth: controller: Cleanup redundant ticker busy loop Cleanup redundant ticker busy loop that could hang if the worker and job IRQ priority levels are misconfigured, and job gets disabled before all users/mayfly functions using job complete. Change-id: I053ad75a4328c51cfe651b820a2fa961e42ae48f Signed-off-by: Vinayak Chettimada --- subsys/bluetooth/controller/ll_sw/ctrl.c | 43 ++++-------------------- 1 file changed, 7 insertions(+), 36 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ctrl.c b/subsys/bluetooth/controller/ll_sw/ctrl.c index e185e92b2d1..adedf4d3dc5 100644 --- a/subsys/bluetooth/controller/ll_sw/ctrl.c +++ b/subsys/bluetooth/controller/ll_sw/ctrl.c @@ -3140,7 +3140,6 @@ static uint32_t preempt_calc(struct shdr *hdr, uint8_t ticker_id, */ static void mayfly_xtal_stop_calc(void *params) { - uint32_t volatile ret_cb = TICKER_STATUS_BUSY; uint32_t ticks_to_expire; uint32_t ticks_current; uint8_t ticker_id; @@ -3150,17 +3149,9 @@ static void mayfly_xtal_stop_calc(void *params) ticks_to_expire = 0; ret = ticker_next_slot_get(RADIO_TICKER_INSTANCE_ID_RADIO, RADIO_TICKER_USER_ID_JOB, &ticker_id, - &ticks_current, &ticks_to_expire, - ticker_if_done, (void *)&ret_cb); - - if (ret == TICKER_STATUS_BUSY) { - while (ret_cb == TICKER_STATUS_BUSY) { - ticker_job_sched(RADIO_TICKER_INSTANCE_ID_RADIO, - RADIO_TICKER_USER_ID_JOB); - } - } - - LL_ASSERT(ret_cb == TICKER_STATUS_SUCCESS); + &ticks_current, &ticks_to_expire, NULL, + NULL); + LL_ASSERT(ret == TICKER_STATUS_SUCCESS); if ((ticker_id != 0xff) && (ticks_to_expire < @@ -3350,23 +3341,13 @@ static void sched_after_mstr_free_slot_get(uint8_t user_id, ticks_to_expire = ticks_to_expire_prev = *us_offset = 0; ticks_slot_prev_abs = 0; while (1) { - uint32_t volatile ret_cb = TICKER_STATUS_BUSY; struct connection *conn; uint32_t ret; ret = ticker_next_slot_get(RADIO_TICKER_INSTANCE_ID_RADIO, user_id, &ticker_id, ticks_anchor, - &ticks_to_expire, ticker_if_done, - (void *)&ret_cb); - - if (ret == TICKER_STATUS_BUSY) { - while (ret_cb == TICKER_STATUS_BUSY) { - ticker_job_sched(RADIO_TICKER_INSTANCE_ID_RADIO, - user_id); - } - } - - LL_ASSERT(ret_cb == TICKER_STATUS_SUCCESS); + &ticks_to_expire, NULL, NULL); + LL_ASSERT(ret == TICKER_STATUS_SUCCESS); if (ticker_id == 0xff) { break; @@ -3504,24 +3485,14 @@ static void sched_free_win_offset_calc(struct connection *conn_curr, ticks_anchor_prev = offset_index = _win_offset = 0; ticks_slot_prev_abs = 0; do { - uint32_t volatile ret_cb = TICKER_STATUS_BUSY; struct connection *conn; uint32_t ret; ret = ticker_next_slot_get(RADIO_TICKER_INSTANCE_ID_RADIO, RADIO_TICKER_USER_ID_JOB, &ticker_id, &ticks_anchor, - &ticks_to_expire, ticker_if_done, - (void *)&ret_cb); - - if (ret == TICKER_STATUS_BUSY) { - while (ret_cb == TICKER_STATUS_BUSY) { - ticker_job_sched(RADIO_TICKER_INSTANCE_ID_RADIO, - RADIO_TICKER_USER_ID_JOB); - } - } - - LL_ASSERT(ret_cb == TICKER_STATUS_SUCCESS); + &ticks_to_expire, NULL, NULL); + LL_ASSERT(ret == TICKER_STATUS_SUCCESS); if (ticker_id == 0xff) { break; From 2de3cc95be43a687ee2d8a06245e2190da1c7c7f Mon Sep 17 00:00:00 2001 From: Vinayak Chettimada Date: Mon, 3 Apr 2017 10:00:32 +0200 Subject: [PATCH 27/41] Bluetooth: controller: Move nRF5 specific debug pins to hal/nrf5 Move the nRF5 specific GPIO debug pin macro definitions to hal/nrf5/debug.h. The Controller's hal folder contains prototypes and hal/ shall contain SoC specific implementation to realize a software-based Link Layer. Change-id: Ic7bf283f926bbc3069e7d15c047fe93a6daa894f Signed-off-by: Vinayak Chettimada --- subsys/bluetooth/controller/hal/debug.h | 199 +----------------- subsys/bluetooth/controller/hal/nrf5/debug.h | 204 +++++++++++++++++++ 2 files changed, 208 insertions(+), 195 deletions(-) create mode 100644 subsys/bluetooth/controller/hal/nrf5/debug.h diff --git a/subsys/bluetooth/controller/hal/debug.h b/subsys/bluetooth/controller/hal/debug.h index dc9f4167efe..48f35bd44e2 100644 --- a/subsys/bluetooth/controller/hal/debug.h +++ b/subsys/bluetooth/controller/hal/debug.h @@ -5,8 +5,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -#ifndef _DEBUG_H_ -#define _DEBUG_H_ +#ifndef _HAL_DEBUG_H_ +#define _HAL_DEBUG_H_ #ifdef CONFIG_BLUETOOTH_CONTROLLER_ASSERT_HANDLER void bt_controller_assert_handle(char *file, uint32_t line); @@ -18,197 +18,6 @@ void bt_controller_assert_handle(char *file, uint32_t line); #define LL_ASSERT(cond) BT_ASSERT(cond) #endif -/* below are some interesting macros referenced by controller - * which can be defined to SoC's GPIO toggle to observe/debug the - * controller's runtime behavior. - */ -#ifdef CONFIG_BLUETOOTH_CONTROLLER_DEBUG_PINS -#define DEBUG_INIT() do { \ - NRF_GPIO->DIRSET = 0x03FF0000; \ - NRF_GPIO->OUTCLR = 0x03FF0000; } \ - while (0) +#include "nrf5/debug.h" -#define DEBUG_CPU_SLEEP(flag) do { \ - if (flag) { \ - NRF_GPIO->OUTSET = BIT(16); \ - NRF_GPIO->OUTCLR = BIT(16); } \ - else { \ - NRF_GPIO->OUTCLR = BIT(16); \ - NRF_GPIO->OUTSET = BIT(16); } \ - } while (0) - -#define DEBUG_TICKER_ISR(flag) do { \ - if (flag) { \ - NRF_GPIO->OUTCLR = BIT(17); \ - NRF_GPIO->OUTSET = BIT(17); } \ - else { \ - NRF_GPIO->OUTSET = BIT(17); \ - NRF_GPIO->OUTCLR = BIT(17); } \ - } while (0) - -#define DEBUG_TICKER_TASK(flag) do { \ - if (flag) { \ - NRF_GPIO->OUTCLR = BIT(17); \ - NRF_GPIO->OUTSET = BIT(17); } \ - else { \ - NRF_GPIO->OUTSET = BIT(17); \ - NRF_GPIO->OUTCLR = BIT(17); } \ - } while (0) - -#define DEBUG_TICKER_JOB(flag) do { \ - if (flag) { \ - NRF_GPIO->OUTCLR = BIT(18); \ - NRF_GPIO->OUTSET = BIT(18); } \ - else { \ - NRF_GPIO->OUTSET = BIT(18); \ - NRF_GPIO->OUTCLR = BIT(18); } \ - } while (0) - -#define DEBUG_RADIO_ISR(flag) do { \ - if (flag) { \ - NRF_GPIO->OUTCLR = BIT(23); \ - NRF_GPIO->OUTSET = BIT(23); } \ - else { \ - NRF_GPIO->OUTSET = BIT(23); \ - NRF_GPIO->OUTCLR = BIT(23); } \ - } while (0) - -#define DEBUG_RADIO_XTAL(flag) do { \ - if (flag) { \ - NRF_GPIO->OUTCLR = BIT(24); \ - NRF_GPIO->OUTSET = BIT(24); } \ - else { \ - NRF_GPIO->OUTSET = BIT(24); \ - NRF_GPIO->OUTCLR = BIT(24); } \ - } while (0) - -#define DEBUG_RADIO_ACTIVE(flag) do { \ - if (flag) { \ - NRF_GPIO->OUTCLR = BIT(25); \ - NRF_GPIO->OUTSET = BIT(25); } \ - else { \ - NRF_GPIO->OUTSET = BIT(25); \ - NRF_GPIO->OUTCLR = BIT(25); } \ - } while (0) - -#define DEBUG_RADIO_CLOSE(flag) do { \ - if (flag) { \ - NRF_GPIO->OUTCLR = 0x00000000; \ - NRF_GPIO->OUTSET = 0x00000000; } \ - else { \ - NRF_GPIO->OUTCLR = 0x00780000; } \ - } while (0) - -#define DEBUG_RADIO_PREPARE_A(flag) do { \ - if (flag) { \ - NRF_GPIO->OUTCLR = BIT(19); \ - NRF_GPIO->OUTSET = BIT(19); } \ - else { \ - NRF_GPIO->OUTCLR = BIT(19); \ - NRF_GPIO->OUTSET = BIT(19); } \ - } while (0) - -#define DEBUG_RADIO_START_A(flag) do { \ - if (flag) { \ - NRF_GPIO->OUTCLR = BIT(19); \ - NRF_GPIO->OUTSET = BIT(19); } \ - else { \ - NRF_GPIO->OUTCLR = BIT(19); \ - NRF_GPIO->OUTSET = BIT(19); } \ - } while (0) - -#define DEBUG_RADIO_PREPARE_S(flag) do { \ - if (flag) { \ - NRF_GPIO->OUTCLR = BIT(20); \ - NRF_GPIO->OUTSET = BIT(20); } \ - else { \ - NRF_GPIO->OUTCLR = BIT(20); \ - NRF_GPIO->OUTSET = BIT(20); } \ - } while (0) - -#define DEBUG_RADIO_START_S(flag) do { \ - if (flag) { \ - NRF_GPIO->OUTCLR = BIT(20); \ - NRF_GPIO->OUTSET = BIT(20); } \ - else { \ - NRF_GPIO->OUTCLR = BIT(20); \ - NRF_GPIO->OUTSET = BIT(20); } \ - } while (0) - -#define DEBUG_RADIO_PREPARE_O(flag) do { \ - if (flag) { \ - NRF_GPIO->OUTCLR = BIT(21); \ - NRF_GPIO->OUTSET = BIT(21); } \ - else { \ - NRF_GPIO->OUTCLR = BIT(21); \ - NRF_GPIO->OUTSET = BIT(21); } \ - } while (0) - -#define DEBUG_RADIO_START_O(flag) do { \ - if (flag) { \ - NRF_GPIO->OUTCLR = BIT(21); \ - NRF_GPIO->OUTSET = BIT(21); } \ - else { \ - NRF_GPIO->OUTCLR = BIT(21); \ - NRF_GPIO->OUTSET = BIT(21); } \ - } while (0) - -#define DEBUG_RADIO_PREPARE_M(flag) do { \ - if (flag) { \ - NRF_GPIO->OUTCLR = BIT(22); \ - NRF_GPIO->OUTSET = BIT(22); } \ - else { \ - NRF_GPIO->OUTCLR = BIT(22); \ - NRF_GPIO->OUTSET = BIT(22); } \ - } while (0) - -#define DEBUG_RADIO_START_M(flag) do { \ - if (flag) { \ - NRF_GPIO->OUTCLR = BIT(22); \ - NRF_GPIO->OUTSET = BIT(22); } \ - else { \ - NRF_GPIO->OUTCLR = BIT(22); \ - NRF_GPIO->OUTSET = BIT(22); } \ - } while (0) - -#else - -#define DEBUG_INIT() - -#define DEBUG_CPU_SLEEP(flag) - -#define DEBUG_TICKER_ISR(flag) - -#define DEBUG_TICKER_TASK(flag) - -#define DEBUG_TICKER_JOB(flag) - -#define DEBUG_RADIO_ISR(flag) - -#define DEBUG_RADIO_HCTO(flag) - -#define DEBUG_RADIO_XTAL(flag) - -#define DEBUG_RADIO_ACTIVE(flag) - -#define DEBUG_RADIO_CLOSE(flag) - -#define DEBUG_RADIO_PREPARE_A(flag) - -#define DEBUG_RADIO_START_A(flag) - -#define DEBUG_RADIO_PREPARE_S(flag) - -#define DEBUG_RADIO_START_S(flag) - -#define DEBUG_RADIO_PREPARE_O(flag) - -#define DEBUG_RADIO_START_O(flag) - -#define DEBUG_RADIO_PREPARE_M(flag) - -#define DEBUG_RADIO_START_M(flag) - -#endif /* CONFIG_BLUETOOTH_CONTROLLER_DEBUG_PINS */ - -#endif /* _DEBUG_H_ */ +#endif /* _HAL_DEBUG_H_ */ diff --git a/subsys/bluetooth/controller/hal/nrf5/debug.h b/subsys/bluetooth/controller/hal/nrf5/debug.h new file mode 100644 index 00000000000..f270b0faf20 --- /dev/null +++ b/subsys/bluetooth/controller/hal/nrf5/debug.h @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2016-2017 Nordic Semiconductor ASA + * Copyright (c) 2016 Vinayak Kariappa Chettimada + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _DEBUG_H_ +#define _DEBUG_H_ + +/* below are some interesting macros referenced by controller + * which can be defined to SoC's GPIO toggle to observe/debug the + * controller's runtime behavior. + */ +#ifdef CONFIG_BLUETOOTH_CONTROLLER_DEBUG_PINS +#define DEBUG_INIT() do { \ + NRF_GPIO->DIRSET = 0x03FF0000; \ + NRF_GPIO->OUTCLR = 0x03FF0000; } \ + while (0) + +#define DEBUG_CPU_SLEEP(flag) do { \ + if (flag) { \ + NRF_GPIO->OUTSET = BIT(16); \ + NRF_GPIO->OUTCLR = BIT(16); } \ + else { \ + NRF_GPIO->OUTCLR = BIT(16); \ + NRF_GPIO->OUTSET = BIT(16); } \ + } while (0) + +#define DEBUG_TICKER_ISR(flag) do { \ + if (flag) { \ + NRF_GPIO->OUTCLR = BIT(17); \ + NRF_GPIO->OUTSET = BIT(17); } \ + else { \ + NRF_GPIO->OUTSET = BIT(17); \ + NRF_GPIO->OUTCLR = BIT(17); } \ + } while (0) + +#define DEBUG_TICKER_TASK(flag) do { \ + if (flag) { \ + NRF_GPIO->OUTCLR = BIT(17); \ + NRF_GPIO->OUTSET = BIT(17); } \ + else { \ + NRF_GPIO->OUTSET = BIT(17); \ + NRF_GPIO->OUTCLR = BIT(17); } \ + } while (0) + +#define DEBUG_TICKER_JOB(flag) do { \ + if (flag) { \ + NRF_GPIO->OUTCLR = BIT(18); \ + NRF_GPIO->OUTSET = BIT(18); } \ + else { \ + NRF_GPIO->OUTSET = BIT(18); \ + NRF_GPIO->OUTCLR = BIT(18); } \ + } while (0) + +#define DEBUG_RADIO_ISR(flag) do { \ + if (flag) { \ + NRF_GPIO->OUTCLR = BIT(23); \ + NRF_GPIO->OUTSET = BIT(23); } \ + else { \ + NRF_GPIO->OUTSET = BIT(23); \ + NRF_GPIO->OUTCLR = BIT(23); } \ + } while (0) + +#define DEBUG_RADIO_XTAL(flag) do { \ + if (flag) { \ + NRF_GPIO->OUTCLR = BIT(24); \ + NRF_GPIO->OUTSET = BIT(24); } \ + else { \ + NRF_GPIO->OUTSET = BIT(24); \ + NRF_GPIO->OUTCLR = BIT(24); } \ + } while (0) + +#define DEBUG_RADIO_ACTIVE(flag) do { \ + if (flag) { \ + NRF_GPIO->OUTCLR = BIT(25); \ + NRF_GPIO->OUTSET = BIT(25); } \ + else { \ + NRF_GPIO->OUTSET = BIT(25); \ + NRF_GPIO->OUTCLR = BIT(25); } \ + } while (0) + +#define DEBUG_RADIO_CLOSE(flag) do { \ + if (flag) { \ + NRF_GPIO->OUTCLR = 0x00000000; \ + NRF_GPIO->OUTSET = 0x00000000; } \ + else { \ + NRF_GPIO->OUTCLR = 0x00780000; } \ + } while (0) + +#define DEBUG_RADIO_PREPARE_A(flag) do { \ + if (flag) { \ + NRF_GPIO->OUTCLR = BIT(19); \ + NRF_GPIO->OUTSET = BIT(19); } \ + else { \ + NRF_GPIO->OUTCLR = BIT(19); \ + NRF_GPIO->OUTSET = BIT(19); } \ + } while (0) + +#define DEBUG_RADIO_START_A(flag) do { \ + if (flag) { \ + NRF_GPIO->OUTCLR = BIT(19); \ + NRF_GPIO->OUTSET = BIT(19); } \ + else { \ + NRF_GPIO->OUTCLR = BIT(19); \ + NRF_GPIO->OUTSET = BIT(19); } \ + } while (0) + +#define DEBUG_RADIO_PREPARE_S(flag) do { \ + if (flag) { \ + NRF_GPIO->OUTCLR = BIT(20); \ + NRF_GPIO->OUTSET = BIT(20); } \ + else { \ + NRF_GPIO->OUTCLR = BIT(20); \ + NRF_GPIO->OUTSET = BIT(20); } \ + } while (0) + +#define DEBUG_RADIO_START_S(flag) do { \ + if (flag) { \ + NRF_GPIO->OUTCLR = BIT(20); \ + NRF_GPIO->OUTSET = BIT(20); } \ + else { \ + NRF_GPIO->OUTCLR = BIT(20); \ + NRF_GPIO->OUTSET = BIT(20); } \ + } while (0) + +#define DEBUG_RADIO_PREPARE_O(flag) do { \ + if (flag) { \ + NRF_GPIO->OUTCLR = BIT(21); \ + NRF_GPIO->OUTSET = BIT(21); } \ + else { \ + NRF_GPIO->OUTCLR = BIT(21); \ + NRF_GPIO->OUTSET = BIT(21); } \ + } while (0) + +#define DEBUG_RADIO_START_O(flag) do { \ + if (flag) { \ + NRF_GPIO->OUTCLR = BIT(21); \ + NRF_GPIO->OUTSET = BIT(21); } \ + else { \ + NRF_GPIO->OUTCLR = BIT(21); \ + NRF_GPIO->OUTSET = BIT(21); } \ + } while (0) + +#define DEBUG_RADIO_PREPARE_M(flag) do { \ + if (flag) { \ + NRF_GPIO->OUTCLR = BIT(22); \ + NRF_GPIO->OUTSET = BIT(22); } \ + else { \ + NRF_GPIO->OUTCLR = BIT(22); \ + NRF_GPIO->OUTSET = BIT(22); } \ + } while (0) + +#define DEBUG_RADIO_START_M(flag) do { \ + if (flag) { \ + NRF_GPIO->OUTCLR = BIT(22); \ + NRF_GPIO->OUTSET = BIT(22); } \ + else { \ + NRF_GPIO->OUTCLR = BIT(22); \ + NRF_GPIO->OUTSET = BIT(22); } \ + } while (0) + +#else + +#define DEBUG_INIT() + +#define DEBUG_CPU_SLEEP(flag) + +#define DEBUG_TICKER_ISR(flag) + +#define DEBUG_TICKER_TASK(flag) + +#define DEBUG_TICKER_JOB(flag) + +#define DEBUG_RADIO_ISR(flag) + +#define DEBUG_RADIO_HCTO(flag) + +#define DEBUG_RADIO_XTAL(flag) + +#define DEBUG_RADIO_ACTIVE(flag) + +#define DEBUG_RADIO_CLOSE(flag) + +#define DEBUG_RADIO_PREPARE_A(flag) + +#define DEBUG_RADIO_START_A(flag) + +#define DEBUG_RADIO_PREPARE_S(flag) + +#define DEBUG_RADIO_START_S(flag) + +#define DEBUG_RADIO_PREPARE_O(flag) + +#define DEBUG_RADIO_START_O(flag) + +#define DEBUG_RADIO_PREPARE_M(flag) + +#define DEBUG_RADIO_START_M(flag) + +#endif /* CONFIG_BLUETOOTH_CONTROLLER_DEBUG_PINS */ + +#endif /* _DEBUG_H_ */ From 1277eea15ee76b3361d66ae3e2a89112ffb7e36a Mon Sep 17 00:00:00 2001 From: Vinayak Chettimada Date: Thu, 30 Mar 2017 10:12:56 +0200 Subject: [PATCH 28/41] Bluetooth: controller: Remove util/config.h Remove util/config.h and unnecessary redefinitions of caller ids. Change-id: I85bb9ae3ab7ff9fcce18c886cfa3e33c91ebb670 Signed-off-by: Vinayak Chettimada --- subsys/bluetooth/controller/ll_sw/ctrl.c | 1 - subsys/bluetooth/controller/ll_sw/ctrl.h | 6 +- subsys/bluetooth/controller/ll_sw/ll.c | 1 - subsys/bluetooth/controller/ticker/ticker.c | 203 +++++++++----------- subsys/bluetooth/controller/util/config.h | 30 --- subsys/bluetooth/controller/util/mayfly.c | 2 - subsys/bluetooth/controller/util/mayfly.h | 7 + 7 files changed, 102 insertions(+), 148 deletions(-) delete mode 100644 subsys/bluetooth/controller/util/config.h diff --git a/subsys/bluetooth/controller/ll_sw/ctrl.c b/subsys/bluetooth/controller/ll_sw/ctrl.c index adedf4d3dc5..54b1fa655ad 100644 --- a/subsys/bluetooth/controller/ll_sw/ctrl.c +++ b/subsys/bluetooth/controller/ll_sw/ctrl.c @@ -22,7 +22,6 @@ #include "hal/radio.h" #include "hal/debug.h" -#include "util/config.h" #include "util/util.h" #include "util/mem.h" #include "util/memq.h" diff --git a/subsys/bluetooth/controller/ll_sw/ctrl.h b/subsys/bluetooth/controller/ll_sw/ctrl.h index 96dc0a0e6cd..d47a56a28c0 100644 --- a/subsys/bluetooth/controller/ll_sw/ctrl.h +++ b/subsys/bluetooth/controller/ll_sw/ctrl.h @@ -64,9 +64,9 @@ #define RADIO_TICKER_USERS 3 -#define RADIO_TICKER_USER_ID_WORKER TICKER_MAYFLY_CALL_ID_WORKER0 -#define RADIO_TICKER_USER_ID_JOB TICKER_MAYFLY_CALL_ID_JOB0 -#define RADIO_TICKER_USER_ID_APP TICKER_MAYFLY_CALL_ID_PROGRAM +#define RADIO_TICKER_USER_ID_WORKER MAYFLY_CALL_ID_0 +#define RADIO_TICKER_USER_ID_JOB MAYFLY_CALL_ID_1 +#define RADIO_TICKER_USER_ID_APP MAYFLY_CALL_ID_PROGRAM #define RADIO_TICKER_USER_ID_WORKER_PRIO TICKER_MAYFLY_CALL_ID_WORKER0_PRIO #define RADIO_TICKER_USER_ID_JOB_PRIO TICKER_MAYFLY_CALL_ID_JOB0_PRIO diff --git a/subsys/bluetooth/controller/ll_sw/ll.c b/subsys/bluetooth/controller/ll_sw/ll.c index 83396c66529..dbe24e68d6e 100644 --- a/subsys/bluetooth/controller/ll_sw/ll.c +++ b/subsys/bluetooth/controller/ll_sw/ll.c @@ -25,7 +25,6 @@ #include "hal/radio.h" #include "hal/debug.h" -#include "util/config.h" #include "util/util.h" #include "util/mem.h" #include "util/mayfly.h" diff --git a/subsys/bluetooth/controller/ticker/ticker.c b/subsys/bluetooth/controller/ticker/ticker.c index 31ae339e40e..5e8ee857e72 100644 --- a/subsys/bluetooth/controller/ticker/ticker.c +++ b/subsys/bluetooth/controller/ticker/ticker.c @@ -8,7 +8,6 @@ #include #include -#include "util/config.h" #include "hal/cntr.h" #include "ticker.h" @@ -1181,34 +1180,40 @@ static inline void ticker_job(struct ticker_instance *instance) static uint8_t ticker_instance0_caller_id_get(uint8_t user_id) { - if (user_id == TICKER_MAYFLY_CALL_ID_PROGRAM) { - return CALL_ID_USER; - } else if (user_id == TICKER_MAYFLY_CALL_ID_JOB0) { - return CALL_ID_JOB; - } else if (user_id == TICKER_MAYFLY_CALL_ID_WORKER0) { + switch (user_id) { + case MAYFLY_CALL_ID_0: return CALL_ID_WORKER; - } else if (user_id == TICKER_MAYFLY_CALL_ID_TRIGGER) { - return CALL_ID_TRIGGER; - } - LL_ASSERT(0); + case MAYFLY_CALL_ID_1: + return CALL_ID_JOB; + + case MAYFLY_CALL_ID_PROGRAM: + return CALL_ID_USER; + + case MAYFLY_CALL_ID_2: + default: + LL_ASSERT(0); + break; + } return 0; } static uint8_t ticker_instance1_caller_id_get(uint8_t user_id) { - if (user_id == TICKER_MAYFLY_CALL_ID_PROGRAM) { - return CALL_ID_USER; - } else if (user_id == TICKER_MAYFLY_CALL_ID_JOB1) { + switch (user_id) { + case MAYFLY_CALL_ID_2: return CALL_ID_JOB; - } else if (user_id == TICKER_MAYFLY_CALL_ID_WORKER1) { - return CALL_ID_WORKER; - } else if (user_id == TICKER_MAYFLY_CALL_ID_TRIGGER) { - return CALL_ID_TRIGGER; - } - LL_ASSERT(0); + case MAYFLY_CALL_ID_PROGRAM: + return CALL_ID_USER; + + case MAYFLY_CALL_ID_0: + case MAYFLY_CALL_ID_1: + default: + LL_ASSERT(0); + break; + } return 0; } @@ -1232,24 +1237,8 @@ static void ticker_instance0_sched(uint8_t caller_id, uint8_t callee_id, (void *)ticker_worker }; - mayfly_enqueue(TICKER_MAYFLY_CALL_ID_TRIGGER, - TICKER_MAYFLY_CALL_ID_WORKER0, - chain, - &m); - } - break; - - case CALL_ID_JOB: - { - static void *link[2]; - static struct mayfly m = { - 0, 0, link, - (void *)&_instance[0], - (void *)ticker_job - }; - - mayfly_enqueue(TICKER_MAYFLY_CALL_ID_TRIGGER, - TICKER_MAYFLY_CALL_ID_JOB0, + mayfly_enqueue(MAYFLY_CALL_ID_0, + MAYFLY_CALL_ID_0, chain, &m); } @@ -1272,8 +1261,8 @@ static void ticker_instance0_sched(uint8_t caller_id, uint8_t callee_id, (void *)ticker_job }; - mayfly_enqueue(TICKER_MAYFLY_CALL_ID_WORKER0, - TICKER_MAYFLY_CALL_ID_JOB0, + mayfly_enqueue(MAYFLY_CALL_ID_0, + MAYFLY_CALL_ID_1, chain, &m); } @@ -1296,8 +1285,8 @@ static void ticker_instance0_sched(uint8_t caller_id, uint8_t callee_id, (void *)ticker_worker }; - mayfly_enqueue(TICKER_MAYFLY_CALL_ID_JOB0, - TICKER_MAYFLY_CALL_ID_WORKER0, + mayfly_enqueue(MAYFLY_CALL_ID_1, + MAYFLY_CALL_ID_0, chain, &m); } @@ -1312,8 +1301,33 @@ static void ticker_instance0_sched(uint8_t caller_id, uint8_t callee_id, (void *)ticker_job }; - mayfly_enqueue(TICKER_MAYFLY_CALL_ID_JOB0, - TICKER_MAYFLY_CALL_ID_JOB0, + mayfly_enqueue(MAYFLY_CALL_ID_1, + MAYFLY_CALL_ID_1, + chain, + &m); + } + break; + + default: + LL_ASSERT(0); + break; + } + break; + + case CALL_ID_USER: + switch (callee_id) { + case CALL_ID_JOB: + { + static void *link[2]; + static struct mayfly m = { + 0, 0, link, + (void *)&_instance[0], + (void *)ticker_job + }; + + /* TODO: scheduler lock, if OS used */ + mayfly_enqueue(MAYFLY_CALL_ID_PROGRAM, + MAYFLY_CALL_ID_1, chain, &m); } @@ -1326,28 +1340,7 @@ static void ticker_instance0_sched(uint8_t caller_id, uint8_t callee_id, break; default: - switch (callee_id) { - case CALL_ID_JOB: - { - static void *link[2]; - static struct mayfly m = { - 0, 0, link, - (void *)&_instance[0], - (void *)ticker_job - }; - - /* TODO: scheduler lock, if OS used */ - mayfly_enqueue(TICKER_MAYFLY_CALL_ID_PROGRAM, - TICKER_MAYFLY_CALL_ID_JOB0, - chain, - &m); - } - break; - - default: - LL_ASSERT(0); - break; - } + LL_ASSERT(0); break; } } @@ -1371,24 +1364,8 @@ static void ticker_instance1_sched(uint8_t caller_id, uint8_t callee_id, (void *)ticker_worker }; - mayfly_enqueue(TICKER_MAYFLY_CALL_ID_TRIGGER, - TICKER_MAYFLY_CALL_ID_WORKER1, - chain, - &m); - } - break; - - case CALL_ID_JOB: - { - static void *link[2]; - static struct mayfly m = { - 0, 0, link, - (void *)&_instance[1], - (void *)ticker_job - }; - - mayfly_enqueue(TICKER_MAYFLY_CALL_ID_TRIGGER, - TICKER_MAYFLY_CALL_ID_JOB1, + mayfly_enqueue(MAYFLY_CALL_ID_0, + MAYFLY_CALL_ID_2, chain, &m); } @@ -1411,8 +1388,8 @@ static void ticker_instance1_sched(uint8_t caller_id, uint8_t callee_id, (void *)ticker_job }; - mayfly_enqueue(TICKER_MAYFLY_CALL_ID_WORKER1, - TICKER_MAYFLY_CALL_ID_JOB1, + mayfly_enqueue(MAYFLY_CALL_ID_2, + MAYFLY_CALL_ID_2, chain, &m); } @@ -1435,8 +1412,8 @@ static void ticker_instance1_sched(uint8_t caller_id, uint8_t callee_id, (void *)ticker_worker }; - mayfly_enqueue(TICKER_MAYFLY_CALL_ID_JOB1, - TICKER_MAYFLY_CALL_ID_WORKER1, + mayfly_enqueue(MAYFLY_CALL_ID_2, + MAYFLY_CALL_ID_2, chain, &m); } @@ -1451,8 +1428,33 @@ static void ticker_instance1_sched(uint8_t caller_id, uint8_t callee_id, (void *)ticker_job }; - mayfly_enqueue(TICKER_MAYFLY_CALL_ID_JOB1, - TICKER_MAYFLY_CALL_ID_JOB1, + mayfly_enqueue(MAYFLY_CALL_ID_2, + MAYFLY_CALL_ID_2, + chain, + &m); + } + break; + + default: + LL_ASSERT(0); + break; + } + break; + + case CALL_ID_USER: + switch (callee_id) { + case CALL_ID_JOB: + { + static void *link[2]; + static struct mayfly m = { + 0, 0, link, + (void *)&_instance[1], + (void *)ticker_job + }; + + /* TODO: scheduler lock, if OS used */ + mayfly_enqueue(MAYFLY_CALL_ID_PROGRAM, + MAYFLY_CALL_ID_2, chain, &m); } @@ -1465,28 +1467,7 @@ static void ticker_instance1_sched(uint8_t caller_id, uint8_t callee_id, break; default: - switch (callee_id) { - case CALL_ID_JOB: - { - static void *link[2]; - static struct mayfly m = { - 0, 0, link, - (void *)&_instance[1], - (void *)ticker_job - }; - - /* TODO: scheduler lock, if OS used */ - mayfly_enqueue(TICKER_MAYFLY_CALL_ID_PROGRAM, - TICKER_MAYFLY_CALL_ID_JOB1, - chain, - &m); - } - break; - - default: - LL_ASSERT(0); - break; - } + LL_ASSERT(0); break; } } diff --git a/subsys/bluetooth/controller/util/config.h b/subsys/bluetooth/controller/util/config.h deleted file mode 100644 index 03d9d883e82..00000000000 --- a/subsys/bluetooth/controller/util/config.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2016 Nordic Semiconductor ASA - * Copyright (c) 2016 Vinayak Kariappa Chettimada - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef _CONFIG_H_ -#define _CONFIG_H_ - -#define MAYFLY_CALL_ID_0 0 -#define MAYFLY_CALL_ID_1 1 -#define MAYFLY_CALL_ID_2 2 -#define MAYFLY_CALL_ID_PROGRAM 3 -#define MAYFLY_CALLER_COUNT 4 -#define MAYFLY_CALLEE_COUNT 4 - -#define TICKER_MAYFLY_CALL_ID_TRIGGER MAYFLY_CALL_ID_0 -#define TICKER_MAYFLY_CALL_ID_WORKER0 MAYFLY_CALL_ID_0 -#define TICKER_MAYFLY_CALL_ID_WORKER1 MAYFLY_CALL_ID_2 -#define TICKER_MAYFLY_CALL_ID_JOB0 MAYFLY_CALL_ID_1 -#define TICKER_MAYFLY_CALL_ID_JOB1 MAYFLY_CALL_ID_2 -#define TICKER_MAYFLY_CALL_ID_PROGRAM MAYFLY_CALL_ID_PROGRAM - -#define TICKER_MAYFLY_CALL_ID_WORKER0_PRIO 0 -#define TICKER_MAYFLY_CALL_ID_WORKER1_PRIO 1 -#define TICKER_MAYFLY_CALL_ID_JOB0_PRIO 0 -#define TICKER_MAYFLY_CALL_ID_JOB1_PRIO 1 - -#endif /* _CONFIG_H_ */ diff --git a/subsys/bluetooth/controller/util/mayfly.c b/subsys/bluetooth/controller/util/mayfly.c index d97d796388a..d8bcee5b1c6 100644 --- a/subsys/bluetooth/controller/util/mayfly.c +++ b/subsys/bluetooth/controller/util/mayfly.c @@ -9,8 +9,6 @@ #include "memq.h" #include "mayfly.h" -#include "config.h" - static struct { void *head; void *tail; diff --git a/subsys/bluetooth/controller/util/mayfly.h b/subsys/bluetooth/controller/util/mayfly.h index 61f3df237ca..ea66153c620 100644 --- a/subsys/bluetooth/controller/util/mayfly.h +++ b/subsys/bluetooth/controller/util/mayfly.h @@ -8,6 +8,13 @@ #ifndef _MAYFLY_H_ #define _MAYFLY_H_ +#define MAYFLY_CALL_ID_0 0 +#define MAYFLY_CALL_ID_1 1 +#define MAYFLY_CALL_ID_2 2 +#define MAYFLY_CALL_ID_PROGRAM 3 +#define MAYFLY_CALLER_COUNT 4 +#define MAYFLY_CALLEE_COUNT 4 + struct mayfly { uint8_t volatile _req; uint8_t _ack; From 7c220731952c5a271e30ce4cbd6af9827ea348a7 Mon Sep 17 00:00:00 2001 From: Vinayak Chettimada Date: Thu, 30 Mar 2017 10:49:34 +0200 Subject: [PATCH 29/41] Bluetooth: controller: Make worker and job priority configurable Add Controller advanced Kconfig options to select IRQ priorities of the Radio, Ticker's Worker and JOB IRQs. This will provide an opportunity to have peripheral IRQ's of higher level than Bluetooth Controller. Change-id: Iaa128c1cd64a309a77d42d485fdefe68f31e4895 Signed-off-by: Vinayak Chettimada --- subsys/bluetooth/controller/Kconfig | 20 ++++++++++++++++++++ subsys/bluetooth/controller/ll_sw/ctrl.c | 12 ++++++------ subsys/bluetooth/controller/ll_sw/ctrl.h | 15 ++++++++++++--- subsys/bluetooth/controller/ll_sw/ll.c | 13 +++++++++---- tests/bluetooth/init/prj_controller.conf | 2 ++ tests/bluetooth/init/prj_controller_4_0.conf | 2 ++ tests/bluetooth/init/prj_controller_dbg.conf | 2 ++ 7 files changed, 53 insertions(+), 13 deletions(-) diff --git a/subsys/bluetooth/controller/Kconfig b/subsys/bluetooth/controller/Kconfig index 6ba10166862..01fa344e1c1 100644 --- a/subsys/bluetooth/controller/Kconfig +++ b/subsys/bluetooth/controller/Kconfig @@ -114,6 +114,26 @@ config BLUETOOTH_CONTROLLER_ADVANCED_FEATURES menu "Advanced features" visible if BLUETOOTH_CONTROLLER_ADVANCED_FEATURES +config BLUETOOTH_CONTROLLER_WORKER_PRIO + prompt "Radio and Ticker's Worker IRQ priority" + int + range 0 3 if SOC_SERIES_NRF51X + range 0 6 if SOC_SERIES_NRF52X + default 0 + help + The interrupt priority for event preparation and radio IRQ. This value + shall be less than or equal to the Ticker's Job priority value. + +config BLUETOOTH_CONTROLLER_JOB_PRIO + prompt "Ticker's JOB IRQ priority" + int + range BLUETOOTH_CONTROLLER_WORKER_PRIO 3 if SOC_SERIES_NRF51X + range BLUETOOTH_CONTROLLER_WORKER_PRIO 6 if SOC_SERIES_NRF52X + default 0 + help + The interrupt priority for Ticker's Job (SWI4) IRQ. This value shall + be greater than or equal to the Ticker's Worker IRQ priority value. + config BLUETOOTH_CONTROLLER_XTAL_ADVANCED bool "Advanced event preparation" default y diff --git a/subsys/bluetooth/controller/ll_sw/ctrl.c b/subsys/bluetooth/controller/ll_sw/ctrl.c index 54b1fa655ad..af27f17c193 100644 --- a/subsys/bluetooth/controller/ll_sw/ctrl.c +++ b/subsys/bluetooth/controller/ll_sw/ctrl.c @@ -4192,9 +4192,9 @@ static void event_adv(uint32_t ticks_at_expire, uint32_t remainder, } else #endif /* CONFIG_BLUETOOTH_CONTROLLER_XTAL_ADVANCED */ + { /* Ticker Job Silence */ #if (RADIO_TICKER_USER_ID_WORKER_PRIO == RADIO_TICKER_USER_ID_JOB_PRIO) - { uint32_t ticker_status; ticker_status = @@ -4203,8 +4203,8 @@ static void event_adv(uint32_t ticks_at_expire, uint32_t remainder, ticker_job_disable, NULL); LL_ASSERT((ticker_status == TICKER_STATUS_SUCCESS) || (ticker_status == TICKER_STATUS_BUSY)); - } #endif + } DEBUG_RADIO_START_A(0); } @@ -5696,9 +5696,9 @@ static void event_slave(uint32_t ticks_at_expire, uint32_t remainder, } else #endif /* CONFIG_BLUETOOTH_CONTROLLER_XTAL_ADVANCED */ + { /* Ticker Job Silence */ #if (RADIO_TICKER_USER_ID_WORKER_PRIO == RADIO_TICKER_USER_ID_JOB_PRIO) - { uint32_t ticker_status; ticker_status = @@ -5707,8 +5707,8 @@ static void event_slave(uint32_t ticks_at_expire, uint32_t remainder, ticker_job_disable, NULL); LL_ASSERT((ticker_status == TICKER_STATUS_SUCCESS) || (ticker_status == TICKER_STATUS_BUSY)); - } #endif + } /* Route the tx packet to respective connections */ packet_tx_enqueue(2); @@ -5833,9 +5833,9 @@ static void event_master(uint32_t ticks_at_expire, uint32_t remainder, } else #endif /* CONFIG_BLUETOOTH_CONTROLLER_XTAL_ADVANCED */ + { /* Ticker Job Silence */ #if (RADIO_TICKER_USER_ID_WORKER_PRIO == RADIO_TICKER_USER_ID_JOB_PRIO) - { uint32_t ticker_status; ticker_status = @@ -5844,8 +5844,8 @@ static void event_master(uint32_t ticks_at_expire, uint32_t remainder, ticker_job_disable, NULL); LL_ASSERT((ticker_status == TICKER_STATUS_SUCCESS) || (ticker_status == TICKER_STATUS_BUSY)); - } #endif + } DEBUG_RADIO_START_M(0); } diff --git a/subsys/bluetooth/controller/ll_sw/ctrl.h b/subsys/bluetooth/controller/ll_sw/ctrl.h index d47a56a28c0..c7ebae469e8 100644 --- a/subsys/bluetooth/controller/ll_sw/ctrl.h +++ b/subsys/bluetooth/controller/ll_sw/ctrl.h @@ -68,9 +68,6 @@ #define RADIO_TICKER_USER_ID_JOB MAYFLY_CALL_ID_1 #define RADIO_TICKER_USER_ID_APP MAYFLY_CALL_ID_PROGRAM -#define RADIO_TICKER_USER_ID_WORKER_PRIO TICKER_MAYFLY_CALL_ID_WORKER0_PRIO -#define RADIO_TICKER_USER_ID_JOB_PRIO TICKER_MAYFLY_CALL_ID_JOB0_PRIO - #define RADIO_TICKER_USER_WORKER_OPS (7 + 1) #define RADIO_TICKER_USER_JOB_OPS (2 + 1) #define RADIO_TICKER_USER_APP_OPS (1 + 1) @@ -106,6 +103,18 @@ RADIO_BLE_FEATURES_BIT_PING | \ RADIO_BLE_FEATURES_BIT_DLE) +#if defined(CONFIG_BLUETOOTH_CONTROLLER_WORKER_PRIO) +#define RADIO_TICKER_USER_ID_WORKER_PRIO CONFIG_BLUETOOTH_CONTROLLER_WORKER_PRIO +#else +#define RADIO_TICKER_USER_ID_WORKER_PRIO 0 +#endif + +#if defined(CONFIG_BLUETOOTH_CONTROLLER_JOB_PRIO) +#define RADIO_TICKER_USER_ID_JOB_PRIO CONFIG_BLUETOOTH_CONTROLLER_JOB_PRIO +#else +#define RADIO_TICKER_USER_ID_JOB_PRIO 0 +#endif + /***************************************************************************** * Controller Reference Defines (compile time override-able) ****************************************************************************/ diff --git a/subsys/bluetooth/controller/ll_sw/ll.c b/subsys/bluetooth/controller/ll_sw/ll.c index dbe24e68d6e..821863b1dca 100644 --- a/subsys/bluetooth/controller/ll_sw/ll.c +++ b/subsys/bluetooth/controller/ll_sw/ll.c @@ -229,14 +229,19 @@ int ll_init(struct k_sem *sem_rx) return -ENOMEM; } - IRQ_DIRECT_CONNECT(NRF5_IRQ_RADIO_IRQn, 0, radio_nrf5_isr, 0); - IRQ_CONNECT(NRF5_IRQ_RTC0_IRQn, 0, rtc0_nrf5_isr, NULL, 0); + IRQ_DIRECT_CONNECT(NRF5_IRQ_RADIO_IRQn, + CONFIG_BLUETOOTH_CONTROLLER_WORKER_PRIO, + radio_nrf5_isr, 0); + IRQ_CONNECT(NRF5_IRQ_RTC0_IRQn, CONFIG_BLUETOOTH_CONTROLLER_WORKER_PRIO, + rtc0_nrf5_isr, NULL, 0); + IRQ_CONNECT(NRF5_IRQ_SWI4_IRQn, CONFIG_BLUETOOTH_CONTROLLER_JOB_PRIO, + swi4_nrf5_isr, NULL, 0); IRQ_CONNECT(NRF5_IRQ_RNG_IRQn, 1, rng_nrf5_isr, NULL, 0); - IRQ_CONNECT(NRF5_IRQ_SWI4_IRQn, 0, swi4_nrf5_isr, NULL, 0); + irq_enable(NRF5_IRQ_RADIO_IRQn); irq_enable(NRF5_IRQ_RTC0_IRQn); - irq_enable(NRF5_IRQ_RNG_IRQn); irq_enable(NRF5_IRQ_SWI4_IRQn); + irq_enable(NRF5_IRQ_RNG_IRQn); return 0; } diff --git a/tests/bluetooth/init/prj_controller.conf b/tests/bluetooth/init/prj_controller.conf index 7d679719992..43c1ebd22e9 100644 --- a/tests/bluetooth/init/prj_controller.conf +++ b/tests/bluetooth/init/prj_controller.conf @@ -1,5 +1,7 @@ CONFIG_BLUETOOTH=y CONFIG_BLUETOOTH_CONTROLLER=y +CONFIG_BLUETOOTH_CONTROLLER_WORKER_PRIO=0 +CONFIG_BLUETOOTH_CONTROLLER_JOB_PRIO=0 CONFIG_BLUETOOTH_CONTROLLER_XTAL_ADVANCED=y CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED=y CONFIG_BLUETOOTH_PERIPHERAL=y diff --git a/tests/bluetooth/init/prj_controller_4_0.conf b/tests/bluetooth/init/prj_controller_4_0.conf index f5cad448610..70fadd16050 100644 --- a/tests/bluetooth/init/prj_controller_4_0.conf +++ b/tests/bluetooth/init/prj_controller_4_0.conf @@ -1,5 +1,7 @@ CONFIG_BLUETOOTH=y CONFIG_BLUETOOTH_CONTROLLER=y +CONFIG_BLUETOOTH_CONTROLLER_WORKER_PRIO=0 +CONFIG_BLUETOOTH_CONTROLLER_JOB_PRIO=0 CONFIG_BLUETOOTH_CONTROLLER_XTAL_ADVANCED=y CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED=y CONFIG_BLUETOOTH_CONTROLLER_LE_PING=n diff --git a/tests/bluetooth/init/prj_controller_dbg.conf b/tests/bluetooth/init/prj_controller_dbg.conf index b9128fa73d1..4a3c9119375 100644 --- a/tests/bluetooth/init/prj_controller_dbg.conf +++ b/tests/bluetooth/init/prj_controller_dbg.conf @@ -1,5 +1,7 @@ CONFIG_BLUETOOTH=y CONFIG_BLUETOOTH_CONTROLLER=y +CONFIG_BLUETOOTH_CONTROLLER_WORKER_PRIO=0 +CONFIG_BLUETOOTH_CONTROLLER_JOB_PRIO=1 CONFIG_BLUETOOTH_CONTROLLER_XTAL_ADVANCED=n CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED=n CONFIG_BLUETOOTH_CONTROLLER_CONN_RSSI=y From 27e83660ffd690d4309a1f4bd20fd552da2dc8f8 Mon Sep 17 00:00:00 2001 From: Carles Cufi Date: Tue, 4 Apr 2017 12:54:56 +0200 Subject: [PATCH 30/41] Bluetooth: controller: Implement scan duplicate filter Implement the controller's ability to drop duplicate advertising reports when instructed by the Host. Jira: ZEP-1246 Change-Id: I2d1b7abf1ed950dde705e5df30a858c595f3834c Signed-off-by: Carles Cufi --- subsys/bluetooth/controller/Kconfig | 8 ++++ subsys/bluetooth/controller/hci/hci.c | 64 +++++++++++++++++++++++++++ tests/bluetooth/shell/src/main.c | 39 +++++++++++++--- 3 files changed, 105 insertions(+), 6 deletions(-) diff --git a/subsys/bluetooth/controller/Kconfig b/subsys/bluetooth/controller/Kconfig index 01fa344e1c1..513e8a0d13e 100644 --- a/subsys/bluetooth/controller/Kconfig +++ b/subsys/bluetooth/controller/Kconfig @@ -82,6 +82,14 @@ config BLUETOOTH_CONTROLLER_RX_PRIO_STACK_SIZE int default 320 +config BLUETOOTH_CONTROLLER_DUP_FILTER_LEN + prompt "Number of addresses in the scan duplicate filter" + int + default 16 + help + Set the number of unique BLE addresses that can be filtered as + duplicates while scanning. + comment "BLE Controller features" config BLUETOOTH_CONTROLLER_LE_PING diff --git a/subsys/bluetooth/controller/hci/hci.c b/subsys/bluetooth/controller/hci/hci.c index 76ca6dd68e9..34d8fb23b84 100644 --- a/subsys/bluetooth/controller/hci/hci.c +++ b/subsys/bluetooth/controller/hci/hci.c @@ -35,6 +35,17 @@ */ static uint16_t _opcode; +#if CONFIG_BLUETOOTH_CONTROLLER_DUP_FILTER_LEN > 0 +/* Scan duplicate filter */ +struct dup { + uint8_t mask; + bt_addr_le_t addr; +}; +static struct dup dup_filter[CONFIG_BLUETOOTH_CONTROLLER_DUP_FILTER_LEN]; +static int32_t dup_count; +static uint32_t dup_curr; +#endif + static void evt_create(struct net_buf *buf, uint8_t evt, uint8_t len) { struct bt_hci_evt_hdr *hdr; @@ -143,6 +154,10 @@ static void reset(struct net_buf *buf, struct net_buf **evt) ll_reset(); +#if CONFIG_BLUETOOTH_CONTROLLER_DUP_FILTER_LEN > 0 + dup_count = -1; +#endif + ccst = cmd_complete(evt, sizeof(*ccst)); ccst->status = 0x00; } @@ -411,6 +426,15 @@ static void le_set_scan_enable(struct net_buf *buf, struct net_buf **evt) struct bt_hci_evt_cc_status *ccst; uint32_t status; +#if CONFIG_BLUETOOTH_CONTROLLER_DUP_FILTER_LEN > 0 + /* initialize duplicate filtering */ + if (cmd->enable && cmd->filter_dup) { + dup_count = 0; + dup_curr = 0; + } else { + dup_count = -1; + } +#endif status = ll_scan_enable(cmd->enable); ccst = cmd_complete(evt, sizeof(*ccst)); @@ -973,6 +997,46 @@ static void le_advertising_report(struct pdu_data *pdu_data, uint8_t *b, uint8_t data_len; uint8_t *rssi; uint8_t info_len; + int i; + +#if CONFIG_BLUETOOTH_CONTROLLER_DUP_FILTER_LEN > 0 + /* check for duplicate filtering */ + if (dup_count >= 0) { + for (i = 0; i < dup_count; i++) { + if (!memcmp(&adv->payload.adv_ind.addr[0], + &dup_filter[i].addr.a.val[0], + sizeof(bt_addr_t)) && + adv->tx_addr == dup_filter[i].addr.type) { + + if (dup_filter[i].mask & BIT(adv->type)) { + /* duplicate found */ + return; + } + /* report different adv types */ + dup_filter[i].mask |= BIT(adv->type); + goto fill_report; + } + } + + /* insert into the duplicate filter */ + memcpy(&dup_filter[dup_curr].addr.a.val[0], + &adv->payload.adv_ind.addr[0], sizeof(bt_addr_t)); + dup_filter[dup_curr].addr.type = adv->tx_addr; + dup_filter[dup_curr].mask = BIT(adv->type); + + if (dup_count < CONFIG_BLUETOOTH_CONTROLLER_DUP_FILTER_LEN) { + dup_count++; + dup_curr = dup_count; + } else { + dup_curr++; + } + + if (dup_curr == CONFIG_BLUETOOTH_CONTROLLER_DUP_FILTER_LEN) { + dup_curr = 0; + } + } +fill_report: +#endif if (adv->type != PDU_ADV_TYPE_DIRECT_IND) { data_len = (adv->len - BDADDR_SIZE); diff --git a/tests/bluetooth/shell/src/main.c b/tests/bluetooth/shell/src/main.c index dc04ef9a04d..b5a00a6aae6 100644 --- a/tests/bluetooth/shell/src/main.c +++ b/tests/bluetooth/shell/src/main.c @@ -566,11 +566,20 @@ static int cmd_init(int argc, char *argv[]) return 0; } -static void cmd_active_scan_on(void) +static void cmd_active_scan_on(int dups) { int err; + struct bt_le_scan_param param = { + .type = BT_HCI_LE_SCAN_PASSIVE, + .filter_dup = BT_HCI_LE_SCAN_FILTER_DUP_ENABLE, + .interval = BT_GAP_SCAN_FAST_INTERVAL, + .window = BT_GAP_SCAN_FAST_WINDOW }; - err = bt_le_scan_start(BT_LE_SCAN_ACTIVE, device_found); + if (dups >= 0) { + param.filter_dup = dups; + } + + err = bt_le_scan_start(¶m, device_found); if (err) { printk("Bluetooth set active scan failed (err %d)\n", err); } else { @@ -578,7 +587,7 @@ static void cmd_active_scan_on(void) } } -static void cmd_passive_scan_on(void) +static void cmd_passive_scan_on(int dups) { struct bt_le_scan_param param = { .type = BT_HCI_LE_SCAN_PASSIVE, @@ -587,6 +596,10 @@ static void cmd_passive_scan_on(void) .window = 0x10 }; int err; + if (dups >= 0) { + param.filter_dup = dups; + } + err = bt_le_scan_start(¶m, device_found); if (err) { printk("Bluetooth set passive scan failed (err %d)\n", err); @@ -610,18 +623,32 @@ static void cmd_scan_off(void) static int cmd_scan(int argc, char *argv[]) { const char *action; + int dups = -1; if (argc < 2) { return -EINVAL; } + /* Parse duplicate filtering data */ + if (argc >= 3) { + const char *dup_filter = argv[2]; + + if (!strcmp(dup_filter, "dups")) { + dups = BT_HCI_LE_SCAN_FILTER_DUP_DISABLE; + } else if (!strcmp(dup_filter, "nodups")) { + dups = BT_HCI_LE_SCAN_FILTER_DUP_ENABLE; + } else { + return -EINVAL; + } + } + action = argv[1]; if (!strcmp(action, "on")) { - cmd_active_scan_on(); + cmd_active_scan_on(dups); } else if (!strcmp(action, "off")) { cmd_scan_off(); } else if (!strcmp(action, "passive")) { - cmd_passive_scan_on(); + cmd_passive_scan_on(dups); } else { return -EINVAL; } @@ -2494,7 +2521,7 @@ static int cmd_bredr_sdp_find_record(int argc, char *argv[]) static const struct shell_cmd commands[] = { { "init", cmd_init, HELP_ADDR_LE }, - { "scan", cmd_scan, "" }, + { "scan", cmd_scan, " " }, { "advertise", cmd_advertise, " " }, { "connect", cmd_connect_le, HELP_ADDR_LE }, From 9a9699ebdbfd684342cb1f3082b1c56fc4aa34a4 Mon Sep 17 00:00:00 2001 From: Carles Cufi Date: Tue, 4 Apr 2017 16:20:14 +0200 Subject: [PATCH 31/41] Bluetooth: controller: Implement event masks HCI event masking allows the host to choose which events are reported to it to avoid interruption and excessive traffic. This patch implements masking to drop any non-enabled events as specified by the host. Jira: ZEP-1769 Change-Id: If09d4aa22b0da8f743fc42a3b0db3f369daaff96 Signed-off-by: Carles Cufi --- include/bluetooth/hci.h | 40 ++++++++++++++++ subsys/bluetooth/controller/hci/hci.c | 67 ++++++++++++++++++++++++++- 2 files changed, 105 insertions(+), 2 deletions(-) diff --git a/include/bluetooth/hci.h b/include/bluetooth/hci.h index b74fb972613..304d99f07f9 100644 --- a/include/bluetooth/hci.h +++ b/include/bluetooth/hci.h @@ -1269,6 +1269,46 @@ struct bt_hci_ev_le_direct_adv_report { struct bt_hci_ev_le_direct_adv_info direct_adv_info[0]; } __packed; +/* Event mask bits */ + +#define BT_EVT_BIT_INQUIRY_COMPLETE 0 +#define BT_EVT_BIT_CONN_COMPLETE 2 +#define BT_EVT_BIT_CONN_REQUEST 3 +#define BT_EVT_BIT_DISCONN_COMPLETE 4 +#define BT_EVT_BIT_AUTH_COMPLETE 5 +#define BT_EVT_BIT_REMOTE_NAME_REQ_COMPLETE 6 +#define BT_EVT_BIT_ENCRYPT_CHANGE 7 +#define BT_EVT_BIT_REMOTE_FEATURES 10 +#define BT_EVT_BIT_REMOTE_VERSION_INFO 11 +#define BT_EVT_BIT_ROLE_CHANGE 17 +#define BT_EVT_BIT_PIN_CODE_REQ 21 +#define BT_EVT_BIT_LINK_KEY_REQ 22 +#define BT_EVT_BIT_LINK_KEY_NOTIFY 23 +#define BT_EVT_BIT_INQUIRY_RESULT_WITH_RSSI 33 +#define BT_EVT_BIT_REMOTE_EXT_FEATURES 34 +#define BT_EVT_BIT_SYNC_CONN_COMPLETE 43 +#define BT_EVT_BIT_EXTENDED_INQUIRY_RESULT 46 +#define BT_EVT_BIT_ENCRYPT_KEY_REFRESH_COMPLETE 47 +#define BT_EVT_BIT_IO_CAPA_REQ 48 +#define BT_EVT_BIT_IO_CAPA_RESP 49 +#define BT_EVT_BIT_USER_CONFIRM_REQ 50 +#define BT_EVT_BIT_USER_PASSKEY_REQ 51 +#define BT_EVT_BIT_SSP_COMPLETE 53 +#define BT_EVT_BIT_USER_PASSKEY_NOTIFY 58 +#define BT_EVT_BIT_LE_META_EVENT 61 + +#define BT_EVT_BIT_LE_CONN_COMPLETE 0 +#define BT_EVT_BIT_LE_ADVERTISING_REPORT 1 +#define BT_EVT_BIT_LE_CONN_UPDATE_COMPLETE 2 +#define BT_EVT_BIT_LE_REMOTE_FEAT_COMPLETE 3 +#define BT_EVT_BIT_LE_LTK_REQUEST 4 +#define BT_EVT_BIT_LE_CONN_PARAM_REQ 5 +#define BT_EVT_BIT_LE_DATA_LEN_CHANGE 6 +#define BT_EVT_BIT_LE_P256_PUBLIC_KEY_COMPLETE 7 +#define BT_EVT_BIT_LE_GENERATE_DHKEY_COMPLETE 8 +#define BT_EVT_BIT_LE_ENH_CONN_COMPLETE 9 +#define BT_EVT_BIT_LE_DIRECT_ADV_REPORT 10 + #ifdef __cplusplus } #endif diff --git a/subsys/bluetooth/controller/hci/hci.c b/subsys/bluetooth/controller/hci/hci.c index 34d8fb23b84..e02c8117738 100644 --- a/subsys/bluetooth/controller/hci/hci.c +++ b/subsys/bluetooth/controller/hci/hci.c @@ -46,6 +46,13 @@ static int32_t dup_count; static uint32_t dup_curr; #endif +#define BIT64(n) (1ULL << (n)) +#define DEFAULT_EVENT_MASK 0x1fffffffffff +#define DEFAULT_LE_EVENT_MASK 0x1f + +static uint64_t event_mask = DEFAULT_EVENT_MASK; +static uint64_t le_event_mask = DEFAULT_LE_EVENT_MASK; + static void evt_create(struct net_buf *buf, uint8_t evt, uint8_t len) { struct bt_hci_evt_hdr *hdr; @@ -140,9 +147,10 @@ static int link_control_cmd_handle(uint8_t ocf, struct net_buf *cmd, static void set_event_mask(struct net_buf *buf, struct net_buf **evt) { + struct bt_hci_cp_set_event_mask *cmd = (void *)buf->data; struct bt_hci_evt_cc_status *ccst; - /** TODO */ + event_mask = sys_get_le64(cmd->events); ccst = cmd_complete(evt, sizeof(*ccst)); ccst->status = 0x00; @@ -157,6 +165,9 @@ static void reset(struct net_buf *buf, struct net_buf **evt) #if CONFIG_BLUETOOTH_CONTROLLER_DUP_FILTER_LEN > 0 dup_count = -1; #endif + /* reset event masks */ + event_mask = DEFAULT_EVENT_MASK; + le_event_mask = DEFAULT_LE_EVENT_MASK; ccst = cmd_complete(evt, sizeof(*ccst)); ccst->status = 0x00; @@ -295,9 +306,10 @@ static int info_cmd_handle(uint8_t ocf, struct net_buf *cmd, static void le_set_event_mask(struct net_buf *buf, struct net_buf **evt) { + struct bt_hci_cp_set_event_mask *cmd = (void *)buf->data; struct bt_hci_evt_cc_status *ccst; - /** TODO */ + le_event_mask = sys_get_le64(cmd->events); ccst = cmd_complete(evt, sizeof(*ccst)); ccst->status = 0x00; @@ -999,6 +1011,11 @@ static void le_advertising_report(struct pdu_data *pdu_data, uint8_t *b, uint8_t info_len; int i; + if (!(event_mask & BIT64(BT_EVT_BIT_LE_META_EVENT)) || + !(le_event_mask & BIT64(BT_EVT_BIT_LE_ADVERTISING_REPORT))) { + return; + } + #if CONFIG_BLUETOOTH_CONTROLLER_DUP_FILTER_LEN > 0 /* check for duplicate filtering */ if (dup_count >= 0) { @@ -1072,6 +1089,11 @@ static void le_conn_complete(struct pdu_data *pdu_data, uint16_t handle, struct bt_hci_evt_le_conn_complete *sep; struct radio_le_conn_cmplt *radio_cc; + if (!(event_mask & BIT64(BT_EVT_BIT_LE_META_EVENT)) || + !(le_event_mask & BIT64(BT_EVT_BIT_LE_CONN_COMPLETE))) { + return; + } + radio_cc = (struct radio_le_conn_cmplt *) (pdu_data->payload.lldata); sep = meta_evt(buf, BT_HCI_EVT_LE_CONN_COMPLETE, sizeof(*sep)); @@ -1092,6 +1114,10 @@ static void disconn_complete(struct pdu_data *pdu_data, uint16_t handle, { struct bt_hci_evt_disconn_complete *ep; + if (!(event_mask & BIT64(BT_EVT_BIT_DISCONN_COMPLETE))) { + return; + } + evt_create(buf, BT_HCI_EVT_DISCONN_COMPLETE, sizeof(*ep)); ep = net_buf_add(buf, sizeof(*ep)); @@ -1106,6 +1132,11 @@ static void le_conn_update_complete(struct pdu_data *pdu_data, uint16_t handle, struct bt_hci_evt_le_conn_update_complete *sep; struct radio_le_conn_update_cmplt *radio_cu; + if (!(event_mask & BIT64(BT_EVT_BIT_LE_META_EVENT)) || + !(le_event_mask & BIT64(BT_EVT_BIT_LE_CONN_UPDATE_COMPLETE))) { + return; + } + radio_cu = (struct radio_le_conn_update_cmplt *) (pdu_data->payload.lldata); @@ -1123,6 +1154,10 @@ static void enc_refresh_complete(struct pdu_data *pdu_data, uint16_t handle, { struct bt_hci_evt_encrypt_key_refresh_complete *ep; + if (!(event_mask & BIT64(BT_EVT_BIT_ENCRYPT_KEY_REFRESH_COMPLETE))) { + return; + } + evt_create(buf, BT_HCI_EVT_ENCRYPT_KEY_REFRESH_COMPLETE, sizeof(*ep)); ep = net_buf_add(buf, sizeof(*ep)); @@ -1214,6 +1249,11 @@ static void le_ltk_request(struct pdu_data *pdu_data, uint16_t handle, { struct bt_hci_evt_le_ltk_request *sep; + if (!(event_mask & BIT64(BT_EVT_BIT_LE_META_EVENT)) || + !(le_event_mask & BIT64(BT_EVT_BIT_LE_LTK_REQUEST))) { + return; + } + sep = meta_evt(buf, BT_HCI_EVT_LE_LTK_REQUEST, sizeof(*sep)); sep->handle = sys_cpu_to_le16(handle); @@ -1228,6 +1268,10 @@ static void encrypt_change(uint8_t err, uint16_t handle, { struct bt_hci_evt_encrypt_change *ep; + if (!(event_mask & BIT64(BT_EVT_BIT_ENCRYPT_CHANGE))) { + return; + } + evt_create(buf, BT_HCI_EVT_ENCRYPT_CHANGE, sizeof(*ep)); ep = net_buf_add(buf, sizeof(*ep)); @@ -1241,6 +1285,11 @@ static void le_remote_feat_complete(uint8_t status, struct pdu_data *pdu_data, { struct bt_hci_ev_le_remote_feat_complete *sep; + if (!(event_mask & BIT64(BT_EVT_BIT_LE_META_EVENT)) || + !(le_event_mask & BIT64(BT_EVT_BIT_LE_REMOTE_FEAT_COMPLETE))) { + return; + } + sep = meta_evt(buf, BT_HCI_EV_LE_REMOTE_FEAT_COMPLETE, sizeof(*sep)); sep->status = status; @@ -1276,6 +1325,10 @@ static void remote_version_info(struct pdu_data *pdu_data, uint16_t handle, { struct bt_hci_evt_remote_version_info *ep; + if (!(event_mask & BIT64(BT_EVT_BIT_REMOTE_VERSION_INFO))) { + return; + } + evt_create(buf, BT_HCI_EVT_REMOTE_VERSION_INFO, sizeof(*ep)); ep = net_buf_add(buf, sizeof(*ep)); @@ -1294,6 +1347,11 @@ static void le_conn_param_req(struct pdu_data *pdu_data, uint16_t handle, { struct bt_hci_evt_le_conn_param_req *sep; + if (!(event_mask & BIT64(BT_EVT_BIT_LE_META_EVENT)) || + !(le_event_mask & BIT64(BT_EVT_BIT_LE_CONN_PARAM_REQ))) { + return; + } + sep = meta_evt(buf, BT_HCI_EVT_LE_CONN_PARAM_REQ, sizeof(*sep)); sep->handle = sys_cpu_to_le16(handle); @@ -1310,6 +1368,11 @@ static void le_data_len_change(struct pdu_data *pdu_data, uint16_t handle, { struct bt_hci_evt_le_data_len_change *sep; + if (!(event_mask & BIT64(BT_EVT_BIT_LE_META_EVENT)) || + !(le_event_mask & BIT64(BT_EVT_BIT_LE_DATA_LEN_CHANGE))) { + return; + } + sep = meta_evt(buf, BT_HCI_EVT_LE_DATA_LEN_CHANGE, sizeof(*sep)); sep->handle = sys_cpu_to_le16(handle); From d2ac4a263a5a1cc4fb2d418a64d7219d4f9543ad Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Fri, 7 Apr 2017 14:07:07 +0300 Subject: [PATCH 32/41] Bluetooth: hci_ecc: Fix ECDH API usage The main issue is that after the latest update to TinyCrypt the ecc_make_key() API expects a twice as big random number. Fix this, but also move the variables to the static context since we're limiting one HCI command at a time. Also place the variables in a union based on their temporal dependencies. Thanks to this, we can now further reduce the ECC stack size by 40 bytes (on ARM this then reports 12 bytes of unused stack after key-pair generation and DHKey calculation). Change-Id: I1036e0ca15f7c08063cba9e568d7df99e65c9156 Signed-off-by: Johan Hedberg --- subsys/bluetooth/host/hci_ecc.c | 35 ++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/subsys/bluetooth/host/hci_ecc.c b/subsys/bluetooth/host/hci_ecc.c index 5d3b824c33f..b4a05e52403 100644 --- a/subsys/bluetooth/host/hci_ecc.c +++ b/subsys/bluetooth/host/hci_ecc.c @@ -33,7 +33,7 @@ #include "hci_core.h" #endif -static BT_STACK_NOINIT(ecc_thread_stack, 1100); +static BT_STACK_NOINIT(ecc_thread_stack, 1060); /* based on Core Specification 4.2 Vol 3. Part H 2.3.5.6.1 */ static const uint32_t debug_private_key[8] = { @@ -61,11 +61,19 @@ static atomic_t flags; static K_SEM_DEFINE(cmd_sem, 0, 1); -static uint32_t private_key[8]; +static struct { + /* Based on the current implementation of ecc_make_key() it's safe + * for the private_key and random to occupy the same memory area. + */ + union { + uint32_t private_key[NUM_ECC_DIGITS]; + uint32_t random[NUM_ECC_DIGITS * 2]; + }; -static union { - EccPoint pk; - uint32_t dhkey[8]; + union { + EccPoint pk; + uint32_t dhkey[NUM_ECC_DIGITS]; + }; } ecc; static void send_cmd_status(uint16_t opcode, uint8_t status) @@ -91,29 +99,28 @@ static void send_cmd_status(uint16_t opcode, uint8_t status) bt_recv_prio(buf); } -static uint8_t generate_keys(EccPoint *pkey, uint32_t private_key[8]) +static uint8_t generate_keys(void) { #if !defined(CONFIG_BLUETOOTH_USE_DEBUG_KEYS) do { - uint32_t random[8]; int rc; - if (bt_rand((uint8_t *)random, sizeof(random))) { + if (bt_rand((uint8_t *)ecc.random, sizeof(ecc.random))) { BT_ERR("Failed to get random bytes for ECC keys"); return BT_HCI_ERR_UNSPECIFIED; } - rc = ecc_make_key(pkey, private_key, random); + rc = ecc_make_key(&ecc.pk, ecc.private_key, ecc.random); if (rc == TC_CRYPTO_FAIL) { BT_ERR("Failed to create ECC public/private pair"); return BT_HCI_ERR_UNSPECIFIED; } /* make sure generated key isn't debug key */ - } while (memcmp(private_key, debug_private_key, 32) == 0); + } while (memcmp(ecc.private_key, debug_private_key, 32) == 0); #else - memcpy(pkey, debug_public_key, 64); - memcpy(private_key, debug_private_key, 32); + memcpy(&ecc.pk, debug_public_key, 64); + memcpy(ecc.private_key, debug_private_key, 32); #endif return 0; } @@ -128,7 +135,7 @@ static void emulate_le_p256_public_key_cmd(void) BT_DBG(""); - status = generate_keys(&ecc.pk, private_key); + status = generate_keys(); buf = bt_buf_get_rx(K_FOREVER); bt_buf_set_type(buf, BT_BUF_EVT); @@ -166,7 +173,7 @@ static void emulate_le_generate_dhkey(void) if (ecc_valid_public_key(&ecc.pk) < 0) { ret = TC_CRYPTO_FAIL; } else { - ret = ecdh_shared_secret(ecc.dhkey, &ecc.pk, private_key); + ret = ecdh_shared_secret(ecc.dhkey, &ecc.pk, ecc.private_key); } buf = bt_buf_get_rx(K_FOREVER); From 1a62acd00e78aa3f5d53dbd521ed196248e282f0 Mon Sep 17 00:00:00 2001 From: Vinayak Chettimada Date: Thu, 6 Apr 2017 09:58:25 +0200 Subject: [PATCH 33/41] Bluetooth: controller: Add BT 5.0 PDU structs Add struct definitions for BT 5.0 PDUs, LL_PHY_REQ, LL_PHY_RSP, LL_PHY_UPDATE_IND, and LL_MIN_USED_CHANNELS_IND. Change-id: Ib54209cdf381ba53217eb425696c24d797fe0a30 Signed-off-by: Vinayak Chettimada --- subsys/bluetooth/controller/ll_sw/pdu.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/subsys/bluetooth/controller/ll_sw/pdu.h b/subsys/bluetooth/controller/ll_sw/pdu.h index d315d2bf1ff..7e4bbbea30d 100644 --- a/subsys/bluetooth/controller/ll_sw/pdu.h +++ b/subsys/bluetooth/controller/ll_sw/pdu.h @@ -220,6 +220,22 @@ struct pdu_data_llctrl_length_req_rsp { uint16_t max_tx_time; } __packed; +struct pdu_data_llctrl_phy_req_rsp { + uint8_t tx_phys; + uint8_t rx_phys; +} __packed; + +struct pdu_data_llctrl_phy_update_ind { + uint8_t m_to_s_phy; + uint8_t s_to_m_phy; + uint16_t instant; +} __packed; + +struct pdu_data_llctrl_min_used_chans_ind { + uint8_t phys; + uint8_t min_used_chans; +} __packed; + struct pdu_data_llctrl { uint8_t opcode; union { @@ -239,6 +255,10 @@ struct pdu_data_llctrl { struct pdu_data_llctrl_reject_ext_ind reject_ext_ind; struct pdu_data_llctrl_length_req_rsp length_req; struct pdu_data_llctrl_length_req_rsp length_rsp; + struct pdu_data_llctrl_phy_req_rsp phy_req; + struct pdu_data_llctrl_phy_req_rsp phy_rsp; + struct pdu_data_llctrl_phy_update_ind phy_update_ind; + struct pdu_data_llctrl_min_used_chans_ind min_used_chans_ind; } __packed ctrldata; } __packed; From 923c470f5d8776b4e9f5d10e60764fa1379b7756 Mon Sep 17 00:00:00 2001 From: Carles Cufi Date: Fri, 7 Apr 2017 16:02:52 +0200 Subject: [PATCH 34/41] Bluetooth: controller: Fix warning with no dup filter Conditionally declare the iterator variable to avoid a warning when compiling the controller without any duplicate filter entries. Change-Id: I69e23d4c594db18172dc57d45e7925243fe2da69 Signed-off-by: Carles Cufi --- subsys/bluetooth/controller/hci/hci.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/subsys/bluetooth/controller/hci/hci.c b/subsys/bluetooth/controller/hci/hci.c index e02c8117738..1b30aab9c01 100644 --- a/subsys/bluetooth/controller/hci/hci.c +++ b/subsys/bluetooth/controller/hci/hci.c @@ -1009,7 +1009,6 @@ static void le_advertising_report(struct pdu_data *pdu_data, uint8_t *b, uint8_t data_len; uint8_t *rssi; uint8_t info_len; - int i; if (!(event_mask & BIT64(BT_EVT_BIT_LE_META_EVENT)) || !(le_event_mask & BIT64(BT_EVT_BIT_LE_ADVERTISING_REPORT))) { @@ -1019,6 +1018,8 @@ static void le_advertising_report(struct pdu_data *pdu_data, uint8_t *b, #if CONFIG_BLUETOOTH_CONTROLLER_DUP_FILTER_LEN > 0 /* check for duplicate filtering */ if (dup_count >= 0) { + int i; + for (i = 0; i < dup_count; i++) { if (!memcmp(&adv->payload.adv_ind.addr[0], &dup_filter[i].addr.a.val[0], From b37f743a131ea7aad129fbd6c5c7a38680f53492 Mon Sep 17 00:00:00 2001 From: Carles Cufi Date: Fri, 7 Apr 2017 16:03:51 +0200 Subject: [PATCH 35/41] Bluetooth: test: Add "tiny" controller configuration Add a configuration that strips the BLE controller down to its simplest form to catch any issues when commonly used options are not enabled. Change-Id: Ifbec01d62b7d45fe9139dadaba734eff3b7a72b6 Signed-off-by: Carles Cufi --- tests/bluetooth/init/prj_controller_tiny.conf | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 tests/bluetooth/init/prj_controller_tiny.conf diff --git a/tests/bluetooth/init/prj_controller_tiny.conf b/tests/bluetooth/init/prj_controller_tiny.conf new file mode 100644 index 00000000000..6db1a6643ba --- /dev/null +++ b/tests/bluetooth/init/prj_controller_tiny.conf @@ -0,0 +1,21 @@ +CONFIG_BLUETOOTH=y +CONFIG_BLUETOOTH_CONTROLLER=y +CONFIG_BLUETOOTH_CONTROLLER_WORKER_PRIO=0 +CONFIG_BLUETOOTH_CONTROLLER_JOB_PRIO=0 +CONFIG_BLUETOOTH_CONTROLLER_XTAL_ADVANCED=n +CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED=n +CONFIG_BLUETOOTH_CONTROLLER_DUP_FILTER_LEN=0 +CONFIG_BLUETOOTH_CONTROLLER_LE_PING=n +CONFIG_BLUETOOTH_CONTROLLER_DATA_LENGTH=n +CONFIG_BLUETOOTH_CONTROLLER_CONN_RSSI=n +CONFIG_BLUETOOTH_CONTROLLER_ADV_INDICATION=n +CONFIG_BLUETOOTH_PERIPHERAL=y +CONFIG_BLUETOOTH_CENTRAL=y +CONFIG_BLUETOOTH_SMP=y +CONFIG_BLUETOOTH_SIGNING=y +CONFIG_BLUETOOTH_SMP_SC_ONLY=y +CONFIG_BLUETOOTH_TINYCRYPT_ECC=y +CONFIG_BLUETOOTH_L2CAP_DYNAMIC_CHANNEL=y +CONFIG_BLUETOOTH_GATT_DYNAMIC_DB=y +CONFIG_BLUETOOTH_GATT_CLIENT=y +CONFIG_BLUETOOTH_BREDR=n From ba7b6b1cedfe87e975093865b641a60ef9dac186 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sun, 9 Apr 2017 19:03:52 +0300 Subject: [PATCH 36/41] Bluetooth: tests/shell: Limit BR/EDR configuration to Qemu for now The BR/EDR configuration doesn't fit e.g. the Arduino 101 anymore. Limit it to Qemu for the time being, which is anyway the primary target where the functionality is being tested. Change-Id: I9a34c82157d56079e43acabe29eeadd6d99e03fe Signed-off-by: Johan Hedberg --- tests/bluetooth/shell/testcase.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/bluetooth/shell/testcase.ini b/tests/bluetooth/shell/testcase.ini index 917110ce3dc..38e53674132 100644 --- a/tests/bluetooth/shell/testcase.ini +++ b/tests/bluetooth/shell/testcase.ini @@ -13,7 +13,7 @@ filter = CONFIG_SOC_QUARK_SE_C1000 tags = bluetooth build_only = true extra_args = CONF_FILE="prj_br.conf" -arch_whitelist = x86 +platform_whitelist = qemu_cortex_m3 qemu_x86 platform_exclude = quark_d2000_crb # Do not run for debug daily build filter = not CONFIG_DEBUG From 71d0843c7d06de89495d1ac0dfca07bc6c726f95 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Fri, 7 Apr 2017 21:28:58 +0300 Subject: [PATCH 37/41] Bluetooth: conn: Pass disconnect error properly to the conn struct The bt_conn_set_state() function will not notify the connected callback of the connection error if conn->err isn't properly set. Jira: ZEP-2005 Change-Id: Idc30e736f4d8ba00156bf5c0e37dcccdb151742f Signed-off-by: Johan Hedberg --- subsys/bluetooth/host/conn.c | 1 + 1 file changed, 1 insertion(+) diff --git a/subsys/bluetooth/host/conn.c b/subsys/bluetooth/host/conn.c index bf8b67094f3..20f7f4274aa 100644 --- a/subsys/bluetooth/host/conn.c +++ b/subsys/bluetooth/host/conn.c @@ -1631,6 +1631,7 @@ int bt_conn_disconnect(struct bt_conn *conn, uint8_t reason) switch (conn->state) { case BT_CONN_CONNECT_SCAN: + conn->err = reason; bt_conn_set_state(conn, BT_CONN_DISCONNECTED); bt_le_scan_update(false); return 0; From 83b7d1b8b7343847bb40589ebd08e9d76c950001 Mon Sep 17 00:00:00 2001 From: Vinayak Chettimada Date: Sun, 9 Apr 2017 05:48:15 +0200 Subject: [PATCH 38/41] Bluetooth: controller: Group dup filter Kconfig with buf options Move the scan duplicate filter length option and group it along with rx/tx buffer size Kconfig options. Change-id: I3df07e667029c7d2571270db442ecb7241a417c2 Signed-off-by: Vinayak Chettimada --- subsys/bluetooth/controller/Kconfig | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/subsys/bluetooth/controller/Kconfig b/subsys/bluetooth/controller/Kconfig index 513e8a0d13e..8511150a768 100644 --- a/subsys/bluetooth/controller/Kconfig +++ b/subsys/bluetooth/controller/Kconfig @@ -30,6 +30,14 @@ endchoice comment "BLE Controller configuration" +config BLUETOOTH_CONTROLLER_DUP_FILTER_LEN + prompt "Number of addresses in the scan duplicate filter" + int + default 16 + help + Set the number of unique BLE addresses that can be filtered as + duplicates while scanning. + config BLUETOOTH_CONTROLLER_RX_BUFFERS prompt "Number of Rx buffers" int @@ -82,14 +90,6 @@ config BLUETOOTH_CONTROLLER_RX_PRIO_STACK_SIZE int default 320 -config BLUETOOTH_CONTROLLER_DUP_FILTER_LEN - prompt "Number of addresses in the scan duplicate filter" - int - default 16 - help - Set the number of unique BLE addresses that can be filtered as - duplicates while scanning. - comment "BLE Controller features" config BLUETOOTH_CONTROLLER_LE_PING From 7a10c35f6b252696c563a6fc6da38addfc6af243 Mon Sep 17 00:00:00 2001 From: Vinayak Chettimada Date: Sun, 9 Apr 2017 05:43:10 +0200 Subject: [PATCH 39/41] Bluetooth: controller: Use defined keyword in #if cond compiles Use #if defined(...) constructs while using conditional compilations of advanced event preparation and advanced scheduling implementations. Change-id: I728c76d0e7dbbfa378e8978b726ec404d9e55a72 Signed-off-by: Vinayak Chettimada --- subsys/bluetooth/controller/ll_sw/ctrl.c | 34 ++++++++++++------------ 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/subsys/bluetooth/controller/ll_sw/ctrl.c b/subsys/bluetooth/controller/ll_sw/ctrl.c index af27f17c193..655982e8d1b 100644 --- a/subsys/bluetooth/controller/ll_sw/ctrl.c +++ b/subsys/bluetooth/controller/ll_sw/ctrl.c @@ -2996,7 +2996,7 @@ static void mayfly_xtal_stop(void *params) DEBUG_RADIO_CLOSE(0); } -#if CONFIG_BLUETOOTH_CONTROLLER_XTAL_ADVANCED +#if defined(CONFIG_BLUETOOTH_CONTROLLER_XTAL_ADVANCED) static void mayfly_xtal_retain(uint8_t caller_id, uint8_t retain) { static uint8_t s_xtal_retained; @@ -3158,7 +3158,7 @@ static void mayfly_xtal_stop_calc(void *params) mayfly_xtal_retain(RADIO_TICKER_USER_ID_JOB, 1); if (ticker_id >= RADIO_TICKER_ID_ADV) { -#if CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED +#if defined(CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED) uint8_t ticker_id_current = ((uint32_t)params & 0xff); struct connection *conn_curr = NULL; #endif /* CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED */ @@ -3221,7 +3221,7 @@ static void mayfly_xtal_stop_calc(void *params) } } -#if CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED +#if defined(CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED) if (ticker_id_current >= RADIO_TICKER_ID_FIRST_CONNECTION) { /* compensate the current ticker for reduced * prepare. @@ -3324,7 +3324,7 @@ static void mayfly_xtal_stop_calc(void *params) } #endif /* CONFIG_BLUETOOTH_CONTROLLER_XTAL_ADVANCED */ -#if CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED +#if defined(CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED) static void sched_after_mstr_free_slot_get(uint8_t user_id, uint32_t ticks_slot_abs, uint32_t *ticks_anchor, @@ -3898,7 +3898,7 @@ static void event_common_prepare(uint32_t ticks_at_expire, /* route all packets queued for connections */ packet_tx_enqueue(0xFF); -#if CONFIG_BLUETOOTH_CONTROLLER_XTAL_ADVANCED +#if defined(CONFIG_BLUETOOTH_CONTROLLER_XTAL_ADVANCED) /* calc whether xtal needs to be retained after this event */ { static void *s_link[2]; @@ -4182,7 +4182,7 @@ static void event_adv(uint32_t ticks_at_expire, uint32_t remainder, _radio.remainder_anchor); radio_tmr_end_capture(); -#if (CONFIG_BLUETOOTH_CONTROLLER_XTAL_ADVANCED && \ +#if (defined(CONFIG_BLUETOOTH_CONTROLLER_XTAL_ADVANCED) && \ (RADIO_TICKER_PREEMPT_PART_US <= RADIO_TICKER_PREEMPT_PART_MIN_US)) /* check if preempt to start has changed */ if (preempt_calc(&_radio.advertiser.hdr, RADIO_TICKER_ID_ADV, @@ -4281,7 +4281,7 @@ static void event_obs_prepare(uint32_t ticks_at_expire, uint32_t remainder, _radio.observer.hdr.ticks_preempt_to_start, RADIO_TICKER_ID_OBS, event_obs, NULL); -#if CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED +#if defined(CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED) /* calc next group in us for the anchor where first connection event * to be placed */ @@ -4371,7 +4371,7 @@ static void event_obs(uint32_t ticks_at_expire, uint32_t remainder, _radio.remainder_anchor); radio_tmr_end_capture(); -#if (CONFIG_BLUETOOTH_CONTROLLER_XTAL_ADVANCED && \ +#if (defined(CONFIG_BLUETOOTH_CONTROLLER_XTAL_ADVANCED) && \ (RADIO_TICKER_PREEMPT_PART_US <= RADIO_TICKER_PREEMPT_PART_MIN_US)) /* check if preempt to start has changed */ if (preempt_calc(&_radio.observer.hdr, RADIO_TICKER_ID_OBS, @@ -4523,7 +4523,7 @@ static inline void event_conn_update_st_req(struct connection *conn, /* Start Procedure Timeout */ conn->procedure_expire = conn->procedure_reload; -#if CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED +#if defined(CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED) { uint32_t retval; @@ -4624,7 +4624,7 @@ static inline uint32_t event_conn_update_prep(struct connection *conn, LLCP_CONN_STATE_APP_WAIT) && (conn->llcp.connection_update.state != LLCP_CONN_STATE_RSP_WAIT)) { -#if CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED +#if defined(CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED) static void *s_link[2]; static struct mayfly s_mfy_sched_offset = {0, 0, s_link, NULL, NULL }; @@ -4641,14 +4641,14 @@ static inline uint32_t event_conn_update_prep(struct connection *conn, pdu_ctrl_tx = (struct pdu_data *)node_tx->pdu_data; -#if CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED +#if defined(CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED) fp_mayfly_select_or_use = mayfly_sched_win_offset_use; #endif /* CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED */ state = conn->llcp.connection_update.state; if ((state == LLCP_CONN_STATE_RSP) && (conn->role.master.role == 0)) { state = LLCP_CONN_STATE_INITIATE; -#if CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED +#if defined(CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED) fp_mayfly_select_or_use = mayfly_sched_win_offset_select; #endif /* CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED */ @@ -4657,7 +4657,7 @@ static inline uint32_t event_conn_update_prep(struct connection *conn, switch (state) { case LLCP_CONN_STATE_INITIATE: if (conn->role.master.role == 0) { -#if CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED +#if defined(CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED) event_conn_update_st_init(conn, event_counter, pdu_ctrl_tx, @@ -4677,7 +4677,7 @@ static inline uint32_t event_conn_update_prep(struct connection *conn, /* fall thru if slave */ case LLCP_CONN_STATE_REQ: -#if CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED +#if defined(CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED) event_conn_update_st_req(conn, event_counter, pdu_ctrl_tx, @@ -5686,7 +5686,7 @@ static void event_slave(uint32_t ticks_at_expire, uint32_t remainder, conn->role.slave.window_size_event_us); radio_tmr_end_capture(); -#if (CONFIG_BLUETOOTH_CONTROLLER_XTAL_ADVANCED && \ +#if (defined(CONFIG_BLUETOOTH_CONTROLLER_XTAL_ADVANCED) && \ (RADIO_TICKER_PREEMPT_PART_US <= RADIO_TICKER_PREEMPT_PART_MIN_US)) /* check if preempt to start has changed */ if (preempt_calc(&conn->hdr, (RADIO_TICKER_ID_FIRST_CONNECTION + @@ -5822,7 +5822,7 @@ static void event_master(uint32_t ticks_at_expire, uint32_t remainder, } #endif -#if (CONFIG_BLUETOOTH_CONTROLLER_XTAL_ADVANCED && \ +#if (defined(CONFIG_BLUETOOTH_CONTROLLER_XTAL_ADVANCED) && \ (RADIO_TICKER_PREEMPT_PART_US <= RADIO_TICKER_PREEMPT_PART_MIN_US)) /* check if preempt to start has changed */ if (0 != @@ -7336,7 +7336,7 @@ uint32_t radio_scan_enable(uint8_t scan_type, uint8_t init_addr_type, !IS_ENABLED(CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED)) { us_offset = 0; } -#if CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED +#if defined(CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED) else { sched_after_mstr_free_slot_get(RADIO_TICKER_USER_ID_APP, (ticks_slot_offset + From 87f2f7afecafe53b4aea2ea307f96149d08af145 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Fri, 24 Mar 2017 11:37:32 +0200 Subject: [PATCH 40/41] Bluetooth: GATT: Use sys_slist_t to represent the database This replaces custom made list manipulation with sys_slist_t which makes the code more readable. Change-Id: I9ee024ad83da3e28f2ecab74b001bf0e795fe489 Signed-off-by: Luiz Augusto von Dentz --- include/bluetooth/gatt.h | 2 +- subsys/bluetooth/host/gatt.c | 48 +++++++++++++++++++----------------- 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/include/bluetooth/gatt.h b/include/bluetooth/gatt.h index c0df10a1157..55c52fc3e15 100644 --- a/include/bluetooth/gatt.h +++ b/include/bluetooth/gatt.h @@ -138,7 +138,7 @@ struct bt_gatt_attr { /** Attribute permissions */ uint8_t perm; #if defined(CONFIG_BLUETOOTH_GATT_DYNAMIC_DB) - struct bt_gatt_attr *_next; + sys_snode_t node; #endif /* CONFIG_BLUETOOTH_GATT_DYNAMIC_DB */ }; diff --git a/subsys/bluetooth/host/gatt.c b/subsys/bluetooth/host/gatt.c index 63839d15bc1..ffa690c3481 100644 --- a/subsys/bluetooth/host/gatt.c +++ b/subsys/bluetooth/host/gatt.c @@ -30,19 +30,21 @@ #include "smp.h" #include "gatt_internal.h" -static struct bt_gatt_attr *db; - #if defined(CONFIG_BLUETOOTH_GATT_CLIENT) static sys_slist_t subscriptions; #endif /* CONFIG_BLUETOOTH_GATT_CLIENT */ #if !defined(CONFIG_BLUETOOTH_GATT_DYNAMIC_DB) +static struct bt_gatt_attr *db; static size_t attr_count; +#else +static sys_slist_t db; #endif /* CONFIG_BLUETOOTH_GATT_DYNAMIC_DB */ int bt_gatt_register(struct bt_gatt_attr *attrs, size_t count) { #if defined(CONFIG_BLUETOOTH_GATT_DYNAMIC_DB) + sys_slist_t list; struct bt_gatt_attr *last; #endif /* CONFIG_BLUETOOTH_GATT_DYNAMIC_DB */ uint16_t handle; @@ -55,24 +57,19 @@ int bt_gatt_register(struct bt_gatt_attr *attrs, size_t count) db = attrs; attr_count = count; #else - if (!db) { - db = attrs; - last = NULL; + sys_slist_init(&list); + + if (!sys_slist_is_empty(&db)) { handle = 0; goto populate; } - /* Fast forward to last attribute in the list */ - for (last = db; last->_next;) { - last = last->_next; - } - + last = SYS_SLIST_PEEK_TAIL_CONTAINER(&db, last, node); handle = last->handle; - last->_next = attrs; populate: #endif /* CONFIG_BLUETOOTH_GATT_DYNAMIC_DB */ - /* Populate the handles and _next pointers */ + /* Populate the handles and append them to the list */ for (; attrs && count; attrs++, count--) { if (!attrs->handle) { /* Allocate handle if not set already */ @@ -82,25 +79,25 @@ populate: handle = attrs->handle; } else { /* Service has conflicting handles */ -#if defined(CONFIG_BLUETOOTH_GATT_DYNAMIC_DB) - last->_next = NULL; -#endif BT_ERR("Unable to register handle 0x%04x", attrs->handle); return -EINVAL; } #if defined(CONFIG_BLUETOOTH_GATT_DYNAMIC_DB) - if (count > 1) { - attrs->_next = &attrs[1]; - } + sys_slist_append(&list, &attrs->node); #endif - BT_DBG("attr %p next %p handle 0x%04x uuid %s perm 0x%02x", - attrs, bt_gatt_attr_next(attrs), attrs->handle, - bt_uuid_str(attrs->uuid), attrs->perm); + BT_DBG("attr %p handle 0x%04x uuid %s perm 0x%02x", + attrs, attrs->handle, bt_uuid_str(attrs->uuid), + attrs->perm); } +#if defined(CONFIG_BLUETOOTH_GATT_DYNAMIC_DB) + /* Merge attribute list into database */ + sys_slist_merge_slist(&db, &list); +#endif + return 0; } @@ -242,9 +239,13 @@ ssize_t bt_gatt_attr_read_chrc(struct bt_conn *conn, void bt_gatt_foreach_attr(uint16_t start_handle, uint16_t end_handle, bt_gatt_attr_func_t func, void *user_data) { - const struct bt_gatt_attr *attr; + struct bt_gatt_attr *attr; +#if defined(CONFIG_BLUETOOTH_GATT_DYNAMIC_DB) + SYS_SLIST_FOR_EACH_CONTAINER(&db, attr, node) { +#else for (attr = db; attr; attr = bt_gatt_attr_next(attr)) { +#endif /* Check if attribute handle is within range */ if (attr->handle < start_handle || attr->handle > end_handle) { continue; @@ -259,7 +260,8 @@ void bt_gatt_foreach_attr(uint16_t start_handle, uint16_t end_handle, struct bt_gatt_attr *bt_gatt_attr_next(const struct bt_gatt_attr *attr) { #if defined(CONFIG_BLUETOOTH_GATT_DYNAMIC_DB) - return attr->_next; + return SYS_SLIST_PEEK_NEXT_CONTAINER((struct bt_gatt_attr *)attr, + node); #else return ((attr < db || attr > &db[attr_count - 2]) ? NULL : (struct bt_gatt_attr *)&attr[1]); From 17efbba7b41789c52e3d42e6802074159b2ed536 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Fri, 7 Apr 2017 21:43:26 +0300 Subject: [PATCH 41/41] Bluetooth: conn: Set initial responder address when connecting If the connection process fails the user may still need to do bt_conn_get_info() in its connected callback, so this needs to give a meaningful value for the remote address. Start off with the one that was given to bt_conn_create_le(). Jira: ZEP-2005 Change-Id: I4e9a033dec7c55fa549f5b6746c3bd81c0ccade5 Signed-off-by: Johan Hedberg --- subsys/bluetooth/host/conn.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/subsys/bluetooth/host/conn.c b/subsys/bluetooth/host/conn.c index 20f7f4274aa..32ed0ce7722 100644 --- a/subsys/bluetooth/host/conn.c +++ b/subsys/bluetooth/host/conn.c @@ -1701,6 +1701,9 @@ struct bt_conn *bt_conn_create_le(const bt_addr_le_t *peer, return NULL; } + /* Set initial address - will be updated later if necessary. */ + bt_addr_le_copy(&conn->le.resp_addr, peer); + bt_conn_set_param_le(conn, param); bt_conn_set_state(conn, BT_CONN_CONNECT_SCAN);