Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion include/ctrlm_ipc.h
Original file line number Diff line number Diff line change
Expand Up @@ -753,7 +753,6 @@ typedef struct {
typedef struct {
unsigned char api_revision; ///< Revision of this API
ctrlm_network_id_t network_id; ///< IN - Identifier of network
unsigned int key_code; ///< IN - Key code from device
unsigned int pair_code; ///< IN - Pairing code from device
ctrlm_iarm_call_result_t result; ///< OUT - return code of the operation
} ctrlm_iarm_call_StartPairWithCode_params_t;
Comment on lines 753 to 758
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The public IARM struct ctrlm_iarm_call_StartPairWithCode_params_t changed layout (key_code removed). This is a breaking ABI/API change for any out-of-process IARM client that still uses the old struct layout, and currently the server-side handler for Main_StartPairWithCode does not appear to validate api_revision. Please bump CTRLM_MAIN_IARM_BUS_API_REVISION and/or add explicit api_revision validation for this call so old clients fail safely instead of misinterpreting fields.

Copilot uses AI. Check for mistakes.
Expand Down
28 changes: 6 additions & 22 deletions src/ble/ctrlm_ble_network.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -740,29 +740,13 @@ void ctrlm_obj_network_ble_t::req_process_pair_with_code(void *data, int size) {
XLOGD_FATAL("Network is not ready!");
} else {
if (ble_rcu_interface_) {

if (dqm->params->key_code == KEY_BLUETOOTH) {
// KEY_BLUETOOTH means the pairing code is random 3 digit code embedded in the name
// so use pairWithCode
if (!ble_rcu_interface_->pairWithCode(dqm->params->pair_code)) {
// don't log error here, pairWithCode will handle printing the error. We do
// this because there is an error that is merely a warning that we don't want
// logged because it only confuses those analyzing the logs.
// XLOGD_ERROR("failed to start pairing with code");
} else {
dqm->params->result = CTRLM_IARM_CALL_RESULT_SUCCESS;
}
if (!ble_rcu_interface_->pairWithCode(dqm->params->pair_code)) {
// don't log error here, pairWithCode will handle printing the error. We do
// this because there is an error that is merely a warning that we don't want
// logged because it only confuses those analyzing the logs.
// XLOGD_ERROR("failed to start pairing with code");
} else {
// if key_code is either not available or KEY_CONNECT, it means the pairing code is a
// hash of the MAC, so use pairWithMacHash
if (!ble_rcu_interface_->pairWithMacHash(dqm->params->pair_code)) {
// don't log error here, pairWithMacHash will handle printing the error. We do
// this because there is an error that is merely a warning that we don't want
// logged because it only confuses those analyzing the logs.
// XLOGD_ERROR("failed to start pairing with MAC hash");
} else {
dqm->params->result = CTRLM_IARM_CALL_RESULT_SUCCESS;
}
dqm->params->result = CTRLM_IARM_CALL_RESULT_SUCCESS;
}
}
}
Expand Down
25 changes: 0 additions & 25 deletions src/ble/ctrlm_ble_rcu_interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -697,31 +697,6 @@ bool ctrlm_ble_rcu_interface_t::pairWithCode(unsigned int code)
XLOGD_ERROR("controller failed to start pairing, %s: %s", error.name().c_str(), error.message().c_str());
}
return false;
} else {
XLOGD_INFO("started pairing with code %hhu", code);
}
return true;
}

bool ctrlm_ble_rcu_interface_t::pairWithMacHash(unsigned int code)
{
if (!m_controller) {
XLOGD_ERROR("m_controller is NULL!!!");
return false;
}

if (!m_controller->startPairingWithMacHash((uint8_t) code)) {
BleRcuError error = m_controller->lastError();

// Remote will continually send out IR pairing signals until the BLE pair request
// has been received. This means that the "Already in pairing state" error is normal.
// Let's omit this error print because it only serves to confuse those analyzing the logs.
if (error.message() != "Already in pairing state") {
XLOGD_ERROR("controller failed to start pairing, %s: %s", error.name().c_str(), error.message().c_str());
}
return false;
} else {
XLOGD_INFO("started pairing with MAC hash 0x%X", code);
}
return true;
}
Expand Down
1 change: 0 additions & 1 deletion src/ble/ctrlm_ble_rcu_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,6 @@ class ctrlm_ble_rcu_interface_t
void handleDeepsleep(bool wakingUp);

bool pairWithCode(unsigned int code);
bool pairWithMacHash(unsigned int code);
bool pairWithMacAddrs(const std::vector<uint64_t> &macAddrList);
bool pairAutoWithTimeout(int timeoutMs);
bool pairCancel();
Expand Down
55 changes: 0 additions & 55 deletions src/ble/hal/blercu/blercucontroller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -271,61 +271,6 @@ bool BleRcuControllerImpl::startPairingWithCode(uint8_t pairingCode)
return true;
}

// -----------------------------------------------------------------------------
/*!
\fn bool BleRcuController::startPairingWithMacHash(uint8_t macHash)

Attempts to start the pairing procedure looking for a device that has
a MAC address matching the supplied MAC hash.

The MAC hash is calculated by adding all the bytes of the MAC address
together, and masking with 0xFF.
e.g., MAC = AA:BB:CC:DD:EE:FF, hash = (AA+BB+CC+DD+EE+FF) & 0xFF

If the controller is currently in pairing mode this method will fail and
return \c false. If the bluetooth adaptor is not available or not powered
then this function will also fail and return \c false.

If \c false is returned use BleRcuController::lastError() to get the failure
reason.

\note This object doesn't actually run the pairing procedure, instead it
just starts and stops the \l{BleRcuPairingStateMachine} object.

\see cancelPairing(), isPairing() & pairingCode()
*/
bool BleRcuControllerImpl::startPairingWithMacHash(uint8_t macHash)
{
if (m_pairingStateMachine.isRunning()) {
if (m_pairingStateMachine.isAutoPairing()) {

XLOGD_WARN("received targeted pairing request in auto pair mode, cancelling auto pair first...");

m_ignorePairingFailure = true;
m_pairingStateMachine.stop();

m_lastError = BleRcuError(BleRcuError::Busy, "Cancelling auto pair operation, send another request.");
} else {
XLOGD_DEBUG("requested pairing while currently running a pairing operation, ignoring request");
m_lastError = BleRcuError(BleRcuError::Busy, "Already in pairing state");
}
return false;
}

// check that the manager has powered on the adapter, without this we
// obviously can't scan / pair / etc. The only time the adaptor should
// (legitimately) be unavailable is right at start-up
if (!m_adapter->isAvailable() || !m_adapter->isPowered()) {
m_lastError = BleRcuError(BleRcuError::General, "Adaptor not available or not powered");
return false;
}

// start the pairing process
m_pairingStateMachine.startWithMacHash(macHash);

return true;
}

// -----------------------------------------------------------------------------
/*!
\fn bool BleRcuController::startPairingWithList(std::vector<BleAddress> macAddrList)
Expand Down
1 change: 0 additions & 1 deletion src/ble/hal/blercu/blercucontroller.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ class BleRcuController

virtual bool startPairingAutoWithTimeout(int timeoutMs) = 0;
virtual bool startPairingWithCode(uint8_t pairingCode) = 0;
virtual bool startPairingWithMacHash(uint8_t macHash) = 0;
virtual bool startPairingWithList(const std::vector<BleAddress> &macAddrList) = 0;
virtual bool cancelPairing() = 0;

Expand Down
1 change: 0 additions & 1 deletion src/ble/hal/blercu/blercucontroller_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ class BleRcuControllerImpl final : public BleRcuController

bool startPairingAutoWithTimeout(int timeoutMs) override;
bool startPairingWithCode(uint8_t pairingCode) override;
bool startPairingWithMacHash(uint8_t macHash) override;
bool startPairingWithList(const std::vector<BleAddress> &macAddrList) override;

bool cancelPairing() override;
Expand Down
59 changes: 9 additions & 50 deletions src/ble/hal/blercu/blercupairingstatemachine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,7 @@ bool BleRcuPairingStateMachine::isRunning() const
This special state is needed because auto pairing consists of running a scan for
an undeterminate amount of time until one of the supported devices listed in the
config file is found. We want to be able to cancel this operation if another
pair request comes in that targets a specific device (like pairWithCode or
pairWithMacHash)
pair request comes in that targets a specific device (like pairWithCode)

*/
bool BleRcuPairingStateMachine::isAutoPairing() const
Expand Down Expand Up @@ -272,9 +271,10 @@ void BleRcuPairingStateMachine::startWithCode(uint8_t pairingCode)
// clear the list of addresses to filter for
m_pairingMacList.clear();

// store the pairing code
// the pairing could be either the mac hash or the code embedded in the name,
// so store both for use when processing found devices
m_pairingCode = pairingCode;
m_pairingMacHash = -1;
m_pairingMacHash = pairingCode;

// create list of supported remotes regex to match to the name of the device
m_targetedPairingNames.clear();
Expand All @@ -296,47 +296,7 @@ void BleRcuPairingStateMachine::startWithCode(uint8_t pairingCode)

m_pairingAttempts++;
m_pairingSucceeded = false;
XLOGD_INFO("started pairing using name prefix code %03d", m_pairingCode);
}

// -----------------------------------------------------------------------------
/*!
Starts the state machine using the supplied \a pairingCode and
\a namePrefixes.

*/
void BleRcuPairingStateMachine::startWithMacHash(uint8_t macHash)
{
// sanity check the statemachine is not already running
if (m_stateMachine.isRunning()) {
XLOGD_WARN("state machine already running");
return;
}

m_discoveryTimeout = m_discoveryTimeoutDefault;
m_isAutoPairing = false;

// clear the target device
m_targetAddress.clear();

// clear the pairing code
m_pairingCode = -1;

// clear the list of addresses to filter for
m_pairingMacList.clear();

// store the MAC hash
m_pairingMacHash = macHash;

// clear the maps, we are trying to pair to a specific device using a hash of the MAC address
m_targetedPairingNames.clear();

// start the state machine
m_stateMachine.start();

m_pairingAttempts++;
m_pairingSucceeded = false;
XLOGD_INFO("started pairing, searching for device with MAC hash 0x%02X", m_pairingMacHash);
XLOGD_INFO("started pairing, searching for device with prefix code %03d or MAC hash 0x%02X", m_pairingCode, m_pairingMacHash);
}

// -----------------------------------------------------------------------------
Expand Down Expand Up @@ -869,23 +829,22 @@ void BleRcuPairingStateMachine::processDevice(const BleAddress &address,
}

if (it_name == m_targetedPairingNames.end()) {
// Device not found through conventional means, see if we are pairing based on MAC hash
// Because if we are pairing based on MAC hash, m_targetedPairingNames is first cleared
if (m_pairingMacHash != -1) {
// Device not found through name match, see if there is a MAC hash match
// Check if MAC hash matches
int macHash = 0;
for (int i = 0; i < 6; ++i) {
macHash += (int)address[i];
}
macHash &= 0xFF;
XLOGD_INFO("Pairing based on MAC hash, requested MAC hash = 0x%02X, this device = 0x%02X (%s, %s)",
XLOGD_INFO("Checking for MAC hash match, requested MAC hash = 0x%02X, this device = 0x%02X (%s, %s)",
m_pairingMacHash, macHash, name.c_str(), address.toString().c_str());
if (m_pairingMacHash != macHash) {
return;
}
// Device not found through conventional means or MAC hash so let's check a mac address list
// Pairing via a mac address list clears supported names and the pairing mac hash
} else if (m_pairingMacList.size() != 0) {
// Device not found through name match or MAC hash so let's check a mac address list
// Pairing via a mac address list clears supported names and the pairing mac hash
if (m_pairingMacList.size() != 0) {
// check if the mac address matches any of the ones in the filter list (if it exists)
bool found = false;
Comment on lines 845 to 850
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In processDevice(), the else if (m_pairingMacList.size() != 0) branch immediately re-checks if (m_pairingMacList.size() != 0) inside, which is redundant and adds noise to the control flow. Please remove the inner size check and keep a single guard for the MAC list path.

Copilot uses AI. Check for mistakes.
Expand Down
1 change: 0 additions & 1 deletion src/ble/hal/blercu/blercupairingstatemachine.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ class BleRcuPairingStateMachine
void start(const BleAddress &target, const std::string &name);
void startAutoWithTimeout(int timeoutMs);
void startWithCode(uint8_t pairingCode);
void startWithMacHash(uint8_t macHash);
void startWithMacList(const std::vector<BleAddress> &macList);
void stop();

Expand Down
Loading
Loading