locked
Sending HID Output Reports to HID Keyboard RRS feed

  • Question

  • I've got a custom HID keyboard device that I'd like to send an output report to. I obtain the device path through SetupDiGetClassDevsW and am able to open the device via CreateFile.

    When I try to call HidD_SetOutputReport or WriteFile, GetLastError() returns ERROR_INVALID_FUNCTION (1) and RtlGetLastNtStatus returns STATUS_INVALID_DEVICE_REQUEST (0xC0000010). Should I be able to send output reports to a HID keyboard? Am I doing something wrong? My code is below:

    My send code looks like this:

    uint8_t report_buffer[2];
    report_buffer[0] = OUT_REPORT_ID_COMMAND;
    report_buffer[1] = COMMAND_ENTER_BOOTLOADER;

    if (!HidD_SetOutputReport(handle, report_buffer, sizeof(report_buffer)))
    throw std::exception("Failed to set output report.")

    I open the device like this:

    auto handle = CreateFileW(path.c_str(), GENERIC_WRITE,
    FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr);

    My search code looks like this:

    std::optional<std::wstring> find_usb_hid_device_path(uint16_t vendor_id, uint16_t product_id)
    {
    // Device path we're looking for - \?usb#vid_vvvv&pid_pppp
    const auto search_string = std::wstring(L"vid_") + int_to_wstring(vendor_id) + 
    std::wstring(L"&pid_") + int_to_wstring(product_id);

    // Find system GUID for HID-class devices
    GUID hid_guid;
    HidD_GetHidGuid(&hid_guid);

    // Look for our device
    auto clean_info_set = [](const HDEVINFO info) { SetupDiDestroyDeviceInfoList(info); };
    const auto info_set = std::unique_ptr<void, decltype(clean_info_set)>(
    SetupDiGetClassDevsW(&hid_guid, nullptr, nullptr,
    DIGCF_PRESENT | DIGCF_DEVICEINTERFACE), clean_info_set);

    SP_DEVICE_INTERFACE_DATA interface_data = { 0 };
    interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);

    const auto detail_bytes = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) + MAX_PATH * sizeof(WCHAR);
    auto detail_buffer = std::make_unique<uint8_t[]>(detail_bytes);
    std::fill(detail_buffer.get(), detail_buffer.get() + detail_bytes, 0);
    const auto interface_detail = reinterpret_cast<SP_DEVICE_INTERFACE_DETAIL_DATA*>(detail_buffer.get());
    interface_detail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

    for (DWORD device_index = 0; ; device_index++)
    {
    if (!SetupDiEnumDeviceInterfaces(info_set.get(), nullptr,
    &hid_guid, device_index, &interface_data))
    break;

    if (!SetupDiGetDeviceInterfaceDetail(info_set.get(), &interface_data,
    interface_detail, detail_bytes, nullptr, nullptr))
    throw std::exception("Failed to retrieve interface details.");

    auto device_path = std::wstring_view(interface_detail->DevicePath,
    wcslen(interface_detail->DevicePath));

    std::wcout << interface_detail->DevicePath << std::endl;

    // Check for a match
    if (device_path.find(search_string) != std::wstring::npos)
    {
    return std::make_optional(std::wstring(interface_detail->DevicePath));
    }
    }

    return std::nullopt;

    }

    Tuesday, August 14, 2018 9:24 PM

All replies

  • Hi,

    thanks for posting here.

    >>When I try to call HidD_SetOutputReport or WriteFile, GetLastError() returns ERROR_INVALID_FUNCTION (1) and RtlGetLastNtStatus returns STATUS_INVALID_DEVICE_REQUEST (0xC0000010). Should I be able to send output reports to a HID keyboard? Am I doing something wrong?

    It seems your device doesn't support sending HID reports. Some devices might not support HidD_SetOutputReport and will become unresponsive if this routine is used.

    Best Regards,

    Baron Bi


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Wednesday, August 15, 2018 1:40 AM