|
@@ -27,12 +27,13 @@
|
|
|
|
|
|
#include "SDL_hidapijoystick_c.h"
|
|
|
#include "SDL_hidapi_rumble.h"
|
|
|
+#include "SDL_hidapi_sinput.h"
|
|
|
|
|
|
#ifdef SDL_JOYSTICK_HIDAPI_SINPUT
|
|
|
|
|
|
/*****************************************************************************************************/
|
|
|
// This protocol is documented at:
|
|
|
-// https://docs.handheldlegend.com/s/sinput/doc/sinput-hid-protocol-TkPYWlDMAg
|
|
|
+// https://docs.handheldlegend.com/s/sinput
|
|
|
/*****************************************************************************************************/
|
|
|
|
|
|
// Define this if you want to log all packets from the controller
|
|
@@ -119,6 +120,39 @@
|
|
|
#define SINPUT_BUTTON_IDX_MISC9 30
|
|
|
#define SINPUT_BUTTON_IDX_MISC10 31
|
|
|
|
|
|
+#define SINPUT_BUTTONMASK_EAST 0x01
|
|
|
+#define SINPUT_BUTTONMASK_SOUTH 0x02
|
|
|
+#define SINPUT_BUTTONMASK_NORTH 0x04
|
|
|
+#define SINPUT_BUTTONMASK_WEST 0x08
|
|
|
+#define SINPUT_BUTTONMASK_DPAD_UP 0x10
|
|
|
+#define SINPUT_BUTTONMASK_DPAD_DOWN 0x20
|
|
|
+#define SINPUT_BUTTONMASK_DPAD_LEFT 0x40
|
|
|
+#define SINPUT_BUTTONMASK_DPAD_RIGHT 0x80
|
|
|
+#define SINPUT_BUTTONMASK_LEFT_STICK 0x01
|
|
|
+#define SINPUT_BUTTONMASK_RIGHT_STICK 0x02
|
|
|
+#define SINPUT_BUTTONMASK_LEFT_BUMPER 0x04
|
|
|
+#define SINPUT_BUTTONMASK_RIGHT_BUMPER 0x08
|
|
|
+#define SINPUT_BUTTONMASK_LEFT_TRIGGER 0x10
|
|
|
+#define SINPUT_BUTTONMASK_RIGHT_TRIGGER 0x20
|
|
|
+#define SINPUT_BUTTONMASK_LEFT_PADDLE1 0x40
|
|
|
+#define SINPUT_BUTTONMASK_RIGHT_PADDLE1 0x80
|
|
|
+#define SINPUT_BUTTONMASK_START 0x01
|
|
|
+#define SINPUT_BUTTONMASK_BACK 0x02
|
|
|
+#define SINPUT_BUTTONMASK_GUIDE 0x04
|
|
|
+#define SINPUT_BUTTONMASK_CAPTURE 0x08
|
|
|
+#define SINPUT_BUTTONMASK_LEFT_PADDLE2 0x10
|
|
|
+#define SINPUT_BUTTONMASK_RIGHT_PADDLE2 0x20
|
|
|
+#define SINPUT_BUTTONMASK_TOUCHPAD1 0x40
|
|
|
+#define SINPUT_BUTTONMASK_TOUCHPAD2 0x80
|
|
|
+#define SINPUT_BUTTONMASK_POWER 0x01
|
|
|
+#define SINPUT_BUTTONMASK_MISC4 0x02
|
|
|
+#define SINPUT_BUTTONMASK_MISC5 0x04
|
|
|
+#define SINPUT_BUTTONMASK_MISC6 0x08
|
|
|
+#define SINPUT_BUTTONMASK_MISC7 0x10
|
|
|
+#define SINPUT_BUTTONMASK_MISC8 0x20
|
|
|
+#define SINPUT_BUTTONMASK_MISC9 0x40
|
|
|
+#define SINPUT_BUTTONMASK_MISC10 0x80
|
|
|
+
|
|
|
#define SINPUT_REPORT_IDX_COMMAND_RESPONSE_ID 1
|
|
|
#define SINPUT_REPORT_IDX_COMMAND_RESPONSE_BULK 2
|
|
|
|
|
@@ -139,7 +173,6 @@
|
|
|
#define EXTRACTUINT32(data, idx) ((Uint32)((data)[(idx)] | ((data)[(idx) + 1] << 8) | ((data)[(idx) + 2] << 16) | ((data)[(idx) + 3] << 24)))
|
|
|
#endif
|
|
|
|
|
|
-
|
|
|
typedef struct
|
|
|
{
|
|
|
uint8_t type;
|
|
@@ -183,6 +216,7 @@ typedef struct
|
|
|
{
|
|
|
SDL_HIDAPI_Device *device;
|
|
|
Uint16 protocol_version;
|
|
|
+ Uint16 usb_device_version;
|
|
|
bool sensors_enabled;
|
|
|
|
|
|
Uint8 player_idx;
|
|
@@ -203,8 +237,8 @@ typedef struct
|
|
|
Uint8 touchpad_count; // 2 touchpads maximum
|
|
|
Uint8 touchpad_finger_count; // 2 fingers for one touchpad, or 1 per touchpad (2 max)
|
|
|
|
|
|
- Uint8 polling_rate_ms;
|
|
|
- Uint8 sub_type; // Subtype of the device, 0 in most cases
|
|
|
+ Uint16 polling_rate_us;
|
|
|
+ Uint8 sub_product; // Subtype of the device, 0 in most cases
|
|
|
|
|
|
Uint16 accelRange; // Example would be 2,4,8,16 +/- (g-force)
|
|
|
Uint16 gyroRange; // Example would be 1000,2000,4000 +/- (degrees per second)
|
|
@@ -213,6 +247,7 @@ typedef struct
|
|
|
float gyroScale; // Scale factor for gyroscope values
|
|
|
Uint8 last_state[USB_PACKET_LENGTH];
|
|
|
|
|
|
+ Uint8 axes_count;
|
|
|
Uint8 buttons_count;
|
|
|
Uint8 usage_masks[4];
|
|
|
|
|
@@ -233,6 +268,172 @@ static inline float CalculateAccelScale(uint16_t g_range)
|
|
|
return SDL_STANDARD_GRAVITY / (32768.0f / (float)g_range);
|
|
|
}
|
|
|
|
|
|
+// This function uses base-n encoding to encode features into the version GUID bytes
|
|
|
+// that properly represents the supported device features
|
|
|
+// This also sets the driver context button mask correctly based on the features
|
|
|
+static void DeviceDynamicEncodingSetup(SDL_HIDAPI_Device *device)
|
|
|
+{
|
|
|
+ SDL_DriverSInput_Context *ctx = device->context;
|
|
|
+
|
|
|
+ // A new button mask is generated to provide
|
|
|
+ // SDL with a mapping string that is sane. In case of
|
|
|
+ // an unconventional gamepad setup, the closest sane
|
|
|
+ // mapping is provided to the driver.
|
|
|
+ Uint8 mask[4] = { 0 };
|
|
|
+
|
|
|
+ // For all gamepads, there is a minimum SInput expectation
|
|
|
+ // to have dpad, abxy, and start buttons
|
|
|
+
|
|
|
+ // ABXY + D-Pad
|
|
|
+ mask[0] = 0xFF;
|
|
|
+ ctx->dpad_supported = true;
|
|
|
+
|
|
|
+ // Start button
|
|
|
+ mask[2] |= SINPUT_BUTTONMASK_START;
|
|
|
+
|
|
|
+ // Bumpers
|
|
|
+ bool left_bumper = (ctx->usage_masks[1] & SINPUT_BUTTONMASK_LEFT_BUMPER) != 0;
|
|
|
+ bool right_bumper = (ctx->usage_masks[1] & SINPUT_BUTTONMASK_RIGHT_BUMPER) != 0;
|
|
|
+
|
|
|
+ int bumperStyle = SINPUT_BUMPERSTYLE_NONE;
|
|
|
+ if (left_bumper && right_bumper) {
|
|
|
+ bumperStyle = SINPUT_BUMPERSTYLE_TWO;
|
|
|
+ mask[1] |= (SINPUT_BUTTONMASK_LEFT_BUMPER | SINPUT_BUTTONMASK_RIGHT_BUMPER);
|
|
|
+ } else if (left_bumper || right_bumper) {
|
|
|
+ bumperStyle = SINPUT_BUMPERSTYLE_ONE;
|
|
|
+
|
|
|
+ if (left_bumper) {
|
|
|
+ mask[1] |= SINPUT_BUTTONMASK_LEFT_BUMPER;
|
|
|
+ } else if (right_bumper) {
|
|
|
+ mask[1] |= SINPUT_BUTTONMASK_RIGHT_BUMPER;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Trigger bits live in mask[1]
|
|
|
+ bool digital_triggers = (ctx->usage_masks[1] & (SINPUT_BUTTONMASK_LEFT_TRIGGER | SINPUT_BUTTONMASK_RIGHT_TRIGGER)) != 0;
|
|
|
+
|
|
|
+ bool analog_triggers = ctx->left_analog_trigger_supported || ctx->right_analog_trigger_supported;
|
|
|
+
|
|
|
+ // Touchpads
|
|
|
+ bool t1 = (ctx->usage_masks[2] & SINPUT_BUTTONMASK_TOUCHPAD1) != 0;
|
|
|
+ bool t2 = (ctx->usage_masks[2] & SINPUT_BUTTONMASK_TOUCHPAD2) != 0;
|
|
|
+
|
|
|
+ int analogStyle = SINPUT_ANALOGSTYLE_NONE;
|
|
|
+ if (ctx->left_analog_stick_supported && ctx->right_analog_stick_supported) {
|
|
|
+ analogStyle = SINPUT_ANALOGSTYLE_LEFTRIGHT;
|
|
|
+ mask[1] |= (SINPUT_BUTTONMASK_LEFT_STICK | SINPUT_BUTTONMASK_RIGHT_STICK);
|
|
|
+ } else if (ctx->left_analog_stick_supported) {
|
|
|
+ analogStyle = SINPUT_ANALOGSTYLE_LEFTONLY;
|
|
|
+ mask[1] |= SINPUT_BUTTONMASK_LEFT_STICK;
|
|
|
+ } else if (ctx->right_analog_stick_supported) {
|
|
|
+ analogStyle = SINPUT_ANALOGSTYLE_RIGHTONLY;
|
|
|
+ mask[1] |= SINPUT_BUTTONMASK_RIGHT_STICK;
|
|
|
+ }
|
|
|
+
|
|
|
+ int triggerStyle = SINPUT_TRIGGERSTYLE_NONE;
|
|
|
+
|
|
|
+ if (analog_triggers && digital_triggers) {
|
|
|
+ // When we have both analog triggers and digital triggers
|
|
|
+ // this is interpreted as having dual-stage triggers
|
|
|
+ triggerStyle = SINPUT_TRIGGERSTYLE_DUALSTAGE;
|
|
|
+ mask[1] |= (SINPUT_BUTTONMASK_LEFT_TRIGGER | SINPUT_BUTTONMASK_RIGHT_TRIGGER);
|
|
|
+ } else if (analog_triggers) {
|
|
|
+ triggerStyle = SINPUT_TRIGGERSTYLE_ANALOG;
|
|
|
+ } else if (digital_triggers) {
|
|
|
+ triggerStyle = SINPUT_TRIGGERSTYLE_DIGITAL;
|
|
|
+ mask[1] |= (SINPUT_BUTTONMASK_LEFT_TRIGGER | SINPUT_BUTTONMASK_RIGHT_TRIGGER);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Paddle bits may touch mask[1] and mask[2]
|
|
|
+ bool pg1 = (ctx->usage_masks[1] & (SINPUT_BUTTONMASK_LEFT_PADDLE1 | SINPUT_BUTTONMASK_RIGHT_PADDLE1)) != 0;
|
|
|
+ bool pg2 = (ctx->usage_masks[2] & (SINPUT_BUTTONMASK_LEFT_PADDLE2 | SINPUT_BUTTONMASK_RIGHT_PADDLE2)) != 0;
|
|
|
+
|
|
|
+ int paddleStyle = SINPUT_PADDLESTYLE_NONE;
|
|
|
+ if (pg1 && pg2) {
|
|
|
+ paddleStyle = SINPUT_PADDLESTYLE_FOUR;
|
|
|
+ mask[1] |= (SINPUT_BUTTONMASK_LEFT_PADDLE1 | SINPUT_BUTTONMASK_RIGHT_PADDLE1);
|
|
|
+ mask[2] |= (SINPUT_BUTTONMASK_LEFT_PADDLE2 | SINPUT_BUTTONMASK_RIGHT_PADDLE2);
|
|
|
+ } else if (pg1) {
|
|
|
+ paddleStyle = SINPUT_PADDLESTYLE_TWO;
|
|
|
+ mask[1] |= (SINPUT_BUTTONMASK_LEFT_PADDLE1 | SINPUT_BUTTONMASK_RIGHT_PADDLE1);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ // Meta Buttons (Back, Guide, Share)
|
|
|
+ bool back = (ctx->usage_masks[2] & SINPUT_BUTTONMASK_BACK) != 0;
|
|
|
+ bool guide = (ctx->usage_masks[2] & SINPUT_BUTTONMASK_GUIDE) != 0;
|
|
|
+ bool share = (ctx->usage_masks[2] & SINPUT_BUTTONMASK_CAPTURE) != 0;
|
|
|
+
|
|
|
+ int metaStyle = SINPUT_METASTYLE_NONE;
|
|
|
+ if (share) {
|
|
|
+ metaStyle = SINPUT_METASTYLE_BACKGUIDESHARE;
|
|
|
+ mask[2] |= (SINPUT_BUTTONMASK_BACK | SINPUT_BUTTONMASK_GUIDE | SINPUT_BUTTONMASK_CAPTURE);
|
|
|
+ } else if (guide) {
|
|
|
+ metaStyle = SINPUT_METASTYLE_BACKGUIDE;
|
|
|
+ mask[2] |= (SINPUT_BUTTONMASK_BACK | SINPUT_BUTTONMASK_GUIDE);
|
|
|
+ } else if (back) {
|
|
|
+ metaStyle = SINPUT_METASTYLE_BACK;
|
|
|
+ mask[2] |= (SINPUT_BUTTONMASK_BACK);
|
|
|
+ }
|
|
|
+
|
|
|
+ int touchStyle = SINPUT_TOUCHSTYLE_NONE;
|
|
|
+ if (t1 && t2) {
|
|
|
+ touchStyle = SINPUT_TOUCHSTYLE_DOUBLE;
|
|
|
+ mask[2] |= (SINPUT_BUTTONMASK_TOUCHPAD1 | SINPUT_BUTTONMASK_TOUCHPAD2);
|
|
|
+ } else if (t1) {
|
|
|
+ touchStyle = SINPUT_TOUCHSTYLE_SINGLE;
|
|
|
+ mask[2] |= SINPUT_BUTTONMASK_TOUCHPAD1;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Misc Buttons
|
|
|
+ int miscStyle = SINPUT_MISCSTYLE_NONE;
|
|
|
+ Uint8 extra_misc = ctx->usage_masks[3] & 0x0F;
|
|
|
+ switch (extra_misc) {
|
|
|
+ case 0x0F:
|
|
|
+ miscStyle = SINPUT_MISCSTYLE_4;
|
|
|
+ mask[3] = 0x0F;
|
|
|
+ break;
|
|
|
+ case 0x07:
|
|
|
+ miscStyle = SINPUT_MISCSTYLE_3;
|
|
|
+ mask[3] = 0x07;
|
|
|
+ break;
|
|
|
+ case 0x03:
|
|
|
+ miscStyle = SINPUT_MISCSTYLE_2;
|
|
|
+ mask[3] = 0x03;
|
|
|
+ break;
|
|
|
+ case 0x01:
|
|
|
+ miscStyle = SINPUT_MISCSTYLE_1;
|
|
|
+ mask[3] = 0x01;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ miscStyle = SINPUT_MISCSTYLE_NONE;
|
|
|
+ mask[3] = 0x00;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ int version = analogStyle;
|
|
|
+ version = (version * (int)SINPUT_BUMPERSTYLE_MAX) + bumperStyle;
|
|
|
+ version = (version * (int)SINPUT_TRIGGERSTYLE_MAX) + triggerStyle;
|
|
|
+ version = (version * (int)SINPUT_PADDLESTYLE_MAX) + paddleStyle;
|
|
|
+ version = (version * (int)SINPUT_METASTYLE_MAX) + metaStyle;
|
|
|
+ version = (version * (int)SINPUT_TOUCHSTYLE_MAX) + touchStyle;
|
|
|
+ version = (version * (int)SINPUT_MISCSTYLE_MAX) + miscStyle;
|
|
|
+
|
|
|
+ // Overwrite our button usage masks
|
|
|
+ // with our sanitized masks
|
|
|
+ ctx->usage_masks[0] = mask[0];
|
|
|
+ ctx->usage_masks[1] = mask[1];
|
|
|
+ ctx->usage_masks[2] = mask[2];
|
|
|
+ ctx->usage_masks[3] = mask[3];
|
|
|
+
|
|
|
+ version = SDL_clamp(version, 0, UINT16_MAX);
|
|
|
+
|
|
|
+ // Overwrite 'Version' field of the GUID data
|
|
|
+ device->guid.data[12] = (Uint8)(version & 0xFF);
|
|
|
+ device->guid.data[13] = (Uint8)(version >> 8);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
static void ProcessSDLFeaturesResponse(SDL_HIDAPI_Device *device, Uint8 *data)
|
|
|
{
|
|
|
SDL_DriverSInput_Context *ctx = (SDL_DriverSInput_Context *)device->context;
|
|
@@ -266,46 +467,70 @@ static void ProcessSDLFeaturesResponse(SDL_HIDAPI_Device *device, Uint8 *data)
|
|
|
// The 5 LSB represent a device sub-type
|
|
|
device->guid.data[15] = data[5];
|
|
|
|
|
|
- ctx->sub_type = (data[5] & 0x1F);
|
|
|
+ ctx->sub_product = (data[5] & 0x1F);
|
|
|
|
|
|
#if defined(DEBUG_SINPUT_INIT)
|
|
|
SDL_Log("SInput Face Style: %d", (data[5] & 0xE0) >> 5);
|
|
|
- SDL_Log("SInput Sub-type: %d", (data[5] & 0x1F));
|
|
|
+ SDL_Log("SInput Sub-product: %d", (data[5] & 0x1F));
|
|
|
#endif
|
|
|
|
|
|
- ctx->polling_rate_ms = data[6];
|
|
|
+ ctx->polling_rate_us = EXTRACTUINT16(data, 6);
|
|
|
+
|
|
|
+#if defined(DEBUG_SINPUT_INIT)
|
|
|
+ SDL_Log("SInput polling interval (microseconds): %d", ctx->polling_rate_us);
|
|
|
+#endif
|
|
|
|
|
|
ctx->accelRange = EXTRACTUINT16(data, 8);
|
|
|
ctx->gyroRange = EXTRACTUINT16(data, 10);
|
|
|
|
|
|
+ ctx->usage_masks[0] = data[12];
|
|
|
+ ctx->usage_masks[1] = data[13];
|
|
|
+ ctx->usage_masks[2] = data[14];
|
|
|
+ ctx->usage_masks[3] = data[15];
|
|
|
|
|
|
- if ((device->product_id == USB_PRODUCT_HANDHELDLEGEND_SINPUT_GENERIC) && (device->vendor_id == USB_VENDOR_RASPBERRYPI)) {
|
|
|
- switch (ctx->sub_type) {
|
|
|
- // SInput generic device, exposes all buttons
|
|
|
- default:
|
|
|
- case 0:
|
|
|
- ctx->usage_masks[0] = 0xFF;
|
|
|
- ctx->usage_masks[1] = 0xFF;
|
|
|
- ctx->usage_masks[2] = 0xFF;
|
|
|
- ctx->usage_masks[3] = 0xFF;
|
|
|
- break;
|
|
|
- }
|
|
|
- } else {
|
|
|
- // Masks in LSB to MSB
|
|
|
- // South, East, West, North, DUp, DDown, DLeft, DRight
|
|
|
- ctx->usage_masks[0] = data[12];
|
|
|
+ // Get and validate touchpad parameters
|
|
|
+ ctx->touchpad_count = data[16];
|
|
|
+ ctx->touchpad_finger_count = data[17];
|
|
|
+
|
|
|
+ // Get device Serial - MAC address
|
|
|
+ char serial[18];
|
|
|
+ (void)SDL_snprintf(serial, sizeof(serial), "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x",
|
|
|
+ data[18], data[19], data[20], data[21], data[22], data[23]);
|
|
|
|
|
|
- // Stick Left, Stick Right, L Shoulder, R Shoulder,
|
|
|
- // L Digital Trigger, R Digital Trigger, L Paddle 1, R Paddle 1
|
|
|
- ctx->usage_masks[1] = data[13];
|
|
|
+#if defined(DEBUG_SINPUT_INIT)
|
|
|
+ SDL_Log("Serial num: %s", serial);
|
|
|
+#endif
|
|
|
+ HIDAPI_SetDeviceSerial(device, serial);
|
|
|
+
|
|
|
+#if defined(DEBUG_SINPUT_INIT)
|
|
|
+ SDL_Log("Accelerometer Range: %d", ctx->accelRange);
|
|
|
+#endif
|
|
|
|
|
|
- // Start, Back, Guide, Capture, L Paddle 2, R Paddle 2, Touchpad L, Touchpad R
|
|
|
- ctx->usage_masks[2] = data[14];
|
|
|
+#if defined(DEBUG_SINPUT_INIT)
|
|
|
+ SDL_Log("Gyro Range: %d", ctx->gyroRange);
|
|
|
+#endif
|
|
|
+
|
|
|
+ ctx->accelScale = CalculateAccelScale(ctx->accelRange);
|
|
|
+ ctx->gyroScale = CalculateGyroScale(ctx->gyroRange);
|
|
|
|
|
|
- // Power, Misc 4 to 10
|
|
|
- ctx->usage_masks[3] = data[15];
|
|
|
+ Uint8 axes = 0;
|
|
|
+ if (ctx->left_analog_stick_supported) {
|
|
|
+ axes += 2;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ctx->right_analog_stick_supported) {
|
|
|
+ axes += 2;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ctx->left_analog_trigger_supported || ctx->right_analog_trigger_supported) {
|
|
|
+ // Always add both analog trigger axes if one is present
|
|
|
+ axes += 2;
|
|
|
}
|
|
|
|
|
|
+ ctx->axes_count = axes;
|
|
|
+
|
|
|
+ DeviceDynamicEncodingSetup(device);
|
|
|
+
|
|
|
// Derive button count from mask
|
|
|
for (Uint8 byte = 0; byte < 4; ++byte) {
|
|
|
for (Uint8 bit = 0; bit < 8; ++bit) {
|
|
@@ -329,31 +554,6 @@ static void ProcessSDLFeaturesResponse(SDL_HIDAPI_Device *device, Uint8 *data)
|
|
|
#if defined(DEBUG_SINPUT_INIT)
|
|
|
SDL_Log("Buttons count: %d", ctx->buttons_count);
|
|
|
#endif
|
|
|
-
|
|
|
- // Get and validate touchpad parameters
|
|
|
- ctx->touchpad_count = data[16];
|
|
|
- ctx->touchpad_finger_count = data[17];
|
|
|
-
|
|
|
- // Get device Serial - MAC address
|
|
|
- char serial[18];
|
|
|
- (void)SDL_snprintf(serial, sizeof(serial), "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x",
|
|
|
- data[18], data[19], data[20], data[21], data[22], data[23]);
|
|
|
-
|
|
|
-#if defined(DEBUG_SINPUT_INIT)
|
|
|
- SDL_Log("Serial num: %s", serial);
|
|
|
-#endif
|
|
|
- HIDAPI_SetDeviceSerial(device, serial);
|
|
|
-
|
|
|
-#if defined(DEBUG_SINPUT_INIT)
|
|
|
- SDL_Log("Accelerometer Range: %d", ctx->accelRange);
|
|
|
-#endif
|
|
|
-
|
|
|
-#if defined(DEBUG_SINPUT_INIT)
|
|
|
- SDL_Log("Gyro Range: %d", ctx->gyroRange);
|
|
|
-#endif
|
|
|
-
|
|
|
- ctx->accelScale = CalculateAccelScale(ctx->accelRange);
|
|
|
- ctx->gyroScale = CalculateGyroScale(ctx->gyroRange);
|
|
|
}
|
|
|
|
|
|
static bool RetrieveSDLFeatures(SDL_HIDAPI_Device *device)
|
|
@@ -460,6 +660,9 @@ static bool HIDAPI_DriverSInput_InitDevice(SDL_HIDAPI_Device *device)
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
+ // Store the USB Device Version because we will overwrite this data
|
|
|
+ ctx->usb_device_version = device->version;
|
|
|
+
|
|
|
switch (device->product_id) {
|
|
|
case USB_PRODUCT_HANDHELDLEGEND_GCULTIMATE:
|
|
|
HIDAPI_SetDeviceName(device, "HHL GC Ultimate");
|
|
@@ -467,8 +670,11 @@ static bool HIDAPI_DriverSInput_InitDevice(SDL_HIDAPI_Device *device)
|
|
|
case USB_PRODUCT_HANDHELDLEGEND_PROGCC:
|
|
|
HIDAPI_SetDeviceName(device, "HHL ProGCC");
|
|
|
break;
|
|
|
+ case USB_PRODUCT_VOIDGAMING_PS4FIREBIRD:
|
|
|
+ HIDAPI_SetDeviceName(device, "Void Gaming PS4 FireBird");
|
|
|
+ break;
|
|
|
case USB_PRODUCT_BONZIRICHANNEL_FIREBIRD:
|
|
|
- HIDAPI_SetDeviceName(device, "Bonziri Firebird");
|
|
|
+ HIDAPI_SetDeviceName(device, "Bonziri FireBird");
|
|
|
break;
|
|
|
case USB_PRODUCT_HANDHELDLEGEND_SINPUT_GENERIC:
|
|
|
default:
|
|
@@ -523,45 +729,18 @@ static bool HIDAPI_DriverSInput_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joys
|
|
|
|
|
|
SDL_zeroa(ctx->last_state);
|
|
|
|
|
|
- int axes = 0;
|
|
|
- if (ctx->left_analog_stick_supported) {
|
|
|
- axes += 2;
|
|
|
- }
|
|
|
-
|
|
|
- if (ctx->right_analog_stick_supported) {
|
|
|
- axes += 2;
|
|
|
- }
|
|
|
-
|
|
|
- if (ctx->left_analog_trigger_supported) {
|
|
|
- ++axes;
|
|
|
- }
|
|
|
-
|
|
|
- if (ctx->right_analog_trigger_supported) {
|
|
|
- ++axes;
|
|
|
- }
|
|
|
-
|
|
|
- if ((device->product_id == USB_PRODUCT_HANDHELDLEGEND_SINPUT_GENERIC) && (device->vendor_id == USB_VENDOR_RASPBERRYPI)) {
|
|
|
- switch (ctx->sub_type) {
|
|
|
- // Default generic device, exposes all axes
|
|
|
- default:
|
|
|
- case 0:
|
|
|
- axes = 6;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- joystick->naxes = axes;
|
|
|
+ joystick->naxes = ctx->axes_count;
|
|
|
|
|
|
if (ctx->dpad_supported) {
|
|
|
joystick->nhats = 1;
|
|
|
}
|
|
|
|
|
|
if (ctx->accelerometer_supported) {
|
|
|
- SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL, 1000.0f / ctx->polling_rate_ms);
|
|
|
+ SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL, 1000000.0f / ctx->polling_rate_us);
|
|
|
}
|
|
|
|
|
|
if (ctx->gyroscope_supported) {
|
|
|
- SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO, 1000.0f / ctx->polling_rate_ms);
|
|
|
+ SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO, 1000000.0f / ctx->polling_rate_us);
|
|
|
}
|
|
|
|
|
|
if (ctx->touchpad_supported) {
|