ESPHome 2026.8.0b4
Loading...
Searching...
No Matches
bdk_scan.cpp
Go to the documentation of this file.
1// Every SDK call the scan reconciler makes. The BDK's own start hardcodes
2// passive (the active bit is commented out in both stacks), so
3// bdk_scan_start() packs the GAPM_ACTIVITY_START_CMD itself, field-for-field
4// the SDK's app_ble_start_scaning() except that prop takes the mode, armed
5// through the SDK's own operation bookkeeping. The component pins
6// beken-bdk 3.0.78; the static asserts catch a layout change on a bump.
7
8#include "bdk_scan.h"
9
10#ifdef USE_BK72XX_BLE
11
12// Same SDK gate as bk72xx_ble.cpp (which carries the explanatory #error).
13#if !defined(CLANG_TIDY) && __has_include("ble_api.h") && __has_include("app_ble.h")
14
15extern "C" {
16#include "app_ble.h" // app_ble_env, app_ble_run, app_ble_reset, actv_state_t,
17 // app_ble_actv_state_get, app_ble_env_state_get,
18 // app_ble_get_idle_actv_idx_handle, UNKNOW_ACT_IDX,
19 // bk_ble_* (via ble_api_5_x.h)
20#include "kernel_msg.h" // KERNEL_MSG_ALLOC, kernel_msg_send
21#if __has_include("gapm_msg.h")
22#include "gapm_msg.h" // BLE 5.2 (BK7238/BK7252N): gapm_activity_start_cmd, GAPM_SCAN_*
23#else
24#include "gapm_task.h" // BLE 5.1 (BK7231N/BK7236): same declarations, older header name
25#endif
26}
27
28#include "esphome/core/log.h"
29
31
32static const char *const TAG = "bk72xx_ble";
33
34// Pin the SDK surface this file depends on: a beken-bdk bump that moves these
35// must fail the build, not corrupt the kernel message.
36static_assert(GAPM_SCAN_PROP_PHY_1M_BIT == (1 << 0) && GAPM_SCAN_PROP_ACTIVE_1M_BIT == (1 << 2) &&
37 sizeof(struct gapm_scan_param) == 16 && sizeof(struct gapm_scan_wd_op_param) == 4,
38 "beken-bdk GAPM scan layout changed; revalidate bdk_scan_start() "
39 "against the SDK's app_ble_start_scaning()");
40static_assert(INVALID_ACTIVITY_IDX == UNKNOW_ACT_IDX,
41 "beken-bdk activity sentinel changed; revalidate the scan reconciler");
42static_assert(GAPM_REPORT_TYPE_SCAN_RSP_EXT == 2 && GAPM_REPORT_TYPE_SCAN_RSP_LEG == 3 &&
43 GAPM_REPORT_INFO_SCAN_ADV_BIT == (1 << 5),
44 "beken-bdk GAPM report info changed; revalidate the tracker's demux constants");
45
46bool bdk_scan_ready() { return app_ble_env_state_get() == APP_BLE_READY; }
47
48BdkActivityState bdk_scan_state(uint8_t activity_idx) {
49 if (activity_idx == INVALID_ACTIVITY_IDX)
51 switch (app_ble_actv_state_get(activity_idx)) {
52 case ACTV_IDLE:
54 case ACTV_SCAN_CREATED:
56 case ACTV_SCAN_STARTED:
58 default:
60 }
61}
62
64 uint8_t idx = app_ble_get_idle_actv_idx_handle(SCAN_ACTV);
65 if (idx == INVALID_ACTIVITY_IDX)
66 ESP_LOGE(TAG, "Scan start failed: no idle activity handle");
67 return idx;
68}
69
70BdkOpResult bdk_scan_create(uint8_t activity_idx) {
71 ble_err_t ret = bk_ble_create_scaning(activity_idx, nullptr);
72 if (ret == ERR_SUCCESS)
73 return BdkOpResult::OK;
74 if (ret == ERR_BLE_STATUS)
75 return BdkOpResult::BUSY;
76 ESP_LOGE(TAG, "Scan activity create failed (err %d)", static_cast<int>(ret));
78}
79
80BdkOpResult bdk_scan_start(uint8_t activity_idx, uint16_t interval, uint16_t window, bool active) {
81 app_ble_run(activity_idx, BLE_START_SCAN, 1 << BLE_OP_START_SCAN_POS, nullptr);
82 struct gapm_activity_start_cmd *cmd =
83 KERNEL_MSG_ALLOC(GAPM_ACTIVITY_START_CMD, TASK_BLE_GAPM, TASK_BLE_APP, gapm_activity_start_cmd);
84 if (cmd == nullptr) {
85 app_ble_reset(); // the SDK's own failure path for an unsent operation
86 ESP_LOGE(TAG, "Scan start failed: kernel message allocation");
88 }
89 cmd->operation = GAPM_START_ACTIVITY;
90 cmd->actv_idx = app_ble_env.actvs[activity_idx].gap_advt_idx;
91 cmd->u_param.scan_param.type = GAPM_SCAN_TYPE_OBSERVER;
92 cmd->u_param.scan_param.prop = GAPM_SCAN_PROP_PHY_1M_BIT | (active ? GAPM_SCAN_PROP_ACTIVE_1M_BIT : 0);
93 cmd->u_param.scan_param.scan_param_1m.scan_intv = interval;
94 cmd->u_param.scan_param.scan_param_1m.scan_wd = window;
95 cmd->u_param.scan_param.scan_param_coded.scan_intv = 0;
96 cmd->u_param.scan_param.scan_param_coded.scan_wd = 0;
97 cmd->u_param.scan_param.dup_filt_pol = 0;
98 cmd->u_param.scan_param.rsvd = 0;
99 cmd->u_param.scan_param.duration = 0; // scan until stopped
100 cmd->u_param.scan_param.period = 10; // matches the SDK's passive start
101 kernel_msg_send(cmd);
102 return BdkOpResult::OK;
103}
104
105BdkOpResult bdk_scan_release(uint8_t activity_idx, bool created, int *err_out) {
106 ble_err_t ret = created ? bk_ble_delete_scaning(activity_idx, nullptr) : bk_ble_scan_stop(activity_idx, nullptr);
107 *err_out = static_cast<int>(ret);
108 if (ret == ERR_SUCCESS)
109 return BdkOpResult::OK;
110 // DEBUG on purpose: the reconciler WARNs once per streak and the stuck
111 // ERROR carries this code — a per-retry ERROR would be unbounded.
112 ESP_LOGD(TAG, "Scan release %s (err %d)", ret == ERR_BLE_STATUS ? "rejected" : "failed", static_cast<int>(ret));
113 return ret == ERR_BLE_STATUS ? BdkOpResult::BUSY : BdkOpResult::FAILED;
114}
115
116} // namespace esphome::bk72xx_ble
117
118#endif // !CLANG_TIDY && ble_api.h && app_ble.h
119#endif // USE_BK72XX_BLE
int ret
BdkOpResult bdk_scan_create(uint8_t activity_idx)
Create the scan activity (asynchronous); started once CREATED is observed.
Definition bdk_scan.cpp:70
BdkOpResult bdk_scan_release(uint8_t activity_idx, bool created, int *err_out)
Release the activity: delete when never started (a stop would be rejected), stop otherwise.
Definition bdk_scan.cpp:105
constexpr uint8_t INVALID_ACTIVITY_IDX
Activity index value marking "no scan activity", the BDK's own convention (asserted against its symbo...
Definition bdk_scan.h:13
uint8_t bdk_scan_acquire_activity()
Claim an idle activity slot; INVALID_ACTIVITY_IDX when none is free.
Definition bdk_scan.cpp:63
BdkOpResult bdk_scan_start(uint8_t activity_idx, uint16_t interval, uint16_t window, bool active)
Start a created activity: the packed GAPM start, taking the scan mode the BDK's own start path hardco...
Definition bdk_scan.cpp:80
BdkOpResult
Outcome of a BDK scan operation request.
Definition bdk_scan.h:24
@ BUSY
Another controller operation is in flight; retry later.
@ OK
Accepted; completion is asynchronous.
BdkActivityState
Scan-relevant controller activity states, read live from the SDK.
Definition bdk_scan.h:16
@ OTHER
A non-scan or transitional state; settles on a later read.
@ CREATED
Created but not started.
@ IDLE
No activity (or one whose create failed).
BdkActivityState bdk_scan_state(uint8_t activity_idx)
Live state of the given activity; INVALID_ACTIVITY_IDX reads as IDLE.
Definition bdk_scan.cpp:48
bool bdk_scan_ready()
True when no controller operation is in flight (APP_BLE_READY).
Definition bdk_scan.cpp:46