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_featureReports = {};
|
||||
bool m_multipleReports = false;
|
||||
ParserStatus ParseItem(HIDReports& reportsOut,
|
||||
std::stack<HIDItemState>& stateStack,
|
||||
std::stack<HIDCollectionItem>& collectionStack,
|
||||
const uint8_t*& it, const uint8_t* end);
|
||||
static ParserStatus ParseItem(HIDReports& reportsOut,
|
||||
std::stack<HIDItemState>& stateStack,
|
||||
std::stack<HIDCollectionItem>& collectionStack,
|
||||
const uint8_t*& it, const uint8_t* end,
|
||||
bool& multipleReports);
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
@ -203,6 +204,8 @@ public:
|
|||
ParserStatus Parse(const PHIDP_PREPARSED_DATA descriptorData);
|
||||
#else
|
||||
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
|
||||
operator bool() const { return m_status == ParserStatus::Done; }
|
||||
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)
|
||||
{
|
||||
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) {
|
||||
Log.report(logvisor::Warning, "[%s] Code %d : %s", pLayerPrefix, msgCode, pMsg);
|
||||
} 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_object_tracker");
|
||||
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");
|
||||
#endif
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include "boo/inputdev/HIDParser.hpp"
|
||||
|
||||
namespace boo
|
||||
{
|
||||
|
@ -29,7 +30,7 @@ udev* GetUdev();
|
|||
class HIDDeviceUdev final : public IHIDDevice
|
||||
{
|
||||
DeviceToken& m_token;
|
||||
DeviceBase& m_devImp;
|
||||
std::shared_ptr<DeviceBase> m_devImp;
|
||||
|
||||
int m_devFd = 0;
|
||||
unsigned m_usbIntfInPipe = 0;
|
||||
|
@ -76,7 +77,7 @@ class HIDDeviceUdev final : public IHIDDevice
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void _threadProcUSBLL(HIDDeviceUdev* device)
|
||||
static void _threadProcUSBLL(std::shared_ptr<HIDDeviceUdev> device)
|
||||
{
|
||||
int i;
|
||||
char errStr[256];
|
||||
|
@ -90,7 +91,7 @@ class HIDDeviceUdev final : public IHIDDevice
|
|||
{
|
||||
snprintf(errStr, 256, "Unable to open %s@%s: %s\n",
|
||||
device->m_token.getProductName().c_str(), dp, strerror(errno));
|
||||
device->m_devImp.deviceError(errStr);
|
||||
device->m_devImp->deviceError(errStr);
|
||||
lk.unlock();
|
||||
device->m_initCond.notify_one();
|
||||
udev_device_unref(udevDev);
|
||||
|
@ -140,10 +141,10 @@ class HIDDeviceUdev final : public IHIDDevice
|
|||
device->m_initCond.notify_one();
|
||||
|
||||
/* Start transfer loop */
|
||||
device->m_devImp.initialCycle();
|
||||
device->m_devImp->initialCycle();
|
||||
while (device->m_runningTransferLoop)
|
||||
device->m_devImp.transferCycle();
|
||||
device->m_devImp.finalCycle();
|
||||
device->m_devImp->transferCycle();
|
||||
device->m_devImp->finalCycle();
|
||||
|
||||
/* Cleanup */
|
||||
close(fd);
|
||||
|
@ -151,7 +152,7 @@ class HIDDeviceUdev final : public IHIDDevice
|
|||
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);
|
||||
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();
|
||||
|
||||
/* Start transfer loop */
|
||||
device->m_devImp.initialCycle();
|
||||
device->m_devImp->initialCycle();
|
||||
while (device->m_runningTransferLoop)
|
||||
device->m_devImp.transferCycle();
|
||||
device->m_devImp.finalCycle();
|
||||
device->m_devImp->transferCycle();
|
||||
device->m_devImp->finalCycle();
|
||||
|
||||
udev_device_unref(udevDev);
|
||||
}
|
||||
|
||||
static void _threadProcHID(HIDDeviceUdev* device)
|
||||
int m_reportDescSz;
|
||||
|
||||
static void _threadProcHID(std::shared_ptr<HIDDeviceUdev> device)
|
||||
{
|
||||
char errStr[256];
|
||||
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",
|
||||
device->m_token.getProductName().c_str(), dp, strerror(errno));
|
||||
device->m_devImp.deviceError(errStr);
|
||||
device->m_devImp->deviceError(errStr);
|
||||
lk.unlock();
|
||||
device->m_initCond.notify_one();
|
||||
udev_device_unref(udevDev);
|
||||
|
@ -196,12 +199,33 @@ class HIDDeviceUdev final : public IHIDDevice
|
|||
lk.unlock();
|
||||
device->m_initCond.notify_one();
|
||||
|
||||
/* Report input size */
|
||||
size_t readSz = device->m_devImp.getInputBufferSize();
|
||||
/* Report descriptor size */
|
||||
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]);
|
||||
|
||||
/* Start transfer loop */
|
||||
device->m_devImp.initialCycle();
|
||||
device->m_devImp->initialCycle();
|
||||
while (device->m_runningTransferLoop)
|
||||
{
|
||||
fd_set readset;
|
||||
|
@ -215,13 +239,13 @@ class HIDDeviceUdev final : public IHIDDevice
|
|||
ssize_t sz = read(fd, readBuf.get(), readSz);
|
||||
if (sz < 0)
|
||||
break;
|
||||
device->m_devImp.receivedHIDReport(readBuf.get(), sz,
|
||||
HIDReportType::Input, readBuf[0]);
|
||||
device->m_devImp->receivedHIDReport(readBuf.get(), sz,
|
||||
HIDReportType::Input, readBuf[0]);
|
||||
}
|
||||
}
|
||||
device->m_devImp.transferCycle();
|
||||
device->m_devImp->transferCycle();
|
||||
}
|
||||
device->m_devImp.finalCycle();
|
||||
device->m_devImp->finalCycle();
|
||||
|
||||
/* Cleanup */
|
||||
close(fd);
|
||||
|
@ -234,6 +258,23 @@ class HIDDeviceUdev final : public IHIDDevice
|
|||
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)
|
||||
{
|
||||
if (m_devFd)
|
||||
|
@ -274,7 +315,7 @@ class HIDDeviceUdev final : public IHIDDevice
|
|||
|
||||
public:
|
||||
|
||||
HIDDeviceUdev(DeviceToken& token, DeviceBase& devImp)
|
||||
HIDDeviceUdev(DeviceToken& token, const std::shared_ptr<DeviceBase>& devImp)
|
||||
: m_token(token),
|
||||
m_devImp(devImp),
|
||||
m_devPath(token.getDevicePath())
|
||||
|
@ -286,11 +327,11 @@ public:
|
|||
std::unique_lock<std::mutex> lk(m_initMutex);
|
||||
DeviceType dType = m_token.getDeviceType();
|
||||
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)
|
||||
m_thread = std::thread(_threadProcBTLL, this);
|
||||
m_thread = std::thread(_threadProcBTLL, std::static_pointer_cast<HIDDeviceUdev>(shared_from_this()));
|
||||
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
|
||||
{
|
||||
fprintf(stderr, "invalid token supplied to device constructor");
|
||||
|
@ -303,7 +344,7 @@ public:
|
|||
{
|
||||
m_runningTransferLoop = false;
|
||||
if (m_thread.joinable())
|
||||
m_thread.join();
|
||||
m_thread.detach();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -115,12 +115,8 @@ class HIDListenerIOKit : public IHIDListener
|
|||
getUSBStringDescriptor(dev, pstridx, pstr);
|
||||
}
|
||||
|
||||
if (!listener->m_finder._insertToken(std::make_unique<DeviceToken>(DeviceType::USB,
|
||||
vid, pid, vstr, pstr, devPath)))
|
||||
{
|
||||
/* Matched-insertion failed; see if generic HID interface is available */
|
||||
/* TODO: Do */
|
||||
}
|
||||
listener->m_finder._insertToken(std::make_unique<DeviceToken>(DeviceType::USB,
|
||||
vid, pid, vstr, pstr, 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)
|
||||
continue;
|
||||
}
|
||||
else if (usagePageV != kHIDPage_Game)
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
@ -216,12 +212,8 @@ class HIDListenerIOKit : public IHIDListener
|
|||
CFStringGetCString(pstridx.get(), pstr, 128, kCFStringEncodingUTF8);
|
||||
}
|
||||
|
||||
if (!listener->m_finder._insertToken(std::make_unique<DeviceToken>(DeviceType::HID,
|
||||
vidv, pidv, vstr, pstr, devPath)))
|
||||
{
|
||||
/* Matched-insertion failed; see if generic HID interface is available */
|
||||
/* TODO: Do */
|
||||
}
|
||||
listener->m_finder._insertToken(std::make_unique<DeviceToken>(DeviceType::HID,
|
||||
vidv, pidv, vstr, pstr, devPath));
|
||||
|
||||
//printf("ADDED %08X %s\n", obj, devPath);
|
||||
}
|
||||
|
|
|
@ -1,9 +1,14 @@
|
|||
#include "boo/inputdev/IHIDListener.hpp"
|
||||
#include "boo/inputdev/DeviceFinder.hpp"
|
||||
#include "boo/inputdev/HIDParser.hpp"
|
||||
#include <libudev.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/hidraw.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
#include <thread>
|
||||
|
||||
namespace boo
|
||||
|
@ -91,6 +96,38 @@ class HIDListenerUdev final : public IHIDListener
|
|||
product = udev_list_entry_get_value(hidnamee);
|
||||
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
|
||||
|
@ -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, "bluetooth", "bluetooth_device");
|
||||
udev_monitor_filter_add_match_subsystem_devtype(m_udevMon, "hidraw", nullptr);
|
||||
udev_monitor_filter_update(m_udevMon);
|
||||
|
||||
/* Initial HID Device Add */
|
||||
|
|
|
@ -481,7 +481,8 @@ HIDParser::ParserStatus
|
|||
HIDParser::ParseItem(HIDReports& reportsOut,
|
||||
std::stack<HIDItemState>& stateStack,
|
||||
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;
|
||||
uint8_t head = *it++;
|
||||
|
@ -560,7 +561,7 @@ HIDParser::ParseItem(HIDReports& reportsOut,
|
|||
stateStack.top().m_reportSize = data;
|
||||
break;
|
||||
case HIDItemTag::ReportID:
|
||||
m_multipleReports = true;
|
||||
multipleReports = true;
|
||||
stateStack.top().m_reportID = data;
|
||||
break;
|
||||
case HIDItemTag::ReportCount:
|
||||
|
@ -620,7 +621,8 @@ HIDParser::ParserStatus HIDParser::Parse(const uint8_t* descriptorData, size_t l
|
|||
|
||||
const uint8_t* end = descriptorData + len;
|
||||
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;
|
||||
|
||||
if (m_status != ParserStatus::Done)
|
||||
|
@ -660,6 +662,60 @@ HIDParser::ParserStatus HIDParser::Parse(const uint8_t* descriptorData, size_t l
|
|||
|
||||
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
|
||||
|
||||
#if _WIN32
|
||||
|
|
Loading…
Reference in New Issue