LibUSBBluetoothAdapter: Add SendBlockingCommand function.

This commit is contained in:
Jordan Woyak 2025-07-07 07:49:13 -05:00
parent 5336c23329
commit 0e90b85bab
2 changed files with 57 additions and 1 deletions

View File

@ -14,6 +14,7 @@
#include <fmt/format.h>
#include <libusb.h>
#include "Common/BitUtils.h"
#include "Common/MsgHandler.h"
#include "Core/Config/MainSettings.h"
@ -62,6 +63,11 @@ bool LibUSBBluetoothAdapter::IsWiiBTModule() const
return m_is_wii_bt_module;
}
bool LibUSBBluetoothAdapter::AreCommandsPendingResponse() const
{
return !m_pending_hci_transfers.empty() || !m_unacknowledged_commands.empty();
}
bool LibUSBBluetoothAdapter::HasConfiguredBluetoothDevice()
{
const int configured_vid = Config::Get(Config::MAIN_BLUETOOTH_PASSTHROUGH_VID);
@ -159,7 +165,7 @@ LibUSBBluetoothAdapter::~LibUSBBluetoothAdapter()
return;
// Wait for completion (or time out) of all HCI commands.
while (!m_pending_hci_transfers.empty() && !m_unacknowledged_commands.empty())
while (AreCommandsPendingResponse())
{
(void)ReceiveHCIEvent();
Common::YieldCPU();
@ -394,6 +400,50 @@ void LibUSBBluetoothAdapter::SendControlTransfer(std::span<const u8> data)
ScheduleControlTransfer(REQUEST_TYPE, 0, 0, 0, data, Clock::now());
}
bool LibUSBBluetoothAdapter::SendBlockingCommand(std::span<const u8> data, std::span<u8> response)
{
SendControlTransfer(data);
const hci_cmd_hdr_t cmd = Common::BitCastPtr<hci_cmd_hdr_t>(data.data());
while (AreCommandsPendingResponse())
{
const auto event = ReceiveHCIEvent();
if (event.empty())
{
Common::YieldCPU();
continue;
}
if (event[0] != HCI_EVENT_COMMAND_COMPL)
continue;
if (event.size() < sizeof(hci_event_hdr_t) + sizeof(hci_command_compl_ep))
{
ERROR_LOG_FMT(IOS_WIIMOTE, "Undersized hci_command_compl_ep");
continue;
}
const hci_command_compl_ep compl_event =
Common::BitCastPtr<hci_command_compl_ep>(event.data() + sizeof(hci_event_hdr_t));
if (compl_event.opcode != cmd.opcode)
continue;
if (event.size() < sizeof(hci_event_hdr_t) + sizeof(hci_command_compl_ep) + response.size())
{
ERROR_LOG_FMT(IOS_WIIMOTE, "Undersized command result");
break;
}
std::copy_n(event.data() + sizeof(hci_event_hdr_t) + sizeof(hci_command_compl_ep),
response.size(), response.data());
return true;
}
return false;
}
void LibUSBBluetoothAdapter::StartInputTransfers()
{
constexpr auto callback = LibUSBMemFunCallback<&LibUSBBluetoothAdapter::HandleInputTransfer>();

View File

@ -53,6 +53,11 @@ public:
// Schedule a transfer to be submitted as soon as possible.
void SendControlTransfer(std::span<const u8> data);
// Blocks and eats events until a command complete event of the correct opcode is received.
// Returns true on success or false on error or timeout.
// The written response does not include the event header or command complete data.
bool SendBlockingCommand(std::span<const u8> data, std::span<u8> response);
bool IsWiiBTModule() const;
private:
@ -122,6 +127,7 @@ private:
std::deque<OutstandingCommand> m_unacknowledged_commands;
bool IsControllerReadyForCommand() const;
bool AreCommandsPendingResponse() const;
// Give the transfer to the worker and track the command appropriately.
// This should only be used when IsControllerReadyForCommand is true.