From 3707096d866cee17b24a6afe90c71a62913fe696 Mon Sep 17 00:00:00 2001 From: Carles Cufi Date: Thu, 22 Jun 2017 15:11:00 +0200 Subject: [PATCH] Bluetooth: controller: Correct adv, scan and init state checks For whitelist and resolving list handling, avoid trying to start the advertiser and scanner roles when they are already running. Additionally, and since simultaneous scanning and initiating is not supported, correctly report this to the host both in the supported states and in the HCI command via an error code, instead of silently disabling scanning. Signed-off-by: Carles Cufi --- subsys/bluetooth/controller/hci/hci.c | 7 ++++- subsys/bluetooth/controller/ll_sw/ctrl.c | 29 +++++++++---------- subsys/bluetooth/controller/ll_sw/ll_adv.c | 8 ++--- subsys/bluetooth/controller/ll_sw/ll_master.c | 4 +++ subsys/bluetooth/controller/ll_sw/ll_scan.c | 9 +++--- 5 files changed, 32 insertions(+), 25 deletions(-) diff --git a/subsys/bluetooth/controller/hci/hci.c b/subsys/bluetooth/controller/hci/hci.c index f7b4428cd4a..9178879ad03 100644 --- a/subsys/bluetooth/controller/hci/hci.c +++ b/subsys/bluetooth/controller/hci/hci.c @@ -570,7 +570,12 @@ static void le_read_supp_states(struct net_buf *buf, struct net_buf **evt) rp = cmd_complete(evt, sizeof(*rp)); rp->status = 0x00; - sys_put_le64(0x000003ffffffffff, rp->le_states); + /* All states and combinations supported except: + * Initiating State + Passive Scanning + * Initiating State + Active Scanning + */ + /*@todo: conditionally disable states based on Kconfig variables */ + sys_put_le64(0x000003ffff3fffff, rp->le_states); } #if defined(CONFIG_BLUETOOTH_BROADCASTER) diff --git a/subsys/bluetooth/controller/ll_sw/ctrl.c b/subsys/bluetooth/controller/ll_sw/ctrl.c index 02e93960959..a055a5a6738 100644 --- a/subsys/bluetooth/controller/ll_sw/ctrl.c +++ b/subsys/bluetooth/controller/ll_sw/ctrl.c @@ -8142,7 +8142,7 @@ u32_t radio_adv_enable(u16_t interval, u8_t chl_map, u8_t filter_policy) u32_t ret; if (_radio.advertiser.is_enabled) { - return 1; + return BT_HCI_ERR_CMD_DISALLOWED; } pdu_adv = (struct pdu_adv *) @@ -8153,19 +8153,19 @@ u32_t radio_adv_enable(u16_t interval, u8_t chl_map, u8_t filter_policy) void *link; if (_radio.advertiser.conn) { - return 1; + return BT_HCI_ERR_CMD_DISALLOWED; } link = mem_acquire(&_radio.link_rx_free); if (!link) { - return 1; + return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED; } conn = mem_acquire(&_radio.conn_free); if (!conn) { mem_release(link, &_radio.link_rx_free); - return 1; + return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED; } conn->handle = 0xFFFF; @@ -8347,7 +8347,7 @@ failure_cleanup: mem_release(conn, &_radio.conn_free); } - return 1; + return BT_HCI_ERR_CMD_DISALLOWED; } u32_t radio_adv_disable(void) @@ -8375,7 +8375,7 @@ u32_t radio_adv_disable(void) } } - return status; + return status ? BT_HCI_ERR_CMD_DISALLOWED : 0; } u32_t radio_adv_is_enabled(void) @@ -8408,7 +8408,7 @@ u32_t radio_scan_enable(u8_t type, u8_t init_addr_type, u8_t *init_addr, u32_t ret; if (_radio.scanner.is_enabled) { - return 1; + return BT_HCI_ERR_CMD_DISALLOWED; } _radio.scanner.type = type; @@ -8479,7 +8479,7 @@ u32_t radio_scan_enable(u8_t type, u8_t init_addr_type, u8_t *init_addr, } if (ret_cb != TICKER_STATUS_SUCCESS) { - return 1; + return BT_HCI_ERR_CMD_DISALLOWED; } _radio.scanner.is_enabled = 1; @@ -8517,7 +8517,7 @@ u32_t radio_scan_disable(void) } } - return status; + return status ? BT_HCI_ERR_CMD_DISALLOWED : 0; } u32_t radio_scan_is_enabled(void) @@ -8548,23 +8548,20 @@ u32_t radio_connect_enable(u8_t adv_addr_type, u8_t *adv_addr, u16_t interval, void *link; if (_radio.scanner.conn) { - return 1; + return BT_HCI_ERR_CMD_DISALLOWED; } link = mem_acquire(&_radio.link_rx_free); if (!link) { - return 1; + return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED; } conn = mem_acquire(&_radio.conn_free); if (!conn) { mem_release(link, &_radio.link_rx_free); - - return 1; + return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED; } - radio_scan_disable(); - _radio.scanner.adv_addr_type = adv_addr_type; memcpy(&_radio.scanner.adv_addr[0], adv_addr, BDADDR_SIZE); _radio.scanner.conn_interval = interval; @@ -8684,7 +8681,7 @@ u32_t ll_connect_disable(void) u32_t status; if (_radio.scanner.conn == 0) { - return 1; + return BT_HCI_ERR_CMD_DISALLOWED; } status = radio_scan_disable(); diff --git a/subsys/bluetooth/controller/ll_sw/ll_adv.c b/subsys/bluetooth/controller/ll_sw/ll_adv.c index 754ba24fd0e..b27e3d13cc7 100644 --- a/subsys/bluetooth/controller/ll_sw/ll_adv.c +++ b/subsys/bluetooth/controller/ll_sw/ll_adv.c @@ -58,7 +58,7 @@ u32_t ll_adv_params_set(u16_t interval, u8_t adv_type, struct pdu_adv *pdu; if (radio_adv_is_enabled()) { - return 0x0C; /* Command Disallowed */ + return BT_HCI_ERR_CMD_DISALLOWED; } #if defined(CONFIG_BLUETOOTH_CONTROLLER_ADV_EXT) @@ -341,9 +341,9 @@ u32_t ll_adv_enable(u8_t enable) u32_t status; if (!enable) { - status = radio_adv_disable(); - - return status; + return radio_adv_disable(); + } else if (radio_adv_is_enabled()) { + return 0; } /* TODO: move the addr remembered into controller diff --git a/subsys/bluetooth/controller/ll_sw/ll_master.c b/subsys/bluetooth/controller/ll_sw/ll_master.c index f0794232435..76328bc76a1 100644 --- a/subsys/bluetooth/controller/ll_sw/ll_master.c +++ b/subsys/bluetooth/controller/ll_sw/ll_master.c @@ -22,6 +22,10 @@ u32_t ll_create_connection(u16_t scan_interval, u16_t scan_window, { u32_t status; + if (radio_scan_is_enabled()) { + return BT_HCI_ERR_CMD_DISALLOWED; + } + status = radio_connect_enable(peer_addr_type, peer_addr, interval, latency, timeout); diff --git a/subsys/bluetooth/controller/ll_sw/ll_scan.c b/subsys/bluetooth/controller/ll_sw/ll_scan.c index 5d6a197efef..544069bdbe4 100644 --- a/subsys/bluetooth/controller/ll_sw/ll_scan.c +++ b/subsys/bluetooth/controller/ll_sw/ll_scan.c @@ -32,7 +32,7 @@ u32_t ll_scan_params_set(u8_t type, u16_t interval, u16_t window, u8_t own_addr_type, u8_t filter_policy) { if (radio_scan_is_enabled()) { - return 0x0C; /* Command Disallowed */ + return BT_HCI_ERR_CMD_DISALLOWED; } /* type value: @@ -61,9 +61,10 @@ u32_t ll_scan_enable(u8_t enable) u32_t status; if (!enable) { - status = radio_scan_disable(); - - return status; + return radio_scan_disable(); + } else if (radio_scan_is_enabled()) { + /* Duplicate filtering is processed in the HCI layer */ + return 0; } status = radio_scan_enable(ll_scan.type, ll_scan.tx_addr,