Skip to content
48 changes: 38 additions & 10 deletions src/ble/ctrlm_ble_rcu_interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,14 @@ void ctrlm_ble_rcu_interface_t::shutdown()
m_controller->shutdown();
}

// Tell ctrlm_ble_key_m to drop every managed device before destructing the controller/adapter.
// Without this, the key monitor thread is left polling an fd that bluez destroys.
if (m_controller) {
for (const BleAddress &address : m_controller->managedDevices()) {
removeDeviceKeyMonitorThread(address);
}
}

// delete the adapter and controller when going into deepsleep so that we don't
// get notified of the remote disconnection that occurs when going to sleep.
// Upon waking, these will be re-initialized.
Expand Down Expand Up @@ -173,10 +181,7 @@ void ctrlm_ble_rcu_interface_t::initialize()
{
XLOGD_DEBUG("deviceRemovedSlot %s", address.toString().c_str());

ctrlm_ble_key_queue_device_changed_msg_t msg;
msg.header.type = CTRLM_BLE_KEY_QUEUE_MSG_TYPE_DEVICE_REMOVED;
msg.address = address;
ctrlm_utils_queue_msg_push(m_keyThreadMsgQ, (const char *)&msg, sizeof(msg));
removeDeviceKeyMonitorThread(address);

ctrlm_hal_ble_IndUnPaired_params_t params;
params.ieee_address = address.toUInt64();
Expand Down Expand Up @@ -283,9 +288,11 @@ bool ctrlm_ble_rcu_interface_t::handleAddedDevice(const BleAddress &address)
{
XLOGD_INFO("BLE RCU %s connected changed to <%s>", address.toString().c_str(), connected ? "TRUE" : "FALSE");

if (connected) {
if (m_keyMonitorThread.running) {
if (m_keyMonitorThread.running) {
if (connected) {
addNewDeviceKeyMonitorThread(address);
} else {
removeDeviceKeyMonitorThread(address);
}
}

Expand Down Expand Up @@ -1448,6 +1455,13 @@ void ctrlm_ble_rcu_interface_t::addNewDeviceKeyMonitorThread(BleAddress address)
msg.address = address;
ctrlm_utils_queue_msg_push(m_keyThreadMsgQ, (const char *)&msg, sizeof(msg));
}

void ctrlm_ble_rcu_interface_t::removeDeviceKeyMonitorThread(BleAddress address){
ctrlm_ble_key_queue_device_changed_msg_t msg;
msg.header.type = CTRLM_BLE_KEY_QUEUE_MSG_TYPE_DEVICE_REMOVED;
msg.address = address;
ctrlm_utils_queue_msg_push(m_keyThreadMsgQ, (const char *)&msg, sizeof(msg));
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// BEGIN - Key Monitor Thread
// -------------------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -1681,15 +1695,29 @@ void *KeyMonitorThread(void *data)
}

// loop the rcu fds to see if any has data to read
for (auto const &rcu : rcuKeypressFds) {
for (auto &rcu : rcuKeypressFds) {
if (rcu.second >= 0) {
if (FD_ISSET(rcu.second, &rfds)) {
safec_rc = memset_s ((void*) &event, sizeof(event), 0, sizeof(event));
ERR_CHK(safec_rc);
ret = read(rcu.second, (void*)&event, sizeof(event));
if (ret < 0) {
// int errsv = errno;
// XLOGD_ERROR("Error reading event: error = <%d>, <%s>", errsv, strerror(errsv));
if (ret == 0) {
// EOF - the underlying input device node is gone.
XLOGD_WARN("Input device for RCU <%s> hit EOF, closing fd <%d>",
rcu.first.toString().c_str(), rcu.second);
close(rcu.second);
rcu.second = -1;
} else if (ret < 0) {
int errsv = errno;
if (errsv == ENODEV || errsv == EBADF || errsv == EINVAL) {
// Device node was destroyed out from under us leaving 100% CPU spin.
// Close fd and FindRcuInputDevices() reopens the device node if it comes back.
XLOGD_WARN("Input device for RCU <%s> gone: error = <%d>, <%s>, closing fd <%d>",
rcu.first.toString().c_str(), errsv, strerror(errsv), rcu.second);
close(rcu.second);
rcu.second = -1;
}
// else: transient error (e.g. EAGAIN) - retry on the next wakeup.
} else {
HandleKeypress(metadata, &event, rcu.first);
}
Expand Down
1 change: 1 addition & 0 deletions src/ble/ctrlm_ble_rcu_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ class ctrlm_ble_rcu_interface_t
std::shared_ptr<BleRcuController> m_controller;

void addNewDeviceKeyMonitorThread(BleAddress address);
void removeDeviceKeyMonitorThread(BleAddress address);
};

#endif //__CTRLM_BLE_RCU_INTERFACE_H__
11 changes: 8 additions & 3 deletions src/ctrlm_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -986,14 +986,13 @@ gboolean ctrlm_thread_monitor(gpointer user_data) {
}
#endif

if(ctrlm_was_cpu_halted()) {
if(ctrlm_was_cpu_halted() && !g_ctrlm.thread_monitor_active) {
XLOGD_INFO("skipping response check due to power state <%s>",ctrlm_power_state_str(g_ctrlm.power_state));
g_ctrlm.thread_monitor_active = false; // Deactivate thread monitoring
} else if(!g_ctrlm.thread_monitor_active) {
XLOGD_INFO("activate due to power state <%s>",ctrlm_power_state_str(g_ctrlm.power_state));
g_ctrlm.thread_monitor_active = true; // Activate thread monitoring again
} else {
// Check the response from each thread on the previous attempt
// Check the response from each thread on the previous attempt, including final iteration before DEEP_SLEEP.
for(vector<ctrlm_thread_monitor_t>::iterator it = g_ctrlm.monitor_threads.begin(); it != g_ctrlm.monitor_threads.end(); it++) {
XLOGD_DEBUG("Checking %s", it->name);

Expand Down Expand Up @@ -1024,6 +1023,12 @@ gboolean ctrlm_thread_monitor(gpointer user_data) {
return (FALSE);
}
}

if(ctrlm_was_cpu_halted()) {
// The DEEP_SLEEP transition has now been checked, go quiet until we wake.
XLOGD_INFO("power state <%s>: transition checked, deactivating thread monitor",ctrlm_power_state_str(g_ctrlm.power_state));
g_ctrlm.thread_monitor_active = false; // Deactivate thread monitoring
}
}

if(g_ctrlm.thread_monitor_active) { // Thread monitoring is active
Expand Down
Loading