@@ -94,6 +94,7 @@ static HidD_GetPreparsedData_ HidD_GetPreparsedData;
9494static HidD_FreePreparsedData_ HidD_FreePreparsedData ;
9595static HidP_GetCaps_ HidP_GetCaps ;
9696static HidD_SetNumInputBuffers_ HidD_SetNumInputBuffers ;
97+ static HidD_SetOutputReport_ HidD_SetOutputReport ;
9798
9899static CM_Locate_DevNodeW_ CM_Locate_DevNodeW = NULL ;
99100static CM_Get_Parent_ CM_Get_Parent = NULL ;
@@ -147,6 +148,7 @@ static int lookup_functions()
147148 RESOLVE (hid_lib_handle , HidD_FreePreparsedData );
148149 RESOLVE (hid_lib_handle , HidP_GetCaps );
149150 RESOLVE (hid_lib_handle , HidD_SetNumInputBuffers );
151+ RESOLVE (hid_lib_handle , HidD_SetOutputReport );
150152
151153 RESOLVE (cfgmgr32_lib_handle , CM_Locate_DevNodeW );
152154 RESOLVE (cfgmgr32_lib_handle , CM_Get_Parent );
@@ -183,8 +185,28 @@ struct hid_device_ {
183185 OVERLAPPED ol ;
184186 OVERLAPPED write_ol ;
185187 struct hid_device_info * device_info ;
188+ BOOL use_hid_write_output_report ;
186189};
187190
191+ static BOOL IsWindowsVersionOrGreater (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+
188210static hid_device * new_hid_device ()
189211{
190212 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)
9921014 dev -> read_buf = (char * ) malloc (dev -> input_report_length );
9931015 dev -> device_info = hid_internal_get_device_info (interface_path , dev -> device_handle );
9941016
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 = !IsWindowsVersionOrGreater ( HIBYTE ( _WIN32_WINNT_WIN8 ), LOBYTE ( _WIN32_WINNT_WIN8 ), 0 );
1020+ }
1021+
9951022end_of_function :
9961023 free (interface_path );
9971024 CloseHandle (device_handle );
@@ -1003,6 +1030,16 @@ HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path)
10031030 return dev ;
10041031}
10051032
1033+ static int hid_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+
10061043int HID_API_EXPORT HID_API_CALL hid_write (hid_device * dev , const unsigned char * data , size_t length )
10071044{
10081045 DWORD bytes_written = 0 ;
@@ -1019,6 +1056,10 @@ int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char *
10191056
10201057 register_string_error (dev , NULL );
10211058
1059+ if (dev -> use_hid_write_output_report ) {
1060+ return hid_write_output_report (dev , data , length );
1061+ }
1062+
10221063 /* Make sure the right number of bytes are passed to WriteFile. Windows
10231064 expects the number of bytes which are in the _longest_ report (plus
10241065 one for the report number) bytes even if the data is a report
0 commit comments