PORTS Forum

Ports and Interfaces => USB => Topic started by: sd on January 16, 2019, 09:08:12 pm

Title: SendOutputReportAsync not sending data to ble hid device
Post by: sd on January 16, 2019, 09:08:12 pm
Hi Jan,

I'm here again asking for your help! I'm trying to develop host application on Windows 10 machine for my Bluetooth Low Energy HID Device. I am referring to https://docs.microsoft.com/en-us/uwp/api/windows.devices.humaninterfacedevice.hiddevice. Everything works upto the enumeration part. But SendOutputReportAsync() isnt actually sending data to my ble hid device. [https://docs.microsoft.com/en-us/uwp/api/windows.devices.humaninterfacedevice.hidoutputreport] Please guide me on how do I proceed ahead or some direction on how to write host application from scratch. Am I looking into the wrong place? I can confirm that the firmware works because I tested it with nrfConnect software.
Title: Re: SendOutputReportAsync not sending data to ble hid device
Post by: Jan Axelson on January 17, 2019, 08:18:42 pm
Use whatever debugging tools you have to isolate the problem.

In the host application, use single-stepping, watch variables, error codes, etc. to monitor what is happening.

A protocol analyzer will show if the host is sending Output reports on the bus.

The host may use interrupt or control transfers to send Output reports depending on whether the HID has an interrupt OUT endpoint.


Title: Re: SendOutputReportAsync not sending data to ble hid device
Post by: sd on January 18, 2019, 04:54:31 pm
Sure. Will generic_hid_cs_62 code work with BLE HID device? I can see declarations & definitions nicely explained in the book. Code compiles error-free and also the generated GUI finds the BLE HID device, but how do I make it send/receive reports?
Title: Re: SendOutputReportAsync not sending data to ble hid device
Post by: Jan Axelson on January 19, 2019, 11:13:44 am
On the host side:

If using WriteFile or Filestreams for Output reports, be sure the buffer matches the size of a defined Output report + 1. The first byte should contain the report ID. Use zero if no report IDs defined.

If using ReadFile or Filestreams for Input reports, be sure the buffer is at least as large as the largest defined Input report + 1. The first received byte will contain the report ID, zero if no report IDs defined.

On the device side:

Be sure the IN endpoint is configured to send data on receiving an IN token packet.

Be sure the OUT endpoint is configured to receive data on receiving an OUT token packet.

How to do this varies with the chip architecture.

Title: Re: SendOutputReportAsync not sending data to ble hid device
Post by: sd on January 20, 2019, 05:27:46 pm
Thank you for this important tip!! So I changed report id = 1 in RequestToSendOutputReport() and got the output as shown in attachment. But I do not see this data on my BLE HID device. What do you think could be the problem? Also in the comments for functions used for input report, it is mentioned that it assumes report id =0. So where do I change the report id used for input report?
Title: Re: SendOutputReportAsync not sending data to ble hid device
Post by: Jan Axelson on January 20, 2019, 09:53:42 pm
The report ID is the first byte in the buffer.

Be sure the OUT endpoint is configured to receive data on receiving an OUT token packet.

Title: Re: SendOutputReportAsync not sending data to ble hid device
Post by: sd on January 21, 2019, 01:28:13 pm
Hi Jan,

I'm able to receive data from BLE HID device on Windows machine using nrfConnect & SimpleHIDWrite as shown the attached images. But how different is generic_hid_cs_v62 code? Do you think I can make any changes in this code instead of firmware?
Title: Re: SendOutputReportAsync not sending data to ble hid device
Post by: Jan Axelson on January 21, 2019, 09:42:33 pm
With a hardware-based protocol analyzer, you can view any differences on the bus between the working and nonworking code.

Otherwise, use any debugging tools you have to verify that the complete data is going out on the bus and the device storing the received data.

Title: Re: SendOutputReportAsync not sending data to ble hid device
Post by: sd on January 26, 2019, 05:17:06 pm
I tried debugging and inserting some debug statements but its not really helping. Can you give me a direction to write an API for BLE HID device from scratch?
Title: Re: SendOutputReportAsync not sending data to ble hid device
Post by: Jan Axelson on January 27, 2019, 06:01:58 pm
In addition to my code, my HID page has links to HID host code from other sources:

http://www.janaxelson.com/hidpage.htm
Title: Re: SendOutputReportAsync not sending data to ble hid device
Post by: sd on January 30, 2019, 08:56:03 pm
I have 3rd and 5th editions of your book. I have pasted the code which I'm trying to use with my BLE HID device. The pasted vendor ID & product ID are the original ones, practically its different. The commented part gives errors on Windows 10. The handle to BLE device is not getting fetched.

Code: [Select]
#include <iostream>
#include <windows.h>
#include <hidclass.h>
#include <hidsdi.h>
#include <setupapi.h>
#include <devguid.h>
#include <regstr.h>

#pragma comment(lib,"hid")

int main()
{
GUID HidGuid;
HidD_GetHidGuid(&HidGuid);

HANDLE DeviceInfoSet;
DeviceInfoSet = SetupDiGetClassDevs(&HidGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);

BOOLEAN Result;
SP_DEVICE_INTERFACE_DATA MyDeviceInterfaceData;
MyDeviceInterfaceData.cbSize = sizeof(MyDeviceInterfaceData);
DWORD MemberIndex = 0;
Result = SetupDiEnumDeviceInterfaces(DeviceInfoSet, 0, &HidGuid, MemberIndex, &MyDeviceInterfaceData);

PSP_DEVICE_INTERFACE_DETAIL_DATA DetailData;
ULONG Length;
Result = SetupDiGetDeviceInterfaceDetail(DeviceInfoSet, &MyDeviceInterfaceData, NULL, 0, &Length, NULL);

DetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(Length);
DetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
Result = SetupDiGetDeviceInterfaceDetail(DeviceInfoSet, &MyDeviceInterfaceData, DetailData, Length, &Length, NULL);

SetupDiDestroyDeviceInfoList(DeviceInfoSet);

HANDLE DeviceHandle;
DeviceHandle = CreateFile(DetailData->DevicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, (LPSECURITY_ATTRIBUTES)NULL, OPEN_EXISTING, 0, NULL);

CloseHandle(DeviceHandle);

/*HDEVNOTIFY DeviceNotificationHandle;
DEV_BROADCAST_DEVICEINTERFACE DevBroadcastDeviceInterface;
DevBroadcastDeviceInterface.dbcc_size = sizeof(DevBroadcastDeviceInterface);
DevBroadcastDeviceInterface.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
DevBroadcastDeviceInterface.dbcc_classguid = HidGuid;
DeviceNotificationHandle = RegisterDeviceNotification(m_hWnd, &DevBroadcastDeviceInterface, DEVICE_NOTIFY_WINDOW_HANDLE);

BOOL CUsbhidiocDlg::OnDeviceChange(WPARAM wParam, LPARAM lParam)
{
switch (wParam)
{
case DBT_DEVICEARRIVAL:
// Find out if the device path name matches wParam. If yes, perform any tasks required on device attachment.
return TRUE;
case DBT_DEVICEREMOVECOMPLETE:
// Find out if the device path name matches wParam. If yes, perform any tasks required on device removal.
return TRUE;
default:
return TRUE;
}
}

PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR)lParam;
if (lpdb->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
{
PDEV_BROADCAST_DEVICEINTERFACE lpdbi = (PDEV_BROADCAST_DEVICEINTERFACE)lParam;
CString DeviceNameString;
DeviceNameString = lpdbi->dbcc_name;
if((DeviceNameString.CompareNoCase(DetailData > DevicePath)) == 0)
{
// The names match.
}
else
{
// It’s a different device.
}
}

UnregisterDeviceNotification(DeviceNotificationHandle);*/

HIDD_ATTRIBUTES Attributes;
Attributes.Size = sizeof(Attributes);
Result = HidD_GetAttributes(DeviceHandle, &Attributes);
const unsigned int VendorID = 0x0925;
const unsigned int ProductID = 0x1234;
if (Attributes.VendorID == VendorID)
{
if (Attributes.ProductID == ProductID)
{
std::cout << "The Vendor ID and Product ID match.";
}
else
{
std::cout << "The Product ID doesn't match.";
CloseHandle(DeviceHandle); // Close the handle.
}
}
else
{
std::cout << "The Vendor ID doesn't match.";
CloseHandle(DeviceHandle); // Close the handle.
}
}

I'm also getting an error --->>>> Exception thrown at 0x1F60E78A in api1.exe: 0xC0000008: An invalid handle was specified.
Title: Re: SendOutputReportAsync not sending data to ble hid device
Post by: Jan Axelson on January 31, 2019, 09:50:10 am
It looks like you are closing the handle immediately after requesting it:

Code: [Select]
DeviceHandle = CreateFile(DetailData->DevicePath, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, (LPSECURITY_ATTRIBUTES)NULL, OPEN_EXISTING, 0, NULL);

CloseHandle(DeviceHandle);
Title: Re: SendOutputReportAsync not sending data to ble hid device
Post by: sd on January 31, 2019, 10:13:07 am
I tried commenting that but does not work.

Also if I comment the CloseHandle here, I do not get exception error.

Code: [Select]
std::cout << "The Vendor ID doesn't match.";
CloseHandle(DeviceHandle); // Close the handle.

But I am not able to detect my device by polling against vendorId & productId.
Title: Re: SendOutputReportAsync not sending data to ble hid device
Post by: Jan Axelson on January 31, 2019, 10:53:54 am
Earlier you said you were detecting the device with my example code? So I suggest comparing your code with that.
Title: Re: SendOutputReportAsync not sending data to ble hid device
Post by: sd on January 31, 2019, 07:35:00 pm
Hey Jan,

I could easily understand and play with your Visual C++ code snippets in 3rd edition. But I cannot compile your visual C++ code put up on the website. Also I cannot think of making any changes to the Visual C# code, so I decided to rewrite everything starting from basics, that way I can get a clear understanding and find where the problem actually lies instead of working in loops and hitting a dead end. I made some progress. Here is my simple code -

Code: [Select]
#include <iostream>
#include <windows.h>
#include <hidclass.h>
#include <hidsdi.h>
#include <setupapi.h>
#include <devguid.h>
#include <regstr.h>

#pragma comment(lib,"hid")

int main()
{
GUID HidGuid;
HidD_GetHidGuid(&HidGuid);

//HANDLE DeviceInfoSet;
HDEVINFO DeviceInfoSet;
DeviceInfoSet = SetupDiGetClassDevs(&HidGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);

/**/
if(DeviceInfoSet== INVALID_HANDLE_VALUE)
return NULL;

SP_DEVICE_INTERFACE_DATA MyDeviceInterfaceData;
MyDeviceInterfaceData.cbSize = sizeof(MyDeviceInterfaceData);
SP_DEVINFO_DATA dd;
dd.cbSize = sizeof(SP_DEVINFO_DATA);
HANDLE DeviceHandle=NULL;

for (DWORD MemberIndex = 0; SetupDiEnumDeviceInterfaces(DeviceInfoSet, 0, &HidGuid, MemberIndex, &MyDeviceInterfaceData); MemberIndex++)
{
SP_DEVICE_INTERFACE_DETAIL_DATA DetailData;
DetailData.cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

DWORD Length = 0;
if (!SetupDiGetDeviceInterfaceDetail(DeviceInfoSet, &MyDeviceInterfaceData, NULL, 0, &Length, NULL))
{
int err = GetLastError();
if (err == ERROR_NO_MORE_ITEMS)
break;

PSP_DEVICE_INTERFACE_DETAIL_DATA pInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)GlobalAlloc(GPTR, Length);
pInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

if (!SetupDiGetDeviceInterfaceDetail(DeviceInfoSet, &MyDeviceInterfaceData, pInterfaceDetailData, Length, &Length, &dd))
break;


DeviceHandle = CreateFile(pInterfaceDetailData->DevicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, (LPSECURITY_ATTRIBUTES)NULL, OPEN_EXISTING, 0, NULL);

HIDD_ATTRIBUTES Attributes;
Attributes.Size = sizeof(Attributes);
HidD_GetAttributes(DeviceHandle, &Attributes);
const unsigned int VendorID = 0x1F38;
const unsigned int ProductID = 0x0100;
if (Attributes.VendorID == VendorID)
{
if (Attributes.ProductID == ProductID)
{
std::cout << "The Vendor ID and Product ID match.";
std::cout << "\nDeviceHandle: " << DeviceHandle;
std::cout << "\nVendor ID: " << Attributes.VendorID;
std::cout << "\nProduct ID: " << Attributes.ProductID;
std::cout << "\nVersionNumber: " << Attributes.VersionNumber;
std::cout << "\nSize: " << Attributes.Size;

PHIDP_PREPARSED_DATA PreparsedData;
HidD_GetPreparsedData(DeviceHandle, &PreparsedData);

HIDP_CAPS Capabilities;
HidP_GetCaps(PreparsedData, &Capabilities);
std::cout << "\nUsage: " << Capabilities.Usage;
std::cout << "\nUsagePage: " << Capabilities.UsagePage;
std::cout << "\nInputReportByteLength: " << Capabilities.InputReportByteLength;
std::cout << "\nOutputReportByteLength: " << Capabilities.OutputReportByteLength;
std::cout << "\nNumberLinkCollectionNodes: " << Capabilities.NumberLinkCollectionNodes;
std::cout << "\nNumberInputButtonCaps: " << Capabilities.NumberInputButtonCaps;
std::cout << "\nNumberInputValueCaps: " << Capabilities.NumberInputValueCaps;
std::cout << "\nNumberInputDataIndices: " << Capabilities.NumberInputDataIndices;
std::cout << "\nNumberOutputButtonCaps: " << Capabilities.NumberOutputButtonCaps;
std::cout << "\nNumberOutputValueCaps: " << Capabilities.NumberOutputValueCaps;
std::cout << "\nNumberOutputDataIndices: " << Capabilities.NumberOutputDataIndices;

CHAR InputReportBuffer[3];
DWORD BytesRead;
DWORD Result;
HANDLE hEventObject;
OVERLAPPED HIDOverlapped;
hEventObject = CreateEvent((LPSECURITY_ATTRIBUTES)NULL, FALSE, TRUE, NULL);
HIDOverlapped.hEvent = hEventObject;
HIDOverlapped.Offset = 0;
HIDOverlapped.OffsetHigh = 0;
// Set the first byte in the buffer to the Report ID.
InputReportBuffer[0] = 0;
HANDLE ReadHandle = CreateFile(pInterfaceDetailData->DevicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, (LPSECURITY_ATTRIBUTES)NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); //NULL, NULL);
if (ReadHandle == INVALID_HANDLE_VALUE)
std::cout << "\ncould not open";
else
std::cout << "\nopened";
Result = ReadFile(ReadHandle, InputReportBuffer, Capabilities.InputReportByteLength, &BytesRead, (LPOVERLAPPED)&HIDOverlapped); //NULL);
Result = WaitForSingleObject(hEventObject, 3000);
switch (Result)
{
case WAIT_OBJECT_0:
{
std::cout << "\nBytesRead: " << BytesRead;
std::cout << "\nInputReportBuffer: " << InputReportBuffer;
// Success;
// Use the report data;
break;
}
case WAIT_TIMEOUT:
{
std::cout << "\nBytesRead: " << BytesRead;
std::cout << "\nInputReportBuffer: " << InputReportBuffer;
// Timeout error;
//Cancel the read operation.
CancelIo(ReadHandle);
break;
}
default:
{
std::cout << "\nBytesRead: " << BytesRead;
std::cout << "\nInputReportBuffer: " << InputReportBuffer;
// Undefined error;
//Cancel the read operation.
CancelIo(ReadHandle);
break;
}
}
}
}
GlobalFree(pInterfaceDetailData);
}
}
SetupDiDestroyDeviceInfoList(DeviceInfoSet);
}

I am able to obtain handle to my device but not able to read any data. Upto CreateFile() everything works fine. Also how can I get information about endpoint/s? Is there any HID function for that?

I tried using
1.
Code: [Select]
Result = HidD_GetInputReport(ReadHandle, InputReportBuffer, Capabilities.InputReportByteLength);
if (Result)
std::cout << "\nsuccess";
else
std::cout << "\nfail";

2.
Code: [Select]
Result = ReadFile(ReadHandle, InputReportBuffer, Capabilities.InputReportByteLength, &BytesRead, NULL); //(LPOVERLAPPED)&HIDOverlapped);
if (Result)
{
std::cout << "\nBytesRead: " << BytesRead;
std::cout << "\nInputReportBuffer[1]" << InputReportBuffer[1];
std::cout << "\nInputReportBuffer[2]" << InputReportBuffer[2];
std::cout << "\nInputReportBuffer[3]" << InputReportBuffer[3];
}
else
std::cout << "\nfail1";

Both print out 'fail'. I also tried changing InputReportBuffer[0] to 0 and 1, just in case.
Title: Re: SendOutputReportAsync not sending data to ble hid device
Post by: Jan Axelson on February 01, 2019, 10:20:10 am
HidP_GetCaps returns report information, which is all you should need to read reports:

https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/hidpi/nf-hidpi-hidp_getcaps

HidD_GetInputReport requires device support for a Get Report control transfer.

The ReadFile buffer should be as long as the longest Input report + 1 byte.

The error code for the failure might help isolate the problem.
Title: Re: SendOutputReportAsync not sending data to ble hid device
Post by: sd on February 01, 2019, 02:32:35 pm
Cool Thanks!

I need to use HidD_GetInputReport(). So by device support you mean from the host side or BLE device? I'm pretty sure my BLE device sends Input reports using control transfers. When InputReportBuffer[0] = 0, I received an error code of 87 (which is I guess ERROR_INVALID_PARAMETER). When InputReportBuffer[0] = 1, I received an error code of 122 (which is I guess ERROR_INSUFFICIENT_BUFFER).

If I use ReadFile(), I received an error code of 997 (ERROR_IO_PENDING).

I have pasted my new code & output. What is NumberInputValueCaps? Is it the number of endpoints? How do I use Get Report control transfer? Is there anything I'm missing out in my code? I also tried setting last 2 parameters in CreateFile() to NULL but did not work.

Code: [Select]
#include <iostream>
#include <windows.h>
#include <hidclass.h>
#include <hidsdi.h>
#include <setupapi.h>
#include <devguid.h>
#include <regstr.h>

#pragma comment(lib,"hid")

int main()
{
GUID HidGuid;
HidD_GetHidGuid(&HidGuid);

//HANDLE DeviceInfoSet;
HDEVINFO DeviceInfoSet;
DeviceInfoSet = SetupDiGetClassDevs(&HidGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);

if(DeviceInfoSet== INVALID_HANDLE_VALUE)
return NULL;

SP_DEVICE_INTERFACE_DATA MyDeviceInterfaceData;
MyDeviceInterfaceData.cbSize = sizeof(MyDeviceInterfaceData);
SP_DEVINFO_DATA dd;
dd.cbSize = sizeof(SP_DEVINFO_DATA);
HANDLE DeviceHandle=NULL;

for (DWORD MemberIndex = 0; SetupDiEnumDeviceInterfaces(DeviceInfoSet, 0, &HidGuid, MemberIndex, &MyDeviceInterfaceData); MemberIndex++)
{
SP_DEVICE_INTERFACE_DETAIL_DATA DetailData;
DetailData.cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

DWORD Length = 0;
if (!SetupDiGetDeviceInterfaceDetail(DeviceInfoSet, &MyDeviceInterfaceData, NULL, 0, &Length, NULL))
{
int err = GetLastError();
if (err == ERROR_NO_MORE_ITEMS)
break;

PSP_DEVICE_INTERFACE_DETAIL_DATA pInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)GlobalAlloc(GPTR, Length);
pInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

if (!SetupDiGetDeviceInterfaceDetail(DeviceInfoSet, &MyDeviceInterfaceData, pInterfaceDetailData, Length, &Length, &dd))
break;

DeviceHandle = CreateFile(pInterfaceDetailData->DevicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, (LPSECURITY_ATTRIBUTES)NULL, OPEN_EXISTING, 0, NULL);

HIDD_ATTRIBUTES Attributes;
Attributes.Size = sizeof(Attributes);
HidD_GetAttributes(DeviceHandle, &Attributes);
const unsigned int VendorID = 0x1F38;
const unsigned int ProductID = 0x0100;
if (Attributes.VendorID == VendorID)
{
if (Attributes.ProductID == ProductID)
{
std::cout << "The Vendor ID and Product ID match.";
std::cout << "\nDeviceHandle: " << DeviceHandle;
std::cout << "\nVendor ID: " << Attributes.VendorID;
std::cout << "\nProduct ID: " << Attributes.ProductID;
std::cout << "\nVersionNumber: " << Attributes.VersionNumber;
std::cout << "\nSize: " << Attributes.Size;

PHIDP_PREPARSED_DATA PreparsedData;
HidD_GetPreparsedData(DeviceHandle, &PreparsedData);

HIDP_CAPS Capabilities;
HidP_GetCaps(PreparsedData, &Capabilities);
std::cout << "\nUsage: " << Capabilities.Usage;
std::cout << "\nUsagePage: " << Capabilities.UsagePage;
std::cout << "\nInputReportByteLength: " << Capabilities.InputReportByteLength;
std::cout << "\nOutputReportByteLength: " << Capabilities.OutputReportByteLength;
std::cout << "\nNumberLinkCollectionNodes: " << Capabilities.NumberLinkCollectionNodes;
std::cout << "\nNumberInputButtonCaps: " << Capabilities.NumberInputButtonCaps;
std::cout << "\nNumberInputValueCaps: " << Capabilities.NumberInputValueCaps;
std::cout << "\nNumberInputDataIndices: " << Capabilities.NumberInputDataIndices;
std::cout << "\nNumberOutputButtonCaps: " << Capabilities.NumberOutputButtonCaps;
std::cout << "\nNumberOutputValueCaps: " << Capabilities.NumberOutputValueCaps;
std::cout << "\nNumberOutputDataIndices: " << Capabilities.NumberOutputDataIndices;

CHAR InputReportBuffer[3];
DWORD BytesRead;
DWORD Result;
HANDLE hEventObject;
OVERLAPPED HIDOverlapped;
hEventObject = CreateEvent((LPSECURITY_ATTRIBUTES)NULL, FALSE, TRUE, NULL);
HIDOverlapped.hEvent = hEventObject;
HIDOverlapped.Offset = 0;
HIDOverlapped.OffsetHigh = 0;
InputReportBuffer[0] = 0; // Report Id
HANDLE ReadHandle = CreateFile(pInterfaceDetailData->DevicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, (LPSECURITY_ATTRIBUTES)NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); //NULL, NULL);
if (ReadHandle == INVALID_HANDLE_VALUE)
std::cout << "\ncould not open"; //printf("Warning: CreateFile failed: %d\n", GetLastError());
else
std::cout << "\nopened";

Result = HidD_GetInputReport(ReadHandle, InputReportBuffer, Capabilities.InputReportByteLength);
DWORD err = GetLastError();
std::cout << "\nerr: " << err;
if (Result)
{
std::cout << "\nSuccess";
for (int i = 0; i < Capabilities.InputReportByteLength; i++)
{
std::cout << "\nInput Report Data: " << InputReportBuffer[i];
}
}
else
std::cout << "\nFailed to get report";
}
}
GlobalFree(pInterfaceDetailData);
}
}
SetupDiDestroyDeviceInfoList(DeviceInfoSet);
}
Title: Re: SendOutputReportAsync not sending data to ble hid device
Post by: Jan Axelson on February 02, 2019, 11:57:58 am
HidD_GetInputReport requires device/firmware support for a Get Report control transfer.

ERROR_INVALID_PARAMETER suggests there is something wrong with the parameters your function is passing.

ERROR_INSUFFICIENT_BUFFER says your buffer is too small, must be at least as large as the largest Input report + 1.

ERROR_IO_PENDING suggests the host isn't receiving data.

NumberInputValueCaps defined here:

https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/hidpi/ns-hidpi-_hidp_caps

A HID always has 1 interrupt IN endpoint and may have 1 interrupt OUT endpoint.

HidD_GetInputReport initiates a Get Report control transfer.
Title: Re: SendOutputReportAsync not sending data to ble hid device
Post by: sd on February 02, 2019, 04:54:21 pm
Thanks! As most of the times I end up getting ERROR_INVALID_PARAMETER, so how do I solve it? How do I define the 2nd parameter to be passed in HidD_GetInputReport()? I tried using malloc for InputReportBuffer & also tried using as a pointer, but nothing seems to work according to definition of HidD_GetInputReport().
Title: Re: SendOutputReportAsync not sending data to ble hid device
Post by: Jan Axelson on February 03, 2019, 12:29:54 pm
see

https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/hidsdi/nf-hidsdi-hidd_getinputreport

My code passes a pointer to a byte array.

The final parameter should be the length of that buffer + 1.
Title: Re: SendOutputReportAsync not sending data to ble hid device
Post by: sd on February 03, 2019, 01:08:39 pm
Right so how do I do that in Visual C++? I tried different declarations as below but could not get through. I had also included that +1 factor.

1.
const unsigned char a = 0;
const unsigned char *InputReportBuffer;
InputReportBuffer = &a;
2.
unsigned char InputReportBuffer[20];
memset(InputReportBuffer, 0, 20);
3.
ULONG bufferSize;
bufferSize = sizeof(Capabilities.InputReportByteLength);
PUCHAR InputReportBuffer = (PUCHAR) malloc(bufferSize);
if (!InputReportBuffer)
{
   printf("malloc failed\n");
}
Title: Re: SendOutputReportAsync not sending data to ble hid device
Post by: Jan Axelson on February 03, 2019, 09:42:30 pm
see if this helps

https://github.com/Microsoft/Windows-driver-samples/blob/master/hid/vhidmini2/app/testvhid.c
Title: Re: SendOutputReportAsync not sending data to ble hid device
Post by: sd on February 04, 2019, 03:41:13 pm
Hey Jan, during my google searches I had stumbled upon this code and I played with it but I'm getting the same 87 & 122 errors.

Also WriteFile is successfully sending data to BLE device but I cant see it on the device. Why so?

Will reading raw data help?

Even your code generic_Hid_cs_v62 does not work with BLE HID custom device.
Title: Re: SendOutputReportAsync not sending data to ble hid device
Post by: Jan Axelson on February 06, 2019, 11:01:16 am
If the data is going out on the bus, be sure the HID's interrupt OUT endpoint is configured to accept data. How to do that varies with the chip architecture. Use whatever debugging tools you have to find out what happens when data arrives at the device.

InputReportBuffer[0] should equal the report ID for the desired report or zero if report IDs not used.
Title: Re: SendOutputReportAsync not sending data to ble hid device
Post by: sd on February 07, 2019, 08:06:03 pm
Hey Jan,

Everything works now! I just had one more question to ask, how do I send 20 byte output report? I know that I should assign values in outputReportBuffer but in the UI only a byte is being sent.
Title: Re: SendOutputReportAsync not sending data to ble hid device
Post by: Jan Axelson on February 08, 2019, 09:57:21 am
Perhaps your function call is passing only the first byte of the array, not the full array.
Title: Re: SendOutputReportAsync not sending data to ble hid device
Post by: sd on February 08, 2019, 01:25:21 pm
Sorry my bad. I was using your code - generic_hid_cs_v62. So in that I'm able to read 20 bytes of input report. Please guide me on how to send 20 bytes output report.
Title: Re: SendOutputReportAsync not sending data to ble hid device
Post by: Jan Axelson on February 09, 2019, 07:48:25 pm
The Microsoft example above should work.