Back again with my problem.
Now I’ve my windows handle I try to register my USB with the RegisterDeviceNotification function.
Everything seems to work correctly until I try to write to the device , I have an error like this “Can’t write to device”
Here is my code to initialize my USB
In the startup function I call : FindTheHID();
#pragma region USB_Interface
void DisplayLastError(const char * const openStr,const char * const Operation)
{
LPVOID lpMsgBuf=“”;
FormatMessage
(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0,
NULL
);
DWORD dw = GetLastError();
LPVOID StrError = (LPVOID)LocalAlloc(LMEM_ZEROINIT,(lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)Operation) + 40) * sizeof(TCHAR));
StringCchPrintf((LPTSTR)StrError,LocalSize(StrError) / sizeof(TCHAR),TEXT(“%4d %s %s”),dw,Operation, lpMsgBuf);
if( fo != NULL )
{
fprintf( fo, “%s”, StrError);
fflush(fo);
}
LocalFree(lpMsgBuf);
LocalFree(StrError);
}
//HWND m_hWnd;
ULONG Length;
PSP_DEVICE_INTERFACE_DETAIL_DATA detailData;
HANDLE DeviceHandle;
GUID HidGuid;
HANDLE hDevInfo;
ULONG Required;
bool MyDeviceDetected = FALSE;
std::string MyDevicePathName;
int VendorID = 0xFFFE;
int ProductID = 0x0001;
HIDP_CAPS Capabilities;
HANDLE WriteHandle;
HANDLE ReadHandle;
HANDLE hEventObject;
OVERLAPPED HIDOverlapped;
unsigned char OutputReport[255];
SERVICE_STATUS_HANDLE m_hServiceStatus;
void DoEvents()
{
MSG msg;
BOOL result;
while ( ::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE ) )
{
result = ::GetMessage(&msg, NULL, 0, 0);
if (result == 0) // WM_QUIT
{
::PostQuitMessage(msg.wParam);
break;
}
else if (result == -1)
{
// Handle errors/exit application, etc.
}
else
{
::TranslateMessage(&msg);
:: DispatchMessage(&msg);
}
}
}
void RegisterForDeviceNotifications()
{
char Str[50];
// Request to receive messages when a device is attached or removed.
// Also see WM_DEVICECHANGE in BEGIN_MESSAGE_MAP(CUsbhidiocDlg, CDialog).
// m_hServiceStatus = RegisterServiceCtrlHandlerEx(“Service”, (LPHANDLER_FUNCTION_EX)_Handler,0);
DEV_BROADCAST_DEVICEINTERFACE DevBroadcastDeviceInterface;
HDEVNOTIFY DeviceNotificationHandle;
ZeroMemory(&DevBroadcastDeviceInterface, sizeof(DevBroadcastDeviceInterface));
DevBroadcastDeviceInterface.dbcc_size = sizeof(DevBroadcastDeviceInterface);
sprintf(Str,“\tInterface Size: %d”,DevBroadcastDeviceInterface.dbcc_size);
WriteToDebugFile(“a+”,Str);
DevBroadcastDeviceInterface.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
sprintf(Str,“\tInterface type: %d”,DevBroadcastDeviceInterface.dbcc_devicetype);
WriteToDebugFile(“a+”,Str);
DevBroadcastDeviceInterface.dbcc_reserved = 0;
DevBroadcastDeviceInterface.dbcc_classguid = HidGuid;//GUID_DEVINTERFACE_USB_DEVICE;
sprintf(Str,“\tInterface HIDGUI: %8X-%4X-%4X-%4X”,DevBroadcastDeviceInterface.dbcc_classguid.Data1,DevBroadcastDeviceInterface.dbcc_classguid.Data2,DevBroadcastDeviceInterface.dbcc_classguid.Data3,DevBroadcastDeviceInterface.dbcc_classguid.Data4);
WriteToDebugFile(“a+”,Str);
// Wait until the fake windows is created
while (WindowsHandle == NULL)
{
sprintf(Str,“\tWait: %d”,WindowsHandle);
WriteToDebugFile(“a+”,Str);
DoEvents();
}
sprintf(Str,“\tGot it: %d”,WindowsHandle);
WriteToDebugFile(“a+”,Str);
DeviceNotificationHandle = RegisterDeviceNotification(WindowsHandle, &DevBroadcastDeviceInterface, DEVICE_NOTIFY_WINDOW_HANDLE);//DEVICE_NOTIFY_SERVICE_HANDLE);
sprintf(Str,“\thandle: %d”,DeviceNotificationHandle);
WriteToDebugFile(“a+”,Str);
DisplayLastError( “a”,"RegisterDeviceNotification: ");
//HDEVNOTIFY hDevNotify = RegisterDeviceNotification(hwnd, &NotificationFilter, DEVICE_NOTIFY_SERVICE_HANDLE);
}
void GetDeviceCapabilities()
{
//Get the Capabilities structure for the device.
PHIDP_PREPARSED_DATA PreparsedData;
/*
API function: HidD_GetPreparsedData
Returns: a pointer to a buffer containing the information about the device’s capabilities.
Requires: A handle returned by CreateFile.
There’s no need to access the buffer directly,
but HidP_GetCaps and other API functions require a pointer to the buffer.
*/
HidD_GetPreparsedData(DeviceHandle,&PreparsedData);
DisplayLastError( “a”,"HidD_GetPreparsedData: ");
char Str[50];
/*
API function: HidP_GetCaps
Learn the device’s capabilities.
For standard devices such as joysticks, you can find out the specific
capabilities of the device.
For a custom device, the software will probably know what the device is capable of,
and the call only verifies the information.
Requires: the pointer to the buffer returned by HidD_GetPreparsedData.
Returns: a Capabilities structure containing the information.
*/
HidP_GetCaps(PreparsedData,&Capabilities);
DisplayLastError( “a”,"HidP_GetCaps: ");
//Display the capabilities
sprintf(Str,“\tUsage Page: %X”,Capabilities.UsagePage);
WriteToDebugFile(“a+”,Str);
sprintf(Str,“\tInput Report Byte Length: %d”, Capabilities.InputReportByteLength);
WriteToDebugFile(“a+”,Str);
sprintf(Str,“\tOutput Report Byte Length: %d”, Capabilities.OutputReportByteLength);
WriteToDebugFile(“a+”,Str);
sprintf(Str,“\tFeature Report Byte Length: %d”, Capabilities.FeatureReportByteLength);
WriteToDebugFile(“a+”,Str);
sprintf(Str,“\tNumber of Link Collection Nodes: %d”, Capabilities.NumberLinkCollectionNodes);
WriteToDebugFile(“a+”,Str);
sprintf(Str,“\tNumber of Input Button Caps: %d”, Capabilities.NumberInputButtonCaps);
WriteToDebugFile(“a+”,Str);
sprintf(Str,“\tNumber of InputValue Caps: %d”, Capabilities.NumberInputValueCaps);
WriteToDebugFile(“a+”,Str);
sprintf(Str,“\tNumber of InputData Indices: %d”, Capabilities.NumberInputDataIndices);
WriteToDebugFile(“a+”,Str);
sprintf(Str,“\tNumber of Output Button Caps: %d”, Capabilities.NumberOutputButtonCaps);
WriteToDebugFile(“a+”,Str);
sprintf(Str,“\tNumber of Output Value Caps: %d”, Capabilities.NumberOutputValueCaps);
WriteToDebugFile(“a+”,Str);
sprintf(Str,“\tNumber of Output Data Indices: %d”, Capabilities.NumberOutputDataIndices);
WriteToDebugFile(“a+”,Str);
sprintf(Str,“\tNumber of Feature Button Caps: %d”, Capabilities.NumberFeatureButtonCaps);
WriteToDebugFile(“a+”,Str);
sprintf(Str,“\tNumber of Feature Value Caps: %d”, Capabilities.NumberFeatureValueCaps);
WriteToDebugFile(“a+”,Str);
sprintf(Str,“\tNumber of Feature Data Indices: %d”, Capabilities.NumberFeatureDataIndices);
WriteToDebugFile(“a+”,Str);
//No need for PreparsedData any more, so free the memory it’s using.
HidD_FreePreparsedData(PreparsedData);
DisplayLastError( “a”,"HidD_FreePreparsedData: ") ;
}
void PrepareForOverlappedTransfer()
{
//Get a handle to the device for the overlapped ReadFiles.
ReadHandle=CreateFile
(detailData->DevicePath,
GENERIC_READ,
FILE_SHARE_READ|FILE_SHARE_WRITE,
(LPSECURITY_ATTRIBUTES)NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL);
DisplayLastError( “a”,"CreateFile (ReadHandle): ");
//Get an event object for the overlapped structure.
/*API function: CreateEvent
Requires:
Security attributes or Null
Manual reset (true). Use ResetEvent to set the event object’s state to non-signaled.
Initial state (true = signaled)
Event object name (optional)
Returns: a handle to the event object
*/
if (hEventObject == 0)
{
hEventObject = CreateEvent
(NULL,
TRUE,
TRUE,
“”);
DisplayLastError( “a”,"CreateEvent: ") ;
//Set the members of the overlapped structure.
HIDOverlapped.hEvent = hEventObject;
HIDOverlapped.Offset = 0;
HIDOverlapped.OffsetHigh = 0;
}
}
bool FindTheHID()
{
//Use a series of API calls to find a HID with a specified Vendor IF and Product ID.
HIDD_ATTRIBUTES Attributes;
//DWORD DeviceUsage;
SP_DEVICE_INTERFACE_DATA devInfoData;
bool LastDevice = FALSE;
int MemberIndex = 0;
LONG Result;
std::string UsageDescription;
Length = 0;
detailData = NULL;
DeviceHandle=NULL;
/*
API function: HidD_GetHidGuid
Get the GUID for all system HIDs.
Returns: the GUID in HidGuid.
*/
HidD_GetHidGuid(&HidGuid);
/*
API function: SetupDiGetClassDevs
Returns: a handle to a device information set for all installed devices.
Requires: the GUID returned by GetHidGuid.
*/
hDevInfo=SetupDiGetClassDevs
(&HidGuid,
NULL,
NULL,
DIGCF_PRESENT|DIGCF_INTERFACEDEVICE);
devInfoData.cbSize = sizeof(devInfoData);
//Step through the available devices looking for the one we want.
//Quit on detecting the desired device or checking all available devices without success.
MemberIndex = 0;
LastDevice = FALSE;
do
{
/*
API function: SetupDiEnumDeviceInterfaces
On return, MyDeviceInterfaceData contains the handle to a
SP_DEVICE_INTERFACE_DATA structure for a detected device.
Requires:
The DeviceInfoSet returned in SetupDiGetClassDevs.
The HidGuid returned in GetHidGuid.
An index to specify a device.
*/
Result=SetupDiEnumDeviceInterfaces
(hDevInfo,
0,
&HidGuid,
MemberIndex,
&devInfoData);
if (Result != 0)
{
//A device has been detected, so get more information about it.
/*
API function: SetupDiGetDeviceInterfaceDetail
Returns: an SP_DEVICE_INTERFACE_DETAIL_DATA structure
containing information about a device.
To retrieve the information, call this function twice.
The first time returns the size of the structure in Length.
The second time returns a pointer to the data in DeviceInfoSet.
Requires:
A DeviceInfoSet returned by SetupDiGetClassDevs
The SP_DEVICE_INTERFACE_DATA structure returned by SetupDiEnumDeviceInterfaces.
The final parameter is an optional pointer to an SP_DEV_INFO_DATA structure.
This application doesn’t retrieve or use the structure.
If retrieving the structure, set
MyDeviceInfoData.cbSize = length of MyDeviceInfoData.
and pass the structure’s address.
*/
//Get the Length value.
//The call will return with a “buffer too small” error which can be ignored.
Result = SetupDiGetDeviceInterfaceDetail
(hDevInfo,
&devInfoData,
NULL,
0,
&Length,
NULL);
//Allocate memory for the hDevInfo structure, using the returned Length.
detailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(Length);
//Set cbSize in the detailData structure.
detailData -> cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
//Call the function again, this time passing it the returned buffer size.
Result = SetupDiGetDeviceInterfaceDetail
(hDevInfo,
&devInfoData,
detailData,
Length,
&Required,
NULL);
// Open a handle to the device.
// To enable retrieving information about a system mouse or keyboard,
// don’t request Read or Write access for this handle.
/*
API function: CreateFile
Returns: a handle that enables reading and writing to the device.
Requires:
The DevicePath in the detailData structure
returned by SetupDiGetDeviceInterfaceDetail.
*/
DeviceHandle=CreateFile
(detailData->DevicePath,
0,
FILE_SHARE_READ|FILE_SHARE_WRITE,
(LPSECURITY_ATTRIBUTES)NULL,
OPEN_EXISTING,
0,
NULL);
DisplayLastError( “w”, “CreateFile: " );
char Str[50];
sprintf(Str,”\t Handle %d", DeviceHandle);
WriteToDebugFile(“a+”,Str);
//WriteToDebugFile(“a”,detailData->DevicePath);
/*
API function: HidD_GetAttributes
Requests information from the device.
Requires: the handle returned by CreateFile.
Returns: a HIDD_ATTRIBUTES structure containing
the Vendor ID, Product ID, and Product Version Number.
Use this information to decide if the detected device is
the one we’re looking for.
*/
//Set the Size to the number of bytes in the structure.
Attributes.Size = sizeof(Attributes);
Result = HidD_GetAttributes
(DeviceHandle,
&Attributes);
DisplayLastError( “a+”, “HidD_GetAttributes: “);
sprintf(Str,”\t Size %lu PID %4X VID %4X Version %4X”, Attributes.Size,Attributes.ProductID,Attributes.VendorID,Attributes.VersionNumber);
WriteToDebugFile(“a+”,Str);
//Is it the desired device?
MyDeviceDetected = FALSE;
if (Attributes.VendorID == VendorID)
{
if (Attributes.ProductID == ProductID)
{
//Both the Vendor ID and Product ID match.
MyDeviceDetected = TRUE;
MyDevicePathName = detailData->DevicePath;
DisplayLastError( “a”, “Device detected”);
//Register to receive device notifications.
RegisterForDeviceNotifications();
DisplayLastError( “a”, “Register for notification”);
//Get the device’s capablities.
GetDeviceCapabilities();
// Get a handle for writing Output reports.
WriteHandle=CreateFile
(detailData->DevicePath,
GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
(LPSECURITY_ATTRIBUTES)NULL,
OPEN_EXISTING,
0,
NULL);
DisplayLastError( “a”,"CreateFile: ");
// Prepare to read reports using Overlapped I/O.
PrepareForOverlappedTransfer();
} //if (Attributes.ProductID == ProductID)
else
//The Product ID doesn’t match.
CloseHandle(DeviceHandle);
} //if (Attributes.VendorID == VendorID)
else
//The Vendor ID doesn’t match.
CloseHandle(DeviceHandle);
//Free the memory used by the detailData structure (no longer needed).
free(detailData);
} //if (Result != 0)
else
//SetupDiEnumDeviceInterfaces returned 0, so there are no more devices to check.
LastDevice=TRUE;
//If we haven’t found the device yet, and haven’t tried every available device,
//try the next one.
MemberIndex = MemberIndex + 1;
} //do
while ((LastDevice == FALSE) && (MyDeviceDetected == FALSE));
if (MyDeviceDetected == FALSE)
DisplayLastError( “a”,“Device not detected”);
else
DisplayLastError( “a”,“Device detected”);
//Free the memory reserved for hDevInfo by SetupDiClassDevs.
SetupDiDestroyDeviceInfoList(hDevInfo);
DisplayLastError( "a ",“SetupDiDestroyDeviceInfoList”);
return MyDeviceDetected;
}
void WriteToDevice()
{
DisplayLastError( “a”,“***HID Test Report***”);
//If the device hasn’t been detected already, look for it.
// Do nothing if the device isn’t detected.
if (MyDeviceDetected==TRUE)
{
WriteOutputReport();
//ReadInputReport();
}
}
void WriteOutputReport()
{
//Send a report to the device.
DWORD BytesWritten = 0;
INT Index =0;
ULONG Result;
std::string strBytesWritten = “”;
/*
HidD_SetOutputReport
Sends a report to the device.
Returns: success or failure.
Requires:
The device handle returned by CreateFile.
A buffer that holds the report.
The Output Report length returned by HidP_GetCaps,
*/
if (WriteHandle != INVALID_HANDLE_VALUE)
{
Result = HidD_SetOutputReport
(WriteHandle,
OutputReport,
Capabilities.OutputReportByteLength);
DisplayLastError( “a”,"HidD_SetOutputReport: ");
}
if (Result)
{
DisplayLastError( “a”,“An Output report was written to the device.”);
}
else
{
//The write attempt failed, so close the handles, display a message,
//and set MyDeviceDetected to FALSE so the next attempt will look for the device.
CloseHandles();
DisplayLastError( “a”,“Can’t write to device”);
MyDeviceDetected = FALSE;
}
}
void CloseHandles()
{
//Close open handles.
if (DeviceHandle != INVALID_HANDLE_VALUE)
{
CloseHandle(DeviceHandle);
DisplayLastError( “a”,“Close Device Handle”);
}
if (ReadHandle != INVALID_HANDLE_VALUE)
{
CloseHandle(ReadHandle);
DisplayLastError( “a”,“Close Read Handle”);
}
if (WriteHandle != INVALID_HANDLE_VALUE)
{
CloseHandle(WriteHandle);
DisplayLastError( “a”,“Close Write Handle”);
}
}
#pragma endregion USB_Interface
and I try to send data with this
void Update()
{
OutputReport[0] = 0x00;
OutputReport[1] = 0x0c;
OutputReport[3] = 0x12;
OutputReport[2] = 0x34;
OutputReport[4] = 0x56;
OutputReport[5] = 0x78;
WriteOutputReport();
}
And In the WriteOutputReport I’ve this error .
I took this code from
http://janaxelson.com/files/usbhidio_vc6.zip
I try to reproduce the function to send once frame.
Thanks you