2017-01-11 1 views
-2

Ich versuche, mit einem generischen HID-Gerät (nicht Maus oder Tastatur) zu kommunizieren. Nach der Dokumentation von Microsoft und einem Beispielcode, den ich gefunden habe, bin ich an den Punkt gelangt, an dem ich glaube, dass ich mit dem Gerät kommunizieren kann. Leider funktioniert das Schreiben nicht.HID WriteFile schlägt fehl mit ERROR_INVALID_PARAMETER

Der folgende Code kommt an den Punkt, an dem die Dinge scheitern. Ein Reinigungscode fehlt oder ist unvollständig, aber der Code sollte mit der richtigen VID und PID funktionieren. Beachten Sie, dass der fest codierte 1 im Anruf an SetupDiEnumDeviceInterfaces der Index ist, dass mein Gerät auf meinem Computer ist.

#include <Windows.h> 
#include <hidsdi.h> 
#include <SetupAPI.h> 
#include <cstdlib> 
#include <cstdint> 
std::uint16_t constexpr vid = /* My VID */; 
std::uint16_t constexpr pid = /* My PID */; 

int main(int argc, char* argv[]) 
{ 
    GUID hidGuid; 
    HidD_GetHidGuid(&hidGuid); 
    HDEVINFO info = SetupDiGetClassDevsA(&hidGuid, nullptr, nullptr, 
     DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); 
    if (info == INVALID_HANDLE_VALUE) 
     return 1; 
    SP_DEVICE_INTERFACE_DATA data; 
    data.cbSize = sizeof(data); 
    if (!SetupDiEnumDeviceInterfaces(info, nullptr, &hidGuid, 1, &data)) 
     return 1; 
    DWORD requiredSize; 
    if (SetupDiGetDeviceInterfaceDetailA(info, &data, nullptr, 0, 
     &requiredSize, nullptr) || GetLastError() != ERROR_INSUFFICIENT_BUFFER) 
     return 1; 
    SP_DEVICE_INTERFACE_DETAIL_DATA_A* detailData = 
     static_cast<SP_DEVICE_INTERFACE_DETAIL_DATA_A*>(
      std::malloc(requiredSize)); 
    detailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A); 
    if (!SetupDiGetDeviceInterfaceDetailA(info, &data, detailData, 
     requiredSize, nullptr, nullptr)) 
     return 1; 
    SetupDiDestroyDeviceInfoList(info); 
    HANDLE capsHandle = CreateFileA(detailData->DevicePath, 0, 
     FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, 
     OPEN_EXISTING, 0, nullptr); 
    if (capsHandle == INVALID_HANDLE_VALUE) 
     return 1; 
    HIDD_ATTRIBUTES attr; 
    attr.Size = sizeof(attr); 
    if (!HidD_GetAttributes(capsHandle, &attr)) 
     return 1; 
    if (attr.VendorID != vid || attr.ProductID != pid) 
     return 1; 
    PHIDP_PREPARSED_DATA preparsedData; 
    if (!HidD_GetPreparsedData(capsHandle, &preparsedData)) 
     return 1; 
    CloseHandle(capsHandle); 
    HIDP_CAPS caps; 
    if (HidP_GetCaps(preparsedData, &caps) != HIDP_STATUS_SUCCESS) 
     return 1; 
    HidD_FreePreparsedData(preparsedData); 
    std::uint8_t* inputBuffer = 
     static_cast<std::uint8_t*>(std::malloc(caps.InputReportByteLength)); 
    std::uint8_t* outputBuffer = 
     static_cast<std::uint8_t*>(std::malloc(caps.OutputReportByteLength)); 
    HANDLE hidHandle = CreateFileA(detailData->DevicePath, 
     GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 
     nullptr, OPEN_EXISTING, 0, nullptr); 
    if (hidHandle == INVALID_HANDLE_VALUE) 
     return 1; 
    ZeroMemory(outputBuffer, caps.OutputReportByteLength); 
    outputBuffer[0] = 11; 
    outputBuffer[1] = 12; 
    DWORD bytesWritten; 
    if (!WriteFile(hidHandle, outputBuffer, caps.OutputReportByteLength, 
     &bytesWritten, nullptr)) 
    { 
     auto x = GetLastError(); 
     return 1; 
    } 
    return 0; 
} 

Dies läuft wie erwartet bis zum Aufruf an WriteFile. An diesem Punkt, wenn fehlgeschlagen und x ist der Wert 87 (ERROR_INVALID_PARAMETER) zugeordnet. Warum würde das scheitern? Alle Parameter scheinen mir richtig zu sein.

+3

Sie haben eine Menge Code entfernt. Die ganze Fehlerüberprüfung für einen Anfang. Ein MCVE wäre nett. –

+0

Haben Sie alle Werte aller Parameter überprüft oder gehen Sie davon aus? – immibis

+0

Die Ergebnisse aller Funktionen werden überprüft, indem Sie sie im Code testen und Zahlen mit einem Step-Through-Debugger validieren. – Graznarak

Antwort

0

Nach der Kommunikation mit den Menschen, die unser Gerät produzieren, habe ich festgestellt, dass das Problem ist, dass der Ausgabepuffer falsch gefüllt ist. Die zwei Bytes, die nicht Null sind, sollten die Bytes der Indizes 1 und 2 sein, nicht die Bytes der Indizes 0 und 1.