mirror of https://github.com/AxioDL/boo.git
HID parser for udev; Vulkan fixes
This commit is contained in:
parent
1f14cc09a1
commit
175893f055
|
@ -192,10 +192,11 @@ private:
|
||||||
std::pair<uint32_t, uint32_t> m_outputReports = {};
|
std::pair<uint32_t, uint32_t> m_outputReports = {};
|
||||||
std::pair<uint32_t, uint32_t> m_featureReports = {};
|
std::pair<uint32_t, uint32_t> m_featureReports = {};
|
||||||
bool m_multipleReports = false;
|
bool m_multipleReports = false;
|
||||||
ParserStatus ParseItem(HIDReports& reportsOut,
|
static ParserStatus ParseItem(HIDReports& reportsOut,
|
||||||
std::stack<HIDItemState>& stateStack,
|
std::stack<HIDItemState>& stateStack,
|
||||||
std::stack<HIDCollectionItem>& collectionStack,
|
std::stack<HIDCollectionItem>& collectionStack,
|
||||||
const uint8_t*& it, const uint8_t* end);
|
const uint8_t*& it, const uint8_t* end,
|
||||||
|
bool& multipleReports);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -203,6 +204,8 @@ public:
|
||||||
ParserStatus Parse(const PHIDP_PREPARSED_DATA descriptorData);
|
ParserStatus Parse(const PHIDP_PREPARSED_DATA descriptorData);
|
||||||
#else
|
#else
|
||||||
ParserStatus Parse(const uint8_t* descriptorData, size_t len);
|
ParserStatus Parse(const uint8_t* descriptorData, size_t len);
|
||||||
|
static size_t CalculateMaxInputReportSize(const uint8_t* descriptorData, size_t len);
|
||||||
|
static std::pair<HIDUsagePage, HIDUsage> GetApplicationUsage(const uint8_t* descriptorData, size_t len);
|
||||||
#endif
|
#endif
|
||||||
operator bool() const { return m_status == ParserStatus::Done; }
|
operator bool() const { return m_status == ParserStatus::Done; }
|
||||||
void EnumerateValues(const std::function<bool(const HIDMainItem& item)>& valueCB) const;
|
void EnumerateValues(const std::function<bool(const HIDMainItem& item)>& valueCB) const;
|
||||||
|
|
|
@ -89,7 +89,7 @@ dbgFunc(VkDebugReportFlagsEXT msgFlags, VkDebugReportObjectTypeEXT objType,
|
||||||
const char *pLayerPrefix, const char *pMsg, void *pUserData)
|
const char *pLayerPrefix, const char *pMsg, void *pUserData)
|
||||||
{
|
{
|
||||||
if (msgFlags & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
|
if (msgFlags & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
|
||||||
Log.report(logvisor::Fatal, "[%s] Code %d : %s", pLayerPrefix, msgCode, pMsg);
|
Log.report(logvisor::Error, "[%s] Code %d : %s", pLayerPrefix, msgCode, pMsg);
|
||||||
} else if (msgFlags & VK_DEBUG_REPORT_WARNING_BIT_EXT) {
|
} else if (msgFlags & VK_DEBUG_REPORT_WARNING_BIT_EXT) {
|
||||||
Log.report(logvisor::Warning, "[%s] Code %d : %s", pLayerPrefix, msgCode, pMsg);
|
Log.report(logvisor::Warning, "[%s] Code %d : %s", pLayerPrefix, msgCode, pMsg);
|
||||||
} else if (msgFlags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) {
|
} else if (msgFlags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) {
|
||||||
|
@ -339,7 +339,6 @@ void VulkanContext::initVulkan(const char* appName)
|
||||||
m_layerNames.push_back("VK_LAYER_LUNARG_core_validation");
|
m_layerNames.push_back("VK_LAYER_LUNARG_core_validation");
|
||||||
m_layerNames.push_back("VK_LAYER_LUNARG_object_tracker");
|
m_layerNames.push_back("VK_LAYER_LUNARG_object_tracker");
|
||||||
m_layerNames.push_back("VK_LAYER_LUNARG_parameter_validation");
|
m_layerNames.push_back("VK_LAYER_LUNARG_parameter_validation");
|
||||||
m_layerNames.push_back("VK_LAYER_LUNARG_swapchain");
|
|
||||||
m_layerNames.push_back("VK_LAYER_GOOGLE_threading");
|
m_layerNames.push_back("VK_LAYER_GOOGLE_threading");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include "boo/inputdev/HIDParser.hpp"
|
||||||
|
|
||||||
namespace boo
|
namespace boo
|
||||||
{
|
{
|
||||||
|
@ -29,7 +30,7 @@ udev* GetUdev();
|
||||||
class HIDDeviceUdev final : public IHIDDevice
|
class HIDDeviceUdev final : public IHIDDevice
|
||||||
{
|
{
|
||||||
DeviceToken& m_token;
|
DeviceToken& m_token;
|
||||||
DeviceBase& m_devImp;
|
std::shared_ptr<DeviceBase> m_devImp;
|
||||||
|
|
||||||
int m_devFd = 0;
|
int m_devFd = 0;
|
||||||
unsigned m_usbIntfInPipe = 0;
|
unsigned m_usbIntfInPipe = 0;
|
||||||
|
@ -76,7 +77,7 @@ class HIDDeviceUdev final : public IHIDDevice
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _threadProcUSBLL(HIDDeviceUdev* device)
|
static void _threadProcUSBLL(std::shared_ptr<HIDDeviceUdev> device)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
char errStr[256];
|
char errStr[256];
|
||||||
|
@ -90,7 +91,7 @@ class HIDDeviceUdev final : public IHIDDevice
|
||||||
{
|
{
|
||||||
snprintf(errStr, 256, "Unable to open %s@%s: %s\n",
|
snprintf(errStr, 256, "Unable to open %s@%s: %s\n",
|
||||||
device->m_token.getProductName().c_str(), dp, strerror(errno));
|
device->m_token.getProductName().c_str(), dp, strerror(errno));
|
||||||
device->m_devImp.deviceError(errStr);
|
device->m_devImp->deviceError(errStr);
|
||||||
lk.unlock();
|
lk.unlock();
|
||||||
device->m_initCond.notify_one();
|
device->m_initCond.notify_one();
|
||||||
udev_device_unref(udevDev);
|
udev_device_unref(udevDev);
|
||||||
|
@ -140,10 +141,10 @@ class HIDDeviceUdev final : public IHIDDevice
|
||||||
device->m_initCond.notify_one();
|
device->m_initCond.notify_one();
|
||||||
|
|
||||||
/* Start transfer loop */
|
/* Start transfer loop */
|
||||||
device->m_devImp.initialCycle();
|
device->m_devImp->initialCycle();
|
||||||
while (device->m_runningTransferLoop)
|
while (device->m_runningTransferLoop)
|
||||||
device->m_devImp.transferCycle();
|
device->m_devImp->transferCycle();
|
||||||
device->m_devImp.finalCycle();
|
device->m_devImp->finalCycle();
|
||||||
|
|
||||||
/* Cleanup */
|
/* Cleanup */
|
||||||
close(fd);
|
close(fd);
|
||||||
|
@ -151,7 +152,7 @@ class HIDDeviceUdev final : public IHIDDevice
|
||||||
udev_device_unref(udevDev);
|
udev_device_unref(udevDev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _threadProcBTLL(HIDDeviceUdev* device)
|
static void _threadProcBTLL(std::shared_ptr<HIDDeviceUdev> device)
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lk(device->m_initMutex);
|
std::unique_lock<std::mutex> lk(device->m_initMutex);
|
||||||
udev_device* udevDev = udev_device_new_from_syspath(GetUdev(), device->m_devPath.c_str());
|
udev_device* udevDev = udev_device_new_from_syspath(GetUdev(), device->m_devPath.c_str());
|
||||||
|
@ -162,15 +163,17 @@ class HIDDeviceUdev final : public IHIDDevice
|
||||||
device->m_initCond.notify_one();
|
device->m_initCond.notify_one();
|
||||||
|
|
||||||
/* Start transfer loop */
|
/* Start transfer loop */
|
||||||
device->m_devImp.initialCycle();
|
device->m_devImp->initialCycle();
|
||||||
while (device->m_runningTransferLoop)
|
while (device->m_runningTransferLoop)
|
||||||
device->m_devImp.transferCycle();
|
device->m_devImp->transferCycle();
|
||||||
device->m_devImp.finalCycle();
|
device->m_devImp->finalCycle();
|
||||||
|
|
||||||
udev_device_unref(udevDev);
|
udev_device_unref(udevDev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _threadProcHID(HIDDeviceUdev* device)
|
int m_reportDescSz;
|
||||||
|
|
||||||
|
static void _threadProcHID(std::shared_ptr<HIDDeviceUdev> device)
|
||||||
{
|
{
|
||||||
char errStr[256];
|
char errStr[256];
|
||||||
std::unique_lock<std::mutex> lk(device->m_initMutex);
|
std::unique_lock<std::mutex> lk(device->m_initMutex);
|
||||||
|
@ -183,7 +186,7 @@ class HIDDeviceUdev final : public IHIDDevice
|
||||||
{
|
{
|
||||||
snprintf(errStr, 256, "Unable to open %s@%s: %s\n",
|
snprintf(errStr, 256, "Unable to open %s@%s: %s\n",
|
||||||
device->m_token.getProductName().c_str(), dp, strerror(errno));
|
device->m_token.getProductName().c_str(), dp, strerror(errno));
|
||||||
device->m_devImp.deviceError(errStr);
|
device->m_devImp->deviceError(errStr);
|
||||||
lk.unlock();
|
lk.unlock();
|
||||||
device->m_initCond.notify_one();
|
device->m_initCond.notify_one();
|
||||||
udev_device_unref(udevDev);
|
udev_device_unref(udevDev);
|
||||||
|
@ -196,12 +199,33 @@ class HIDDeviceUdev final : public IHIDDevice
|
||||||
lk.unlock();
|
lk.unlock();
|
||||||
device->m_initCond.notify_one();
|
device->m_initCond.notify_one();
|
||||||
|
|
||||||
/* Report input size */
|
/* Report descriptor size */
|
||||||
size_t readSz = device->m_devImp.getInputBufferSize();
|
int reportDescSize;
|
||||||
|
if (ioctl(fd, HIDIOCGRDESCSIZE, &reportDescSize) == -1)
|
||||||
|
{
|
||||||
|
snprintf(errStr, 256, "Unable to ioctl(HIDIOCGRDESCSIZE) %s@%s: %s\n",
|
||||||
|
device->m_token.getProductName().c_str(), dp, strerror(errno));
|
||||||
|
device->m_devImp->deviceError(errStr);
|
||||||
|
close(fd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get report descriptor */
|
||||||
|
hidraw_report_descriptor reportDesc;
|
||||||
|
reportDesc.size = reportDescSize;
|
||||||
|
if (ioctl(fd, HIDIOCGRDESC, &reportDesc) == -1)
|
||||||
|
{
|
||||||
|
snprintf(errStr, 256, "Unable to ioctl(HIDIOCGRDESC) %s@%s: %s\n",
|
||||||
|
device->m_token.getProductName().c_str(), dp, strerror(errno));
|
||||||
|
device->m_devImp->deviceError(errStr);
|
||||||
|
close(fd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
size_t readSz = HIDParser::CalculateMaxInputReportSize(reportDesc.value, reportDesc.size);
|
||||||
std::unique_ptr<uint8_t[]> readBuf(new uint8_t[readSz]);
|
std::unique_ptr<uint8_t[]> readBuf(new uint8_t[readSz]);
|
||||||
|
|
||||||
/* Start transfer loop */
|
/* Start transfer loop */
|
||||||
device->m_devImp.initialCycle();
|
device->m_devImp->initialCycle();
|
||||||
while (device->m_runningTransferLoop)
|
while (device->m_runningTransferLoop)
|
||||||
{
|
{
|
||||||
fd_set readset;
|
fd_set readset;
|
||||||
|
@ -215,13 +239,13 @@ class HIDDeviceUdev final : public IHIDDevice
|
||||||
ssize_t sz = read(fd, readBuf.get(), readSz);
|
ssize_t sz = read(fd, readBuf.get(), readSz);
|
||||||
if (sz < 0)
|
if (sz < 0)
|
||||||
break;
|
break;
|
||||||
device->m_devImp.receivedHIDReport(readBuf.get(), sz,
|
device->m_devImp->receivedHIDReport(readBuf.get(), sz,
|
||||||
HIDReportType::Input, readBuf[0]);
|
HIDReportType::Input, readBuf[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
device->m_devImp.transferCycle();
|
device->m_devImp->transferCycle();
|
||||||
}
|
}
|
||||||
device->m_devImp.finalCycle();
|
device->m_devImp->finalCycle();
|
||||||
|
|
||||||
/* Cleanup */
|
/* Cleanup */
|
||||||
close(fd);
|
close(fd);
|
||||||
|
@ -234,6 +258,23 @@ class HIDDeviceUdev final : public IHIDDevice
|
||||||
m_runningTransferLoop = false;
|
m_runningTransferLoop = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<uint8_t> _getReportDescriptor()
|
||||||
|
{
|
||||||
|
/* Report descriptor size */
|
||||||
|
int reportDescSize;
|
||||||
|
if (ioctl(m_devFd, HIDIOCGRDESCSIZE, &reportDescSize) == -1)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
/* Get report descriptor */
|
||||||
|
hidraw_report_descriptor reportDesc;
|
||||||
|
reportDesc.size = reportDescSize;
|
||||||
|
if (ioctl(m_devFd, HIDIOCGRDESC, &reportDesc) == -1)
|
||||||
|
return {};
|
||||||
|
std::vector<uint8_t> ret(reportDesc.size, '\0');
|
||||||
|
memmove(ret.data(), reportDesc.value, reportDesc.size);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
bool _sendHIDReport(const uint8_t* data, size_t length, HIDReportType tp, uint32_t message)
|
bool _sendHIDReport(const uint8_t* data, size_t length, HIDReportType tp, uint32_t message)
|
||||||
{
|
{
|
||||||
if (m_devFd)
|
if (m_devFd)
|
||||||
|
@ -274,7 +315,7 @@ class HIDDeviceUdev final : public IHIDDevice
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
HIDDeviceUdev(DeviceToken& token, DeviceBase& devImp)
|
HIDDeviceUdev(DeviceToken& token, const std::shared_ptr<DeviceBase>& devImp)
|
||||||
: m_token(token),
|
: m_token(token),
|
||||||
m_devImp(devImp),
|
m_devImp(devImp),
|
||||||
m_devPath(token.getDevicePath())
|
m_devPath(token.getDevicePath())
|
||||||
|
@ -286,11 +327,11 @@ public:
|
||||||
std::unique_lock<std::mutex> lk(m_initMutex);
|
std::unique_lock<std::mutex> lk(m_initMutex);
|
||||||
DeviceType dType = m_token.getDeviceType();
|
DeviceType dType = m_token.getDeviceType();
|
||||||
if (dType == DeviceType::USB)
|
if (dType == DeviceType::USB)
|
||||||
m_thread = std::thread(_threadProcUSBLL, this);
|
m_thread = std::thread(_threadProcUSBLL, std::static_pointer_cast<HIDDeviceUdev>(shared_from_this()));
|
||||||
else if (dType == DeviceType::Bluetooth)
|
else if (dType == DeviceType::Bluetooth)
|
||||||
m_thread = std::thread(_threadProcBTLL, this);
|
m_thread = std::thread(_threadProcBTLL, std::static_pointer_cast<HIDDeviceUdev>(shared_from_this()));
|
||||||
else if (dType == DeviceType::HID)
|
else if (dType == DeviceType::HID)
|
||||||
m_thread = std::thread(_threadProcHID, this);
|
m_thread = std::thread(_threadProcHID, std::static_pointer_cast<HIDDeviceUdev>(shared_from_this()));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fprintf(stderr, "invalid token supplied to device constructor");
|
fprintf(stderr, "invalid token supplied to device constructor");
|
||||||
|
@ -303,7 +344,7 @@ public:
|
||||||
{
|
{
|
||||||
m_runningTransferLoop = false;
|
m_runningTransferLoop = false;
|
||||||
if (m_thread.joinable())
|
if (m_thread.joinable())
|
||||||
m_thread.join();
|
m_thread.detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -115,12 +115,8 @@ class HIDListenerIOKit : public IHIDListener
|
||||||
getUSBStringDescriptor(dev, pstridx, pstr);
|
getUSBStringDescriptor(dev, pstridx, pstr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!listener->m_finder._insertToken(std::make_unique<DeviceToken>(DeviceType::USB,
|
listener->m_finder._insertToken(std::make_unique<DeviceToken>(DeviceType::USB,
|
||||||
vid, pid, vstr, pstr, devPath)))
|
vid, pid, vstr, pstr, devPath));
|
||||||
{
|
|
||||||
/* Matched-insertion failed; see if generic HID interface is available */
|
|
||||||
/* TODO: Do */
|
|
||||||
}
|
|
||||||
|
|
||||||
//printf("ADDED %08X %s\n", obj, devPath);
|
//printf("ADDED %08X %s\n", obj, devPath);
|
||||||
}
|
}
|
||||||
|
@ -195,7 +191,7 @@ class HIDListenerIOKit : public IHIDListener
|
||||||
if (usageV != kHIDUsage_GD_Joystick && usageV != kHIDUsage_GD_GamePad)
|
if (usageV != kHIDUsage_GD_Joystick && usageV != kHIDUsage_GD_GamePad)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (usagePageV != kHIDPage_Game)
|
else
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -216,12 +212,8 @@ class HIDListenerIOKit : public IHIDListener
|
||||||
CFStringGetCString(pstridx.get(), pstr, 128, kCFStringEncodingUTF8);
|
CFStringGetCString(pstridx.get(), pstr, 128, kCFStringEncodingUTF8);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!listener->m_finder._insertToken(std::make_unique<DeviceToken>(DeviceType::HID,
|
listener->m_finder._insertToken(std::make_unique<DeviceToken>(DeviceType::HID,
|
||||||
vidv, pidv, vstr, pstr, devPath)))
|
vidv, pidv, vstr, pstr, devPath));
|
||||||
{
|
|
||||||
/* Matched-insertion failed; see if generic HID interface is available */
|
|
||||||
/* TODO: Do */
|
|
||||||
}
|
|
||||||
|
|
||||||
//printf("ADDED %08X %s\n", obj, devPath);
|
//printf("ADDED %08X %s\n", obj, devPath);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,14 @@
|
||||||
#include "boo/inputdev/IHIDListener.hpp"
|
#include "boo/inputdev/IHIDListener.hpp"
|
||||||
#include "boo/inputdev/DeviceFinder.hpp"
|
#include "boo/inputdev/DeviceFinder.hpp"
|
||||||
|
#include "boo/inputdev/HIDParser.hpp"
|
||||||
#include <libudev.h>
|
#include <libudev.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <linux/hidraw.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
namespace boo
|
namespace boo
|
||||||
|
@ -91,6 +96,38 @@ class HIDListenerUdev final : public IHIDListener
|
||||||
product = udev_list_entry_get_value(hidnamee);
|
product = udev_list_entry_get_value(hidnamee);
|
||||||
manuf = product;
|
manuf = product;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Get device file */
|
||||||
|
const char* dp = udev_device_get_devnode(device);
|
||||||
|
int fd = open(dp, O_RDWR);
|
||||||
|
if (fd < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Report descriptor size */
|
||||||
|
int reportDescSize;
|
||||||
|
if (ioctl(fd, HIDIOCGRDESCSIZE, &reportDescSize) == -1)
|
||||||
|
{
|
||||||
|
const char* err = strerror(errno);
|
||||||
|
close(fd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get report descriptor */
|
||||||
|
hidraw_report_descriptor reportDesc;
|
||||||
|
reportDesc.size = reportDescSize;
|
||||||
|
if (ioctl(fd, HIDIOCGRDESC, &reportDesc) == -1)
|
||||||
|
{
|
||||||
|
const char* err = strerror(errno);
|
||||||
|
close(fd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
std::pair<HIDUsagePage, HIDUsage> usage =
|
||||||
|
HIDParser::GetApplicationUsage(reportDesc.value, reportDesc.size);
|
||||||
|
if (usage.first != HIDUsagePage::GenericDesktop ||
|
||||||
|
(usage.second != HIDUsage::Joystick && usage.second != HIDUsage::GamePad))
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -171,6 +208,7 @@ public:
|
||||||
}
|
}
|
||||||
udev_monitor_filter_add_match_subsystem_devtype(m_udevMon, "usb", "usb_device");
|
udev_monitor_filter_add_match_subsystem_devtype(m_udevMon, "usb", "usb_device");
|
||||||
udev_monitor_filter_add_match_subsystem_devtype(m_udevMon, "bluetooth", "bluetooth_device");
|
udev_monitor_filter_add_match_subsystem_devtype(m_udevMon, "bluetooth", "bluetooth_device");
|
||||||
|
udev_monitor_filter_add_match_subsystem_devtype(m_udevMon, "hidraw", nullptr);
|
||||||
udev_monitor_filter_update(m_udevMon);
|
udev_monitor_filter_update(m_udevMon);
|
||||||
|
|
||||||
/* Initial HID Device Add */
|
/* Initial HID Device Add */
|
||||||
|
|
|
@ -481,7 +481,8 @@ HIDParser::ParserStatus
|
||||||
HIDParser::ParseItem(HIDReports& reportsOut,
|
HIDParser::ParseItem(HIDReports& reportsOut,
|
||||||
std::stack<HIDItemState>& stateStack,
|
std::stack<HIDItemState>& stateStack,
|
||||||
std::stack<HIDCollectionItem>& collectionStack,
|
std::stack<HIDCollectionItem>& collectionStack,
|
||||||
const uint8_t*& it, const uint8_t* end)
|
const uint8_t*& it, const uint8_t* end,
|
||||||
|
bool& multipleReports)
|
||||||
{
|
{
|
||||||
ParserStatus status = ParserStatus::OK;
|
ParserStatus status = ParserStatus::OK;
|
||||||
uint8_t head = *it++;
|
uint8_t head = *it++;
|
||||||
|
@ -560,7 +561,7 @@ HIDParser::ParseItem(HIDReports& reportsOut,
|
||||||
stateStack.top().m_reportSize = data;
|
stateStack.top().m_reportSize = data;
|
||||||
break;
|
break;
|
||||||
case HIDItemTag::ReportID:
|
case HIDItemTag::ReportID:
|
||||||
m_multipleReports = true;
|
multipleReports = true;
|
||||||
stateStack.top().m_reportID = data;
|
stateStack.top().m_reportID = data;
|
||||||
break;
|
break;
|
||||||
case HIDItemTag::ReportCount:
|
case HIDItemTag::ReportCount:
|
||||||
|
@ -620,7 +621,8 @@ HIDParser::ParserStatus HIDParser::Parse(const uint8_t* descriptorData, size_t l
|
||||||
|
|
||||||
const uint8_t* end = descriptorData + len;
|
const uint8_t* end = descriptorData + len;
|
||||||
for (const uint8_t* it = descriptorData; it != end;)
|
for (const uint8_t* it = descriptorData; it != end;)
|
||||||
if ((m_status = ParseItem(reports, stateStack, collectionStack, it, end)) != ParserStatus::OK)
|
if ((m_status =
|
||||||
|
ParseItem(reports, stateStack, collectionStack, it, end, m_multipleReports)) != ParserStatus::OK)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (m_status != ParserStatus::Done)
|
if (m_status != ParserStatus::Done)
|
||||||
|
@ -660,6 +662,60 @@ HIDParser::ParserStatus HIDParser::Parse(const uint8_t* descriptorData, size_t l
|
||||||
|
|
||||||
return m_status;
|
return m_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t HIDParser::CalculateMaxInputReportSize(const uint8_t* descriptorData, size_t len)
|
||||||
|
{
|
||||||
|
std::stack<HIDItemState> stateStack;
|
||||||
|
stateStack.emplace();
|
||||||
|
std::stack<HIDCollectionItem> collectionStack;
|
||||||
|
HIDReports reports;
|
||||||
|
ParserStatus status = ParserStatus::Done;
|
||||||
|
|
||||||
|
bool multipleReports = false;
|
||||||
|
const uint8_t* end = descriptorData + len;
|
||||||
|
for (const uint8_t* it = descriptorData; it != end;)
|
||||||
|
if ((status = ParseItem(reports, stateStack, collectionStack, it, end, multipleReports)) != ParserStatus::OK)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (status != ParserStatus::Done)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
size_t maxSize = 0;
|
||||||
|
for (const auto& rep : reports.m_inputReports)
|
||||||
|
{
|
||||||
|
size_t repSize = 0;
|
||||||
|
for (const auto& item : rep.second)
|
||||||
|
repSize += item.m_reportSize;
|
||||||
|
if (repSize > maxSize)
|
||||||
|
maxSize = repSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (maxSize + 7) / 8 + multipleReports;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<HIDUsagePage, HIDUsage> HIDParser::GetApplicationUsage(const uint8_t* descriptorData, size_t len)
|
||||||
|
{
|
||||||
|
std::stack<HIDItemState> stateStack;
|
||||||
|
stateStack.emplace();
|
||||||
|
std::stack<HIDCollectionItem> collectionStack;
|
||||||
|
HIDReports reports;
|
||||||
|
ParserStatus status = ParserStatus::Done;
|
||||||
|
|
||||||
|
bool multipleReports = false;
|
||||||
|
const uint8_t* end = descriptorData + len;
|
||||||
|
for (const uint8_t* it = descriptorData; it != end;)
|
||||||
|
{
|
||||||
|
status = ParseItem(reports, stateStack, collectionStack, it, end, multipleReports);
|
||||||
|
if (collectionStack.empty())
|
||||||
|
continue;
|
||||||
|
if (collectionStack.top().m_type == HIDCollectionType::Application)
|
||||||
|
return { collectionStack.top().m_usagePage, collectionStack.top().m_usage };
|
||||||
|
if (status != ParserStatus::OK)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if _WIN32
|
#if _WIN32
|
||||||
|
|
Loading…
Reference in New Issue