mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-06-16 04:07:51 +00:00
Compare commits
8 Commits
75fa0febfd
...
c66b5943a5
Author | SHA1 | Date | |
---|---|---|---|
![]() |
c66b5943a5 | ||
![]() |
49fc7e78cc | ||
![]() |
074add14ac | ||
![]() |
3a0aed2560 | ||
![]() |
3469727435 | ||
![]() |
80b8b52387 | ||
![]() |
757d03896f | ||
![]() |
2fb1f17c89 |
2
Externals/SDL/SDL
vendored
2
Externals/SDL/SDL
vendored
@ -1 +1 @@
|
|||||||
Subproject commit c9a6709bd21750f1ad9597be21abace78c6378c9
|
Subproject commit 8d604353a53853fa56d1bdce0363535605ca868f
|
@ -165,27 +165,9 @@ int HIDKeyboard::SubmitTransfer(std::unique_ptr<CtrlMessage> cmd)
|
|||||||
}
|
}
|
||||||
case USBHDR(DIR_HOST2DEVICE, TYPE_CLASS, REC_INTERFACE, HIDRequestCodes::SET_IDLE):
|
case USBHDR(DIR_HOST2DEVICE, TYPE_CLASS, REC_INTERFACE, HIDRequestCodes::SET_IDLE):
|
||||||
{
|
{
|
||||||
const u8 duration = cmd->value >> 8;
|
WARN_LOG_FMT(IOS_USB, "SET_IDLE not implemented (value={:04x}, index={})", cmd->value,
|
||||||
const u8 report_id = cmd->value & 0xFF;
|
cmd->index);
|
||||||
|
// TODO: Handle idle duration and implement NAK
|
||||||
{
|
|
||||||
std::lock_guard lock(m_pending_lock);
|
|
||||||
if (duration == 0)
|
|
||||||
{
|
|
||||||
m_idle_duration.reset();
|
|
||||||
INFO_LOG_FMT(IOS_USB, "SET_IDLE duration to indefinite (report_id={:02x}, index={})",
|
|
||||||
report_id, cmd->index);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const auto idle_duration =
|
|
||||||
4 * duration; // 4 millisecond resolution (see HID specification)
|
|
||||||
m_idle_duration = std::chrono::milliseconds(idle_duration);
|
|
||||||
INFO_LOG_FMT(IOS_USB, "SET_IDLE duration to {} milliseconds (report_id={:02x}, index={})",
|
|
||||||
idle_duration, report_id, cmd->index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ios.EnqueueIPCReply(cmd->ios_request, IPC_SUCCESS);
|
ios.EnqueueIPCReply(cmd->ios_request, IPC_SUCCESS);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -225,15 +207,23 @@ int HIDKeyboard::SubmitTransfer(std::unique_ptr<BulkMessage> cmd)
|
|||||||
|
|
||||||
int HIDKeyboard::SubmitTransfer(std::unique_ptr<IntrMessage> cmd)
|
int HIDKeyboard::SubmitTransfer(std::unique_ptr<IntrMessage> cmd)
|
||||||
{
|
{
|
||||||
|
static auto start_time = std::chrono::steady_clock::now();
|
||||||
|
const auto current_time = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
|
const bool should_poll =
|
||||||
|
(current_time - start_time) >= POLLING_RATE && ControlReference::GetInputGate();
|
||||||
|
const Common::HIDPressedState state =
|
||||||
|
should_poll ? m_keyboard_context->GetPressedState() : m_last_state;
|
||||||
|
|
||||||
// We can't use cmd->ScheduleTransferCompletion here as it might provoke
|
// We can't use cmd->ScheduleTransferCompletion here as it might provoke
|
||||||
// invalid memory access with scheduled transfers when CancelTransfer is called.
|
// invalid memory access with scheduled transfers when CancelTransfer is called.
|
||||||
auto transfer = std::make_shared<PendingTransfer>(std::move(cmd));
|
EnqueueTransfer(std::move(cmd), state);
|
||||||
{
|
|
||||||
std::lock_guard lock(m_pending_lock);
|
|
||||||
m_pending_tranfers.insert(transfer);
|
|
||||||
}
|
|
||||||
m_worker.EmplaceItem(transfer);
|
|
||||||
|
|
||||||
|
if (should_poll)
|
||||||
|
{
|
||||||
|
m_last_state = std::move(state);
|
||||||
|
start_time = std::chrono::steady_clock::now();
|
||||||
|
}
|
||||||
return IPC_SUCCESS;
|
return IPC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -246,45 +236,47 @@ int HIDKeyboard::SubmitTransfer(std::unique_ptr<IsoMessage> cmd)
|
|||||||
return IPC_SUCCESS;
|
return IPC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HIDKeyboard::EnqueueTransfer(std::unique_ptr<IntrMessage> msg,
|
||||||
|
const Common::HIDPressedState& state)
|
||||||
|
{
|
||||||
|
msg->FillBuffer(reinterpret_cast<const u8*>(&state), sizeof(state));
|
||||||
|
auto transfer = std::make_shared<PendingTransfer>(std::move(msg));
|
||||||
|
m_worker.EmplaceItem(transfer);
|
||||||
|
{
|
||||||
|
std::lock_guard lock(m_pending_lock);
|
||||||
|
m_pending_tranfers.insert(transfer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void HIDKeyboard::HandlePendingTransfer(std::shared_ptr<PendingTransfer> transfer)
|
void HIDKeyboard::HandlePendingTransfer(std::shared_ptr<PendingTransfer> transfer)
|
||||||
{
|
{
|
||||||
static constexpr auto SLEEP_DURATION = POLLING_RATE / 2;
|
|
||||||
|
|
||||||
std::unique_lock lock(m_pending_lock);
|
std::unique_lock lock(m_pending_lock);
|
||||||
if (transfer->IsCanceled())
|
if (transfer->IsCanceled())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Common::HIDPressedState state;
|
while (!transfer->IsReady())
|
||||||
if (ControlReference::GetInputGate())
|
|
||||||
state = m_keyboard_context->GetPressedState();
|
|
||||||
|
|
||||||
while (state == m_last_state && transfer->Idle(m_idle_duration))
|
|
||||||
{
|
{
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
std::this_thread::sleep_for(SLEEP_DURATION);
|
std::this_thread::sleep_for(POLLING_RATE / 2);
|
||||||
lock.lock();
|
lock.lock();
|
||||||
|
|
||||||
if (transfer->IsCanceled())
|
if (transfer->IsCanceled())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (ControlReference::GetInputGate())
|
|
||||||
state = m_keyboard_context->GetPressedState();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
transfer->Do(state);
|
transfer->Do();
|
||||||
m_pending_tranfers.erase(transfer);
|
m_pending_tranfers.erase(transfer);
|
||||||
m_last_state = std::move(state);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HIDKeyboard::CancelPendingTransfers()
|
void HIDKeyboard::CancelPendingTransfers()
|
||||||
{
|
{
|
||||||
|
m_worker.Cancel();
|
||||||
{
|
{
|
||||||
std::lock_guard lock(m_pending_lock);
|
std::lock_guard lock(m_pending_lock);
|
||||||
for (auto& transfer : m_pending_tranfers)
|
for (auto& transfer : m_pending_tranfers)
|
||||||
transfer->Cancel();
|
transfer->Cancel();
|
||||||
m_pending_tranfers.clear();
|
m_pending_tranfers.clear();
|
||||||
}
|
}
|
||||||
m_worker.Cancel();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HIDKeyboard::PendingTransfer::PendingTransfer(std::unique_ptr<IntrMessage> msg)
|
HIDKeyboard::PendingTransfer::PendingTransfer(std::unique_ptr<IntrMessage> msg)
|
||||||
@ -301,17 +293,9 @@ HIDKeyboard::PendingTransfer::~PendingTransfer()
|
|||||||
m_msg->ScheduleTransferCompletion(-5, 0);
|
m_msg->ScheduleTransferCompletion(-5, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HIDKeyboard::PendingTransfer::Idle(
|
bool HIDKeyboard::PendingTransfer::IsReady() const
|
||||||
std::optional<std::chrono::milliseconds> idle_duration) const
|
|
||||||
{
|
{
|
||||||
if (!idle_duration.has_value())
|
return (std::chrono::steady_clock::now() - m_time) >= POLLING_RATE;
|
||||||
{
|
|
||||||
// Based on the HID specification for Set_Idle Request:
|
|
||||||
// - inhibit reporting forever,
|
|
||||||
// - only reporting when a change is detected in the report data
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return (std::chrono::steady_clock::now() - m_time) < *idle_duration;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HIDKeyboard::PendingTransfer::IsCanceled() const
|
bool HIDKeyboard::PendingTransfer::IsCanceled() const
|
||||||
@ -319,9 +303,8 @@ bool HIDKeyboard::PendingTransfer::IsCanceled() const
|
|||||||
return m_is_canceled;
|
return m_is_canceled;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HIDKeyboard::PendingTransfer::Do(const Common::HIDPressedState& state)
|
void HIDKeyboard::PendingTransfer::Do()
|
||||||
{
|
{
|
||||||
m_msg->FillBuffer(reinterpret_cast<const u8*>(&state), sizeof(state));
|
|
||||||
m_msg->ScheduleTransferCompletion(IPC_SUCCESS, 0);
|
m_msg->ScheduleTransferCompletion(IPC_SUCCESS, 0);
|
||||||
m_pending = false;
|
m_pending = false;
|
||||||
}
|
}
|
||||||
|
@ -47,9 +47,9 @@ private:
|
|||||||
PendingTransfer(std::unique_ptr<IntrMessage> msg);
|
PendingTransfer(std::unique_ptr<IntrMessage> msg);
|
||||||
~PendingTransfer();
|
~PendingTransfer();
|
||||||
|
|
||||||
bool Idle(std::optional<std::chrono::milliseconds> idle_duration) const;
|
bool IsReady() const;
|
||||||
bool IsCanceled() const;
|
bool IsCanceled() const;
|
||||||
void Do(const Common::HIDPressedState& state);
|
void Do();
|
||||||
void Cancel();
|
void Cancel();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -59,13 +59,13 @@ private:
|
|||||||
bool m_pending = true;
|
bool m_pending = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void EnqueueTransfer(std::unique_ptr<IntrMessage> msg, const Common::HIDPressedState& state);
|
||||||
void HandlePendingTransfer(std::shared_ptr<PendingTransfer> transfer);
|
void HandlePendingTransfer(std::shared_ptr<PendingTransfer> transfer);
|
||||||
void CancelPendingTransfers();
|
void CancelPendingTransfers();
|
||||||
|
|
||||||
Common::WorkQueueThreadSP<std::shared_ptr<PendingTransfer>> m_worker;
|
Common::WorkQueueThreadSP<std::shared_ptr<PendingTransfer>> m_worker;
|
||||||
std::mutex m_pending_lock;
|
std::mutex m_pending_lock;
|
||||||
std::set<std::shared_ptr<PendingTransfer>> m_pending_tranfers;
|
std::set<std::shared_ptr<PendingTransfer>> m_pending_tranfers;
|
||||||
std::optional<std::chrono::milliseconds> m_idle_duration;
|
|
||||||
|
|
||||||
HIDProtocol m_current_protocol = HIDProtocol::Report;
|
HIDProtocol m_current_protocol = HIDProtocol::Report;
|
||||||
Common::HIDPressedState m_last_state;
|
Common::HIDPressedState m_last_state;
|
||||||
|
Loading…
Reference in New Issue
Block a user