Merge bluetooth branch into master

Controller:
	- Added duplicate filtering support
	- Added event mask support
	- Kconfig enhancements
	- Various cleanups

 Host:
	- IRQ locking fix to monitor protocol
	- Fixed potential deadlock in ECDH support
	- Fix to connection error reporting
	- Fix to GATT signing
	- Fix to LE CoC
	- AT command & HFP improvements

----------------------------------------------------------------
Carles Cufi (4):
      Bluetooth: controller: Implement scan duplicate filter
      Bluetooth: controller: Implement event masks
      Bluetooth: controller: Fix warning with no dup filter
      Bluetooth: test: Add "tiny" controller configuration

Johan Hedberg (11):
      Bluetooth: monitor: Drop data instead of holding IRQ lock for long
      Bluetooth: monitor: Add support for logging packet drops
      Bluetooth: HCI: Add define for success status
      Bluetooth: ECC: Fix command status emission from wrong thread
      Bluetooth: Controller: Introduce rate-limiting on stack analysis
      Bluetooth: Remove unnecessary controller-side buffers tracking
      Bluetooth: SMP: Remove redundant ';'
      Bluetooth: hci_ecc: Fix ECDH API usage
      Bluetooth: tests/shell: Limit BR/EDR configuration to Qemu for now
      Bluetooth: conn: Pass disconnect error properly to the conn struct
      Bluetooth: conn: Set initial responder address when connecting

Luiz Augusto von Dentz (4):
      Bluetooth: GATT: Fix using write command when signing was requested
      Bluetooth: GATT: Be consistent with error in case SMP is disabled
      Bluetooth: L2CAP: Fix accounting SDU header len as data
      Bluetooth: GATT: Use sys_slist_t to represent the database

Sathish Narasimman (5):
      Bluetooth: AT: Unit test application init
      Bluetooth: HFP HF: Lookup table for unsolicited commands
      Bluetooth: HFP HF: Add support for RING indication cb
      Bluetooth: HFP HF: Support to send hf AT command
      Bluetooth: AT: Fix - chance of missing UNSOLICITED state

Vinayak Chettimada (17):
      Bluetooth: controller: Kconfig for advanced event preparation
      Bluetooth: controller: Kconfig option for advanced scheduling
      Bluetooth: controller: Hide advance features in Kconfig
      Bluetooth: controller: Move comp id and subver to configuration
      Bluetooth: Kconfig: Move BLUETOOTH_CONTROLLER to Controller file
      Bluetooth: Kconfig: Group stack size related options
      Bluetooth: Kconfig: Group HCI_RAW related options
      Bluetooth: Kconfig: Move BLUETOOTH_MAX_SCO_CONN to BR/EDR
      Bluetooth: Compile BR/EDR independent of BLUETOOTH_CONN check
      Bluetooth: Permit connectionless host-controller combined build
      Bluetooth: controller: Cleanup redundant ticker busy loop
      Bluetooth: controller: Move nRF5 specific debug pins to hal/nrf5
      Bluetooth: controller: Remove util/config.h
      Bluetooth: controller: Make worker and job priority configurable
      Bluetooth: controller: Add BT 5.0 PDU structs
      Bluetooth: controller: Group dup filter Kconfig with buf options
      Bluetooth: controller: Use defined keyword in #if cond compiles

 include/bluetooth/gatt.h                      |   2 +-
 include/bluetooth/hci.h                       |  41 ++++++
 include/bluetooth/hfp_hf.h                    |  50 +++++++
 samples/bluetooth/handsfree/src/main.c        |   6 +
 subsys/bluetooth/Kconfig                      |  12 +-
 subsys/bluetooth/controller/Kconfig           | 120 ++++++++++++++-
 subsys/bluetooth/controller/hal/debug.h       | 199 +------------------------
 subsys/bluetooth/controller/hal/nrf5/debug.h  | 204 ++++++++++++++++++++++++++
 subsys/bluetooth/controller/hci/hci.c         | 132 ++++++++++++++++-
 subsys/bluetooth/controller/hci/hci_driver.c  |  24 ++-
 subsys/bluetooth/controller/ll_sw/ctrl.c      | 152 ++++++++-----------
 subsys/bluetooth/controller/ll_sw/ctrl.h      |  21 ++-
 subsys/bluetooth/controller/ll_sw/ll.c        |  14 +-
 subsys/bluetooth/controller/ll_sw/pdu.h       |  20 +++
 subsys/bluetooth/controller/ticker/ticker.c   | 127 +++++++---------
 subsys/bluetooth/controller/util/config.h     |  30 ----
 subsys/bluetooth/controller/util/mayfly.c     |   2 -
 subsys/bluetooth/controller/util/mayfly.h     |   7 +
 subsys/bluetooth/host/Kconfig                 | 120 +++++++--------
 subsys/bluetooth/host/Makefile                |  32 ++--
 subsys/bluetooth/host/at.c                    |  28 +++-
 subsys/bluetooth/host/at.h                    |   3 +-
 subsys/bluetooth/host/conn.c                  |  15 ++
 subsys/bluetooth/host/conn_internal.h         |  11 +-
 subsys/bluetooth/host/gatt.c                  |  66 ++++-----
 subsys/bluetooth/host/hci_core.c              |  11 +-
 subsys/bluetooth/host/hci_core.h              |   2 +
 subsys/bluetooth/host/hci_ecc.c               | 169 +++++++++++++--------
 subsys/bluetooth/host/hfp_hf.c                | 138 ++++++++++++++++-
 subsys/bluetooth/host/l2cap.c                 |   7 +-
 subsys/bluetooth/host/monitor.c               | 108 +++++++++++---
 subsys/bluetooth/host/monitor.h               |  13 +-
 subsys/bluetooth/host/smp.c                   |   2 +-
 tests/bluetooth/init/prj_controller.conf      |   4 +
 tests/bluetooth/init/prj_controller_4_0.conf  |   4 +
 tests/bluetooth/init/prj_controller_dbg.conf  |   4 +
 tests/bluetooth/init/prj_controller_tiny.conf |  21 +++
 tests/bluetooth/shell/src/main.c              |  39 ++++-
 tests/bluetooth/shell/testcase.ini            |   2 +-
 tests/unit/bluetooth/at/Makefile              |   4 +
 tests/unit/bluetooth/at/prj.conf              |   5 +
 tests/unit/bluetooth/at/src/Makefile          |   4 +
 tests/unit/bluetooth/at/src/main.c            |  76 ++++++++++
 tests/unit/bluetooth/at/testcase.ini          |   4 +
 44 files changed, 1408 insertions(+), 647 deletions(-)
 create mode 100644 subsys/bluetooth/controller/hal/nrf5/debug.h
 delete mode 100644 subsys/bluetooth/controller/util/config.h
 create mode 100644 tests/bluetooth/init/prj_controller_tiny.conf
 create mode 100644 tests/unit/bluetooth/at/Makefile
 create mode 100644 tests/unit/bluetooth/at/prj.conf
 create mode 100644 tests/unit/bluetooth/at/src/Makefile
 create mode 100644 tests/unit/bluetooth/at/src/main.c
 create mode 100644 tests/unit/bluetooth/at/testcase.ini

Change-Id: I3b0f10cdbc59bcaeaea0a1bd8f613e42c829b13f
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
This commit is contained in:
Johan Hedberg 2017-04-10 12:10:20 +03:00
commit 2ed8d83d4d
44 changed files with 1448 additions and 687 deletions

View File

@ -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 */
};

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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);

View File

@ -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
}
}

View File

@ -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,

View File

@ -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)
****************************************************************************/

View File

@ -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;
}

View File

@ -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;

View File

@ -8,7 +8,6 @@
#include <stdint.h>
#include <soc.h>
#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;
}
}

View File

@ -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_ */

View File

@ -9,8 +9,6 @@
#include "memq.h"
#include "mayfly.h"
#include "config.h"
static struct {
void *head;
void *tail;

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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;

View File

@ -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);

View File

@ -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[]);

View File

@ -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 {

View File

@ -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;
}

View File

@ -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)

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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,

View File

@ -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;

View File

@ -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++;

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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(&param, 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(&param, 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, "<value: on, off>" },
{ "scan", cmd_scan, "<value: on, off> <dup filter: dups, nodups>" },
{ "advertise", cmd_advertise,
"<type: off, on, scan, nconn> <mode: discov, non_discov>" },
{ "connect", cmd_connect_le, HELP_ADDR_LE },

View File

@ -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

View File

@ -0,0 +1,4 @@
BOARD ?= qemu_x86
CONF_FILE = prj.conf
include $(ZEPHYR_BASE)/Makefile.test

View File

@ -0,0 +1,5 @@
CONFIG_BLUETOOTH=y
CONFIG_BLUETOOTH_BREDR=y
CONFIG_BLUETOOTH_HFP_HF=y
CONFIG_NET_BUF=y
CONFIG_ZTEST=y

View File

@ -0,0 +1,4 @@
obj-y = main.o
ccflags-y += -I${ZEPHYR_BASE}/subsys
include $(ZEPHYR_BASE)/tests/Makefile.test

View File

@ -0,0 +1,76 @@
/*
* Copyright (c) 2017 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include <net/buf.h>
#include "../../../../subsys/bluetooth/host/at.h"
#include <ztest.h>
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);
}

View File

@ -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 )