Verify and publish dual-controller AIO firmware
This commit is contained in:
parent
edf6ecaae1
commit
18c27b06ae
5 changed files with 297 additions and 48 deletions
|
|
@ -39,6 +39,7 @@ struct RumbleEnvelope {
|
|||
|
||||
struct BackendSlot {
|
||||
SwitchInputState state;
|
||||
// Non-null with active=false is a connected device still becoming ready.
|
||||
uni_hid_device_t* device;
|
||||
uint32_t state_generation;
|
||||
uint32_t connection_generation;
|
||||
|
|
@ -83,14 +84,22 @@ int slot_for_device(const uni_hid_device_t* device) {
|
|||
return slot >= 0 && slot < kSlotCount ? slot : -1;
|
||||
}
|
||||
|
||||
bool all_slots_ready() {
|
||||
ConnectionStatus compute_connection_status() {
|
||||
critical_section_enter_blocking(&g_state_lock);
|
||||
bool ready = true;
|
||||
bool all_ready = true;
|
||||
bool any_connecting = false;
|
||||
for (const BackendSlot& slot : g_slots) {
|
||||
ready = ready && slot.active && slot.device != nullptr;
|
||||
const bool has_device = slot.device != nullptr;
|
||||
all_ready = all_ready && slot.active && has_device;
|
||||
any_connecting = any_connecting || (!slot.active && has_device);
|
||||
}
|
||||
critical_section_exit(&g_state_lock);
|
||||
return ready;
|
||||
|
||||
if (all_ready) {
|
||||
return ConnectionStatus::Ready;
|
||||
}
|
||||
return any_connecting ? ConnectionStatus::Connecting
|
||||
: ConnectionStatus::Scanning;
|
||||
}
|
||||
|
||||
void publish_device_state(uint8_t slot, uni_hid_device_t* device,
|
||||
|
|
@ -115,6 +124,8 @@ void publish_all_neutral() {
|
|||
++slot.connection_generation;
|
||||
}
|
||||
critical_section_exit(&g_state_lock);
|
||||
g_connection_status = ConnectionStatus::Initializing;
|
||||
g_status_led_tick = 0;
|
||||
}
|
||||
|
||||
constexpr int32_t clamp_axis(int32_t value) {
|
||||
|
|
@ -287,6 +298,16 @@ void resume_connections() {
|
|||
uni_bt_allow_incoming_connections(true);
|
||||
uni_bt_start_scanning_and_autoconnect_unsafe();
|
||||
}
|
||||
void recompute_connection_status() {
|
||||
g_connection_status = compute_connection_status();
|
||||
g_status_led_tick = 0;
|
||||
if (g_connection_status == ConnectionStatus::Ready) {
|
||||
uni_bt_stop_scanning_unsafe();
|
||||
uni_bt_allow_incoming_connections(false);
|
||||
} else {
|
||||
resume_connections();
|
||||
}
|
||||
}
|
||||
|
||||
void platform_init(int argc, const char** argv) {
|
||||
(void)argc;
|
||||
|
|
@ -297,9 +318,7 @@ void platform_on_init_complete() {
|
|||
btstack_run_loop_set_timer_handler(&g_rumble_timer, process_rumble_timer);
|
||||
btstack_run_loop_set_timer(&g_rumble_timer, kRumblePollIntervalMs);
|
||||
btstack_run_loop_add_timer(&g_rumble_timer);
|
||||
g_connection_status = ConnectionStatus::Scanning;
|
||||
g_status_led_tick = 0;
|
||||
resume_connections();
|
||||
recompute_connection_status();
|
||||
}
|
||||
|
||||
uni_error_t platform_on_device_discovered(bd_addr_t addr, const char* name, uint16_t cod, uint8_t rssi) {
|
||||
|
|
@ -307,14 +326,31 @@ uni_error_t platform_on_device_discovered(bd_addr_t addr, const char* name, uint
|
|||
(void)name;
|
||||
(void)cod;
|
||||
(void)rssi;
|
||||
return all_slots_ready() ? UNI_ERROR_IGNORE_DEVICE : UNI_ERROR_SUCCESS;
|
||||
return compute_connection_status() == ConnectionStatus::Ready
|
||||
? UNI_ERROR_IGNORE_DEVICE
|
||||
: UNI_ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
void platform_on_device_connected(uni_hid_device_t* device) {
|
||||
(void)device;
|
||||
if (!all_slots_ready()) {
|
||||
g_connection_status = ConnectionStatus::Connecting;
|
||||
g_status_led_tick = 0;
|
||||
const int slot_index = slot_for_device(device);
|
||||
if (slot_index < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool tracked_connection = false;
|
||||
critical_section_enter_blocking(&g_state_lock);
|
||||
BackendSlot& slot = g_slots[slot_index];
|
||||
if (!slot.active && slot.device == nullptr) {
|
||||
slot.device = device;
|
||||
slot.rumble_pending = false;
|
||||
tracked_connection = true;
|
||||
} else {
|
||||
tracked_connection = slot.device == device;
|
||||
}
|
||||
critical_section_exit(&g_state_lock);
|
||||
|
||||
if (tracked_connection) {
|
||||
recompute_connection_status();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -324,24 +360,24 @@ void platform_on_device_disconnected(uni_hid_device_t* device) {
|
|||
return;
|
||||
}
|
||||
|
||||
bool disconnected_active_slot = false;
|
||||
bool disconnected_tracked_device = false;
|
||||
critical_section_enter_blocking(&g_state_lock);
|
||||
BackendSlot& slot = g_slots[slot_index];
|
||||
if (slot.active && slot.device == device) {
|
||||
slot.state = make_neutral_state();
|
||||
if (slot.device == device) {
|
||||
if (slot.active) {
|
||||
slot.state = make_neutral_state();
|
||||
++slot.state_generation;
|
||||
}
|
||||
slot.device = nullptr;
|
||||
slot.active = false;
|
||||
slot.rumble_pending = false;
|
||||
++slot.state_generation;
|
||||
++slot.connection_generation;
|
||||
disconnected_active_slot = true;
|
||||
disconnected_tracked_device = true;
|
||||
}
|
||||
critical_section_exit(&g_state_lock);
|
||||
|
||||
if (disconnected_active_slot) {
|
||||
g_connection_status = ConnectionStatus::Scanning;
|
||||
g_status_led_tick = 0;
|
||||
resume_connections();
|
||||
if (disconnected_tracked_device) {
|
||||
recompute_connection_status();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -358,13 +394,15 @@ uni_error_t platform_on_device_ready(uni_hid_device_t* device) {
|
|||
bool occupied_mismatch = false;
|
||||
critical_section_enter_blocking(&g_state_lock);
|
||||
BackendSlot& slot = g_slots[slot_index];
|
||||
occupied_mismatch = slot.active && slot.device != device;
|
||||
if (!occupied_mismatch && !slot.active) {
|
||||
slot.state = make_neutral_state();
|
||||
occupied_mismatch = slot.device != nullptr && slot.device != device;
|
||||
if (!occupied_mismatch) {
|
||||
slot.device = device;
|
||||
slot.active = true;
|
||||
slot.rumble_pending = false;
|
||||
++slot.state_generation;
|
||||
if (!slot.active) {
|
||||
slot.state = make_neutral_state();
|
||||
slot.active = true;
|
||||
slot.rumble_pending = false;
|
||||
++slot.state_generation;
|
||||
}
|
||||
}
|
||||
critical_section_exit(&g_state_lock);
|
||||
|
||||
|
|
@ -372,15 +410,7 @@ uni_error_t platform_on_device_ready(uni_hid_device_t* device) {
|
|||
return UNI_ERROR_NO_SLOTS;
|
||||
}
|
||||
|
||||
g_status_led_tick = 0;
|
||||
if (all_slots_ready()) {
|
||||
g_connection_status = ConnectionStatus::Ready;
|
||||
uni_bt_stop_scanning_unsafe();
|
||||
uni_bt_allow_incoming_connections(false);
|
||||
} else {
|
||||
g_connection_status = ConnectionStatus::Scanning;
|
||||
resume_connections();
|
||||
}
|
||||
recompute_connection_status();
|
||||
return UNI_ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue