Pause Bluetooth discovery during active play
This commit is contained in:
parent
ae4abbfeb4
commit
7449d6d029
5 changed files with 45 additions and 16 deletions
|
|
@ -85,6 +85,7 @@ enum class ConnectionStatus {
|
||||||
enum class ConnectionPolicyState {
|
enum class ConnectionPolicyState {
|
||||||
Uninitialized,
|
Uninitialized,
|
||||||
Open,
|
Open,
|
||||||
|
Passive,
|
||||||
Paused,
|
Paused,
|
||||||
FailedClosed,
|
FailedClosed,
|
||||||
};
|
};
|
||||||
|
|
@ -624,26 +625,40 @@ void process_clear_pairings(uint32_t now_ms) {
|
||||||
|
|
||||||
void apply_connection_policy() {
|
void apply_connection_policy() {
|
||||||
const bool free_slot = has_free_slot();
|
const bool free_slot = has_free_slot();
|
||||||
if ((!free_slot &&
|
const bool active_controller = has_active_controller();
|
||||||
g_connection_policy_state == ConnectionPolicyState::Paused) ||
|
const bool pairing_open =
|
||||||
(free_slot &&
|
pairing_window_active_at(btstack_run_loop_get_time_ms());
|
||||||
g_connection_policy_state == ConnectionPolicyState::Open)) {
|
const bool active_scan =
|
||||||
|
free_slot && (!active_controller || pairing_open);
|
||||||
|
const ConnectionPolicyState desired_state =
|
||||||
|
!free_slot
|
||||||
|
? ConnectionPolicyState::Paused
|
||||||
|
: (active_scan ? ConnectionPolicyState::Open
|
||||||
|
: ConnectionPolicyState::Passive);
|
||||||
|
if (g_connection_policy_state == desired_state) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uni_bt_allow_incoming_connections(false);
|
// Classic inquiry and BLE scanning consume radio time and measurably delay
|
||||||
|
// active controller HID traffic. Stop them before every policy transition.
|
||||||
uni_bt_stop_scanning_unsafe();
|
uni_bt_stop_scanning_unsafe();
|
||||||
|
|
||||||
if (!free_slot) {
|
if (!free_slot) {
|
||||||
|
uni_bt_allow_incoming_connections(false);
|
||||||
g_connection_policy_state = ConnectionPolicyState::Paused;
|
g_connection_policy_state = ConnectionPolicyState::Paused;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bluepad32's normal scan/autoconnect path handles both remembered
|
// Passive mode still accepts controller-initiated reconnects without
|
||||||
// controllers powering on and controllers in explicit pairing mode.
|
// running inquiry. Active discovery is reserved for zero-controller idle
|
||||||
|
// state and the explicit BOOTSEL pairing window.
|
||||||
uni_bt_allow_incoming_connections(true);
|
uni_bt_allow_incoming_connections(true);
|
||||||
uni_bt_start_scanning_and_autoconnect_unsafe();
|
if (active_scan) {
|
||||||
g_connection_policy_state = ConnectionPolicyState::Open;
|
uni_bt_start_scanning_and_autoconnect_unsafe();
|
||||||
|
g_connection_policy_state = ConnectionPolicyState::Open;
|
||||||
|
} else {
|
||||||
|
g_connection_policy_state = ConnectionPolicyState::Passive;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_status_led() {
|
void update_status_led() {
|
||||||
|
|
@ -676,7 +691,9 @@ void process_rumble_timer(btstack_timer_source_t* timer) {
|
||||||
const uint32_t now_ms = btstack_run_loop_get_time_ms();
|
const uint32_t now_ms = btstack_run_loop_get_time_ms();
|
||||||
process_clear_pairings(now_ms);
|
process_clear_pairings(now_ms);
|
||||||
process_pairing_snapshot_request();
|
process_pairing_snapshot_request();
|
||||||
update_pairing_window(now_ms);
|
if (update_pairing_window(now_ms)) {
|
||||||
|
apply_connection_policy();
|
||||||
|
}
|
||||||
|
|
||||||
for (uint8_t slot_index = 0; slot_index < kSlotCount; ++slot_index) {
|
for (uint8_t slot_index = 0; slot_index < kSlotCount; ++slot_index) {
|
||||||
RumbleEnvelope envelope{};
|
RumbleEnvelope envelope{};
|
||||||
|
|
@ -781,7 +798,8 @@ void platform_on_device_connected(uni_hid_device_t* device) {
|
||||||
if (device == nullptr) {
|
if (device == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (g_connection_policy_state != ConnectionPolicyState::Open) {
|
if (g_connection_policy_state != ConnectionPolicyState::Open &&
|
||||||
|
g_connection_policy_state != ConnectionPolicyState::Passive) {
|
||||||
uni_hid_device_disconnect(device);
|
uni_hid_device_disconnect(device);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -833,9 +851,9 @@ void platform_on_device_disconnected(uni_hid_device_t* device) {
|
||||||
critical_section_exit(&g_state_lock);
|
critical_section_exit(&g_state_lock);
|
||||||
|
|
||||||
if (disconnected_tracked_device) {
|
if (disconnected_tracked_device) {
|
||||||
// A controller can disconnect while the policy is already Open.
|
// Re-evaluate from scratch: resume discovery only after the final
|
||||||
// Restart both scans so host-initiated reconnect controllers such as
|
// active controller disconnects; otherwise keep passive incoming
|
||||||
// 8BitDo Ultimate become reachable without rebooting the Pico.
|
// reconnect support without inquiry-induced latency.
|
||||||
g_connection_policy_state = ConnectionPolicyState::Uninitialized;
|
g_connection_policy_state = ConnectionPolicyState::Uninitialized;
|
||||||
recompute_connection_status();
|
recompute_connection_status();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
|
|
@ -800,13 +800,23 @@ void test_pairing_window_policy() {
|
||||||
g_connection_policy_state == ConnectionPolicyState::Paused,
|
g_connection_policy_state == ConnectionPolicyState::Paused,
|
||||||
"Classic and BLE pairing authentication must close at the deadline");
|
"Classic and BLE pairing authentication must close at the deadline");
|
||||||
platform_on_device_disconnected(&devices[3]);
|
platform_on_device_disconnected(&devices[3]);
|
||||||
|
require(g_connection_policy_state == ConnectionPolicyState::Passive &&
|
||||||
|
!classic_scanning_enabled && !scanning_enabled &&
|
||||||
|
incoming_connections,
|
||||||
|
"a freed slot with active controllers must remain passive");
|
||||||
|
require(platform_on_device_discovered(address, "controller", 0, 0) ==
|
||||||
|
UNI_ERROR_IGNORE_DEVICE,
|
||||||
|
"passive policy must reject inquiry discoveries");
|
||||||
|
|
||||||
|
bluepad32_input_backend_open_pairing_window();
|
||||||
|
process_rumble_timer(&g_rumble_timer);
|
||||||
require(g_connection_policy_state == ConnectionPolicyState::Open &&
|
require(g_connection_policy_state == ConnectionPolicyState::Open &&
|
||||||
classic_scanning_enabled && scanning_enabled &&
|
classic_scanning_enabled && scanning_enabled &&
|
||||||
incoming_connections,
|
incoming_connections,
|
||||||
"a freed slot must resume autoconnect after pairing indication expires");
|
"explicit BOOTSEL window must resume active discovery");
|
||||||
require(platform_on_device_discovered(address, "controller", 0, 0) ==
|
require(platform_on_device_discovered(address, "controller", 0, 0) ==
|
||||||
UNI_ERROR_SUCCESS,
|
UNI_ERROR_SUCCESS,
|
||||||
"resumed autoconnect must accept a discovered controller");
|
"pairing window discovery must accept a controller");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ def test_bluepad32_imu_normalization_native(tmp_path: Path) -> None:
|
||||||
"-Wextra",
|
"-Wextra",
|
||||||
"-Werror",
|
"-Werror",
|
||||||
"-pedantic",
|
"-pedantic",
|
||||||
|
f"-I{root / 'bluepad32_config'}",
|
||||||
f"-I{root / 'external' / 'bluepad32' / 'src' / 'components' / 'bluepad32' / 'include'}",
|
f"-I{root / 'external' / 'bluepad32' / 'src' / 'components' / 'bluepad32' / 'include'}",
|
||||||
str(root / "tests" / "bluepad32_imu_normalization_test.cpp"),
|
str(root / "tests" / "bluepad32_imu_normalization_test.cpp"),
|
||||||
"-o",
|
"-o",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue