mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-09-05 19:08:12 +00:00
hidapi/windows: fixed PS4 controllers over Bluetooth on Windows 7
Signed-off-by: Sam Lantinga <slouken@libsdl.org>
This commit is contained in:
@@ -97,6 +97,7 @@ static HidD_GetPreparsedData_ HidD_GetPreparsedData;
|
|||||||
static HidD_FreePreparsedData_ HidD_FreePreparsedData;
|
static HidD_FreePreparsedData_ HidD_FreePreparsedData;
|
||||||
static HidP_GetCaps_ HidP_GetCaps;
|
static HidP_GetCaps_ HidP_GetCaps;
|
||||||
static HidD_SetNumInputBuffers_ HidD_SetNumInputBuffers;
|
static HidD_SetNumInputBuffers_ HidD_SetNumInputBuffers;
|
||||||
|
static HidD_SetOutputReport_ HidD_SetOutputReport;
|
||||||
|
|
||||||
static CM_Locate_DevNodeW_ CM_Locate_DevNodeW = NULL;
|
static CM_Locate_DevNodeW_ CM_Locate_DevNodeW = NULL;
|
||||||
static CM_Get_Parent_ CM_Get_Parent = NULL;
|
static CM_Get_Parent_ CM_Get_Parent = NULL;
|
||||||
@@ -151,6 +152,7 @@ static int lookup_functions()
|
|||||||
RESOLVE(hid_lib_handle, HidD_FreePreparsedData);
|
RESOLVE(hid_lib_handle, HidD_FreePreparsedData);
|
||||||
RESOLVE(hid_lib_handle, HidP_GetCaps);
|
RESOLVE(hid_lib_handle, HidP_GetCaps);
|
||||||
RESOLVE(hid_lib_handle, HidD_SetNumInputBuffers);
|
RESOLVE(hid_lib_handle, HidD_SetNumInputBuffers);
|
||||||
|
RESOLVE(hid_lib_handle, HidD_SetOutputReport);
|
||||||
|
|
||||||
RESOLVE(cfgmgr32_lib_handle, CM_Locate_DevNodeW);
|
RESOLVE(cfgmgr32_lib_handle, CM_Locate_DevNodeW);
|
||||||
RESOLVE(cfgmgr32_lib_handle, CM_Get_Parent);
|
RESOLVE(cfgmgr32_lib_handle, CM_Get_Parent);
|
||||||
@@ -188,8 +190,28 @@ struct hid_device_ {
|
|||||||
OVERLAPPED ol;
|
OVERLAPPED ol;
|
||||||
OVERLAPPED write_ol;
|
OVERLAPPED write_ol;
|
||||||
struct hid_device_info* device_info;
|
struct hid_device_info* device_info;
|
||||||
|
BOOL use_hid_write_output_report;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static BOOL IsWindowsVersionOrGreater(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor)
|
||||||
|
{
|
||||||
|
OSVERSIONINFOEXW osvi;
|
||||||
|
DWORDLONG const dwlConditionMask = VerSetConditionMask(
|
||||||
|
VerSetConditionMask(
|
||||||
|
VerSetConditionMask(
|
||||||
|
0, VER_MAJORVERSION, VER_GREATER_EQUAL ),
|
||||||
|
VER_MINORVERSION, VER_GREATER_EQUAL ),
|
||||||
|
VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL );
|
||||||
|
|
||||||
|
memset(&osvi, 0, sizeof(osvi));
|
||||||
|
osvi.dwOSVersionInfoSize = sizeof( osvi );
|
||||||
|
osvi.dwMajorVersion = wMajorVersion;
|
||||||
|
osvi.dwMinorVersion = wMinorVersion;
|
||||||
|
osvi.wServicePackMajor = wServicePackMajor;
|
||||||
|
|
||||||
|
return VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR, dwlConditionMask) != FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
static hid_device *new_hid_device()
|
static hid_device *new_hid_device()
|
||||||
{
|
{
|
||||||
hid_device *dev = (hid_device*) calloc(1, sizeof(hid_device));
|
hid_device *dev = (hid_device*) calloc(1, sizeof(hid_device));
|
||||||
@@ -1020,6 +1042,11 @@ HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path)
|
|||||||
dev->read_buf = (char*) malloc(dev->input_report_length);
|
dev->read_buf = (char*) malloc(dev->input_report_length);
|
||||||
dev->device_info = hid_internal_get_device_info(interface_path, dev->device_handle);
|
dev->device_info = hid_internal_get_device_info(interface_path, dev->device_handle);
|
||||||
|
|
||||||
|
/* On Windows 7, we need to use hid_write_output_report() over Bluetooth */
|
||||||
|
if (dev->output_report_length > 512) {
|
||||||
|
dev->use_hid_write_output_report = !IsWindowsVersionOrGreater( HIBYTE( _WIN32_WINNT_WIN8 ), LOBYTE( _WIN32_WINNT_WIN8 ), 0 );
|
||||||
|
}
|
||||||
|
|
||||||
end_of_function:
|
end_of_function:
|
||||||
free(interface_path);
|
free(interface_path);
|
||||||
CloseHandle(device_handle);
|
CloseHandle(device_handle);
|
||||||
@@ -1031,6 +1058,16 @@ end_of_function:
|
|||||||
return dev;
|
return dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int hid_write_output_report(hid_device *dev, const unsigned char *data, size_t length)
|
||||||
|
{
|
||||||
|
BOOL res;
|
||||||
|
res = HidD_SetOutputReport(dev->device_handle, (void *)data, (ULONG)length);
|
||||||
|
if (res)
|
||||||
|
return (int)length;
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char *data, size_t length)
|
int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char *data, size_t length)
|
||||||
{
|
{
|
||||||
DWORD bytes_written = 0;
|
DWORD bytes_written = 0;
|
||||||
@@ -1047,6 +1084,10 @@ int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char *
|
|||||||
|
|
||||||
register_string_error(dev, NULL);
|
register_string_error(dev, NULL);
|
||||||
|
|
||||||
|
if (dev->use_hid_write_output_report) {
|
||||||
|
return hid_write_output_report(dev, data, length);
|
||||||
|
}
|
||||||
|
|
||||||
/* Make sure the right number of bytes are passed to WriteFile. Windows
|
/* Make sure the right number of bytes are passed to WriteFile. Windows
|
||||||
expects the number of bytes which are in the _longest_ report (plus
|
expects the number of bytes which are in the _longest_ report (plus
|
||||||
one for the report number) bytes even if the data is a report
|
one for the report number) bytes even if the data is a report
|
||||||
|
@@ -52,6 +52,7 @@ typedef BOOLEAN (__stdcall *HidD_GetIndexedString_)(HANDLE handle, ULONG string_
|
|||||||
typedef BOOLEAN (__stdcall *HidD_GetPreparsedData_)(HANDLE handle, PHIDP_PREPARSED_DATA *preparsed_data);
|
typedef BOOLEAN (__stdcall *HidD_GetPreparsedData_)(HANDLE handle, PHIDP_PREPARSED_DATA *preparsed_data);
|
||||||
typedef BOOLEAN (__stdcall *HidD_FreePreparsedData_)(PHIDP_PREPARSED_DATA preparsed_data);
|
typedef BOOLEAN (__stdcall *HidD_FreePreparsedData_)(PHIDP_PREPARSED_DATA preparsed_data);
|
||||||
typedef BOOLEAN (__stdcall *HidD_SetNumInputBuffers_)(HANDLE handle, ULONG number_buffers);
|
typedef BOOLEAN (__stdcall *HidD_SetNumInputBuffers_)(HANDLE handle, ULONG number_buffers);
|
||||||
|
typedef BOOLEAN (__stdcall *HidD_SetOutputReport_)(HANDLE HidDeviceObject, PVOID ReportBuffer, ULONG ReportBufferLength);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user