Skip to content

Commit

Permalink
Make sure only one report is returned per call to hid_read().
Browse files Browse the repository at this point in the history
  • Loading branch information
signal11 committed Aug 23, 2010
1 parent defb938 commit cc51331
Showing 1 changed file with 56 additions and 4 deletions.
60 changes: 56 additions & 4 deletions windows/hid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,28 +52,49 @@ extern "C" {
USHORT ProductID;
USHORT VersionNumber;
} HIDD_ATTRIBUTES, *PHIDD_ATTRIBUTES;

typedef USHORT USAGE;
typedef struct _HIDP_CAPS {
USAGE Usage;
USAGE UsagePage;
USHORT InputReportByteLength;
USHORT OutputReportByteLength;
USHORT FeatureReportByteLength;
USHORT Reserved[17];
USHORT fields_not_used_by_hidapi[10];
} HIDP_CAPS, *PHIDP_CAPS;
typedef char* HIDP_PREPARSED_DATA;
#define HIDP_STATUS_SUCCESS 0x0

typedef BOOLEAN (__stdcall *HidD_GetAttributes_)(HANDLE device, PHIDD_ATTRIBUTES attrib);
typedef BOOLEAN (__stdcall *HidD_GetSerialNumberString_)(HANDLE device, PVOID buffer, ULONG buffer_len);
typedef BOOLEAN (__stdcall *HidD_GetManufacturerString_)(HANDLE handle, PVOID buffer, ULONG buffer_len);
typedef BOOLEAN (__stdcall *HidD_GetProductString_)(HANDLE handle, PVOID buffer, ULONG buffer_len);
typedef BOOLEAN (__stdcall *HidD_SetFeature_)(HANDLE handle, PVOID data, ULONG length);
typedef BOOLEAN (__stdcall *HidD_GetFeature_)(HANDLE handle, PVOID data, ULONG length);
typedef BOOLEAN (__stdcall *HidD_GetIndexedString_)(HANDLE handle, ULONG string_index, PVOID buffer, ULONG buffer_len);

typedef BOOLEAN (__stdcall *HidD_GetPreparsedData_)(HANDLE handle, HIDP_PREPARSED_DATA **preparsed_data);
typedef BOOLEAN (__stdcall *HidD_FreePreparsedData_)(HIDP_PREPARSED_DATA *preparsed_data);
typedef BOOLEAN (__stdcall *HidP_GetCaps_)(HIDP_PREPARSED_DATA *preparsed_data, HIDP_CAPS *caps);

static HidD_GetAttributes_ HidD_GetAttributes;
static HidD_GetSerialNumberString_ HidD_GetSerialNumberString;
static HidD_GetManufacturerString_ HidD_GetManufacturerString;
static HidD_GetProductString_ HidD_GetProductString;
static HidD_SetFeature_ HidD_SetFeature;
static HidD_GetFeature_ HidD_GetFeature;
static HidD_GetIndexedString_ HidD_GetIndexedString;
static HidD_GetPreparsedData_ HidD_GetPreparsedData;
static HidD_FreePreparsedData_ HidD_FreePreparsedData;
static HidP_GetCaps_ HidP_GetCaps;

static BOOLEAN initialized = FALSE;
#endif // HIDAPI_USE_DDK

struct hid_device_ {
HANDLE device_handle;
BOOL blocking;
int input_report_length;
void *last_error_str;
DWORD last_error_num;
};
Expand All @@ -83,6 +104,7 @@ static hid_device *new_hid_device()
hid_device *dev = (hid_device*) calloc(1, sizeof(hid_device));
dev->device_handle = INVALID_HANDLE_VALUE;
dev->blocking = true;
dev->input_report_length = -1;
dev->last_error_str = NULL;
dev->last_error_num = 0;

Expand Down Expand Up @@ -133,6 +155,9 @@ static void lookup_functions()
RESOLVE(HidD_SetFeature);
RESOLVE(HidD_GetFeature);
RESOLVE(HidD_GetIndexedString);
RESOLVE(HidD_GetPreparsedData);
RESOLVE(HidD_FreePreparsedData);
RESOLVE(HidP_GetCaps);
//FreeLibrary(lib);
#undef RESOLVE
}
Expand Down Expand Up @@ -368,6 +393,10 @@ HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsi
HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path)
{
hid_device *dev;
HIDP_CAPS caps;
HIDP_PREPARSED_DATA *pp_data = NULL;
BOOLEAN res;
NTSTATUS nt_res;

#ifndef HIDAPI_USE_DDK
if (!initialized)
Expand All @@ -389,12 +418,31 @@ HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path)
if (dev->device_handle == INVALID_HANDLE_VALUE) {
// Unable to open the device.
register_error(dev, "CreateFile");
CloseHandle(dev->device_handle);
free(dev);
return NULL;
goto err;
}

// Get the Input Report length for the device.
res = HidD_GetPreparsedData(dev->device_handle, &pp_data);
if (!res) {
register_error(dev, "HidD_GetPreparsedData");
goto err;
}
nt_res = HidP_GetCaps(pp_data, &caps);
if (nt_res != HIDP_STATUS_SUCCESS) {
register_error(dev, "HidP_GetCaps");
goto err_pp_data;
}
dev->input_report_length = caps.InputReportByteLength;
HidD_FreePreparsedData(pp_data);

return dev;

err_pp_data:
HidD_FreePreparsedData(pp_data);
err:
CloseHandle(dev->device_handle);
free(dev);
return NULL;
}

int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char *data, size_t length)
Expand Down Expand Up @@ -447,6 +495,10 @@ int HID_API_EXPORT HID_API_CALL hid_read(hid_device *dev, unsigned char *data, s
ol.Pointer = 0x0;
ol.hEvent = ev;

// Limit the data to be returned. This ensures we get
// only one report returned per call to hid_read().
length = (length < dev->input_report_length)? length: dev->input_report_length;

res = ReadFile(dev->device_handle, data, length, &bytes_read, &ol);


Expand Down

0 comments on commit cc51331

Please sign in to comment.