Я пытаюсь использовать Windows .Devices.HumanInterfaceDevice UWP API, чтобы открыть HID-устройство (в моем случае - геймпад) и отправить отчет о выходе HID. Но метод HidDevice.FromIdAsync()
не может открыть устройство в режиме FileAccessMode::ReadWrite
в моем классе c консольное приложение Win32:
Вот минимальный C ++ / WinRT Пример воспроизведения:
#include "pch.h"
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Foundation.Collections.h>
#include <winrt/Windows.Devices.Enumeration.h>
#include <winrt/Windows.Devices.HumanInterfaceDevice.h>
#include <winrt/Windows.Storage.h>
#include <string>
#include <iostream>
#include <functional>
using namespace std;
using namespace winrt;
using namespace Windows::Devices::Enumeration;
using namespace Windows::Devices::HumanInterfaceDevice;
using namespace Windows::Storage;
void OnDeviceAdded(const winrt::Windows::Devices::Enumeration::DeviceInformation& deviceInformation)
{
std::cout << "*****Device Init End*******" << std::endl;
try {
string id = to_string(deviceInformation.Id());
string name = to_string(deviceInformation.Name());
std::cout << "New HID device connected:" << std::endl;
std::cout << "Id: " << id << std::endl;
std::cout << "Name: " << name << std::endl;
HidDevice m_Device = HidDevice::FromIdAsync(deviceInformation.Id(), FileAccessMode::ReadWrite).get();
if (!m_Device)
{
std::cout << "Cannot open device for writing! Trying read-only..." << std::endl;
m_Device = HidDevice::FromIdAsync(deviceInformation.Id(), FileAccessMode::Read).get();
}
if (!m_Device)
{
std::cout << "Cannot open device for reading!" << std::endl;
throw;
}
uint16_t vendorId = m_Device.VendorId();
uint16_t productId = m_Device.ProductId();
uint16_t version = m_Device.Version();
uint16_t usagePage = m_Device.UsagePage();
uint16_t usageId = m_Device.UsageId();
std::cout << "VendorId: " << vendorId << std::endl;
std::cout << "ProductId: " << productId << std::endl;
std::cout << "Version: " << version << std::endl;
std::cout << "UsagePage: " << usagePage << std::endl;
std::cout << "UsageId: " << usageId << std::endl;
}
catch (...)
{
std::cout << "Something went wrong while device init! :(" << std::endl;
}
std::cout << "*****Device Init End*******" << std::endl;
}
hstring hidDeviceSelector;
DeviceWatcher hidDeviceWatcher = nullptr;
event_token hidAddedToken;
int main()
{
winrt::init_apartment();
hidDeviceSelector = HidDevice::GetDeviceSelector(0x01 /*HID_USAGE_PAGE_GENERIC*/, 0x05 /*HID_USAGE_GENERIC_GAMEPAD*/);
hidDeviceWatcher = DeviceInformation::CreateWatcher(hidDeviceSelector);
hidAddedToken = hidDeviceWatcher.Added(std::bind(&OnDeviceAdded, std::placeholders::_2));
hidDeviceWatcher.Start();
while (true)
{
// wait
}
hidDeviceWatcher.Added(hidAddedToken);
winrt::uninit_apartment();
return 0;
}
Подобные вопросы относительно приложений UWP, в которых упоминается, что должно быть *.appxmanifest
вроде этого:
<Capabilities>
<DeviceCapability Name="humaninterfacedevice">
<!--SuperMutt Device-->
<Device Id="vidpid:045E 0610">
<Function Type="usage:FFAA 0001" />
</Device>
</DeviceCapability>
</Capabilities>
Но, похоже, это необходимо только для приложений UWP.
Стоит упомянуть, что HidDevice Class имеет атрибут DualApiPartition и API должен быть разрешен для вызова из любого настольного приложения.
Это ошибка или я ' м что-то не хватает?
Мой код демонстрационного приложения C ++ / WinRT находится здесь: https://github.com/DJm00n/HidGamepadConsoleApp