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/include/bluetooth/hci.h b/include/bluetooth/hci.h index fe7a3762287..304d99f07f9 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 @@ -1268,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/include/bluetooth/hfp_hf.h b/include/bluetooth/hfp_hf.h index 81420d97097..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 @@ -98,6 +120,23 @@ 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); + /** 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 @@ -111,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/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/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 d98f2ead0f6..8511150a768 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,16 @@ config BLUETOOTH_LL_SW 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 @@ -47,12 +70,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 +86,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 @@ -91,6 +114,85 @@ 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_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 + 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_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 @@ -114,6 +216,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 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_ */ diff --git a/subsys/bluetooth/controller/hci/hci.c b/subsys/bluetooth/controller/hci/hci.c index 76ca6dd68e9..1b30aab9c01 100644 --- a/subsys/bluetooth/controller/hci/hci.c +++ b/subsys/bluetooth/controller/hci/hci.c @@ -35,6 +35,24 @@ */ 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 + +#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; @@ -129,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; @@ -143,6 +162,13 @@ 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 + /* reset event masks */ + event_mask = DEFAULT_EVENT_MASK; + le_event_mask = DEFAULT_LE_EVENT_MASK; + ccst = cmd_complete(evt, sizeof(*ccst)); ccst->status = 0x00; } @@ -280,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; @@ -411,6 +438,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)); @@ -974,6 +1010,52 @@ static void le_advertising_report(struct pdu_data *pdu_data, uint8_t *b, uint8_t *rssi; uint8_t info_len; + 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) { + int i; + + 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); } else { @@ -1008,6 +1090,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)); @@ -1028,6 +1115,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)); @@ -1042,6 +1133,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); @@ -1059,6 +1155,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)); @@ -1150,6 +1250,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); @@ -1164,6 +1269,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)); @@ -1177,6 +1286,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; @@ -1212,6 +1326,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)); @@ -1230,6 +1348,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); @@ -1246,6 +1369,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); 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 } } diff --git a/subsys/bluetooth/controller/ll_sw/ctrl.c b/subsys/bluetooth/controller/ll_sw/ctrl.c index 2495e33a64d..655982e8d1b 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" @@ -56,8 +55,6 @@ #define RADIO_IRK_COUNT_MAX 8 -#define XTAL_ADVANCED 1 -#define SCHED_ADVANCED 1 #define SILENT_CONNECTION 0 #define RADIO_PHY_ADV 0 @@ -2999,7 +2996,7 @@ static void mayfly_xtal_stop(void *params) DEBUG_RADIO_CLOSE(0); } -#if 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; @@ -3142,7 +3139,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; @@ -3152,27 +3148,20 @@ 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 < 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) { -#if SCHED_ADVANCED +#if defined(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 +3221,7 @@ static void mayfly_xtal_stop_calc(void *params) } } -#if 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. @@ -3302,7 +3291,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); @@ -3333,9 +3322,9 @@ static void mayfly_xtal_stop_calc(void *params) } } } -#endif /* XTAL_ADVANCED */ +#endif /* CONFIG_BLUETOOTH_CONTROLLER_XTAL_ADVANCED */ -#if 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, @@ -3351,23 +3340,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; @@ -3505,24 +3484,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; @@ -3743,7 +3712,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) { @@ -3929,8 +3898,8 @@ static void event_common_prepare(uint32_t ticks_at_expire, /* route all packets queued for connections */ packet_tx_enqueue(0xFF); +#if defined(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 +3913,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,19 +4182,19 @@ 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 (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, 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) - { uint32_t ticker_status; ticker_status = @@ -4234,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); } @@ -4312,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 SCHED_ADVANCED +#if defined(CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED) /* calc next group in us for the anchor where first connection event * to be placed */ @@ -4345,7 +4314,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); } @@ -4402,15 +4371,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 (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, ticks_at_expire) != 0) { _radio.state = STATE_STOP; radio_disable(); } else -#endif +#endif /* CONFIG_BLUETOOTH_CONTROLLER_XTAL_ADVANCED */ { /* start window close timeout */ ticker_status = @@ -4480,7 +4449,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 +4481,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 +4523,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 defined(CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED) { uint32_t retval; @@ -4583,10 +4552,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 +4624,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 defined(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 +4641,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 defined(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 defined(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 defined(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 defined(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: @@ -5717,19 +5686,19 @@ 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 (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 + 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) - { uint32_t ticker_status; ticker_status = @@ -5738,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); @@ -5853,8 +5822,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 (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 != preempt_calc(&conn->hdr, (RADIO_TICKER_ID_FIRST_CONNECTION + @@ -5862,11 +5831,11 @@ 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) - { uint32_t ticker_status; ticker_status = @@ -5875,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); } @@ -7363,17 +7332,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 defined(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/subsys/bluetooth/controller/ll_sw/ctrl.h b/subsys/bluetooth/controller/ll_sw/ctrl.h index 96dc0a0e6cd..c7ebae469e8 100644 --- a/subsys/bluetooth/controller/ll_sw/ctrl.h +++ b/subsys/bluetooth/controller/ll_sw/ctrl.h @@ -64,12 +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_PRIO TICKER_MAYFLY_CALL_ID_WORKER0_PRIO -#define RADIO_TICKER_USER_ID_JOB_PRIO TICKER_MAYFLY_CALL_ID_JOB0_PRIO +#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_WORKER_OPS (7 + 1) #define RADIO_TICKER_USER_JOB_OPS (2 + 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 83396c66529..821863b1dca 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" @@ -230,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/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; 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; diff --git a/subsys/bluetooth/host/Kconfig b/subsys/bluetooth/host/Kconfig index 804387b732d..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 @@ -8,38 +9,54 @@ 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 This option allows to access Bluetooth controller from the application with the RAW HCI protocol. -# Virtual/hidden option to make the conditions more intuitive +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_HOST + # Virtual/hidden option to make the conditions more intuitive bool default y 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(). +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 @@ -70,14 +87,24 @@ 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 + # 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" @@ -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,24 +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_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 - default 1 - range 1 64 - help - Maximum number of simultaneous Bluetooth connections - supported. The minimum (and default) number is 1. - config BLUETOOTH_DEBUG bool @@ -456,6 +450,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 diff --git a/subsys/bluetooth/host/Makefile b/subsys/bluetooth/host/Makefile index 6f4c0bb0d41..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,24 +10,28 @@ 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 - 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 + obj-$(CONFIG_BLUETOOTH_HOST_CRYPTO) += crypto.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 diff --git a/subsys/bluetooth/host/at.c b/subsys/bluetooth/host/at.c index 28963e950ba..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; @@ -227,11 +228,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 +342,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 +358,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/conn.c b/subsys/bluetooth/host/conn.c index 86add72b4f4..32ed0ce7722 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) { @@ -1620,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; @@ -1689,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); 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/gatt.c b/subsys/bluetooth/host/gatt.c index 2b0ebacfe60..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]); @@ -1481,15 +1483,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 +1496,14 @@ 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; + } +#endif + + if (sign) { buf = bt_att_create_pdu(conn, BT_ATT_OP_SIGNED_WRITE_CMD, sizeof(*cmd) + length + 12); } else { 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) diff --git a/subsys/bluetooth/host/hci_ecc.c b/subsys/bluetooth/host/hci_ecc.c index 5473c1b59e8..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, 1280); +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] = { @@ -52,8 +52,29 @@ static const uint8_t debug_public_key[64] = { }; #endif -static K_FIFO_DEFINE(ecc_queue); -static uint32_t private_key[8]; +enum { + PENDING_PUB_KEY, + PENDING_DHKEY, +}; + +static atomic_t flags; + +static K_SEM_DEFINE(cmd_sem, 0, 1); + +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]; + }; + + union { + EccPoint pk; + uint32_t dhkey[NUM_ECC_DIGITS]; + }; +} ecc; static void send_cmd_status(uint16_t opcode, uint8_t status) { @@ -78,48 +99,43 @@ 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; } -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(); buf = bt_buf_get_rx(K_FOREVER); bt_buf_set_type(buf, BT_BUF_EVT); @@ -137,47 +153,27 @@ 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; } 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); @@ -200,31 +196,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 +233,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); diff --git a/subsys/bluetooth/host/hfp_hf.c b/subsys/bluetooth/host/hfp_hf.c index 7ac89e1c8d7..fc5c7b260fd 100644 --- a/subsys/bluetooth/host/hfp_hf.c +++ b/subsys/bluetooth/host/hfp_hf.c @@ -342,14 +342,90 @@ 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 }, + { "RING", AT_CMD_TYPE_OTHER, ring_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 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, @@ -472,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); 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; diff --git a/subsys/bluetooth/host/monitor.c b/subsys/bluetooth/host/monitor.c index e1e040b7038..ee075756b3b 100644 --- a/subsys/bluetooth/host/monitor.c +++ b/subsys/bluetooth/host/monitor.c @@ -31,6 +31,24 @@ static struct device *monitor_dev; +enum { + BT_LOG_BUSY, +}; + +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); @@ -43,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) @@ -65,13 +105,42 @@ 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; 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); @@ -84,12 +153,15 @@ void bt_log(int prio, const char *fmt, ...) log.priority = prio; log.ident_len = sizeof(id); + if (atomic_test_and_set_bit(&flags, BT_LOG_BUSY)) { + drop_add(BT_MONITOR_USER_LOGGING); + return; + } + encode_hdr(&hdr, BT_MONITOR_USER_LOGGING, sizeof(log) + sizeof(id) + len + 1); - key = irq_lock(); - - monitor_send(&hdr, sizeof(hdr)); + monitor_send(&hdr, BT_MONITOR_BASE_HDR_LEN + hdr.hdr_len); monitor_send(&log, sizeof(log)); monitor_send(id, sizeof(id)); @@ -100,22 +172,24 @@ 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; + + if (atomic_test_and_set_bit(&flags, BT_LOG_BUSY)) { + drop_add(opcode); + return; + } encode_hdr(&hdr, opcode, len); - key = irq_lock(); - - monitor_send(&hdr, sizeof(hdr)); + monitor_send(&hdr, BT_MONITOR_BASE_HDR_LEN + hdr.hdr_len); 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, 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; 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++; diff --git a/tests/bluetooth/init/prj_controller.conf b/tests/bluetooth/init/prj_controller.conf index fcade189e21..43c1ebd22e9 100644 --- a/tests/bluetooth/init/prj_controller.conf +++ b/tests/bluetooth/init/prj_controller.conf @@ -1,5 +1,9 @@ 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 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..70fadd16050 100644 --- a/tests/bluetooth/init/prj_controller_4_0.conf +++ b/tests/bluetooth/init/prj_controller_4_0.conf @@ -1,5 +1,9 @@ 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 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..4a3c9119375 100644 --- a/tests/bluetooth/init/prj_controller_dbg.conf +++ b/tests/bluetooth/init/prj_controller_dbg.conf @@ -1,5 +1,9 @@ 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 CONFIG_BLUETOOTH_CONTROLLER_ADV_INDICATION=y CONFIG_BLUETOOTH_CONTROLLER_PROFILE_ISR=y 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 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 }, 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 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 )