mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-08-09 08:41:31 +00:00
[idd] input: preserve reports under backpressure
Move named pipe writes off the LGMP input worker so a stalled LGInput endpoint cannot block queue draining or lease maintenance. Coalesce motion only under queue pressure while preserving mode, button, wheel, and keyboard transitions. Reset HID state after discontinuities and carry all 32 mouse button bits through the pipe and HID reports.
This commit is contained in:
@@ -26,16 +26,21 @@
|
||||
#include "ipc/CInputPipeClient.h"
|
||||
|
||||
#include <hidport.h>
|
||||
#include <limits.h>
|
||||
#include <new>
|
||||
#include <string.h>
|
||||
|
||||
static constexpr USHORT LG_INPUT_VENDOR_ID = 0x0000;
|
||||
static constexpr USHORT LG_INPUT_PRODUCT_ID = 0x0000;
|
||||
static constexpr USHORT LG_INPUT_VERSION = 0x0001;
|
||||
static constexpr size_t REPORT_QUEUE_LENGTH = 64;
|
||||
static constexpr USHORT LG_INPUT_VENDOR_ID = 0x0000;
|
||||
static constexpr USHORT LG_INPUT_PRODUCT_ID = 0x0000;
|
||||
static constexpr USHORT LG_INPUT_VERSION = 0x0001;
|
||||
static constexpr size_t REPORT_QUEUE_LENGTH = 64;
|
||||
static constexpr size_t MOTION_COALESCE_THRESHOLD =
|
||||
REPORT_QUEUE_LENGTH / 2;
|
||||
|
||||
struct HIDQueuedReport
|
||||
{
|
||||
UCHAR data[sizeof(HIDKeyboardReport)];
|
||||
UCHAR data[HID_MAX_INPUT_REPORT_SIZE];
|
||||
bool pureMotion;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
@@ -49,8 +54,14 @@ struct HIDDeviceContext
|
||||
SRWLOCK reportLock;
|
||||
bool active;
|
||||
bool stopping;
|
||||
UCHAR mouseMode;
|
||||
size_t reportHead;
|
||||
size_t reportCount;
|
||||
uint32_t relativeButtons;
|
||||
uint32_t absoluteButtons;
|
||||
bool absoluteValid;
|
||||
uint16_t absoluteX;
|
||||
uint16_t absoluteY;
|
||||
HIDQueuedReport reports[REPORT_QUEUE_LENGTH];
|
||||
CInputPipeClient * inputPipe;
|
||||
};
|
||||
@@ -151,19 +162,114 @@ static void PopReport(
|
||||
--context->reportCount;
|
||||
}
|
||||
|
||||
static HIDQueuedReport& GetQueuedReport(
|
||||
_Inout_ HIDDeviceContext * context,
|
||||
_In_ size_t position)
|
||||
{
|
||||
return context->reports[
|
||||
(context->reportHead + position) % REPORT_QUEUE_LENGTH];
|
||||
}
|
||||
|
||||
static void RemoveQueuedReport(
|
||||
_Inout_ HIDDeviceContext * context,
|
||||
_In_ size_t position)
|
||||
{
|
||||
for (size_t i = position; i + 1 < context->reportCount; ++i)
|
||||
GetQueuedReport(context, i) = GetQueuedReport(context, i + 1);
|
||||
--context->reportCount;
|
||||
}
|
||||
|
||||
static bool CompactStaleMotion(
|
||||
_Inout_ HIDDeviceContext * context,
|
||||
_In_ UCHAR incomingReportId)
|
||||
{
|
||||
for (size_t i = 0; i < context->reportCount; ++i)
|
||||
{
|
||||
HIDQueuedReport& report = GetQueuedReport(context, i);
|
||||
if (!report.pureMotion ||
|
||||
report.data[0] != HID_REPORT_ID_MOUSE_ABSOLUTE)
|
||||
continue;
|
||||
|
||||
bool superseded = incomingReportId == HID_REPORT_ID_MOUSE_ABSOLUTE;
|
||||
for (size_t j = i + 1; !superseded && j < context->reportCount; ++j)
|
||||
superseded = GetQueuedReport(context, j).data[0] ==
|
||||
HID_REPORT_ID_MOUSE_ABSOLUTE;
|
||||
|
||||
if (superseded)
|
||||
{
|
||||
RemoveQueuedReport(context, i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static NTSTATUS QueueReport(
|
||||
_Inout_ HIDDeviceContext * context,
|
||||
_In_reads_bytes_(size) const void * data,
|
||||
_In_ size_t size)
|
||||
_In_ size_t size,
|
||||
_In_ bool pureMotion)
|
||||
{
|
||||
const UCHAR reportId = *static_cast<const UCHAR *>(data);
|
||||
if (context->reportCount)
|
||||
{
|
||||
HIDQueuedReport& tail =
|
||||
GetQueuedReport(context, context->reportCount - 1);
|
||||
if (tail.data[0] == reportId)
|
||||
{
|
||||
if (reportId == HID_REPORT_ID_MOUSE_RELATIVE &&
|
||||
context->reportCount >= MOTION_COALESCE_THRESHOLD &&
|
||||
tail.pureMotion && pureMotion)
|
||||
{
|
||||
HIDMouseRelativeReport * previous =
|
||||
reinterpret_cast<HIDMouseRelativeReport *>(tail.data);
|
||||
const HIDMouseRelativeReport * current =
|
||||
static_cast<const HIDMouseRelativeReport *>(data);
|
||||
const int32_t x = static_cast<int32_t>(previous->x) +
|
||||
current->x;
|
||||
const int32_t y = static_cast<int32_t>(previous->y) +
|
||||
current->y;
|
||||
if (x >= INT16_MIN && x <= INT16_MAX &&
|
||||
y >= INT16_MIN && y <= INT16_MAX &&
|
||||
previous->buttons == current->buttons)
|
||||
{
|
||||
previous->x = static_cast<int16_t>(x);
|
||||
previous->y = static_cast<int16_t>(y);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
else if (reportId == HID_REPORT_ID_MOUSE_ABSOLUTE &&
|
||||
tail.pureMotion && pureMotion)
|
||||
{
|
||||
const HIDMouseAbsoluteReport * previous =
|
||||
reinterpret_cast<const HIDMouseAbsoluteReport *>(tail.data);
|
||||
const HIDMouseAbsoluteReport * current =
|
||||
static_cast<const HIDMouseAbsoluteReport *>(data);
|
||||
if (previous->buttons == current->buttons)
|
||||
{
|
||||
CopyMemory(tail.data, data, size);
|
||||
tail.size = size;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
else if (reportId == HID_REPORT_ID_KEYBOARD &&
|
||||
tail.size == size && memcmp(tail.data, data, size) == 0)
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
if (context->reportCount == REPORT_QUEUE_LENGTH)
|
||||
return STATUS_BUFFER_OVERFLOW;
|
||||
{
|
||||
if (!CompactStaleMotion(context, reportId))
|
||||
return STATUS_BUFFER_OVERFLOW;
|
||||
}
|
||||
|
||||
const size_t index =
|
||||
(context->reportHead + context->reportCount) % REPORT_QUEUE_LENGTH;
|
||||
HIDQueuedReport * report = &context->reports[index];
|
||||
CopyMemory(report->data, data, size);
|
||||
report->size = size;
|
||||
report->size = size;
|
||||
report->pureMotion = pureMotion;
|
||||
++context->reportCount;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
@@ -343,38 +449,136 @@ NTSTATUS CHIDDevice::SubmitReport(
|
||||
status = STATUS_DEVICE_NOT_READY;
|
||||
else
|
||||
{
|
||||
bool pureMotion = false;
|
||||
switch (reportId)
|
||||
{
|
||||
case HID_REPORT_ID_MOUSE_RELATIVE:
|
||||
{
|
||||
const HIDMouseRelativeReport * mouse =
|
||||
static_cast<const HIDMouseRelativeReport *>(report);
|
||||
pureMotion = context->mouseMode == reportId &&
|
||||
(mouse->x != 0 || mouse->y != 0 || mouse->buttons != 0) &&
|
||||
mouse->wheel == 0 &&
|
||||
mouse->buttons == context->relativeButtons;
|
||||
break;
|
||||
}
|
||||
|
||||
case HID_REPORT_ID_MOUSE_ABSOLUTE:
|
||||
{
|
||||
const HIDMouseAbsoluteReport * mouse =
|
||||
static_cast<const HIDMouseAbsoluteReport *>(report);
|
||||
pureMotion = context->mouseMode == reportId &&
|
||||
(mouse->x != context->absoluteX ||
|
||||
mouse->y != context->absoluteY || mouse->buttons != 0) &&
|
||||
mouse->wheel == 0 &&
|
||||
mouse->buttons == context->absoluteButtons;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
status = WdfIoQueueRetrieveNextRequest(context->reportQueue, &request);
|
||||
if (status == STATUS_NO_MORE_ENTRIES)
|
||||
{
|
||||
request = nullptr;
|
||||
status = QueueReport(context, report, size);
|
||||
status = QueueReport(context, report, size, pureMotion);
|
||||
}
|
||||
else if (NT_SUCCESS(status))
|
||||
status = CopyToRequest(request, report, size);
|
||||
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
switch (reportId)
|
||||
{
|
||||
case HID_REPORT_ID_MOUSE_RELATIVE:
|
||||
context->mouseMode = reportId;
|
||||
context->relativeButtons =
|
||||
static_cast<const HIDMouseRelativeReport *>(report)->buttons;
|
||||
break;
|
||||
|
||||
case HID_REPORT_ID_MOUSE_ABSOLUTE:
|
||||
{
|
||||
const HIDMouseAbsoluteReport * mouse =
|
||||
static_cast<const HIDMouseAbsoluteReport *>(report);
|
||||
context->mouseMode = reportId;
|
||||
context->absoluteButtons = mouse->buttons;
|
||||
context->absoluteValid = true;
|
||||
context->absoluteX = mouse->x;
|
||||
context->absoluteY = mouse->y;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (request)
|
||||
{
|
||||
status = CopyToRequest(request, report, size);
|
||||
WdfRequestComplete(request, status);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
NTSTATUS CHIDDevice::ClearReports()
|
||||
NTSTATUS CHIDDevice::ResetReports()
|
||||
{
|
||||
CSRWSharedLock deviceLock(&s_deviceLock);
|
||||
HIDDeviceContext * context = s_device;
|
||||
if (!context)
|
||||
return STATUS_DEVICE_NOT_READY;
|
||||
uint16_t absoluteX = 0;
|
||||
uint16_t absoluteY = 0;
|
||||
bool absoluteValid = false;
|
||||
{
|
||||
CSRWSharedLock deviceLock(&s_deviceLock);
|
||||
HIDDeviceContext * context = s_device;
|
||||
if (!context)
|
||||
return STATUS_DEVICE_NOT_READY;
|
||||
|
||||
CSRWExclusiveLock reportLock(&context->reportLock);
|
||||
if (context->stopping)
|
||||
return STATUS_DEVICE_NOT_READY;
|
||||
CSRWExclusiveLock reportLock(&context->reportLock);
|
||||
if (context->stopping)
|
||||
return STATUS_DEVICE_NOT_READY;
|
||||
|
||||
context->reportHead = 0;
|
||||
context->reportCount = 0;
|
||||
return STATUS_SUCCESS;
|
||||
absoluteValid = context->absoluteValid;
|
||||
absoluteX = context->absoluteX;
|
||||
absoluteY = context->absoluteY;
|
||||
context->reportHead = 0;
|
||||
context->reportCount = 0;
|
||||
context->mouseMode = 0;
|
||||
context->relativeButtons = 0;
|
||||
context->absoluteButtons = 0;
|
||||
}
|
||||
|
||||
const HIDMouseRelativeReport relative = {
|
||||
HID_REPORT_ID_MOUSE_RELATIVE,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
};
|
||||
const HIDKeyboardReport keyboard = {
|
||||
HID_REPORT_ID_KEYBOARD,
|
||||
};
|
||||
|
||||
NTSTATUS status = SubmitReport(&relative, sizeof(relative));
|
||||
if (absoluteValid)
|
||||
{
|
||||
const HIDMouseAbsoluteReport absolute = {
|
||||
HID_REPORT_ID_MOUSE_ABSOLUTE,
|
||||
0,
|
||||
absoluteX,
|
||||
absoluteY,
|
||||
0,
|
||||
};
|
||||
const NTSTATUS absoluteStatus =
|
||||
SubmitReport(&absolute, sizeof(absolute));
|
||||
if (NT_SUCCESS(status))
|
||||
status = absoluteStatus;
|
||||
}
|
||||
const NTSTATUS keyboardStatus =
|
||||
SubmitReport(&keyboard, sizeof(keyboard));
|
||||
if (NT_SUCCESS(status))
|
||||
status = keyboardStatus;
|
||||
return status;
|
||||
}
|
||||
|
||||
VOID HIDEvtIoDeviceControl(
|
||||
|
||||
@@ -30,5 +30,5 @@ public:
|
||||
static NTSTATUS SubmitReport(
|
||||
_In_reads_bytes_(size) const void * report,
|
||||
_In_ size_t size);
|
||||
static NTSTATUS ClearReports();
|
||||
static NTSTATUS ResetReports();
|
||||
};
|
||||
|
||||
@@ -31,15 +31,12 @@ static const uint8_t REPORT_DESCRIPTOR[] =
|
||||
0xA1, 0x00, // Collection (Physical)
|
||||
0x05, 0x09, // Usage Page (Button)
|
||||
0x19, 0x01, // Usage Minimum (Button 1)
|
||||
0x29, 0x05, // Usage Maximum (Button 5)
|
||||
0x29, 0x20, // Usage Maximum (Button 32)
|
||||
0x15, 0x00, // Logical Minimum (0)
|
||||
0x25, 0x01, // Logical Maximum (1)
|
||||
0x75, 0x01, // Report Size (1)
|
||||
0x95, 0x05, // Report Count (5)
|
||||
0x95, 0x20, // Report Count (32)
|
||||
0x81, 0x02, // Input (Data, Variable, Absolute)
|
||||
0x75, 0x03, // Report Size (3)
|
||||
0x95, 0x01, // Report Count (1)
|
||||
0x81, 0x03, // Input (Constant)
|
||||
0x05, 0x01, // Usage Page (Generic Desktop)
|
||||
0x09, 0x30, // Usage (X)
|
||||
0x09, 0x31, // Usage (Y)
|
||||
@@ -66,15 +63,12 @@ static const uint8_t REPORT_DESCRIPTOR[] =
|
||||
0xA1, 0x00, // Collection (Physical)
|
||||
0x05, 0x09, // Usage Page (Button)
|
||||
0x19, 0x01, // Usage Minimum (Button 1)
|
||||
0x29, 0x05, // Usage Maximum (Button 5)
|
||||
0x29, 0x20, // Usage Maximum (Button 32)
|
||||
0x15, 0x00, // Logical Minimum (0)
|
||||
0x25, 0x01, // Logical Maximum (1)
|
||||
0x75, 0x01, // Report Size (1)
|
||||
0x95, 0x05, // Report Count (5)
|
||||
0x95, 0x20, // Report Count (32)
|
||||
0x81, 0x02, // Input (Data, Variable, Absolute)
|
||||
0x75, 0x03, // Report Size (3)
|
||||
0x95, 0x01, // Report Count (1)
|
||||
0x81, 0x03, // Input (Constant)
|
||||
0x05, 0x01, // Usage Page (Generic Desktop)
|
||||
0x09, 0x30, // Usage (X)
|
||||
0x09, 0x31, // Usage (Y)
|
||||
|
||||
@@ -35,7 +35,7 @@ enum HIDReportId : uint8_t
|
||||
struct HIDMouseAbsoluteReport
|
||||
{
|
||||
uint8_t reportId;
|
||||
uint8_t buttons;
|
||||
uint32_t buttons;
|
||||
uint16_t x;
|
||||
uint16_t y;
|
||||
int8_t wheel;
|
||||
@@ -44,7 +44,7 @@ struct HIDMouseAbsoluteReport
|
||||
struct HIDMouseRelativeReport
|
||||
{
|
||||
uint8_t reportId;
|
||||
uint8_t buttons;
|
||||
uint32_t buttons;
|
||||
int16_t x;
|
||||
int16_t y;
|
||||
int8_t wheel;
|
||||
@@ -66,11 +66,14 @@ struct HIDKeyboardLedsReport
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
static_assert(sizeof(HIDMouseAbsoluteReport) == 7);
|
||||
static_assert(sizeof(HIDMouseRelativeReport) == 7);
|
||||
static_assert(sizeof(HIDMouseAbsoluteReport) == 10);
|
||||
static_assert(sizeof(HIDMouseRelativeReport) == 10);
|
||||
static_assert(sizeof(HIDKeyboardReport) == 9);
|
||||
static_assert(sizeof(HIDKeyboardLedsReport) == 2);
|
||||
|
||||
static constexpr size_t HID_MAX_INPUT_REPORT_SIZE =
|
||||
sizeof(HIDMouseAbsoluteReport);
|
||||
|
||||
const uint8_t * HIDGetReportDescriptor();
|
||||
size_t HIDGetReportDescriptorSize();
|
||||
size_t HIDGetInputReportSize(uint8_t reportId);
|
||||
|
||||
@@ -80,7 +80,7 @@
|
||||
<WppRecorderEnabled>true</WppRecorderEnabled>
|
||||
<WppScanConfigurationData Condition="'%(ClCompile.ScanConfigurationData)' == ''">Trace.h</WppScanConfigurationData>
|
||||
<AdditionalOptions>/EHsc /D_ATL_NO_WIN_SUPPORT %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\LGCommon;$(DDK_INC_PATH);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)..\LGCommon;$(ProjectDir)..\..\common\include;$(DDK_INC_PATH);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);OneCoreUAP.lib</AdditionalDependencies>
|
||||
|
||||
@@ -43,7 +43,7 @@ void CInputPipeClient::Stop()
|
||||
m_endpoint.Stop();
|
||||
m_lastSequence = 0;
|
||||
if (wasRunning)
|
||||
CHIDDevice::ClearReports();
|
||||
CHIDDevice::ResetReports();
|
||||
}
|
||||
|
||||
void CInputPipeClient::OnPipeConnected()
|
||||
@@ -55,7 +55,7 @@ void CInputPipeClient::OnPipeConnected()
|
||||
void CInputPipeClient::OnPipeDisconnected()
|
||||
{
|
||||
m_lastSequence = 0;
|
||||
CHIDDevice::ClearReports();
|
||||
CHIDDevice::ResetReports();
|
||||
DEBUG_INFO("Disconnected from the LGIdd input transport; reconnecting");
|
||||
}
|
||||
|
||||
@@ -78,6 +78,7 @@ bool CInputPipeClient::OnPipeMessage(
|
||||
(m_lastSequence && message.sequence != m_lastSequence + 1))
|
||||
{
|
||||
DEBUG_WARN("LGInput pipe report sequence changed unexpectedly");
|
||||
CHIDDevice::ResetReports();
|
||||
return false;
|
||||
}
|
||||
bool handled = false;
|
||||
@@ -117,18 +118,41 @@ bool CInputPipeClient::HandleMouseRelative(
|
||||
|
||||
LGInputPipeMouseRelative input = {};
|
||||
memcpy(&input, payload, sizeof(input));
|
||||
if (input.wheel < LG_INPUT_MOUSE_WHEEL_MIN ||
|
||||
(input.buttons & ~LG_INPUT_MOUSE_BUTTON_MASK))
|
||||
if (input.deltaX < LG_INPUT_MOUSE_DELTA_MIN ||
|
||||
input.deltaX > LG_INPUT_MOUSE_DELTA_MAX ||
|
||||
input.deltaY < LG_INPUT_MOUSE_DELTA_MIN ||
|
||||
input.deltaY > LG_INPUT_MOUSE_DELTA_MAX ||
|
||||
input.wheel < LG_INPUT_MOUSE_WHEEL_MIN_TOTAL ||
|
||||
input.wheel > LG_INPUT_MOUSE_WHEEL_MAX)
|
||||
return false;
|
||||
|
||||
const HIDMouseRelativeReport report = {
|
||||
HID_REPORT_ID_MOUSE_RELATIVE,
|
||||
input.buttons,
|
||||
input.deltaX,
|
||||
input.deltaY,
|
||||
input.wheel,
|
||||
};
|
||||
return SubmitReport(&report, sizeof(report));
|
||||
int32_t x = input.deltaX;
|
||||
int32_t y = input.deltaY;
|
||||
int32_t wheel = input.wheel;
|
||||
do
|
||||
{
|
||||
const int16_t reportX = x > INT16_MAX ? INT16_MAX :
|
||||
x < INT16_MIN ? INT16_MIN : static_cast<int16_t>(x);
|
||||
const int16_t reportY = y > INT16_MAX ? INT16_MAX :
|
||||
y < INT16_MIN ? INT16_MIN : static_cast<int16_t>(y);
|
||||
const int8_t reportWheel = wheel > INT8_MAX ? INT8_MAX :
|
||||
wheel < LG_INPUT_MOUSE_WHEEL_MIN ? LG_INPUT_MOUSE_WHEEL_MIN :
|
||||
static_cast<int8_t>(wheel);
|
||||
const HIDMouseRelativeReport report = {
|
||||
HID_REPORT_ID_MOUSE_RELATIVE,
|
||||
input.buttons,
|
||||
reportX,
|
||||
reportY,
|
||||
reportWheel,
|
||||
};
|
||||
if (!SubmitReport(&report, sizeof(report)))
|
||||
return false;
|
||||
x -= reportX;
|
||||
y -= reportY;
|
||||
wheel -= reportWheel;
|
||||
}
|
||||
while (x || y || wheel);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CInputPipeClient::HandleMouseAbsolute(
|
||||
@@ -142,18 +166,30 @@ bool CInputPipeClient::HandleMouseAbsolute(
|
||||
memcpy(&input, payload, sizeof(input));
|
||||
if (input.x > LG_INPUT_MOUSE_ABSOLUTE_MAX ||
|
||||
input.y > LG_INPUT_MOUSE_ABSOLUTE_MAX ||
|
||||
input.wheel < LG_INPUT_MOUSE_WHEEL_MIN ||
|
||||
(input.buttons & ~LG_INPUT_MOUSE_BUTTON_MASK))
|
||||
input.wheel < LG_INPUT_MOUSE_WHEEL_MIN_TOTAL ||
|
||||
input.wheel > LG_INPUT_MOUSE_WHEEL_MAX ||
|
||||
input.reserved)
|
||||
return false;
|
||||
|
||||
const HIDMouseAbsoluteReport report = {
|
||||
HID_REPORT_ID_MOUSE_ABSOLUTE,
|
||||
input.buttons,
|
||||
input.x,
|
||||
input.y,
|
||||
input.wheel,
|
||||
};
|
||||
return SubmitReport(&report, sizeof(report));
|
||||
int32_t wheel = input.wheel;
|
||||
do
|
||||
{
|
||||
const int8_t reportWheel = wheel > INT8_MAX ? INT8_MAX :
|
||||
wheel < LG_INPUT_MOUSE_WHEEL_MIN ? LG_INPUT_MOUSE_WHEEL_MIN :
|
||||
static_cast<int8_t>(wheel);
|
||||
const HIDMouseAbsoluteReport report = {
|
||||
HID_REPORT_ID_MOUSE_ABSOLUTE,
|
||||
input.buttons,
|
||||
input.x,
|
||||
input.y,
|
||||
reportWheel,
|
||||
};
|
||||
if (!SubmitReport(&report, sizeof(report)))
|
||||
return false;
|
||||
wheel -= reportWheel;
|
||||
}
|
||||
while (wheel);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CInputPipeClient::HandleKeyboard(
|
||||
@@ -166,6 +202,10 @@ bool CInputPipeClient::HandleKeyboard(
|
||||
LGInputPipeKeyboard input = {};
|
||||
memcpy(&input, payload, sizeof(input));
|
||||
|
||||
for (size_t i = 0; i < sizeof(input.reserved); ++i)
|
||||
if (input.reserved[i])
|
||||
return false;
|
||||
|
||||
HIDKeyboardReport report = {};
|
||||
report.reportId = HID_REPORT_ID_KEYBOARD;
|
||||
report.modifiers = input.modifiers;
|
||||
@@ -189,8 +229,16 @@ bool CInputPipeClient::SubmitReport(
|
||||
return false;
|
||||
|
||||
if (status == STATUS_BUFFER_OVERFLOW)
|
||||
DEBUG_WARN("LGInput HID report queue is full; dropping a report");
|
||||
else if (!NT_SUCCESS(status) && status != STATUS_DEVICE_NOT_READY)
|
||||
DEBUG_WARN_HR(status, "Failed to submit an LGInput HID report");
|
||||
{
|
||||
DEBUG_WARN("LGInput HID report queue overflowed; resetting input state");
|
||||
CHIDDevice::ResetReports();
|
||||
return false;
|
||||
}
|
||||
if (!NT_SUCCESS(status))
|
||||
{
|
||||
if (status != STATUS_DEVICE_NOT_READY)
|
||||
DEBUG_WARN_HR(status, "Failed to submit an LGInput HID report");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -32,7 +32,6 @@ public:
|
||||
|
||||
bool Start();
|
||||
void Stop();
|
||||
bool IsConnected() const { return m_endpoint.IsConnected(); }
|
||||
|
||||
private:
|
||||
void OnPipeConnected() override;
|
||||
|
||||
Reference in New Issue
Block a user