|
|
@@ -26,160 +26,13 @@
|
|
|
#include "SDL_hidapijoystick_c.h"
|
|
|
#include "SDL_hidapi_rumble.h"
|
|
|
|
|
|
-/* ========================================================================= */
|
|
|
-/* Win32 HID helper */
|
|
|
-/* ========================================================================= */
|
|
|
-
|
|
|
-/* This helper requires full desktop Win32 HID APIs.
|
|
|
- * These APIs are NOT available on GDK platforms.
|
|
|
- */
|
|
|
-#if defined(SDL_PLATFORM_WIN32) && !defined(SDL_PLATFORM_GDK)
|
|
|
-#define SDL_HAS_WIN32_HID 1
|
|
|
-#else
|
|
|
-#define SDL_HAS_WIN32_HID 0
|
|
|
-#endif
|
|
|
-
|
|
|
-#if SDL_HAS_WIN32_HID
|
|
|
-
|
|
|
-/* --- Win32 HID includes ------------------------------------------------- */
|
|
|
-#include <windows.h>
|
|
|
-#include <setupapi.h>
|
|
|
-#include <hidsdi.h>
|
|
|
-
|
|
|
-#if defined(_MSC_VER)
|
|
|
-#pragma comment(lib, "setupapi.lib")
|
|
|
-#pragma comment(lib, "hid.lib")
|
|
|
-#endif
|
|
|
-
|
|
|
-static char *FindHIDInterfacePath(Uint16 vid, Uint16 pid, int collection_index)
|
|
|
-{
|
|
|
- GUID hidGuid;
|
|
|
- HidD_GetHidGuid(&hidGuid);
|
|
|
-
|
|
|
- HDEVINFO deviceInfoSet = SetupDiGetClassDevs(
|
|
|
- &hidGuid, NULL, NULL,
|
|
|
- DIGCF_PRESENT | DIGCF_DEVICEINTERFACE
|
|
|
- );
|
|
|
- if (deviceInfoSet == INVALID_HANDLE_VALUE) {
|
|
|
- return NULL;
|
|
|
- }
|
|
|
-
|
|
|
- SP_DEVICE_INTERFACE_DATA deviceInterfaceData;
|
|
|
- deviceInterfaceData.cbSize = sizeof(deviceInterfaceData);
|
|
|
-
|
|
|
- for (DWORD i = 0;
|
|
|
- SetupDiEnumDeviceInterfaces(deviceInfoSet, NULL, &hidGuid, i, &deviceInterfaceData);
|
|
|
- i++) {
|
|
|
-
|
|
|
- DWORD requiredSize = 0;
|
|
|
- SetupDiGetDeviceInterfaceDetail(
|
|
|
- deviceInfoSet, &deviceInterfaceData,
|
|
|
- NULL, 0, &requiredSize, NULL
|
|
|
- );
|
|
|
-
|
|
|
- PSP_DEVICE_INTERFACE_DETAIL_DATA deviceDetail =
|
|
|
- (PSP_DEVICE_INTERFACE_DETAIL_DATA)SDL_malloc(requiredSize);
|
|
|
- if (!deviceDetail) {
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- deviceDetail->cbSize = sizeof(*deviceDetail);
|
|
|
-
|
|
|
- if (!SetupDiGetDeviceInterfaceDetail(
|
|
|
- deviceInfoSet, &deviceInterfaceData,
|
|
|
- deviceDetail, requiredSize, NULL, NULL)) {
|
|
|
- SDL_free(deviceDetail);
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- HANDLE hDevice = CreateFile(
|
|
|
- deviceDetail->DevicePath,
|
|
|
- GENERIC_READ | GENERIC_WRITE,
|
|
|
- FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
|
- NULL,
|
|
|
- OPEN_EXISTING,
|
|
|
- FILE_FLAG_OVERLAPPED,
|
|
|
- NULL
|
|
|
- );
|
|
|
-
|
|
|
- if (hDevice == INVALID_HANDLE_VALUE) {
|
|
|
- SDL_free(deviceDetail);
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- HIDD_ATTRIBUTES attributes;
|
|
|
- attributes.Size = sizeof(attributes);
|
|
|
-
|
|
|
- if (!HidD_GetAttributes(hDevice, &attributes) ||
|
|
|
- attributes.VendorID != vid ||
|
|
|
- attributes.ProductID != pid) {
|
|
|
- CloseHandle(hDevice);
|
|
|
- SDL_free(deviceDetail);
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- PHIDP_PREPARSED_DATA preparsedData = NULL;
|
|
|
- if (!HidD_GetPreparsedData(hDevice, &preparsedData) || !preparsedData) {
|
|
|
- CloseHandle(hDevice);
|
|
|
- SDL_free(deviceDetail);
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- HIDP_CAPS caps;
|
|
|
- if (HidP_GetCaps(preparsedData, &caps) != HIDP_STATUS_SUCCESS) {
|
|
|
- HidD_FreePreparsedData(preparsedData);
|
|
|
- CloseHandle(hDevice);
|
|
|
- SDL_free(deviceDetail);
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- if ((caps.InputReportByteLength == 64 && caps.OutputReportByteLength == 64) ||
|
|
|
- (caps.InputReportByteLength == 37 && caps.OutputReportByteLength == 37)) {
|
|
|
-
|
|
|
- char col_str[16];
|
|
|
- SDL_snprintf(col_str, sizeof(col_str), "col%02d", collection_index);
|
|
|
-
|
|
|
- if (SDL_strcasestr(deviceDetail->DevicePath, col_str)) {
|
|
|
- char *result = SDL_strdup(deviceDetail->DevicePath);
|
|
|
- HidD_FreePreparsedData(preparsedData);
|
|
|
- CloseHandle(hDevice);
|
|
|
- SDL_free(deviceDetail);
|
|
|
- SetupDiDestroyDeviceInfoList(deviceInfoSet);
|
|
|
- return result;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- HidD_FreePreparsedData(preparsedData);
|
|
|
- CloseHandle(hDevice);
|
|
|
- SDL_free(deviceDetail);
|
|
|
- }
|
|
|
-
|
|
|
- SetupDiDestroyDeviceInfoList(deviceInfoSet);
|
|
|
- return NULL;
|
|
|
-}
|
|
|
-
|
|
|
-#else /* !SDL_HAS_WIN32_HID */
|
|
|
-/* Stub for GDK / non-Win32 platforms */
|
|
|
+#ifdef SDL_JOYSTICK_HIDAPI_GAMESIR
|
|
|
|
|
|
-#if defined(__GNUC__) || defined(__clang__)
|
|
|
-#define SDL_UNUSED_FUNC __attribute__((unused))
|
|
|
-#else
|
|
|
-#define SDL_UNUSED_FUNC
|
|
|
+// Define this if you want to log all packets from the controller
|
|
|
+#if 0
|
|
|
+#define DEBUG_GAMESIR_PROTOCOL
|
|
|
#endif
|
|
|
|
|
|
-static char *FindHIDInterfacePath(Uint16 vid, Uint16 pid, int collection_index) SDL_UNUSED_FUNC;
|
|
|
-static char *FindHIDInterfacePath(Uint16 vid, Uint16 pid, int collection_index)
|
|
|
-{
|
|
|
- (void)vid;
|
|
|
- (void)pid;
|
|
|
- (void)collection_index;
|
|
|
- return NULL;
|
|
|
-}
|
|
|
-
|
|
|
-#endif /* SDL_HAS_WIN32_HID */
|
|
|
-
|
|
|
-#ifdef SDL_JOYSTICK_HIDAPI_GAMESIR
|
|
|
-
|
|
|
#define GAMESIR_PACKET_HEADER_0 0xA1
|
|
|
#define GAMESIR_PACKET_HEADER_1_GAMEPAD 0xC8
|
|
|
|
|
|
@@ -224,12 +77,6 @@ static char *FindHIDInterfacePath(Uint16 vid, Uint16 pid, int collection_index)
|
|
|
#define BTN_L8 0x40
|
|
|
#define BTN_R8 0x80
|
|
|
|
|
|
-#ifndef DEG2RAD
|
|
|
-#define DEG2RAD(x) ((float)(x) * (float)(SDL_PI_F / 180.f))
|
|
|
-#endif
|
|
|
-
|
|
|
-#define LOAD16(A, B) (Sint16)((Uint16)(A) | (((Uint16)(B)) << 8))
|
|
|
-
|
|
|
typedef struct {
|
|
|
Uint8 cmd;
|
|
|
Uint8 mode;
|
|
|
@@ -276,10 +123,7 @@ static SDL_hid_device *HIDAPI_DriverGameSir_GetOutputHandle(SDL_HIDAPI_Device *d
|
|
|
{
|
|
|
#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINGDK)
|
|
|
SDL_DriverGamesir_Context *ctx = (SDL_DriverGamesir_Context *)device->context;
|
|
|
- if (ctx && ctx->output_handle) {
|
|
|
- return ctx->output_handle;
|
|
|
- }
|
|
|
- return NULL;
|
|
|
+ return ctx->output_handle;
|
|
|
#else
|
|
|
return device->dev;
|
|
|
#endif
|
|
|
@@ -291,7 +135,7 @@ static SDL_hid_device *HIDAPI_DriverGameSir_GetInputHandle(SDL_HIDAPI_Device *de
|
|
|
if (device->is_bluetooth) {
|
|
|
return device->dev;
|
|
|
}
|
|
|
- if (ctx && ctx->output_handle) {
|
|
|
+ if (ctx->output_handle) {
|
|
|
return ctx->output_handle;
|
|
|
}
|
|
|
return device->dev;
|
|
|
@@ -300,7 +144,6 @@ static SDL_hid_device *HIDAPI_DriverGameSir_GetInputHandle(SDL_HIDAPI_Device *de
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
-
|
|
|
static bool SendGameSirModeSwitch(SDL_HIDAPI_Device *device)
|
|
|
{
|
|
|
Gamesir_CommandMode cmd = { 0x01, 0x00 };
|
|
|
@@ -310,10 +153,10 @@ static bool SendGameSirModeSwitch(SDL_HIDAPI_Device *device)
|
|
|
SDL_memcpy(buf + 1, &cmd, sizeof(cmd));
|
|
|
|
|
|
SDL_hid_device *handle = HIDAPI_DriverGameSir_GetOutputHandle(device);
|
|
|
- SDL_assert(handle != NULL);
|
|
|
if (handle == NULL) {
|
|
|
return false;
|
|
|
}
|
|
|
+
|
|
|
for (int attempt = 0; attempt < 3; ++attempt) {
|
|
|
int result = SDL_hid_write(handle, buf, sizeof(buf));
|
|
|
if (result < 0) {
|
|
|
@@ -336,58 +179,177 @@ static bool SendGameSirModeSwitch(SDL_HIDAPI_Device *device)
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+ return false;
|
|
|
+}
|
|
|
|
|
|
- SDL_Delay(10);
|
|
|
- return true;
|
|
|
+/* ========================================================================= */
|
|
|
+/* Win32 HID helper */
|
|
|
+/* ========================================================================= */
|
|
|
+
|
|
|
+/* This helper requires full desktop Win32 HID APIs.
|
|
|
+ * These APIs are NOT available on GDK platforms.
|
|
|
+ */
|
|
|
+#if defined(SDL_PLATFORM_WIN32) && !defined(SDL_PLATFORM_GDK)
|
|
|
+
|
|
|
+/* --- Win32 HID includes ------------------------------------------------- */
|
|
|
+#include <windows.h>
|
|
|
+#include <setupapi.h>
|
|
|
+#include <hidsdi.h>
|
|
|
+
|
|
|
+#if defined(_MSC_VER)
|
|
|
+#pragma comment(lib, "setupapi.lib")
|
|
|
+#pragma comment(lib, "hid.lib")
|
|
|
+#endif
|
|
|
+
|
|
|
+static char *FindHIDInterfacePath(Uint16 vid, Uint16 pid, int collection_index)
|
|
|
+{
|
|
|
+ GUID hidGuid;
|
|
|
+ HidD_GetHidGuid(&hidGuid);
|
|
|
+
|
|
|
+ HDEVINFO deviceInfoSet = SetupDiGetClassDevs(
|
|
|
+ &hidGuid, NULL, NULL,
|
|
|
+ DIGCF_PRESENT | DIGCF_DEVICEINTERFACE
|
|
|
+ );
|
|
|
+ if (deviceInfoSet == INVALID_HANDLE_VALUE) {
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ SP_DEVICE_INTERFACE_DATA deviceInterfaceData;
|
|
|
+ deviceInterfaceData.cbSize = sizeof(deviceInterfaceData);
|
|
|
+
|
|
|
+ for (DWORD i = 0;
|
|
|
+ SetupDiEnumDeviceInterfaces(deviceInfoSet, NULL, &hidGuid, i, &deviceInterfaceData);
|
|
|
+ i++) {
|
|
|
+
|
|
|
+ DWORD requiredSize = 0;
|
|
|
+ SetupDiGetDeviceInterfaceDetail(
|
|
|
+ deviceInfoSet, &deviceInterfaceData,
|
|
|
+ NULL, 0, &requiredSize, NULL
|
|
|
+ );
|
|
|
+
|
|
|
+ PSP_DEVICE_INTERFACE_DETAIL_DATA deviceDetail =
|
|
|
+ (PSP_DEVICE_INTERFACE_DETAIL_DATA)SDL_malloc(requiredSize);
|
|
|
+ if (!deviceDetail) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ deviceDetail->cbSize = sizeof(*deviceDetail);
|
|
|
+
|
|
|
+ if (!SetupDiGetDeviceInterfaceDetail(
|
|
|
+ deviceInfoSet, &deviceInterfaceData,
|
|
|
+ deviceDetail, requiredSize, NULL, NULL)) {
|
|
|
+ SDL_free(deviceDetail);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ HANDLE hDevice = CreateFile(
|
|
|
+ deviceDetail->DevicePath,
|
|
|
+ GENERIC_READ | GENERIC_WRITE,
|
|
|
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
|
+ NULL,
|
|
|
+ OPEN_EXISTING,
|
|
|
+ FILE_FLAG_OVERLAPPED,
|
|
|
+ NULL
|
|
|
+ );
|
|
|
+
|
|
|
+ if (hDevice == INVALID_HANDLE_VALUE) {
|
|
|
+ SDL_free(deviceDetail);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ HIDD_ATTRIBUTES attributes;
|
|
|
+ attributes.Size = sizeof(attributes);
|
|
|
+
|
|
|
+ if (!HidD_GetAttributes(hDevice, &attributes) ||
|
|
|
+ attributes.VendorID != vid ||
|
|
|
+ attributes.ProductID != pid) {
|
|
|
+ CloseHandle(hDevice);
|
|
|
+ SDL_free(deviceDetail);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ PHIDP_PREPARSED_DATA preparsedData = NULL;
|
|
|
+ if (!HidD_GetPreparsedData(hDevice, &preparsedData) || !preparsedData) {
|
|
|
+ CloseHandle(hDevice);
|
|
|
+ SDL_free(deviceDetail);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ HIDP_CAPS caps;
|
|
|
+ if (HidP_GetCaps(preparsedData, &caps) != HIDP_STATUS_SUCCESS) {
|
|
|
+ HidD_FreePreparsedData(preparsedData);
|
|
|
+ CloseHandle(hDevice);
|
|
|
+ SDL_free(deviceDetail);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ((caps.InputReportByteLength == 64 && caps.OutputReportByteLength == 64) ||
|
|
|
+ (caps.InputReportByteLength == 37 && caps.OutputReportByteLength == 37)) {
|
|
|
+
|
|
|
+ char col_str[16];
|
|
|
+ SDL_snprintf(col_str, sizeof(col_str), "col%02d", collection_index);
|
|
|
+
|
|
|
+ if (SDL_strcasestr(deviceDetail->DevicePath, col_str)) {
|
|
|
+ char *result = SDL_strdup(deviceDetail->DevicePath);
|
|
|
+ HidD_FreePreparsedData(preparsedData);
|
|
|
+ CloseHandle(hDevice);
|
|
|
+ SDL_free(deviceDetail);
|
|
|
+ SetupDiDestroyDeviceInfoList(deviceInfoSet);
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ HidD_FreePreparsedData(preparsedData);
|
|
|
+ CloseHandle(hDevice);
|
|
|
+ SDL_free(deviceDetail);
|
|
|
+ }
|
|
|
+
|
|
|
+ SetupDiDestroyDeviceInfoList(deviceInfoSet);
|
|
|
+ return NULL;
|
|
|
}
|
|
|
|
|
|
-static bool HIDAPI_DriverGameSir_InitDevice(SDL_HIDAPI_Device *device)
|
|
|
+#endif // SDL_PLATFORM_WIN32 && !SDL_PLATFORM_GDK
|
|
|
+
|
|
|
+static SDL_hid_device *GetOutputHandle(SDL_HIDAPI_Device *device)
|
|
|
{
|
|
|
Uint16 vendor_id = device->vendor_id;
|
|
|
Uint16 product_id = device->product_id;
|
|
|
SDL_hid_device *output_handle = NULL;
|
|
|
-
|
|
|
struct SDL_hid_device_info *devs = SDL_hid_enumerate(vendor_id, product_id);
|
|
|
- for (struct SDL_hid_device_info *info = devs; info; info = info->next) {
|
|
|
+ for (struct SDL_hid_device_info *info = devs; info && !output_handle; info = info->next) {
|
|
|
if (info->interface_number == 0) {
|
|
|
-#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK)
|
|
|
- if (!output_handle) {
|
|
|
- char *col02_path = FindHIDInterfacePath(vendor_id, product_id, 2);
|
|
|
- if (col02_path) {
|
|
|
- output_handle = SDL_hid_open_path(col02_path);
|
|
|
- SDL_free(col02_path);
|
|
|
- }
|
|
|
+#if defined(SDL_PLATFORM_WIN32) && !defined(SDL_PLATFORM_GDK)
|
|
|
+ char *col02_path = FindHIDInterfacePath(vendor_id, product_id, 2);
|
|
|
+ if (col02_path) {
|
|
|
+ output_handle = SDL_hid_open_path(col02_path);
|
|
|
+ SDL_free(col02_path);
|
|
|
}
|
|
|
#endif
|
|
|
- }
|
|
|
- if (info->interface_number == -1) {
|
|
|
+ } else if (info->interface_number == -1) {
|
|
|
#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINGDK)
|
|
|
if (info->usage_page == 0x0001 && info->usage == 0x0005) {
|
|
|
output_handle = SDL_hid_open_path(info->path);
|
|
|
- if (output_handle) {
|
|
|
- SDL_LogDebug(SDL_LOG_CATEGORY_INPUT, "GameSir: Opened output interface via path pattern");
|
|
|
- break;
|
|
|
- }
|
|
|
}
|
|
|
#endif
|
|
|
- } else if (!output_handle && info->interface_number == 1) {
|
|
|
+ } else if (info->interface_number == 1) {
|
|
|
output_handle = SDL_hid_open_path(info->path);
|
|
|
}
|
|
|
}
|
|
|
SDL_hid_free_enumeration(devs);
|
|
|
|
|
|
+ return output_handle;
|
|
|
+}
|
|
|
+
|
|
|
+static bool HIDAPI_DriverGameSir_InitDevice(SDL_HIDAPI_Device *device)
|
|
|
+{
|
|
|
SDL_DriverGamesir_Context *ctx = (SDL_DriverGamesir_Context *)SDL_calloc(1, sizeof(*ctx));
|
|
|
if (!ctx) {
|
|
|
- SDL_hid_close(device->dev);
|
|
|
- if (output_handle) {
|
|
|
- SDL_hid_close(output_handle);
|
|
|
- }
|
|
|
return false;
|
|
|
}
|
|
|
+ device->context = ctx;
|
|
|
|
|
|
ctx->led_supported = true;
|
|
|
- ctx->output_handle = output_handle;
|
|
|
- device->context = ctx;
|
|
|
+ ctx->output_handle = GetOutputHandle(device);
|
|
|
|
|
|
switch (device->product_id) {
|
|
|
case USB_PRODUCT_GAMESIR_GAMEPAD_G7_PRO_HID:
|
|
|
@@ -438,30 +400,6 @@ static bool HIDAPI_DriverGameSir_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joy
|
|
|
|
|
|
SendGameSirModeSwitch(device);
|
|
|
|
|
|
- if (device->product_id == USB_PRODUCT_GAMESIR_GAMEPAD_G7_PRO_HID) {
|
|
|
- if (device->is_bluetooth) {
|
|
|
- joystick->connection_state = SDL_JOYSTICK_CONNECTION_WIRELESS;
|
|
|
- SDL_LogDebug(SDL_LOG_CATEGORY_INPUT, "GameSir: Joystick opened - Connection type: Bluetooth (wireless, HID mode)");
|
|
|
- } else {
|
|
|
- joystick->connection_state = SDL_JOYSTICK_CONNECTION_WIRED;
|
|
|
- SDL_LogDebug(SDL_LOG_CATEGORY_INPUT, "GameSir: Joystick opened - Connection type: USB/2.4G (HID mode)");
|
|
|
- }
|
|
|
- } else if (device->product_id == USB_PRODUCT_GAMESIR_GAMEPAD_G7_PRO_8K_HID) {
|
|
|
- if (device->is_bluetooth) {
|
|
|
- joystick->connection_state = SDL_JOYSTICK_CONNECTION_WIRELESS;
|
|
|
- SDL_LogDebug(SDL_LOG_CATEGORY_INPUT, "GameSir: Joystick opened - Connection type: Bluetooth (wireless, 8K HID mode)");
|
|
|
- } else {
|
|
|
- joystick->connection_state = SDL_JOYSTICK_CONNECTION_WIRED;
|
|
|
- SDL_LogDebug(SDL_LOG_CATEGORY_INPUT, "GameSir: Joystick opened - Connection type: USB/2.4G (8K HID mode)");
|
|
|
- }
|
|
|
- } else if (device->is_bluetooth) {
|
|
|
- joystick->connection_state = SDL_JOYSTICK_CONNECTION_WIRELESS;
|
|
|
- SDL_LogDebug(SDL_LOG_CATEGORY_INPUT, "GameSir: Joystick opened - Connection type: Bluetooth (wireless)");
|
|
|
- } else {
|
|
|
- joystick->connection_state = SDL_JOYSTICK_CONNECTION_WIRED;
|
|
|
- SDL_LogDebug(SDL_LOG_CATEGORY_INPUT, "GameSir: Joystick opened - Connection type: USB (wired)");
|
|
|
- }
|
|
|
-
|
|
|
joystick->nbuttons = 35;
|
|
|
joystick->naxes = SDL_GAMEPAD_AXIS_COUNT;
|
|
|
joystick->nhats = 1;
|
|
|
@@ -491,13 +429,6 @@ static bool HIDAPI_DriverGameSir_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joy
|
|
|
|
|
|
static bool HIDAPI_DriverGameSir_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
|
|
|
{
|
|
|
- if (!device) {
|
|
|
- return false;
|
|
|
- }
|
|
|
- SDL_DriverGamesir_Context *ctx = (SDL_DriverGamesir_Context *)device->context;
|
|
|
- if (!ctx) {
|
|
|
- return false;
|
|
|
- }
|
|
|
Uint8 buf[64];
|
|
|
SDL_zero(buf);
|
|
|
buf[0] = 0xA2;
|
|
|
@@ -506,7 +437,6 @@ static bool HIDAPI_DriverGameSir_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_J
|
|
|
buf[3] = (Uint8)(high_frequency_rumble / 256);
|
|
|
|
|
|
SDL_hid_device *handle = HIDAPI_DriverGameSir_GetOutputHandle(device);
|
|
|
- SDL_assert(handle != NULL);
|
|
|
if (handle == NULL) {
|
|
|
return false;
|
|
|
}
|
|
|
@@ -515,20 +445,13 @@ static bool HIDAPI_DriverGameSir_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_J
|
|
|
if (result < 0) {
|
|
|
return false;
|
|
|
}
|
|
|
-
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
|
|
|
static bool HIDAPI_DriverGameSir_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble)
|
|
|
{
|
|
|
- if (!device) {
|
|
|
- return false;
|
|
|
- }
|
|
|
- SDL_DriverGamesir_Context *ctx = (SDL_DriverGamesir_Context *)device->context;
|
|
|
- if (!ctx) {
|
|
|
- return false;
|
|
|
- }
|
|
|
+ // FIXME: This is the same report as rumble above, is this intentional?
|
|
|
Uint8 buf[64];
|
|
|
SDL_zero(buf);
|
|
|
buf[0] = 0xA2;
|
|
|
@@ -537,7 +460,6 @@ static bool HIDAPI_DriverGameSir_RumbleJoystickTriggers(SDL_HIDAPI_Device *devic
|
|
|
buf[5] = (Uint8)(right_rumble / 256);
|
|
|
|
|
|
SDL_hid_device *handle = HIDAPI_DriverGameSir_GetOutputHandle(device);
|
|
|
- SDL_assert(handle != NULL);
|
|
|
if (handle == NULL) {
|
|
|
return false;
|
|
|
}
|
|
|
@@ -546,7 +468,6 @@ static bool HIDAPI_DriverGameSir_RumbleJoystickTriggers(SDL_HIDAPI_Device *devic
|
|
|
if (result < 0) {
|
|
|
return false;
|
|
|
}
|
|
|
-
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
@@ -564,17 +485,12 @@ static Uint32 HIDAPI_DriverGameSir_GetJoystickCapabilities(SDL_HIDAPI_Device *de
|
|
|
|
|
|
static bool HIDAPI_DriverGameSir_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
|
|
|
{
|
|
|
- if (!device) {
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
SDL_DriverGamesir_Context *ctx = (SDL_DriverGamesir_Context *)device->context;
|
|
|
- if (!ctx) {
|
|
|
- return false;
|
|
|
- }
|
|
|
+
|
|
|
if (!ctx->led_supported) {
|
|
|
return SDL_Unsupported();
|
|
|
}
|
|
|
+
|
|
|
Uint8 buf[64];
|
|
|
SDL_zero(buf);
|
|
|
buf[0] = 0xA2;
|
|
|
@@ -585,7 +501,6 @@ static bool HIDAPI_DriverGameSir_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_J
|
|
|
buf[5] = green;
|
|
|
buf[6] = blue;
|
|
|
SDL_hid_device *handle = HIDAPI_DriverGameSir_GetOutputHandle(device);
|
|
|
- SDL_assert(handle != NULL);
|
|
|
if (handle == NULL) {
|
|
|
return false;
|
|
|
}
|
|
|
@@ -594,7 +509,6 @@ static bool HIDAPI_DriverGameSir_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_J
|
|
|
if (result < 0) {
|
|
|
return false;
|
|
|
}
|
|
|
-
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
@@ -606,7 +520,7 @@ static bool HIDAPI_DriverGameSir_SendJoystickEffect(SDL_HIDAPI_Device *device, S
|
|
|
static bool HIDAPI_DriverGameSir_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, bool enabled)
|
|
|
{
|
|
|
SDL_DriverGamesir_Context *ctx = (SDL_DriverGamesir_Context *)device->context;
|
|
|
- if (ctx && ctx->sensors_supported) {
|
|
|
+ if (ctx->sensors_supported) {
|
|
|
ctx->sensors_enabled = enabled;
|
|
|
return true;
|
|
|
}
|
|
|
@@ -645,11 +559,6 @@ static void HIDAPI_DriverGameSir_HandleStatePacket(SDL_Joystick *joystick, SDL_D
|
|
|
{
|
|
|
Sint16 axis;
|
|
|
Uint64 timestamp = SDL_GetTicksNS();
|
|
|
-
|
|
|
- if (!joystick || !ctx || !data || size <= 0) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
const Uint8 *last = ctx->last_state;
|
|
|
bool is_initial_packet = !ctx->last_state_initialized;
|
|
|
|
|
|
@@ -907,72 +816,47 @@ static void HIDAPI_DriverGameSir_HandleStatePacket(SDL_Joystick *joystick, SDL_D
|
|
|
|
|
|
static bool HIDAPI_DriverGameSir_UpdateDevice(SDL_HIDAPI_Device *device)
|
|
|
{
|
|
|
- if (!device) {
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
SDL_DriverGamesir_Context *ctx = (SDL_DriverGamesir_Context *)device->context;
|
|
|
- if (!ctx) {
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
SDL_Joystick *joystick = NULL;
|
|
|
Uint8 data[USB_PACKET_LENGTH];
|
|
|
int size;
|
|
|
|
|
|
if (device->num_joysticks > 0) {
|
|
|
joystick = SDL_GetJoystickFromID(device->joysticks[0]);
|
|
|
- if (!joystick) {
|
|
|
- return false;
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
SDL_hid_device *handle = HIDAPI_DriverGameSir_GetInputHandle(device, ctx);
|
|
|
- SDL_assert(handle != NULL);
|
|
|
if (handle == NULL) {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
while ((size = SDL_hid_read_timeout(handle, data, sizeof(data), 0)) > 0) {
|
|
|
- if (joystick) {
|
|
|
- Uint8 *payload = NULL;
|
|
|
- int payload_size = 0;
|
|
|
-
|
|
|
- // Check packet format: it may include a report ID (0x43) as the first byte
|
|
|
- // Actual packet format: 43 a1 c8 [button data...]
|
|
|
- // If the first byte is 0x43, the second is 0xA1 and the third is 0xC8, skip the report ID
|
|
|
- if (size >= 3 && data[0] == 0x43 && data[1] == GAMESIR_PACKET_HEADER_0 && data[2] == GAMESIR_PACKET_HEADER_1_GAMEPAD) {
|
|
|
- payload = data + 3;
|
|
|
- payload_size = size - 3;
|
|
|
- } else if (size >= 2 && data[0] == GAMESIR_PACKET_HEADER_0 && data[1] == GAMESIR_PACKET_HEADER_1_GAMEPAD) {
|
|
|
- payload = data + 2;
|
|
|
- payload_size = size - 2;
|
|
|
- }
|
|
|
+#ifdef DEBUG_GAMESIR_PROTOCOL
|
|
|
+ HIDAPI_DumpPacket("GameSir packet: size = %d", data, size);
|
|
|
+#endif
|
|
|
+ if (!joystick) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
|
|
|
- if (payload) {
|
|
|
- HIDAPI_DriverGameSir_HandleStatePacket(joystick, ctx, payload, payload_size);
|
|
|
- }
|
|
|
+ // Check packet format: it may include a report ID (0x43) as the first byte
|
|
|
+ // Actual packet format: 43 a1 c8 [button data...]
|
|
|
+ // If the first byte is 0x43, the second is 0xA1 and the third is 0xC8, skip the report ID
|
|
|
+ Uint8 *payload = NULL;
|
|
|
+ int payload_size = 0;
|
|
|
+ if (size >= 3 && data[0] == 0x43 && data[1] == GAMESIR_PACKET_HEADER_0 && data[2] == GAMESIR_PACKET_HEADER_1_GAMEPAD) {
|
|
|
+ payload = data + 3;
|
|
|
+ payload_size = size - 3;
|
|
|
+ } else if (size >= 2 && data[0] == GAMESIR_PACKET_HEADER_0 && data[1] == GAMESIR_PACKET_HEADER_1_GAMEPAD) {
|
|
|
+ payload = data + 2;
|
|
|
+ payload_size = size - 2;
|
|
|
+ }
|
|
|
+ if (payload) {
|
|
|
+ HIDAPI_DriverGameSir_HandleStatePacket(joystick, ctx, payload, payload_size);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if (size < 0) {
|
|
|
- if (device->product_id == USB_PRODUCT_GAMESIR_GAMEPAD_G7_PRO_HID) {
|
|
|
- if (device->is_bluetooth) {
|
|
|
- SDL_LogDebug(SDL_LOG_CATEGORY_INPUT, "GameSir: Device disconnected - Connection type was: Bluetooth (wireless, HID mode)");
|
|
|
- } else {
|
|
|
- SDL_LogDebug(SDL_LOG_CATEGORY_INPUT, "GameSir: Device disconnected - Connection type was: USB/2.4G (HID mode)");
|
|
|
- }
|
|
|
- } else if (device->product_id == USB_PRODUCT_GAMESIR_GAMEPAD_G7_PRO_8K_HID) {
|
|
|
- if (device->is_bluetooth) {
|
|
|
- SDL_LogDebug(SDL_LOG_CATEGORY_INPUT, "GameSir: Device disconnected - Connection type was: Bluetooth (wireless, 8K HID mode)");
|
|
|
- } else {
|
|
|
- SDL_LogDebug(SDL_LOG_CATEGORY_INPUT, "GameSir: Device disconnected - Connection type was: USB/2.4G (8K HID mode)");
|
|
|
- }
|
|
|
- } else if (device->is_bluetooth) {
|
|
|
- SDL_LogDebug(SDL_LOG_CATEGORY_INPUT, "GameSir: Device disconnected - Connection type was: Bluetooth (wireless)");
|
|
|
- } else {
|
|
|
- SDL_LogDebug(SDL_LOG_CATEGORY_INPUT, "GameSir: Device disconnected - Connection type was: USB (wired)");
|
|
|
- }
|
|
|
+ if (size < 0 && device->num_joysticks > 0) {
|
|
|
+ // Read error, device is disconnected
|
|
|
HIDAPI_JoystickDisconnected(device, device->joysticks[0]);
|
|
|
}
|
|
|
return (size >= 0);
|
|
|
@@ -1017,6 +901,6 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverGameSir = {
|
|
|
HIDAPI_DriverGameSir_FreeDevice,
|
|
|
};
|
|
|
|
|
|
-#endif
|
|
|
+#endif // SDL_JOYSTICK_HIDAPI_GAMESIR
|
|
|
|
|
|
-#endif
|
|
|
+#endif // SDL_JOYSTICK_HIDAPI
|