@@ -94,6 +94,7 @@ static HidD_GetPreparsedData_ HidD_GetPreparsedData;
94
94
static HidD_FreePreparsedData_ HidD_FreePreparsedData ;
95
95
static HidP_GetCaps_ HidP_GetCaps ;
96
96
static HidD_SetNumInputBuffers_ HidD_SetNumInputBuffers ;
97
+ static HidD_SetOutputReport_ HidD_SetOutputReport ;
97
98
98
99
static CM_Locate_DevNodeW_ CM_Locate_DevNodeW = NULL ;
99
100
static CM_Get_Parent_ CM_Get_Parent = NULL ;
@@ -147,6 +148,7 @@ static int lookup_functions()
147
148
RESOLVE (hid_lib_handle , HidD_FreePreparsedData );
148
149
RESOLVE (hid_lib_handle , HidP_GetCaps );
149
150
RESOLVE (hid_lib_handle , HidD_SetNumInputBuffers );
151
+ RESOLVE (hid_lib_handle , HidD_SetOutputReport );
150
152
151
153
RESOLVE (cfgmgr32_lib_handle , CM_Locate_DevNodeW );
152
154
RESOLVE (cfgmgr32_lib_handle , CM_Get_Parent );
@@ -183,8 +185,28 @@ struct hid_device_ {
183
185
OVERLAPPED ol ;
184
186
OVERLAPPED write_ol ;
185
187
struct hid_device_info * device_info ;
188
+ BOOL use_hid_write_output_report ;
186
189
};
187
190
191
+ static BOOL hid_internal_is_windows_version_or_greater (WORD wMajorVersion , WORD wMinorVersion , WORD wServicePackMajor )
192
+ {
193
+ OSVERSIONINFOEXW osvi ;
194
+ DWORDLONG const dwlConditionMask = VerSetConditionMask (
195
+ VerSetConditionMask (
196
+ VerSetConditionMask (
197
+ 0 , VER_MAJORVERSION , VER_GREATER_EQUAL ),
198
+ VER_MINORVERSION , VER_GREATER_EQUAL ),
199
+ VER_SERVICEPACKMAJOR , VER_GREATER_EQUAL );
200
+
201
+ memset (& osvi , 0 , sizeof (osvi ));
202
+ osvi .dwOSVersionInfoSize = sizeof ( osvi );
203
+ osvi .dwMajorVersion = wMajorVersion ;
204
+ osvi .dwMinorVersion = wMinorVersion ;
205
+ osvi .wServicePackMajor = wServicePackMajor ;
206
+
207
+ return VerifyVersionInfoW (& osvi , VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR , dwlConditionMask ) != FALSE;
208
+ }
209
+
188
210
static hid_device * new_hid_device ()
189
211
{
190
212
hid_device * dev = (hid_device * ) calloc (1 , sizeof (hid_device ));
@@ -992,6 +1014,11 @@ HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path)
992
1014
dev -> read_buf = (char * ) malloc (dev -> input_report_length );
993
1015
dev -> device_info = hid_internal_get_device_info (interface_path , dev -> device_handle );
994
1016
1017
+ /* On Windows 7, we need to use hid_write_output_report() over Bluetooth */
1018
+ if (dev -> output_report_length > 512 ) {
1019
+ dev -> use_hid_write_output_report = !hid_internal_is_windows_version_or_greater ( HIBYTE ( _WIN32_WINNT_WIN8 ), LOBYTE ( _WIN32_WINNT_WIN8 ), 0 );
1020
+ }
1021
+
995
1022
end_of_function :
996
1023
free (interface_path );
997
1024
CloseHandle (device_handle );
@@ -1003,6 +1030,16 @@ HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path)
1003
1030
return dev ;
1004
1031
}
1005
1032
1033
+ static int hid_internal_write_output_report (hid_device * dev , const unsigned char * data , size_t length )
1034
+ {
1035
+ BOOL res ;
1036
+ res = HidD_SetOutputReport (dev -> device_handle , (void * )data , (ULONG )length );
1037
+ if (res )
1038
+ return (int )length ;
1039
+ else
1040
+ return -1 ;
1041
+ }
1042
+
1006
1043
int HID_API_EXPORT HID_API_CALL hid_write (hid_device * dev , const unsigned char * data , size_t length )
1007
1044
{
1008
1045
DWORD bytes_written = 0 ;
@@ -1019,6 +1056,10 @@ int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char *
1019
1056
1020
1057
register_string_error (dev , NULL );
1021
1058
1059
+ if (dev -> use_hid_write_output_report ) {
1060
+ return hid_internal_write_output_report (dev , data , length );
1061
+ }
1062
+
1022
1063
/* Make sure the right number of bytes are passed to WriteFile. Windows
1023
1064
expects the number of bytes which are in the _longest_ report (plus
1024
1065
one for the report number) bytes even if the data is a report
0 commit comments