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:
commit
2ed8d83d4d
@ -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 */
|
||||
};
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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_ */
|
||||
|
||||
204
subsys/bluetooth/controller/hal/nrf5/debug.h
Normal file
204
subsys/bluetooth/controller/hal/nrf5/debug.h
Normal 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_ */
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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)
|
||||
****************************************************************************/
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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_ */
|
||||
@ -9,8 +9,6 @@
|
||||
#include "memq.h"
|
||||
#include "mayfly.h"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
static struct {
|
||||
void *head;
|
||||
void *tail;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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[]);
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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++;
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
21
tests/bluetooth/init/prj_controller_tiny.conf
Normal file
21
tests/bluetooth/init/prj_controller_tiny.conf
Normal 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
|
||||
@ -566,11 +566,20 @@ static int cmd_init(int argc, char *argv[])
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cmd_active_scan_on(void)
|
||||
static void cmd_active_scan_on(int dups)
|
||||
{
|
||||
int err;
|
||||
struct bt_le_scan_param param = {
|
||||
.type = BT_HCI_LE_SCAN_PASSIVE,
|
||||
.filter_dup = BT_HCI_LE_SCAN_FILTER_DUP_ENABLE,
|
||||
.interval = BT_GAP_SCAN_FAST_INTERVAL,
|
||||
.window = BT_GAP_SCAN_FAST_WINDOW };
|
||||
|
||||
err = bt_le_scan_start(BT_LE_SCAN_ACTIVE, device_found);
|
||||
if (dups >= 0) {
|
||||
param.filter_dup = dups;
|
||||
}
|
||||
|
||||
err = bt_le_scan_start(¶m, device_found);
|
||||
if (err) {
|
||||
printk("Bluetooth set active scan failed (err %d)\n", err);
|
||||
} else {
|
||||
@ -578,7 +587,7 @@ static void cmd_active_scan_on(void)
|
||||
}
|
||||
}
|
||||
|
||||
static void cmd_passive_scan_on(void)
|
||||
static void cmd_passive_scan_on(int dups)
|
||||
{
|
||||
struct bt_le_scan_param param = {
|
||||
.type = BT_HCI_LE_SCAN_PASSIVE,
|
||||
@ -587,6 +596,10 @@ static void cmd_passive_scan_on(void)
|
||||
.window = 0x10 };
|
||||
int err;
|
||||
|
||||
if (dups >= 0) {
|
||||
param.filter_dup = dups;
|
||||
}
|
||||
|
||||
err = bt_le_scan_start(¶m, device_found);
|
||||
if (err) {
|
||||
printk("Bluetooth set passive scan failed (err %d)\n", err);
|
||||
@ -610,18 +623,32 @@ static void cmd_scan_off(void)
|
||||
static int cmd_scan(int argc, char *argv[])
|
||||
{
|
||||
const char *action;
|
||||
int dups = -1;
|
||||
|
||||
if (argc < 2) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Parse duplicate filtering data */
|
||||
if (argc >= 3) {
|
||||
const char *dup_filter = argv[2];
|
||||
|
||||
if (!strcmp(dup_filter, "dups")) {
|
||||
dups = BT_HCI_LE_SCAN_FILTER_DUP_DISABLE;
|
||||
} else if (!strcmp(dup_filter, "nodups")) {
|
||||
dups = BT_HCI_LE_SCAN_FILTER_DUP_ENABLE;
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
action = argv[1];
|
||||
if (!strcmp(action, "on")) {
|
||||
cmd_active_scan_on();
|
||||
cmd_active_scan_on(dups);
|
||||
} else if (!strcmp(action, "off")) {
|
||||
cmd_scan_off();
|
||||
} else if (!strcmp(action, "passive")) {
|
||||
cmd_passive_scan_on();
|
||||
cmd_passive_scan_on(dups);
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -2494,7 +2521,7 @@ static int cmd_bredr_sdp_find_record(int argc, char *argv[])
|
||||
|
||||
static const struct shell_cmd commands[] = {
|
||||
{ "init", cmd_init, HELP_ADDR_LE },
|
||||
{ "scan", cmd_scan, "<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 },
|
||||
|
||||
@ -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
|
||||
|
||||
4
tests/unit/bluetooth/at/Makefile
Normal file
4
tests/unit/bluetooth/at/Makefile
Normal file
@ -0,0 +1,4 @@
|
||||
BOARD ?= qemu_x86
|
||||
CONF_FILE = prj.conf
|
||||
|
||||
include $(ZEPHYR_BASE)/Makefile.test
|
||||
5
tests/unit/bluetooth/at/prj.conf
Normal file
5
tests/unit/bluetooth/at/prj.conf
Normal file
@ -0,0 +1,5 @@
|
||||
CONFIG_BLUETOOTH=y
|
||||
CONFIG_BLUETOOTH_BREDR=y
|
||||
CONFIG_BLUETOOTH_HFP_HF=y
|
||||
CONFIG_NET_BUF=y
|
||||
CONFIG_ZTEST=y
|
||||
4
tests/unit/bluetooth/at/src/Makefile
Normal file
4
tests/unit/bluetooth/at/src/Makefile
Normal file
@ -0,0 +1,4 @@
|
||||
obj-y = main.o
|
||||
ccflags-y += -I${ZEPHYR_BASE}/subsys
|
||||
|
||||
include $(ZEPHYR_BASE)/tests/Makefile.test
|
||||
76
tests/unit/bluetooth/at/src/main.c
Normal file
76
tests/unit/bluetooth/at/src/main.c
Normal 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);
|
||||
}
|
||||
4
tests/unit/bluetooth/at/testcase.ini
Normal file
4
tests/unit/bluetooth/at/testcase.ini
Normal 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 )
|
||||
Loading…
Reference in New Issue
Block a user