first push
This commit is contained in:
189
DRI/Dri_Hid.cpp
Normal file
189
DRI/Dri_Hid.cpp
Normal file
@@ -0,0 +1,189 @@
|
||||
#include "DRI/Dri_Hid.h"
|
||||
|
||||
#include <hidsdi.h>
|
||||
|
||||
#pragma comment(lib, "hid.lib")
|
||||
|
||||
namespace
|
||||
{
|
||||
bool Dri_Hid_BeginRead(Dri_Hid_Struct_ReadPort* p_Port, QString* p_TextStatus)
|
||||
{
|
||||
if (!p_Port->IsOpened || (p_Port->InputLength == 0)) return false;
|
||||
if (p_Port->IsReadPending) return true;
|
||||
|
||||
ResetEvent(p_Port->HandleEvent);
|
||||
p_Port->ReadBuffer.fill(0, p_Port->InputLength);
|
||||
p_Port->OverlappedRead = {};
|
||||
p_Port->OverlappedRead.hEvent = p_Port->HandleEvent;
|
||||
|
||||
DWORD BytesRead = 0;
|
||||
if (ReadFile(
|
||||
p_Port->HandleRead,
|
||||
p_Port->ReadBuffer.data(),
|
||||
p_Port->InputLength,
|
||||
&BytesRead,
|
||||
&p_Port->OverlappedRead) ||
|
||||
(GetLastError() == ERROR_IO_PENDING))
|
||||
{
|
||||
p_Port->IsReadPending = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (p_TextStatus != nullptr) *p_TextStatus = QStringLiteral("%1 failed to start async read: %2").arg(p_Port->PortName).arg(GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void Dri_Hid_CloseReadPort(Dri_Hid_Struct_ReadPort* p_Port)
|
||||
{
|
||||
if ((p_Port->HandleRead != INVALID_HANDLE_VALUE) && p_Port->IsReadPending) CancelIoEx(p_Port->HandleRead, &p_Port->OverlappedRead);
|
||||
if (p_Port->HandleRead != INVALID_HANDLE_VALUE) CloseHandle(p_Port->HandleRead);
|
||||
if (p_Port->HandleEvent != nullptr) CloseHandle(p_Port->HandleEvent);
|
||||
*p_Port = Dri_Hid_Struct_ReadPort();
|
||||
}
|
||||
|
||||
bool Dri_Hid_InitReadPort(
|
||||
Dri_Hid_Struct_ReadPort* p_Port,
|
||||
const QString& DevicePath,
|
||||
quint16 InputLength,
|
||||
Mid_Enum_RawPacketSource PacketSource,
|
||||
const QString& PortName,
|
||||
QString* p_TextStatus)
|
||||
{
|
||||
Dri_Hid_CloseReadPort(p_Port);
|
||||
|
||||
p_Port->HandleRead = CreateFileW(
|
||||
reinterpret_cast<LPCWSTR>(DevicePath.utf16()),
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
nullptr,
|
||||
OPEN_EXISTING,
|
||||
FILE_FLAG_OVERLAPPED,
|
||||
nullptr);
|
||||
if (p_Port->HandleRead == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if (p_TextStatus != nullptr) *p_TextStatus = QStringLiteral("%1 failed to open read handle: %2").arg(PortName).arg(GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
p_Port->HandleEvent = CreateEventW(nullptr, TRUE, FALSE, nullptr);
|
||||
if (p_Port->HandleEvent == nullptr)
|
||||
{
|
||||
if (p_TextStatus != nullptr) *p_TextStatus = QStringLiteral("%1 failed to create event: %2").arg(PortName).arg(GetLastError());
|
||||
Dri_Hid_CloseReadPort(p_Port);
|
||||
return false;
|
||||
}
|
||||
|
||||
p_Port->InputLength = InputLength;
|
||||
p_Port->PacketSource = PacketSource;
|
||||
p_Port->PortName = PortName;
|
||||
p_Port->ReadBuffer = QByteArray(InputLength, 0);
|
||||
p_Port->OverlappedRead.hEvent = p_Port->HandleEvent;
|
||||
p_Port->IsOpened = true;
|
||||
|
||||
if (!Dri_Hid_BeginRead(p_Port, p_TextStatus)) { Dri_Hid_CloseReadPort(p_Port); return false; }
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Dri_Hid_Read(
|
||||
Dri_Hid_Struct_ReadPort* p_Port,
|
||||
Mid_Struct_RawPacket* p_Packet,
|
||||
QString* p_TextStatus)
|
||||
{
|
||||
*p_Packet = Mid_Struct_RawPacket();
|
||||
p_Packet->Source = p_Port->PacketSource;
|
||||
p_Packet->PortName = p_Port->PortName;
|
||||
|
||||
if (!p_Port->IsOpened) return false;
|
||||
if (!p_Port->IsReadPending)
|
||||
{
|
||||
Dri_Hid_BeginRead(p_Port, p_TextStatus);
|
||||
return false;
|
||||
}
|
||||
|
||||
DWORD BytesRead = 0;
|
||||
if (!GetOverlappedResult(p_Port->HandleRead, &p_Port->OverlappedRead, &BytesRead, FALSE))
|
||||
{
|
||||
const DWORD ErrorCode = GetLastError();
|
||||
if (ErrorCode == ERROR_IO_INCOMPLETE) return false;
|
||||
if (p_TextStatus != nullptr) *p_TextStatus = QStringLiteral("%1 read packet failed: %2").arg(p_Port->PortName).arg(ErrorCode);
|
||||
Dri_Hid_CloseReadPort(p_Port);
|
||||
return false;
|
||||
}
|
||||
|
||||
p_Port->IsReadPending = false;
|
||||
if (BytesRead > 0) { p_Packet->IsValid = true; p_Packet->ByteArray = p_Port->ReadBuffer.left(static_cast<int>(BytesRead)); }
|
||||
|
||||
Dri_Hid_BeginRead(p_Port, p_TextStatus);
|
||||
return p_Packet->IsValid;
|
||||
}
|
||||
|
||||
HANDLE Dri_Hid_OpenWriteHandle(const QString& DevicePath, QString* p_TextError)
|
||||
{
|
||||
HANDLE HandleWrite = CreateFileW(
|
||||
reinterpret_cast<LPCWSTR>(DevicePath.utf16()),
|
||||
GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
nullptr,
|
||||
OPEN_EXISTING,
|
||||
0,
|
||||
nullptr);
|
||||
if (HandleWrite != INVALID_HANDLE_VALUE) return HandleWrite;
|
||||
|
||||
const DWORD WriteError = GetLastError();
|
||||
HandleWrite = CreateFileW(
|
||||
reinterpret_cast<LPCWSTR>(DevicePath.utf16()),
|
||||
0,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
nullptr,
|
||||
OPEN_EXISTING,
|
||||
0,
|
||||
nullptr);
|
||||
if ((HandleWrite == INVALID_HANDLE_VALUE) && (p_TextError != nullptr)) *p_TextError = QStringLiteral("GENERIC_WRITE=%1, ZeroAccess=%2").arg(WriteError).arg(GetLastError());
|
||||
return HandleWrite;
|
||||
}
|
||||
|
||||
bool Dri_Hid_WritePacket(
|
||||
HANDLE HandleWrite,
|
||||
quint16 OutputLength,
|
||||
const QByteArray& Packet,
|
||||
QString* p_TextError)
|
||||
{
|
||||
if ((HandleWrite == INVALID_HANDLE_VALUE) || Packet.isEmpty()) return false;
|
||||
|
||||
QByteArray Buffer = Packet;
|
||||
if (HidD_SetOutputReport(HandleWrite, Buffer.data(), static_cast<ULONG>(Buffer.size()))) return true;
|
||||
|
||||
const DWORD SetReportError = GetLastError();
|
||||
DWORD BytesWritten = 0;
|
||||
if (WriteFile(HandleWrite, Buffer.constData(), static_cast<DWORD>(Buffer.size()), &BytesWritten, nullptr) && (BytesWritten == static_cast<DWORD>(Buffer.size()))) return true;
|
||||
|
||||
const DWORD WriteFileError = GetLastError();
|
||||
if ((OutputLength > 0) && (Buffer.size() < OutputLength))
|
||||
{
|
||||
Buffer.append(OutputLength - Buffer.size(), 0);
|
||||
|
||||
if (HidD_SetOutputReport(HandleWrite, Buffer.data(), static_cast<ULONG>(Buffer.size()))) return true;
|
||||
|
||||
const DWORD PaddedSetReportError = GetLastError();
|
||||
BytesWritten = 0;
|
||||
if (WriteFile(HandleWrite, Buffer.constData(), static_cast<DWORD>(Buffer.size()), &BytesWritten, nullptr) && (BytesWritten == static_cast<DWORD>(Buffer.size()))) return true;
|
||||
|
||||
const DWORD PaddedWriteFileError = GetLastError();
|
||||
if (p_TextError != nullptr)
|
||||
{
|
||||
*p_TextError = QStringLiteral(
|
||||
"SetOutputReport=%1, WriteFile=%2, PaddedSetOutputReport=%3, PaddedWriteFile=%4")
|
||||
.arg(SetReportError)
|
||||
.arg(WriteFileError)
|
||||
.arg(PaddedSetReportError)
|
||||
.arg(PaddedWriteFileError);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (p_TextError != nullptr) *p_TextError = QStringLiteral("SetOutputReport=%1, WriteFile=%2").arg(SetReportError).arg(WriteFileError);
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user