early-access version 2281

This commit is contained in:
pineappleEA
2021-12-07 02:20:09 +01:00
parent c2ae6d480a
commit c4fa174d53
591 changed files with 36978 additions and 18653 deletions

View File

@@ -32,7 +32,7 @@
#include "../SDL_sysjoystick.h"
#include "SDL_hidapijoystick_c.h"
#include "SDL_hidapi_rumble.h"
#include "../../hidapi/SDL_hidapi.h"
#include "../../hidapi/SDL_hidapi_c.h"
#ifdef SDL_JOYSTICK_HIDAPI_GAMECUBE
@@ -129,7 +129,7 @@ HIDAPI_DriverGameCube_InitDevice(SDL_HIDAPI_Device *device)
return SDL_FALSE;
}
device->dev = hid_open_path(device->path, 0);
device->dev = SDL_hid_open_path(device->path, 0);
if (!device->dev) {
SDL_free(ctx);
SDL_SetError("Couldn't open %s", device->path);
@@ -154,7 +154,7 @@ HIDAPI_DriverGameCube_InitDevice(SDL_HIDAPI_Device *device)
}
} else {
/* This is all that's needed to initialize the device. Really! */
if (hid_write(device->dev, &initMagic, sizeof(initMagic)) != sizeof(initMagic)) {
if (SDL_hid_write(device->dev, &initMagic, sizeof(initMagic)) != sizeof(initMagic)) {
SDL_SetError("Couldn't initialize WUP-028");
goto error;
}
@@ -163,7 +163,7 @@ HIDAPI_DriverGameCube_InitDevice(SDL_HIDAPI_Device *device)
SDL_Delay(10);
/* Add all the applicable joysticks */
while ((size = hid_read_timeout(device->dev, packet, sizeof(packet), 0)) > 0) {
while ((size = SDL_hid_read_timeout(device->dev, packet, sizeof(packet), 0)) > 0) {
#ifdef DEBUG_GAMECUBE_PROTOCOL
HIDAPI_DumpPacket("Nintendo GameCube packet: size = %d", packet, size);
#endif
@@ -204,7 +204,7 @@ error:
SDL_LockMutex(device->dev_lock);
{
if (device->dev) {
hid_close(device->dev);
SDL_hid_close(device->dev);
device->dev = NULL;
}
if (device->context) {
@@ -389,7 +389,7 @@ HIDAPI_DriverGameCube_UpdateDevice(SDL_HIDAPI_Device *device)
int size;
/* Read input packet */
while ((size = hid_read_timeout(device->dev, packet, sizeof(packet), 0)) > 0) {
while ((size = SDL_hid_read_timeout(device->dev, packet, sizeof(packet), 0)) > 0) {
#ifdef DEBUG_GAMECUBE_PROTOCOL
//HIDAPI_DumpPacket("Nintendo GameCube packet: size = %d", packet, size);
#endif
@@ -464,10 +464,26 @@ HIDAPI_DriverGameCube_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SDL_Joys
return SDL_Unsupported();
}
static SDL_bool
HIDAPI_DriverGameCube_HasJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
static Uint32
HIDAPI_DriverGameCube_GetJoystickCapabilities(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
{
return SDL_FALSE;
SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)device->context;
Uint32 result = 0;
if (!ctx->pc_mode) {
Uint8 i;
for (i = 0; i < MAX_CONTROLLERS; i += 1) {
if (joystick->instance_id == ctx->joysticks[i]) {
if (!ctx->wireless[i] && ctx->rumbleAllowed[i]) {
result |= SDL_JOYCAP_RUMBLE;
break;
}
}
}
}
return result;
}
static int
@@ -510,7 +526,7 @@ HIDAPI_DriverGameCube_FreeDevice(SDL_HIDAPI_Device *device)
SDL_LockMutex(device->dev_lock);
{
hid_close(device->dev);
SDL_hid_close(device->dev);
device->dev = NULL;
SDL_free(device->context);
@@ -523,6 +539,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverGameCube =
{
SDL_HINT_JOYSTICK_HIDAPI_GAMECUBE,
SDL_TRUE,
SDL_TRUE,
HIDAPI_DriverGameCube_IsSupportedDevice,
HIDAPI_DriverGameCube_GetDeviceName,
HIDAPI_DriverGameCube_InitDevice,
@@ -532,7 +549,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverGameCube =
HIDAPI_DriverGameCube_OpenJoystick,
HIDAPI_DriverGameCube_RumbleJoystick,
HIDAPI_DriverGameCube_RumbleJoystickTriggers,
HIDAPI_DriverGameCube_HasJoystickLED,
HIDAPI_DriverGameCube_GetJoystickCapabilities,
HIDAPI_DriverGameCube_SetJoystickLED,
HIDAPI_DriverGameCube_SendJoystickEffect,
HIDAPI_DriverGameCube_SetJoystickSensorsEnabled,

View File

@@ -87,7 +87,7 @@ HIDAPI_DriverLuna_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick
return SDL_FALSE;
}
device->dev = hid_open_path(device->path, 0);
device->dev = SDL_hid_open_path(device->path, 0);
if (!device->dev) {
SDL_SetError("Couldn't open %s", device->path);
SDL_free(ctx);
@@ -132,10 +132,16 @@ HIDAPI_DriverLuna_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SDL_Joystick
return SDL_Unsupported();
}
static SDL_bool
HIDAPI_DriverLuna_HasJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
static Uint32
HIDAPI_DriverLuna_GetJoystickCapabilities(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
{
return SDL_FALSE;
Uint32 result = 0;
if (device->product_id == BLUETOOTH_PRODUCT_LUNA_CONTROLLER) {
result |= SDL_JOYCAP_RUMBLE;
}
return result;
}
static int
@@ -386,7 +392,7 @@ HIDAPI_DriverLuna_UpdateDevice(SDL_HIDAPI_Device *device)
return SDL_FALSE;
}
while ((size = hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
while ((size = SDL_hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
#ifdef DEBUG_LUNA_PROTOCOL
HIDAPI_DumpPacket("Amazon Luna packet: size = %d", data, size);
#endif
@@ -413,7 +419,7 @@ HIDAPI_DriverLuna_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystic
SDL_LockMutex(device->dev_lock);
{
if (device->dev) {
hid_close(device->dev);
SDL_hid_close(device->dev);
device->dev = NULL;
}
@@ -432,6 +438,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverLuna =
{
SDL_HINT_JOYSTICK_HIDAPI_LUNA,
SDL_TRUE,
SDL_TRUE,
HIDAPI_DriverLuna_IsSupportedDevice,
HIDAPI_DriverLuna_GetDeviceName,
HIDAPI_DriverLuna_InitDevice,
@@ -441,7 +448,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverLuna =
HIDAPI_DriverLuna_OpenJoystick,
HIDAPI_DriverLuna_RumbleJoystick,
HIDAPI_DriverLuna_RumbleJoystickTriggers,
HIDAPI_DriverLuna_HasJoystickLED,
HIDAPI_DriverLuna_GetJoystickCapabilities,
HIDAPI_DriverLuna_SetJoystickLED,
HIDAPI_DriverLuna_SendJoystickEffect,
HIDAPI_DriverLuna_SetJoystickSensorsEnabled,

View File

@@ -163,11 +163,11 @@ HIDAPI_DriverPS4_GetDeviceName(Uint16 vendor_id, Uint16 product_id)
return NULL;
}
static int ReadFeatureReport(hid_device *dev, Uint8 report_id, Uint8 *report, size_t length)
static int ReadFeatureReport(SDL_hid_device *dev, Uint8 report_id, Uint8 *report, size_t length)
{
SDL_memset(report, 0, length);
report[0] = report_id;
return hid_get_feature_report(dev, report, length);
return SDL_hid_get_feature_report(dev, report, length);
}
static SDL_bool HIDAPI_DriverPS4_CanRumble(Uint16 vendor_id, Uint16 product_id)
@@ -415,7 +415,7 @@ HIDAPI_DriverPS4_TickleBluetooth(SDL_HIDAPI_Device *device)
/* This is just a dummy packet that should have no effect, since we don't set the CRC */
Uint8 data[78];
SDL_zero(data);
SDL_zeroa(data);
data[0] = k_EPS4ReportIdBluetoothEffects;
data[1] = 0xC0; /* Magic value HID + CRC */
@@ -479,7 +479,7 @@ HIDAPI_DriverPS4_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
ctx->joystick = joystick;
ctx->last_packet = SDL_GetTicks();
device->dev = hid_open_path(device->path, 0);
device->dev = SDL_hid_open_path(device->path, 0);
if (!device->dev) {
SDL_free(ctx);
SDL_SetError("Couldn't open %s", device->path);
@@ -511,7 +511,7 @@ HIDAPI_DriverPS4_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
ctx->is_bluetooth = SDL_TRUE;
/* Read a report to see if we're in enhanced mode */
size = hid_read_timeout(device->dev, data, sizeof(data), 16);
size = SDL_hid_read_timeout(device->dev, data, sizeof(data), 16);
#ifdef DEBUG_PS4_PROTOCOL
if (size > 0) {
HIDAPI_DumpPacket("PS4 first packet: size = %d", data, size);
@@ -598,10 +598,17 @@ HIDAPI_DriverPS4_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SDL_Joystick
return SDL_Unsupported();
}
static SDL_bool
HIDAPI_DriverPS4_HasJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
static Uint32
HIDAPI_DriverPS4_GetJoystickCapabilities(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
{
return SDL_TRUE;
SDL_DriverPS4_Context *ctx = (SDL_DriverPS4_Context *)device->context;
Uint32 result = 0;
if (ctx->enhanced_mode && ctx->effects_supported) {
result |= SDL_JOYCAP_LED | SDL_JOYCAP_RUMBLE;
}
return result;
}
static int
@@ -632,7 +639,7 @@ HIDAPI_DriverPS4_SendJoystickEffect(SDL_HIDAPI_Device *device, SDL_Joystick *joy
HIDAPI_DriverPS4_SetEnhancedMode(device, joystick);
}
SDL_zero(data);
SDL_zeroa(data);
if (ctx->is_bluetooth) {
data[0] = k_EPS4ReportIdBluetoothEffects;
@@ -684,7 +691,7 @@ HIDAPI_DriverPS4_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *device, SDL_Joysti
}
static void
HIDAPI_DriverPS4_HandleStatePacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverPS4_Context *ctx, PS4StatePacket_t *packet)
HIDAPI_DriverPS4_HandleStatePacket(SDL_Joystick *joystick, SDL_hid_device *dev, SDL_DriverPS4_Context *ctx, PS4StatePacket_t *packet)
{
static const float TOUCHPAD_SCALEX = 1.0f / 1920;
static const float TOUCHPAD_SCALEY = 1.0f / 920; /* This is noted as being 944 resolution, but 920 feels better */
@@ -846,7 +853,7 @@ HIDAPI_DriverPS4_UpdateDevice(SDL_HIDAPI_Device *device)
return SDL_FALSE;
}
while ((size = hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
while ((size = SDL_hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
#ifdef DEBUG_PS4_PROTOCOL
HIDAPI_DumpPacket("PS4 packet: size = %d", data, size);
#endif
@@ -908,7 +915,7 @@ HIDAPI_DriverPS4_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick
SDL_LockMutex(device->dev_lock);
{
hid_close(device->dev);
SDL_hid_close(device->dev);
device->dev = NULL;
SDL_free(device->context);
@@ -926,6 +933,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverPS4 =
{
SDL_HINT_JOYSTICK_HIDAPI_PS4,
SDL_TRUE,
SDL_TRUE,
HIDAPI_DriverPS4_IsSupportedDevice,
HIDAPI_DriverPS4_GetDeviceName,
HIDAPI_DriverPS4_InitDevice,
@@ -935,7 +943,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverPS4 =
HIDAPI_DriverPS4_OpenJoystick,
HIDAPI_DriverPS4_RumbleJoystick,
HIDAPI_DriverPS4_RumbleJoystickTriggers,
HIDAPI_DriverPS4_HasJoystickLED,
HIDAPI_DriverPS4_GetJoystickCapabilities,
HIDAPI_DriverPS4_SetJoystickLED,
HIDAPI_DriverPS4_SendJoystickEffect,
HIDAPI_DriverPS4_SetJoystickSensorsEnabled,

View File

@@ -192,11 +192,11 @@ HIDAPI_DriverPS5_GetDeviceName(Uint16 vendor_id, Uint16 product_id)
return NULL;
}
static int ReadFeatureReport(hid_device *dev, Uint8 report_id, Uint8 *report, size_t length)
static int ReadFeatureReport(SDL_hid_device *dev, Uint8 report_id, Uint8 *report, size_t length)
{
SDL_memset(report, 0, length);
report[0] = report_id;
return hid_get_feature_report(dev, report, length);
return SDL_hid_get_feature_report(dev, report, length);
}
static void
@@ -471,7 +471,7 @@ HIDAPI_DriverPS5_TickleBluetooth(SDL_HIDAPI_Device *device)
/* This is just a dummy packet that should have no effect, since we don't set the CRC */
Uint8 data[78];
SDL_zero(data);
SDL_zeroa(data);
data[0] = k_EPS5ReportIdBluetoothEffects;
data[1] = 0x02; /* Magic value */
@@ -553,7 +553,7 @@ HIDAPI_DriverPS5_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
ctx->joystick = joystick;
ctx->last_packet = SDL_GetTicks();
device->dev = hid_open_path(device->path, 0);
device->dev = SDL_hid_open_path(device->path, 0);
if (!device->dev) {
SDL_free(ctx);
SDL_SetError("Couldn't open %s", device->path);
@@ -562,7 +562,7 @@ HIDAPI_DriverPS5_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
device->context = ctx;
/* Read a report to see what mode we're in */
size = hid_read_timeout(device->dev, data, sizeof(data), 16);
size = SDL_hid_read_timeout(device->dev, data, sizeof(data), 16);
#ifdef DEBUG_PS5_PROTOCOL
if (size > 0) {
HIDAPI_DumpPacket("PS5 first packet: size = %d", data, size);
@@ -663,10 +663,17 @@ HIDAPI_DriverPS5_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SDL_Joystick
return SDL_Unsupported();
}
static SDL_bool
HIDAPI_DriverPS5_HasJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
static Uint32
HIDAPI_DriverPS5_GetJoystickCapabilities(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
{
return SDL_TRUE;
SDL_DriverPS5_Context *ctx = (SDL_DriverPS5_Context *)device->context;
Uint32 result = 0;
if (ctx->enhanced_mode) {
result |= SDL_JOYCAP_LED | SDL_JOYCAP_RUMBLE;
}
return result;
}
static int
@@ -696,7 +703,7 @@ HIDAPI_DriverPS5_SendJoystickEffect(SDL_HIDAPI_Device *device, SDL_Joystick *joy
HIDAPI_DriverPS5_SetEnhancedMode(device, joystick);
}
SDL_zero(data);
SDL_zeroa(data);
if (ctx->is_bluetooth) {
data[0] = k_EPS5ReportIdBluetoothEffects;
@@ -761,7 +768,7 @@ HIDAPI_DriverPS5_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *device, SDL_Joysti
}
static void
HIDAPI_DriverPS5_HandleSimpleStatePacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverPS5_Context *ctx, PS5SimpleStatePacket_t *packet)
HIDAPI_DriverPS5_HandleSimpleStatePacket(SDL_Joystick *joystick, SDL_hid_device *dev, SDL_DriverPS5_Context *ctx, PS5SimpleStatePacket_t *packet)
{
Sint16 axis;
@@ -855,7 +862,7 @@ HIDAPI_DriverPS5_HandleSimpleStatePacket(SDL_Joystick *joystick, hid_device *dev
}
static void
HIDAPI_DriverPS5_HandleStatePacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverPS5_Context *ctx, PS5StatePacket_t *packet)
HIDAPI_DriverPS5_HandleStatePacket(SDL_Joystick *joystick, SDL_hid_device *dev, SDL_DriverPS5_Context *ctx, PS5StatePacket_t *packet)
{
static const float TOUCHPAD_SCALEX = 1.0f / 1920;
static const float TOUCHPAD_SCALEY = 1.0f / 1070;
@@ -1010,7 +1017,7 @@ HIDAPI_DriverPS5_UpdateDevice(SDL_HIDAPI_Device *device)
return SDL_FALSE;
}
while ((size = hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
while ((size = SDL_hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
#ifdef DEBUG_PS5_PROTOCOL
HIDAPI_DumpPacket("PS5 packet: size = %d", data, size);
#endif
@@ -1071,7 +1078,7 @@ HIDAPI_DriverPS5_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick
SDL_LockMutex(device->dev_lock);
{
hid_close(device->dev);
SDL_hid_close(device->dev);
device->dev = NULL;
SDL_free(device->context);
@@ -1089,6 +1096,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverPS5 =
{
SDL_HINT_JOYSTICK_HIDAPI_PS5,
SDL_TRUE,
SDL_TRUE,
HIDAPI_DriverPS5_IsSupportedDevice,
HIDAPI_DriverPS5_GetDeviceName,
HIDAPI_DriverPS5_InitDevice,
@@ -1098,7 +1106,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverPS5 =
HIDAPI_DriverPS5_OpenJoystick,
HIDAPI_DriverPS5_RumbleJoystick,
HIDAPI_DriverPS5_RumbleJoystickTriggers,
HIDAPI_DriverPS5_HasJoystickLED,
HIDAPI_DriverPS5_GetJoystickCapabilities,
HIDAPI_DriverPS5_SetJoystickLED,
HIDAPI_DriverPS5_SendJoystickEffect,
HIDAPI_DriverPS5_SetJoystickSensorsEnabled,

View File

@@ -80,7 +80,7 @@ static int SDL_HIDAPI_RumbleThread(void *data)
#ifdef DEBUG_RUMBLE
HIDAPI_DumpPacket("Rumble packet: size = %d", request->data, request->size);
#endif
hid_write(request->device->dev, request->data, request->size);
SDL_hid_write(request->device->dev, request->data, request->size);
}
SDL_UnlockMutex(request->device->dev_lock);
(void)SDL_AtomicDecRef(&request->device->rumble_pending);

View File

@@ -88,7 +88,7 @@ HIDAPI_DriverStadia_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joysti
return SDL_FALSE;
}
device->dev = hid_open_path(device->path, 0);
device->dev = SDL_hid_open_path(device->path, 0);
if (!device->dev) {
SDL_SetError("Couldn't open %s", device->path);
SDL_free(ctx);
@@ -126,10 +126,10 @@ HIDAPI_DriverStadia_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SDL_Joysti
return SDL_Unsupported();
}
static SDL_bool
HIDAPI_DriverStadia_HasJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
static Uint32
HIDAPI_DriverStadia_GetJoystickCapabilities(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
{
return SDL_FALSE;
return SDL_JOYCAP_RUMBLE;
}
static int
@@ -267,7 +267,7 @@ HIDAPI_DriverStadia_UpdateDevice(SDL_HIDAPI_Device *device)
return SDL_FALSE;
}
while ((size = hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
while ((size = SDL_hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
#ifdef DEBUG_STADIA_PROTOCOL
HIDAPI_DumpPacket("Google Stadia packet: size = %d", data, size);
#endif
@@ -287,7 +287,7 @@ HIDAPI_DriverStadia_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joyst
SDL_LockMutex(device->dev_lock);
{
if (device->dev) {
hid_close(device->dev);
SDL_hid_close(device->dev);
device->dev = NULL;
}
@@ -306,6 +306,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverStadia =
{
SDL_HINT_JOYSTICK_HIDAPI_STADIA,
SDL_TRUE,
SDL_TRUE,
HIDAPI_DriverStadia_IsSupportedDevice,
HIDAPI_DriverStadia_GetDeviceName,
HIDAPI_DriverStadia_InitDevice,
@@ -315,7 +316,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverStadia =
HIDAPI_DriverStadia_OpenJoystick,
HIDAPI_DriverStadia_RumbleJoystick,
HIDAPI_DriverStadia_RumbleJoystickTriggers,
HIDAPI_DriverStadia_HasJoystickLED,
HIDAPI_DriverStadia_GetJoystickCapabilities,
HIDAPI_DriverStadia_SetJoystickLED,
HIDAPI_DriverStadia_SendJoystickEffect,
HIDAPI_DriverStadia_SetJoystickSensorsEnabled,

View File

@@ -190,7 +190,7 @@ typedef struct
// Wireless firmware quirk: the firmware intentionally signals "failure" when performing
// SET_FEATURE / GET_FEATURE when it actually means "pending radio round-trip". The only
// SET_FEATURE / GET_FEATURE when it actually means "pending radio roundtrip". The only
// way to make SET_FEATURE / GET_FEATURE work is to loop several times with a sleep. If
// it takes more than 50ms to get the response for SET_FEATURE / GET_FEATURE, we assume
// that the controller has failed.
@@ -220,7 +220,7 @@ static void hexdump( const uint8_t *ptr, int len )
static void ResetSteamControllerPacketAssembler( SteamControllerPacketAssembler *pAssembler )
{
memset( pAssembler->uBuffer, 0, sizeof( pAssembler->uBuffer ) );
SDL_memset( pAssembler->uBuffer, 0, sizeof( pAssembler->uBuffer ) );
pAssembler->nExpectedSegmentNumber = 0;
}
@@ -239,6 +239,9 @@ static int WriteSegmentToSteamControllerPacketAssembler( SteamControllerPacketAs
{
if ( pAssembler->bIsBle )
{
uint8_t uSegmentHeader = pSegment[ 1 ];
int nSegmentNumber = uSegmentHeader & 0x07;
HEXDUMP( pSegment, nSegmentLength );
if ( pSegment[ 0 ] != BLE_REPORT_NUMBER )
@@ -255,7 +258,6 @@ static int WriteSegmentToSteamControllerPacketAssembler( SteamControllerPacketAs
return -1;
}
uint8_t uSegmentHeader = pSegment[ 1 ];
DPRINTF("GOT PACKET HEADER = 0x%x\n", uSegmentHeader);
if ( ( uSegmentHeader & REPORT_SEGMENT_DATA_FLAG ) == 0 )
@@ -264,7 +266,6 @@ static int WriteSegmentToSteamControllerPacketAssembler( SteamControllerPacketAs
return 0;
}
int nSegmentNumber = uSegmentHeader & 0x07;
if ( nSegmentNumber != pAssembler->nExpectedSegmentNumber )
{
ResetSteamControllerPacketAssembler( pAssembler );
@@ -278,7 +279,7 @@ static int WriteSegmentToSteamControllerPacketAssembler( SteamControllerPacketAs
}
}
memcpy( pAssembler->uBuffer + nSegmentNumber * MAX_REPORT_SEGMENT_PAYLOAD_SIZE,
SDL_memcpy( pAssembler->uBuffer + nSegmentNumber * MAX_REPORT_SEGMENT_PAYLOAD_SIZE,
pSegment + 2, // ignore header and report number
MAX_REPORT_SEGMENT_PAYLOAD_SIZE );
@@ -293,7 +294,7 @@ static int WriteSegmentToSteamControllerPacketAssembler( SteamControllerPacketAs
else
{
// Just pass through
memcpy( pAssembler->uBuffer,
SDL_memcpy( pAssembler->uBuffer,
pSegment,
nSegmentLength );
return nSegmentLength;
@@ -304,22 +305,23 @@ static int WriteSegmentToSteamControllerPacketAssembler( SteamControllerPacketAs
#define BLE_MAX_READ_RETRIES 8
static int SetFeatureReport( hid_device *dev, unsigned char uBuffer[65], int nActualDataLen )
static int SetFeatureReport( SDL_hid_device *dev, unsigned char uBuffer[65], int nActualDataLen )
{
DPRINTF("SetFeatureReport %p %p %d\n", dev, uBuffer, nActualDataLen);
int nRet = -1;
bool bBle = true; // only wireless/BLE for now, though macOS could do wired in the future
DPRINTF("SetFeatureReport %p %p %d\n", dev, uBuffer, nActualDataLen);
if ( bBle )
{
int nSegmentNumber = 0;
uint8_t uPacketBuffer[ MAX_REPORT_SEGMENT_SIZE ];
unsigned char *pBufferPtr = uBuffer + 1;
if ( nActualDataLen < 1 )
return -1;
int nSegmentNumber = 0;
uint8_t uPacketBuffer[ MAX_REPORT_SEGMENT_SIZE ];
// Skip report number in data
unsigned char *pBufferPtr = uBuffer + 1;
nActualDataLen--;
while ( nActualDataLen > 0 )
@@ -329,15 +331,15 @@ static int SetFeatureReport( hid_device *dev, unsigned char uBuffer[65], int nAc
nActualDataLen -= nBytesInPacket;
// Construct packet
memset( uPacketBuffer, 0, sizeof( uPacketBuffer ) );
SDL_memset( uPacketBuffer, 0, sizeof( uPacketBuffer ) );
uPacketBuffer[ 0 ] = BLE_REPORT_NUMBER;
uPacketBuffer[ 1 ] = GetSegmentHeader( nSegmentNumber, nActualDataLen == 0 );
memcpy( &uPacketBuffer[ 2 ], pBufferPtr, nBytesInPacket );
SDL_memcpy( &uPacketBuffer[ 2 ], pBufferPtr, nBytesInPacket );
pBufferPtr += nBytesInPacket;
nSegmentNumber++;
nRet = hid_send_feature_report( dev, uPacketBuffer, sizeof( uPacketBuffer ) );
nRet = SDL_hid_send_feature_report( dev, uPacketBuffer, sizeof( uPacketBuffer ) );
DPRINTF("SetFeatureReport() ret = %d\n", nRet);
}
}
@@ -345,24 +347,26 @@ static int SetFeatureReport( hid_device *dev, unsigned char uBuffer[65], int nAc
return nRet;
}
static int GetFeatureReport( hid_device *dev, unsigned char uBuffer[65] )
static int GetFeatureReport( SDL_hid_device *dev, unsigned char uBuffer[65] )
{
DPRINTF("GetFeatureReport( %p %p )\n", dev, uBuffer );
int nRet = -1;
bool bBle = true;
DPRINTF("GetFeatureReport( %p %p )\n", dev, uBuffer );
if ( bBle )
{
int nRetries = 0;
uint8_t uSegmentBuffer[ MAX_REPORT_SEGMENT_SIZE ];
SteamControllerPacketAssembler assembler;
InitializeSteamControllerPacketAssembler( &assembler );
int nRetries = 0;
uint8_t uSegmentBuffer[ MAX_REPORT_SEGMENT_SIZE ];
while( nRetries < BLE_MAX_READ_RETRIES )
{
memset( uSegmentBuffer, 0, sizeof( uSegmentBuffer ) );
SDL_memset( uSegmentBuffer, 0, sizeof( uSegmentBuffer ) );
uSegmentBuffer[ 0 ] = BLE_REPORT_NUMBER;
nRet = hid_get_feature_report( dev, uSegmentBuffer, sizeof( uSegmentBuffer ) );
nRet = SDL_hid_get_feature_report( dev, uSegmentBuffer, sizeof( uSegmentBuffer ) );
DPRINTF( "GetFeatureReport ble ret=%d\n", nRet );
HEXDUMP( uSegmentBuffer, nRet );
@@ -382,7 +386,7 @@ static int GetFeatureReport( hid_device *dev, unsigned char uBuffer[65] )
{
// Leave space for "report number"
uBuffer[ 0 ] = 0;
memcpy( uBuffer + 1, assembler.uBuffer, nPacketLength );
SDL_memcpy( uBuffer + 1, assembler.uBuffer, nPacketLength );
return nPacketLength;
}
}
@@ -396,11 +400,12 @@ static int GetFeatureReport( hid_device *dev, unsigned char uBuffer[65] )
return nRet;
}
static int ReadResponse( hid_device *dev, uint8_t uBuffer[65], int nExpectedResponse )
static int ReadResponse( SDL_hid_device *dev, uint8_t uBuffer[65], int nExpectedResponse )
{
DPRINTF("ReadResponse( %p %p %d )\n", dev, uBuffer, nExpectedResponse );
int nRet = GetFeatureReport( dev, uBuffer );
DPRINTF("ReadResponse( %p %p %d )\n", dev, uBuffer, nExpectedResponse );
if ( nRet < 0 )
return nRet;
@@ -416,13 +421,18 @@ static int ReadResponse( hid_device *dev, uint8_t uBuffer[65], int nExpectedResp
//---------------------------------------------------------------------------
// Reset steam controller (unmap buttons and pads) and re-fetch capability bits
//---------------------------------------------------------------------------
static bool ResetSteamController( hid_device *dev, bool bSuppressErrorSpew )
static bool ResetSteamController( SDL_hid_device *dev, bool bSuppressErrorSpew, uint32_t *punUpdateRateUS )
{
DPRINTF( "ResetSteamController hid=%p\n", dev );
// Firmware quirk: Set Feature and Get Feature requests always require a 65-byte buffer.
unsigned char buf[65];
int res = -1;
int res = -1, i;
int nSettings = 0;
int nAttributesLength;
FeatureReportMsg *msg;
uint32_t unUpdateRateUS = 9000; // Good default rate
DPRINTF( "ResetSteamController hid=%p\n", dev );
buf[0] = 0;
buf[1] = ID_GET_ATTRIBUTES_VALUES;
res = SetFeatureReport( dev, buf, 2 );
@@ -444,14 +454,40 @@ static bool ResetSteamController( hid_device *dev, bool bSuppressErrorSpew )
return false;
}
int nAttributesLength = buf[ 2 ];
nAttributesLength = buf[ 2 ];
if ( nAttributesLength > res )
{
if ( !bSuppressErrorSpew )
printf( "Bad GET_ATTRIBUTES_VALUES response for controller %p\n", dev );
return false;
}
msg = (FeatureReportMsg *)&buf[1];
for ( i = 0; i < (int)msg->header.length / sizeof( ControllerAttribute ); ++i )
{
uint8_t unAttribute = msg->payload.getAttributes.attributes[i].attributeTag;
uint32_t unValue = msg->payload.getAttributes.attributes[i].attributeValue;
switch ( unAttribute )
{
case ATTRIB_UNIQUE_ID:
break;
case ATTRIB_PRODUCT_ID:
break;
case ATTRIB_CAPABILITIES:
break;
case ATTRIB_CONNECTION_INTERVAL_IN_US:
unUpdateRateUS = unValue;
break;
default:
break;
}
}
if ( punUpdateRateUS )
{
*punUpdateRateUS = unUpdateRateUS;
}
// Clear digital button mappings
buf[0] = 0;
buf[1] = ID_CLEAR_DIGITAL_MAPPINGS;
@@ -464,7 +500,7 @@ static bool ResetSteamController( hid_device *dev, bool bSuppressErrorSpew )
}
// Reset the default settings
memset( buf, 0, 65 );
SDL_memset( buf, 0, 65 );
buf[1] = ID_LOAD_DEFAULT_SETTINGS;
buf[2] = 0;
res = SetFeatureReport( dev, buf, 3 );
@@ -476,14 +512,13 @@ static bool ResetSteamController( hid_device *dev, bool bSuppressErrorSpew )
}
// Apply custom settings - clear trackpad modes (cancel mouse emulation), etc
int nSettings = 0;
#define ADD_SETTING(SETTING, VALUE) \
buf[3+nSettings*3] = SETTING; \
buf[3+nSettings*3+1] = ((uint16_t)VALUE)&0xFF; \
buf[3+nSettings*3+2] = ((uint16_t)VALUE)>>8; \
++nSettings;
memset( buf, 0, 65 );
SDL_memset( buf, 0, 65 );
buf[1] = ID_SET_SETTINGS_VALUES;
ADD_SETTING( SETTING_WIRELESS_PACKET_VERSION, 2 );
ADD_SETTING( SETTING_LEFT_TRACKPAD_MODE, TRACKPAD_NONE );
@@ -512,7 +547,7 @@ buf[3+nSettings*3+2] = ((uint16_t)VALUE)>>8; \
int iRetry;
for ( iRetry = 0; iRetry < 2; ++iRetry )
{
memset( buf, 0, 65 );
SDL_memset( buf, 0, 65 );
buf[1] = ID_GET_DIGITAL_MAPPINGS;
buf[2] = 1; // one byte - requesting from index 0
buf[3] = 0;
@@ -545,7 +580,7 @@ buf[3+nSettings*3+2] = ((uint16_t)VALUE)>>8; \
}
// Set our new mappings
memset( buf, 0, 65 );
SDL_memset( buf, 0, 65 );
buf[1] = ID_SET_DIGITAL_MAPPINGS;
buf[2] = 6; // 2 settings x 3 bytes
buf[3] = IO_DIGITAL_BUTTON_RIGHT_TRIGGER;
@@ -571,36 +606,36 @@ buf[3+nSettings*3+2] = ((uint16_t)VALUE)>>8; \
//---------------------------------------------------------------------------
// Read from a Steam Controller
//---------------------------------------------------------------------------
static int ReadSteamController( hid_device *dev, uint8_t *pData, int nDataSize )
static int ReadSteamController( SDL_hid_device *dev, uint8_t *pData, int nDataSize )
{
memset( pData, 0, nDataSize );
SDL_memset( pData, 0, nDataSize );
pData[ 0 ] = BLE_REPORT_NUMBER; // hid_read will also overwrite this with the same value, 0x03
return hid_read( dev, pData, nDataSize );
return SDL_hid_read( dev, pData, nDataSize );
}
//---------------------------------------------------------------------------
// Close a Steam Controller
//---------------------------------------------------------------------------
static void CloseSteamController( hid_device *dev )
static void CloseSteamController( SDL_hid_device *dev )
{
// Switch the Steam Controller back to lizard mode so it works with the OS
unsigned char buf[65];
int nSettings = 0;
// Reset digital button mappings
memset( buf, 0, 65 );
SDL_memset( buf, 0, 65 );
buf[1] = ID_SET_DEFAULT_DIGITAL_MAPPINGS;
SetFeatureReport( dev, buf, 2 );
// Reset the default settings
memset( buf, 0, 65 );
SDL_memset( buf, 0, 65 );
buf[1] = ID_LOAD_DEFAULT_SETTINGS;
buf[2] = 0;
SetFeatureReport( dev, buf, 3 );
// Reset mouse mode for lizard mode
memset( buf, 0, 65 );
SDL_memset( buf, 0, 65 );
buf[1] = ID_SET_SETTINGS_VALUES;
ADD_SETTING( SETTING_RIGHT_TRACKPAD_MODE, TRACKPAD_ABSOLUTE_MOUSE );
buf[2] = nSettings*3;
@@ -651,14 +686,23 @@ static void RotatePadShort( short *pX, short *pY, float flAngleInRad )
//---------------------------------------------------------------------------
static void FormatStatePacketUntilGyro( SteamControllerStateInternal_t *pState, ValveControllerStatePacket_t *pStatePacket )
{
memset(pState, 0, offsetof(SteamControllerStateInternal_t, sBatteryLevel));
int nLeftPadX;
int nLeftPadY;
int nRightPadX;
int nRightPadY;
int nPadOffset;
// 15 degrees in rad
const float flRotationAngle = 0.261799f;
SDL_memset(pState, 0, offsetof(SteamControllerStateInternal_t, sBatteryLevel));
//pState->eControllerType = m_eControllerType;
pState->eControllerType = 2; // k_eControllerType_SteamController;
pState->unPacketNum = pStatePacket->unPacketNum;
// We have a chunk of trigger data in the packet format here, so zero it out afterwards
memcpy(&pState->ulButtons, &pStatePacket->ButtonTriggerData.ulButtons, 8);
SDL_memcpy(&pState->ulButtons, &pStatePacket->ButtonTriggerData.ulButtons, 8);
pState->ulButtons &= ~0xFFFF000000LL;
// The firmware uses this bit to tell us what kind of data is packed into the left two axises
@@ -735,18 +779,14 @@ static void FormatStatePacketUntilGyro( SteamControllerStateInternal_t *pState,
pState->sRightPadX = pStatePacket->sRightPadX;
pState->sRightPadY = pStatePacket->sRightPadY;
int nLeftPadX = pState->sLeftPadX;
int nLeftPadY = pState->sLeftPadY;
int nRightPadX = pState->sRightPadX;
int nRightPadY = pState->sRightPadY;
// 15 degrees in rad
const float flRotationAngle = 0.261799f;
nLeftPadX = pState->sLeftPadX;
nLeftPadY = pState->sLeftPadY;
nRightPadX = pState->sRightPadX;
nRightPadY = pState->sRightPadY;
RotatePad(&nLeftPadX, &nLeftPadY, -flRotationAngle);
RotatePad(&nRightPadX, &nRightPadY, flRotationAngle);
int nPadOffset;
if (pState->ulButtons & STEAM_LEFTPAD_FINGERDOWN_MASK)
nPadOffset = 1000;
else
@@ -782,7 +822,7 @@ static bool UpdateBLESteamControllerState( const uint8_t *pData, int nDataSize,
ucOptionDataMask |= (uint32_t)(*pData++) << 8;
if ( ucOptionDataMask & k_EBLEButtonChunk1 )
{
memcpy( &pState->ulButtons, pData, 3 );
SDL_memcpy( &pState->ulButtons, pData, 3 );
pData += 3;
}
if ( ucOptionDataMask & k_EBLEButtonChunk2 )
@@ -804,14 +844,14 @@ static bool UpdateBLESteamControllerState( const uint8_t *pData, int nDataSize,
// This doesn't handle any of the special headcrab stuff for raw joystick which is OK for now since that FW doesn't support
// this protocol yet either
int nLength = sizeof( pState->sLeftStickX ) + sizeof( pState->sLeftStickY );
memcpy( &pState->sLeftStickX, pData, nLength );
SDL_memcpy( &pState->sLeftStickX, pData, nLength );
pData += nLength;
}
if ( ucOptionDataMask & k_EBLELeftTrackpadChunk )
{
int nLength = sizeof( pState->sLeftPadX ) + sizeof( pState->sLeftPadY );
int nPadOffset;
memcpy( &pState->sLeftPadX, pData, nLength );
SDL_memcpy( &pState->sLeftPadX, pData, nLength );
if ( pState->ulButtons & STEAM_LEFTPAD_FINGERDOWN_MASK )
nPadOffset = 1000;
else
@@ -827,7 +867,7 @@ static bool UpdateBLESteamControllerState( const uint8_t *pData, int nDataSize,
int nLength = sizeof( pState->sRightPadX ) + sizeof( pState->sRightPadY );
int nPadOffset = 0;
memcpy( &pState->sRightPadX, pData, nLength );
SDL_memcpy( &pState->sRightPadX, pData, nLength );
if ( pState->ulButtons & STEAM_RIGHTPAD_FINGERDOWN_MASK )
nPadOffset = 1000;
@@ -842,19 +882,19 @@ static bool UpdateBLESteamControllerState( const uint8_t *pData, int nDataSize,
if ( ucOptionDataMask & k_EBLEIMUAccelChunk )
{
int nLength = sizeof( pState->sAccelX ) + sizeof( pState->sAccelY ) + sizeof( pState->sAccelZ );
memcpy( &pState->sAccelX, pData, nLength );
SDL_memcpy( &pState->sAccelX, pData, nLength );
pData += nLength;
}
if ( ucOptionDataMask & k_EBLEIMUGyroChunk )
{
int nLength = sizeof( pState->sAccelX ) + sizeof( pState->sAccelY ) + sizeof( pState->sAccelZ );
memcpy( &pState->sGyroX, pData, nLength );
SDL_memcpy( &pState->sGyroX, pData, nLength );
pData += nLength;
}
if ( ucOptionDataMask & k_EBLEIMUQuatChunk )
{
int nLength = sizeof( pState->sGyroQuatW ) + sizeof( pState->sGyroQuatX ) + sizeof( pState->sGyroQuatY ) + sizeof( pState->sGyroQuatZ );
memcpy( &pState->sGyroQuatW, pData, nLength );
SDL_memcpy( &pState->sGyroQuatW, pData, nLength );
pData += nLength;
}
return true;
@@ -950,6 +990,7 @@ static bool UpdateSteamControllerState( const uint8_t *pData, int nDataSize, Ste
/*****************************************************************************************************/
typedef struct {
SDL_bool report_sensors;
SteamControllerPacketAssembler m_assembler;
SteamControllerStateInternal_t m_state;
SteamControllerStateInternal_t m_last_state;
@@ -989,6 +1030,8 @@ static SDL_bool
HIDAPI_DriverSteam_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
{
SDL_DriverSteam_Context *ctx;
uint32_t update_rate_in_us = 0;
float update_rate_in_hz = 0.0f;
ctx = (SDL_DriverSteam_Context *)SDL_calloc(1, sizeof(*ctx));
if (!ctx) {
@@ -997,15 +1040,20 @@ HIDAPI_DriverSteam_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystic
}
device->context = ctx;
device->dev = hid_open_path(device->path, 0);
device->dev = SDL_hid_open_path(device->path, 0);
if (!device->dev) {
SDL_SetError("Couldn't open %s", device->path);
goto error;
}
SDL_hid_set_nonblocking(device->dev, 1);
if (!ResetSteamController(device->dev, false)) {
if (!ResetSteamController(device->dev, false, &update_rate_in_us)) {
SDL_SetError("Couldn't reset controller");
goto error;
}
if (update_rate_in_us > 0) {
update_rate_in_hz = 1000000.0f / update_rate_in_us;
}
InitializeSteamControllerPacketAssembler(&ctx->m_assembler);
@@ -1013,13 +1061,16 @@ HIDAPI_DriverSteam_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystic
joystick->nbuttons = 17;
joystick->naxes = SDL_CONTROLLER_AXIS_MAX;
SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO, update_rate_in_hz);
SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL, update_rate_in_hz);
return SDL_TRUE;
error:
SDL_LockMutex(device->dev_lock);
{
if (device->dev) {
hid_close(device->dev);
SDL_hid_close(device->dev);
device->dev = NULL;
}
if (device->context) {
@@ -1044,11 +1095,11 @@ HIDAPI_DriverSteam_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SDL_Joystic
return SDL_Unsupported();
}
static SDL_bool
HIDAPI_DriverSteam_HasJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
static Uint32
HIDAPI_DriverSteam_GetJoystickCapabilities(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
{
/* You should use the full Steam Input API for LED support */
return SDL_FALSE;
return 0;
}
static int
@@ -1067,8 +1118,25 @@ HIDAPI_DriverSteam_SendJoystickEffect(SDL_HIDAPI_Device *device, SDL_Joystick *j
static int
HIDAPI_DriverSteam_SetSensorsEnabled(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, SDL_bool enabled)
{
/* You should use the full Steam Input API for sensor support */
return SDL_Unsupported();
SDL_DriverSteam_Context *ctx = (SDL_DriverSteam_Context *)device->context;
unsigned char buf[65];
int nSettings = 0;
SDL_memset( buf, 0, 65 );
buf[1] = ID_SET_SETTINGS_VALUES;
if (enabled) {
ADD_SETTING( SETTING_GYRO_MODE, 0x18 /* SETTING_GYRO_SEND_RAW_ACCEL | SETTING_GYRO_MODE_SEND_RAW_GYRO */ );
} else {
ADD_SETTING( SETTING_GYRO_MODE, 0x00 /* SETTING_GYRO_MODE_OFF */ );
}
buf[2] = nSettings*3;
if (SetFeatureReport( device->dev, buf, 3+nSettings*3 ) < 0) {
return SDL_SetError("Couldn't write feature report");
}
ctx->report_sensors = enabled;
return 0;
}
static SDL_bool
@@ -1165,6 +1233,20 @@ HIDAPI_DriverSteam_UpdateDevice(SDL_HIDAPI_Device *device)
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTX, ctx->m_state.sRightPadX);
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTY, ~ctx->m_state.sRightPadY);
if (ctx->report_sensors) {
float values[3];
values[0] = (ctx->m_state.sGyroX / 32768.0f) * (2000.0f * (M_PI / 180.0f));
values[1] = (ctx->m_state.sGyroZ / 32768.0f) * (2000.0f * (M_PI / 180.0f));
values[2] = (ctx->m_state.sGyroY / 32768.0f) * (2000.0f * (M_PI / 180.0f));
SDL_PrivateJoystickSensor(joystick, SDL_SENSOR_GYRO, values, 3);
values[0] = (ctx->m_state.sAccelX / 32768.0f) * 2.0f * SDL_STANDARD_GRAVITY;
values[1] = (ctx->m_state.sAccelZ / 32768.0f) * 2.0f * SDL_STANDARD_GRAVITY;
values[2] = (-ctx->m_state.sAccelY / 32768.0f) * 2.0f * SDL_STANDARD_GRAVITY;
SDL_PrivateJoystickSensor(joystick, SDL_SENSOR_ACCEL, values, 3);
}
ctx->m_last_state = ctx->m_state;
}
@@ -1184,7 +1266,7 @@ HIDAPI_DriverSteam_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joysti
{
CloseSteamController(device->dev);
hid_close(device->dev);
SDL_hid_close(device->dev);
device->dev = NULL;
SDL_free(device->context);
@@ -1202,6 +1284,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverSteam =
{
SDL_HINT_JOYSTICK_HIDAPI_STEAM,
SDL_TRUE,
SDL_FALSE,
HIDAPI_DriverSteam_IsSupportedDevice,
HIDAPI_DriverSteam_GetDeviceName,
HIDAPI_DriverSteam_InitDevice,
@@ -1211,7 +1294,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverSteam =
HIDAPI_DriverSteam_OpenJoystick,
HIDAPI_DriverSteam_RumbleJoystick,
HIDAPI_DriverSteam_RumbleJoystickTriggers,
HIDAPI_DriverSteam_HasJoystickLED,
HIDAPI_DriverSteam_GetJoystickCapabilities,
HIDAPI_DriverSteam_SetJoystickLED,
HIDAPI_DriverSteam_SendJoystickEffect,
HIDAPI_DriverSteam_SetSensorsEnabled,

View File

@@ -346,13 +346,13 @@ static int ReadInput(SDL_DriverSwitch_Context *ctx)
return 0;
}
return hid_read_timeout(ctx->device->dev, ctx->m_rgucReadBuffer, sizeof(ctx->m_rgucReadBuffer), 0);
return SDL_hid_read_timeout(ctx->device->dev, ctx->m_rgucReadBuffer, sizeof(ctx->m_rgucReadBuffer), 0);
}
static int WriteOutput(SDL_DriverSwitch_Context *ctx, const Uint8 *data, int size)
{
#ifdef SWITCH_SYNCHRONOUS_WRITES
return hid_write(ctx->device->dev, data, size);
return SDL_hid_write(ctx->device->dev, data, size);
#else
/* Use the rumble thread for general asynchronous writes */
if (SDL_HIDAPI_LockRumble() < 0) {
@@ -418,7 +418,7 @@ static void ConstructSubcommand(SDL_DriverSwitch_Context *ctx, ESwitchSubcommand
outPacket->commonData.ucPacketType = k_eSwitchOutputReportIDs_RumbleAndSubcommand;
outPacket->commonData.ucPacketNumber = ctx->m_nCommandNumber;
SDL_memcpy(&outPacket->commonData.rumbleData, &ctx->m_RumblePacket.rumbleData, sizeof(ctx->m_RumblePacket.rumbleData));
SDL_memcpy(outPacket->commonData.rumbleData, ctx->m_RumblePacket.rumbleData, sizeof(ctx->m_RumblePacket.rumbleData));
outPacket->ucSubcommandID = ucCommandID;
SDL_memcpy(outPacket->rgucSubcommandData, pBuf, ucLen);
@@ -621,7 +621,7 @@ static SDL_bool BReadDeviceInfo(SDL_DriverSwitch_Context *ctx)
ctx->m_eControllerType = (ESwitchDeviceInfoControllerType)reply->deviceInfo.ucDeviceType;
// Bytes 4-9: MAC address (big-endian)
memcpy(ctx->m_rgucMACAddress, reply->deviceInfo.rgucMACAddress, sizeof(ctx->m_rgucMACAddress));
SDL_memcpy(ctx->m_rgucMACAddress, reply->deviceInfo.rgucMACAddress, sizeof(ctx->m_rgucMACAddress));
return SDL_TRUE;
}
@@ -856,7 +856,7 @@ HIDAPI_DriverSwitch_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joysti
ctx->device = device;
device->context = ctx;
device->dev = hid_open_path(device->path, 0);
device->dev = SDL_hid_open_path(device->path, 0);
if (!device->dev) {
SDL_SetError("Couldn't open %s", device->path);
goto error;
@@ -936,10 +936,13 @@ HIDAPI_DriverSwitch_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joysti
/* Set the LED state */
if (ctx->m_bHasHomeLED) {
if (SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_SWITCH_HOME_LED, SDL_TRUE)) {
SetHomeLED(ctx, 100);
} else {
SetHomeLED(ctx, 0);
const char *hint = SDL_GetHint(SDL_HINT_JOYSTICK_HIDAPI_SWITCH_HOME_LED);
if (hint && *hint) {
if (SDL_GetStringBoolean(hint, SDL_TRUE)) {
SetHomeLED(ctx, 100);
} else {
SetHomeLED(ctx, 0);
}
}
}
SetSlotLED(ctx, (joystick->instance_id % 4));
@@ -983,7 +986,7 @@ error:
SDL_LockMutex(device->dev_lock);
{
if (device->dev) {
hid_close(device->dev);
SDL_hid_close(device->dev);
device->dev = NULL;
}
if (device->context) {
@@ -1103,11 +1106,18 @@ HIDAPI_DriverSwitch_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SDL_Joysti
return SDL_Unsupported();
}
static SDL_bool
HIDAPI_DriverSwitch_HasJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
static Uint32
HIDAPI_DriverSwitch_GetJoystickCapabilities(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
{
/* Doesn't have an RGB LED, so don't return true here */
return SDL_FALSE;
SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)device->context;
Uint32 result = 0;
if (!ctx->m_bInputOnly) {
/* Doesn't have an RGB LED, so don't return SDL_JOYCAP_LED here */
result |= SDL_JOYCAP_RUMBLE;
}
return result;
}
static int
@@ -1527,7 +1537,7 @@ HIDAPI_DriverSwitch_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joyst
SDL_LockMutex(device->dev_lock);
{
hid_close(device->dev);
SDL_hid_close(device->dev);
device->dev = NULL;
SDL_free(device->context);
@@ -1545,6 +1555,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverSwitch =
{
SDL_HINT_JOYSTICK_HIDAPI_SWITCH,
SDL_TRUE,
SDL_TRUE,
HIDAPI_DriverSwitch_IsSupportedDevice,
HIDAPI_DriverSwitch_GetDeviceName,
HIDAPI_DriverSwitch_InitDevice,
@@ -1554,7 +1565,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverSwitch =
HIDAPI_DriverSwitch_OpenJoystick,
HIDAPI_DriverSwitch_RumbleJoystick,
HIDAPI_DriverSwitch_RumbleJoystickTriggers,
HIDAPI_DriverSwitch_HasJoystickLED,
HIDAPI_DriverSwitch_GetJoystickCapabilities,
HIDAPI_DriverSwitch_SetJoystickLED,
HIDAPI_DriverSwitch_SendJoystickEffect,
HIDAPI_DriverSwitch_SetJoystickSensorsEnabled,

View File

@@ -88,14 +88,14 @@ HIDAPI_DriverXbox360_GetDeviceName(Uint16 vendor_id, Uint16 product_id)
return NULL;
}
static SDL_bool SetSlotLED(hid_device *dev, Uint8 slot)
static SDL_bool SetSlotLED(SDL_hid_device *dev, Uint8 slot)
{
const SDL_bool blink = SDL_FALSE;
Uint8 mode = (blink ? 0x02 : 0x06) + slot;
Uint8 led_packet[] = { 0x01, 0x03, 0x00 };
led_packet[2] = mode;
if (hid_write(dev, led_packet, sizeof(led_packet)) != sizeof(led_packet)) {
if (SDL_hid_write(dev, led_packet, sizeof(led_packet)) != sizeof(led_packet)) {
return SDL_FALSE;
}
return SDL_TRUE;
@@ -136,7 +136,7 @@ HIDAPI_DriverXbox360_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joyst
return SDL_FALSE;
}
device->dev = hid_open_path(device->path, 0);
device->dev = SDL_hid_open_path(device->path, 0);
if (!device->dev) {
SDL_SetError("Couldn't open %s", device->path);
SDL_free(ctx);
@@ -203,11 +203,11 @@ HIDAPI_DriverXbox360_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SDL_Joyst
return SDL_Unsupported();
}
static SDL_bool
HIDAPI_DriverXbox360_HasJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
static Uint32
HIDAPI_DriverXbox360_GetJoystickCapabilities(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
{
/* Doesn't have an RGB LED, so don't return true here */
return SDL_FALSE;
/* Doesn't have an RGB LED, so don't return SDL_JOYCAP_LED here */
return SDL_JOYCAP_RUMBLE;
}
static int
@@ -296,7 +296,7 @@ HIDAPI_DriverXbox360_UpdateDevice(SDL_HIDAPI_Device *device)
return SDL_FALSE;
}
while ((size = hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
while ((size = SDL_hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
#ifdef DEBUG_XBOX_PROTOCOL
HIDAPI_DumpPacket("Xbox 360 packet: size = %d", data, size);
#endif
@@ -318,7 +318,7 @@ HIDAPI_DriverXbox360_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joys
SDL_LockMutex(device->dev_lock);
{
if (device->dev) {
hid_close(device->dev);
SDL_hid_close(device->dev);
device->dev = NULL;
}
@@ -337,6 +337,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXbox360 =
{
SDL_HINT_JOYSTICK_HIDAPI_XBOX,
SDL_TRUE,
SDL_TRUE,
HIDAPI_DriverXbox360_IsSupportedDevice,
HIDAPI_DriverXbox360_GetDeviceName,
HIDAPI_DriverXbox360_InitDevice,
@@ -346,7 +347,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXbox360 =
HIDAPI_DriverXbox360_OpenJoystick,
HIDAPI_DriverXbox360_RumbleJoystick,
HIDAPI_DriverXbox360_RumbleJoystickTriggers,
HIDAPI_DriverXbox360_HasJoystickLED,
HIDAPI_DriverXbox360_GetJoystickCapabilities,
HIDAPI_DriverXbox360_SetJoystickLED,
HIDAPI_DriverXbox360_SendJoystickEffect,
HIDAPI_DriverXbox360_SetJoystickSensorsEnabled,

View File

@@ -62,14 +62,14 @@ HIDAPI_DriverXbox360W_GetDeviceName(Uint16 vendor_id, Uint16 product_id)
return "Xbox 360 Wireless Controller";
}
static SDL_bool SetSlotLED(hid_device *dev, Uint8 slot)
static SDL_bool SetSlotLED(SDL_hid_device *dev, Uint8 slot)
{
const SDL_bool blink = SDL_FALSE;
Uint8 mode = (blink ? 0x02 : 0x06) + slot;
Uint8 led_packet[] = { 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
led_packet[3] = 0x40 + (mode % 0x0e);
if (hid_write(dev, led_packet, sizeof(led_packet)) != sizeof(led_packet)) {
if (SDL_hid_write(dev, led_packet, sizeof(led_packet)) != sizeof(led_packet)) {
return SDL_FALSE;
}
return SDL_TRUE;
@@ -105,7 +105,7 @@ HIDAPI_DriverXbox360W_InitDevice(SDL_HIDAPI_Device *device)
return SDL_FALSE;
}
device->dev = hid_open_path(device->path, 0);
device->dev = SDL_hid_open_path(device->path, 0);
if (!device->dev) {
SDL_free(ctx);
SDL_SetError("Couldn't open %s", device->path);
@@ -113,7 +113,7 @@ HIDAPI_DriverXbox360W_InitDevice(SDL_HIDAPI_Device *device)
}
device->context = ctx;
if (hid_write(device->dev, init_packet, sizeof(init_packet)) != sizeof(init_packet)) {
if (SDL_hid_write(device->dev, init_packet, sizeof(init_packet)) != sizeof(init_packet)) {
SDL_SetError("Couldn't write init packet");
return SDL_FALSE;
}
@@ -173,11 +173,11 @@ HIDAPI_DriverXbox360W_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SDL_Joys
return SDL_Unsupported();
}
static SDL_bool
HIDAPI_DriverXbox360W_HasJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
static Uint32
HIDAPI_DriverXbox360W_GetJoystickCapabilities(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
{
/* Doesn't have an RGB LED, so don't return true here */
return SDL_FALSE;
/* Doesn't have an RGB LED, so don't return SDL_JOYCAP_LED here */
return SDL_JOYCAP_RUMBLE;
}
static int
@@ -199,7 +199,7 @@ HIDAPI_DriverXbox360W_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *device, SDL_J
}
static void
HIDAPI_DriverXbox360W_HandleStatePacket(SDL_Joystick *joystick, hid_device *dev, SDL_DriverXbox360W_Context *ctx, Uint8 *data, int size)
HIDAPI_DriverXbox360W_HandleStatePacket(SDL_Joystick *joystick, SDL_hid_device *dev, SDL_DriverXbox360W_Context *ctx, Uint8 *data, int size)
{
Sint16 axis;
const SDL_bool invert_y_axes = SDL_TRUE;
@@ -259,7 +259,7 @@ HIDAPI_DriverXbox360W_UpdateDevice(SDL_HIDAPI_Device *device)
joystick = SDL_JoystickFromInstanceID(device->joysticks[0]);
}
while ((size = hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
while ((size = SDL_hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
#ifdef DEBUG_XBOX_PROTOCOL
HIDAPI_DumpPacket("Xbox 360 wireless packet: size = %d", data, size);
#endif
@@ -321,7 +321,7 @@ HIDAPI_DriverXbox360W_FreeDevice(SDL_HIDAPI_Device *device)
{
SDL_LockMutex(device->dev_lock);
{
hid_close(device->dev);
SDL_hid_close(device->dev);
device->dev = NULL;
SDL_free(device->context);
@@ -334,6 +334,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXbox360W =
{
SDL_HINT_JOYSTICK_HIDAPI_XBOX,
SDL_TRUE,
SDL_TRUE,
HIDAPI_DriverXbox360W_IsSupportedDevice,
HIDAPI_DriverXbox360W_GetDeviceName,
HIDAPI_DriverXbox360W_InitDevice,
@@ -343,7 +344,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXbox360W =
HIDAPI_DriverXbox360W_OpenJoystick,
HIDAPI_DriverXbox360W_RumbleJoystick,
HIDAPI_DriverXbox360W_RumbleJoystickTriggers,
HIDAPI_DriverXbox360W_HasJoystickLED,
HIDAPI_DriverXbox360W_GetJoystickCapabilities,
HIDAPI_DriverXbox360W_SetJoystickLED,
HIDAPI_DriverXbox360W_SendJoystickEffect,
HIDAPI_DriverXbox360W_SetJoystickSensorsEnabled,

View File

@@ -44,33 +44,23 @@
#define CONTROLLER_PREPARE_INPUT_TIMEOUT_MS 50
/* Connect controller */
/* Start controller */
static const Uint8 xboxone_init0[] = {
0x04, 0x20, 0x00, 0x00
};
/* Start controller - extended? */
static const Uint8 xboxone_init1[] = {
0x05, 0x20, 0x00, 0x0F, 0x06, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x55, 0x53, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00
};
/* Start controller with input */
static const Uint8 xboxone_init2[] = {
0x05, 0x20, 0x03, 0x01, 0x00
};
/* Enable LED */
static const Uint8 xboxone_init3[] = {
static const Uint8 xboxone_init1[] = {
0x0A, 0x20, 0x00, 0x03, 0x00, 0x01, 0x14
};
/* Start input reports? */
static const Uint8 xboxone_init4[] = {
0x06, 0x20, 0x00, 0x02, 0x01, 0x00
};
/* Start rumble? */
static const Uint8 xboxone_init5[] = {
/* Setup rumble (not needed for Microsoft controllers, but it doesn't hurt) */
static const Uint8 xboxone_init2[] = {
0x09, 0x00, 0x00, 0x09, 0x00, 0x0F, 0x00, 0x00,
0x00, 0x00, 0xFF, 0x00, 0xEB
};
/* This controller passed security check */
static const Uint8 security_passed_packet[] = {
0x06, 0x20, 0x00, 0x02, 0x01, 0x00
};
/*
* This specifies the selection of init packets that a gamepad
@@ -90,16 +80,11 @@ typedef struct {
static const SDL_DriverXboxOne_InitPacket xboxone_init_packets[] = {
{ 0x0000, 0x0000, 0x0000, 0x0000, xboxone_init0, sizeof(xboxone_init0), { 0x04, 0xb0 } },
/* The PDP Rock Candy controller doesn't start sending input until it gets this packet */
{ 0x0e6f, 0x0246, 0x0000, 0x0000, security_passed_packet, sizeof(security_passed_packet), { 0x00, 0x00 } },
{ 0x0000, 0x0000, 0x0000, 0x0000, xboxone_init0, sizeof(xboxone_init0), { 0x00, 0x00 } },
{ 0x0000, 0x0000, 0x0000, 0x0000, xboxone_init1, sizeof(xboxone_init1), { 0x00, 0x00 } },
{ 0x0000, 0x0000, 0x0000, 0x0000, xboxone_init2, sizeof(xboxone_init2), { 0x00, 0x00 } },
{ 0x0000, 0x0000, 0x0000, 0x0000, xboxone_init3, sizeof(xboxone_init3), { 0x00, 0x00 } },
/* These next packets are required for third party controllers (PowerA, PDP, HORI),
but aren't the correct protocol for Microsoft Xbox controllers.
*/
{ 0x0000, 0x0000, 0x045e, 0x0000, xboxone_init4, sizeof(xboxone_init4), { 0x00, 0x00 } },
{ 0x0000, 0x0000, 0x045e, 0x0000, xboxone_init5, sizeof(xboxone_init5), { 0x00, 0x00 } },
};
typedef enum {
@@ -120,6 +105,7 @@ typedef struct {
Uint32 send_time;
Uint8 last_state[USB_PACKET_LENGTH];
SDL_bool has_guide_packet;
SDL_bool has_color_led;
SDL_bool has_paddles;
SDL_bool has_trigger_rumble;
SDL_bool has_share_button;
@@ -129,6 +115,12 @@ typedef struct {
Uint8 right_trigger_rumble;
} SDL_DriverXboxOne_Context;
static SDL_bool
ControllerHasColorLED(Uint16 vendor_id, Uint16 product_id)
{
return (vendor_id == USB_VENDOR_MICROSOFT && product_id == USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2);
}
static SDL_bool
ControllerHasPaddles(Uint16 vendor_id, Uint16 product_id)
{
@@ -138,7 +130,7 @@ ControllerHasPaddles(Uint16 vendor_id, Uint16 product_id)
static SDL_bool
ControllerHasTriggerRumble(Uint16 vendor_id, Uint16 product_id)
{
// All the Microsoft Xbox One controllers have trigger rumble
/* All the Microsoft Xbox One controllers have trigger rumble */
return (vendor_id == USB_VENDOR_MICROSOFT);
}
@@ -178,7 +170,10 @@ SendAckIfNeeded(SDL_HIDAPI_Device *device, Uint8 *data, int size)
#ifdef DEBUG_XBOX_PROTOCOL
HIDAPI_DumpPacket("Xbox One sending ACK packet: size = %d", ack_packet, sizeof(ack_packet));
#endif
hid_write(device->dev, ack_packet, sizeof(ack_packet));
if (SDL_HIDAPI_LockRumble() < 0 ||
SDL_HIDAPI_SendRumbleAndUnlock(device, ack_packet, sizeof(ack_packet)) != sizeof(ack_packet)) {
SDL_SetError("Couldn't send ack packet");
}
}
#endif /* __WIN32__ */
}
@@ -322,7 +317,7 @@ HIDAPI_DriverXboxOne_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joyst
return SDL_FALSE;
}
device->dev = hid_open_path(device->path, 0);
device->dev = SDL_hid_open_path(device->path, 0);
if (!device->dev) {
SDL_free(ctx);
SDL_SetError("Couldn't open %s", device->path);
@@ -335,6 +330,7 @@ HIDAPI_DriverXboxOne_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joyst
ctx->bluetooth = SDL_IsJoystickBluetoothXboxOne(device->vendor_id, device->product_id);
ctx->start_time = SDL_GetTicks();
ctx->sequence = 1;
ctx->has_color_led = ControllerHasColorLED(ctx->vendor_id, ctx->product_id);
ctx->has_paddles = ControllerHasPaddles(ctx->vendor_id, ctx->product_id);
ctx->has_trigger_rumble = ControllerHasTriggerRumble(ctx->vendor_id, ctx->product_id);
ctx->has_share_button = ControllerHasShareButton(ctx->vendor_id, ctx->product_id);
@@ -426,17 +422,44 @@ HIDAPI_DriverXboxOne_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SDL_Joyst
return HIDAPI_DriverXboxOne_UpdateRumble(device);
}
static SDL_bool
HIDAPI_DriverXboxOne_HasJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
static Uint32
HIDAPI_DriverXboxOne_GetJoystickCapabilities(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
{
/* Doesn't have an RGB LED, so don't return true here */
return SDL_FALSE;
SDL_DriverXboxOne_Context *ctx = (SDL_DriverXboxOne_Context *)device->context;
Uint32 result = 0;
result |= SDL_JOYCAP_RUMBLE;
if (ctx->has_trigger_rumble) {
result |= SDL_JOYCAP_RUMBLE_TRIGGERS;
}
if (ctx->has_color_led) {
result |= SDL_JOYCAP_LED;
}
return result;
}
static int
HIDAPI_DriverXboxOne_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
{
return SDL_Unsupported();
SDL_DriverXboxOne_Context *ctx = (SDL_DriverXboxOne_Context *)device->context;
if (ctx->has_color_led) {
Uint8 led_packet[] = { 0x0E, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00 };
led_packet[5] = 0x00; /* Whiteness? Sets white intensity when RGB is 0, seems additive */
led_packet[6] = red;
led_packet[7] = green;
led_packet[8] = blue;
if (SDL_HIDAPI_SendRumble(device, led_packet, sizeof(led_packet)) != sizeof(led_packet)) {
return SDL_SetError("Couldn't send LED packet");
}
return 0;
} else {
return SDL_Unsupported();
}
}
static int
@@ -508,12 +531,16 @@ HIDAPI_DriverXboxOne_HandleStatePacket(SDL_Joystick *joystick, SDL_DriverXboxOne
Paddle bits:
P3: 0x01 (A) P1: 0x02 (B)
P4: 0x04 (X) P2: 0x08 (Y)
Xbox One Elite Series 2 report is 38 bytes, paddles in data[18], mode in data[19], mode 0 has no mapped paddles by default
Xbox One Elite Series 2 4.x firmware report is 38 bytes, paddles in data[18], mode in data[19], mode 0 has no mapped paddles by default
Paddle bits:
P3: 0x04 (A) P1: 0x01 (B)
P4: 0x08 (X) P2: 0x02 (Y)
Xbox One Elite Series 2 5.x firmware report is 50 bytes, paddles in data[22], mode in data[23], mode 0 has no mapped paddles by default
Paddle bits:
P3: 0x04 (A) P1: 0x01 (B)
P4: 0x08 (X) P2: 0x02 (Y)
*/
if (ctx->has_paddles && (size == 33 || size == 38)) {
if (ctx->has_paddles && (size == 33 || size == 38 || size == 50)) {
int paddle_index;
int button1_bit;
int button2_bit;
@@ -532,7 +559,7 @@ HIDAPI_DriverXboxOne_HandleStatePacket(SDL_Joystick *joystick, SDL_DriverXboxOne
/* The mapped controller state is at offset 4, the raw state is at offset 18, compare them to see if the paddles are mapped */
paddles_mapped = (SDL_memcmp(&data[4], &data[18], 2) != 0);
} else /* if (size == 38) */ {
} else if (size == 38) {
/* XBox One Elite Series 2 */
paddle_index = 18;
button1_bit = 0x01;
@@ -540,6 +567,15 @@ HIDAPI_DriverXboxOne_HandleStatePacket(SDL_Joystick *joystick, SDL_DriverXboxOne
button3_bit = 0x04;
button4_bit = 0x08;
paddles_mapped = (data[19] != 0);
} else /* if (size == 50) */{
/* XBox One Elite Series 2 */
paddle_index = 22;
button1_bit = 0x01;
button2_bit = 0x02;
button3_bit = 0x04;
button4_bit = 0x08;
paddles_mapped = (data[23] != 0);
}
#ifdef DEBUG_XBOX_PROTOCOL
SDL_Log(">>> Paddles: %d,%d,%d,%d mapped = %s\n",
@@ -595,6 +631,14 @@ HIDAPI_DriverXboxOne_HandleStatePacket(SDL_Joystick *joystick, SDL_DriverXboxOne
SDL_memcpy(ctx->last_state, data, SDL_min(size, sizeof(ctx->last_state)));
}
static void
HIDAPI_DriverXboxOne_HandleStatusPacket(SDL_Joystick *joystick, SDL_DriverXboxOne_Context *ctx, Uint8 *data, int size)
{
if (ctx->init_state < XBOX_ONE_INIT_STATE_COMPLETE) {
SetInitState(ctx, XBOX_ONE_INIT_STATE_COMPLETE);
}
}
static void
HIDAPI_DriverXboxOne_HandleModePacket(SDL_Joystick *joystick, SDL_DriverXboxOne_Context *ctx, Uint8 *data, int size)
{
@@ -627,8 +671,10 @@ HIDAPI_DriverXboxOneBluetooth_HandleButtons16(SDL_Joystick *joystick, SDL_Driver
/*
* Xbox One S with firmware 4.8.1923 uses a 17 byte packet with BACK button in byte 16 and the GUIDE button in a separate packet (on Windows), or in byte 15 (on Linux)
* Xbox One S with firmware 5.x uses a 17 byte packet with BACK and GUIDE buttons in byte 15
* Xbox One Elite Series 2 with firmware 4.7.1872 uses a 55 byte packet with BACK button in byte 16, paddles starting at byte 33, and the GUIDE button in a separate packet
* Xbox One Elite Series 2 with firmware 4.8.1908 uses a 33 byte packet with BACK button in byte 16, paddles starting at byte 17, and the GUIDE button in a separate packet
* Xbox One Elite Series 2 with firmware 5.11.3112 uses a 19 byte packet with BACK and GUIDE buttons in byte 15
* Xbox Series X with firmware 5.5.2641 uses a 17 byte packet with BACK and GUIDE buttons in byte 15, and SHARE button in byte 17
*/
static void
@@ -644,10 +690,7 @@ HIDAPI_DriverXboxOneBluetooth_HandleButtons(SDL_Joystick *joystick, SDL_DriverXb
}
if (ctx->last_state[15] != data[15]) {
if (ctx->has_share_button) {
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_BACK, (data[15] & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_GUIDE, (data[15] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
} else if (!ctx->has_guide_packet) {
if (!ctx->has_guide_packet) {
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_GUIDE, (data[15] & 0x10) ? SDL_PRESSED : SDL_RELEASED);
}
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_START, (data[15] & 0x08) ? SDL_PRESSED : SDL_RELEASED);
@@ -655,12 +698,11 @@ HIDAPI_DriverXboxOneBluetooth_HandleButtons(SDL_Joystick *joystick, SDL_DriverXb
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSTICK, (data[15] & 0x40) ? SDL_PRESSED : SDL_RELEASED);
}
if (ctx->last_state[16] != data[16]) {
if (ctx->has_share_button) {
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_MISC1, (data[16] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
} else {
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_BACK, (data[16] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
}
if (ctx->has_share_button) {
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_BACK, (data[15] & 0x04) ? SDL_PRESSED : SDL_RELEASED);
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_MISC1, (data[16] & 0x01) ? SDL_PRESSED : SDL_RELEASED);
} else {
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_BACK, ((data[15] & 0x04) || (data[16] & 0x01)) ? SDL_PRESSED : SDL_RELEASED);
}
/*
@@ -727,8 +769,13 @@ HIDAPI_DriverXboxOneBluetooth_HandleStatePacket(SDL_Joystick *joystick, SDL_Driv
if (size == 16) {
/* Original Xbox One S, with separate report for guide button */
HIDAPI_DriverXboxOneBluetooth_HandleButtons16(joystick, ctx, data, size);
} else {
} else if (size > 16) {
HIDAPI_DriverXboxOneBluetooth_HandleButtons(joystick, ctx, data, size);
} else {
#ifdef DEBUG_XBOX_PROTOCOL
SDL_Log("Unknown Bluetooth state packet format\n");
#endif
return;
}
if (ctx->last_state[13] != data[13]) {
@@ -908,7 +955,7 @@ HIDAPI_DriverXboxOne_UpdateJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joy
Uint8 data[USB_PACKET_LENGTH];
int size;
while ((size = hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
while ((size = SDL_hid_read_timeout(device->dev, data, sizeof(data), 0)) > 0) {
#ifdef DEBUG_XBOX_PROTOCOL
HIDAPI_DumpPacket("Xbox One packet: size = %d", data, size);
#endif
@@ -961,16 +1008,18 @@ HIDAPI_DriverXboxOne_UpdateJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joy
is firmware version 5.5.2641.0, and product version 0x0505 = 1285
then 8 bytes of unknown data
*/
if (data[1] == 0x20) {
#ifdef DEBUG_JOYSTICK
SDL_Log("Controller announce after %u ms\n", (SDL_GetTicks() - ctx->start_time));
SDL_Log("Controller announce after %u ms\n", (SDL_GetTicks() - ctx->start_time));
#endif
SetInitState(ctx, XBOX_ONE_INIT_STATE_START_NEGOTIATING);
SetInitState(ctx, XBOX_ONE_INIT_STATE_START_NEGOTIATING);
} else {
/* Possibly an announce from a device plugged into the controller */
}
break;
case 0x03:
/* Controller heartbeat */
if (ctx->init_state < XBOX_ONE_INIT_STATE_COMPLETE) {
SetInitState(ctx, XBOX_ONE_INIT_STATE_COMPLETE);
}
/* Controller status update */
HIDAPI_DriverXboxOne_HandleStatusPacket(joystick, ctx, data, size);
break;
case 0x04:
/* Unknown chatty controller information, sent by both sides */
@@ -1060,7 +1109,7 @@ HIDAPI_DriverXboxOne_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joys
{
SDL_LockMutex(device->dev_lock);
{
hid_close(device->dev);
SDL_hid_close(device->dev);
device->dev = NULL;
SDL_free(device->context);
@@ -1078,6 +1127,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXboxOne =
{
SDL_HINT_JOYSTICK_HIDAPI_XBOX,
SDL_TRUE,
SDL_TRUE,
HIDAPI_DriverXboxOne_IsSupportedDevice,
HIDAPI_DriverXboxOne_GetDeviceName,
HIDAPI_DriverXboxOne_InitDevice,
@@ -1087,7 +1137,7 @@ SDL_HIDAPI_DeviceDriver SDL_HIDAPI_DriverXboxOne =
HIDAPI_DriverXboxOne_OpenJoystick,
HIDAPI_DriverXboxOne_RumbleJoystick,
HIDAPI_DriverXboxOne_RumbleJoystickTriggers,
HIDAPI_DriverXboxOne_HasJoystickLED,
HIDAPI_DriverXboxOne_GetJoystickCapabilities,
HIDAPI_DriverXboxOne_SetJoystickLED,
HIDAPI_DriverXboxOne_SendJoystickEffect,
HIDAPI_DriverXboxOne_SetJoystickSensorsEnabled,

View File

@@ -25,52 +25,17 @@
#include "SDL_atomic.h"
#include "SDL_endian.h"
#include "SDL_hints.h"
#include "SDL_thread.h"
#include "SDL_timer.h"
#include "SDL_joystick.h"
#include "SDL_log.h"
#include "../SDL_sysjoystick.h"
#include "SDL_hidapijoystick_c.h"
#include "SDL_hidapi_rumble.h"
#include "../../SDL_hints_c.h"
#if defined(__WIN32__)
#include "../../core/windows/SDL_windows.h"
#include "../windows/SDL_rawinputjoystick_c.h"
#endif
#if defined(__MACOSX__)
#include <CoreFoundation/CoreFoundation.h>
#include <mach/mach.h>
#include <IOKit/IOKitLib.h>
#include <IOKit/hid/IOHIDDevice.h>
#include <IOKit/usb/USBSpec.h>
#endif
#ifdef SDL_USE_LIBUDEV
#include "../../core/linux/SDL_udev.h"
#include <poll.h>
#include <unistd.h>
#endif
#ifdef HAVE_INOTIFY
#include <unistd.h> /* just in case we didn't use that SDL_USE_LIBUDEV block... */
#include <errno.h> /* errno, strerror */
#include <fcntl.h>
#include <limits.h> /* For the definition of NAME_MAX */
#include <sys/inotify.h>
#endif
#if defined(SDL_USE_LIBUDEV)
typedef enum
{
ENUMERATION_UNSET,
ENUMERATION_LIBUDEV,
ENUMERATION_FALLBACK
} LinuxEnumerationMethod;
static LinuxEnumerationMethod linux_enumeration_method = ENUMERATION_UNSET;
#endif
struct joystick_hwdata
{
@@ -109,434 +74,12 @@ static SDL_HIDAPI_DeviceDriver *SDL_HIDAPI_drivers[] = {
};
static int SDL_HIDAPI_numdrivers = 0;
static SDL_SpinLock SDL_HIDAPI_spinlock;
static Uint32 SDL_HIDAPI_change_count = 0;
static SDL_HIDAPI_Device *SDL_HIDAPI_devices;
static int SDL_HIDAPI_numjoysticks = 0;
static SDL_bool initialized = SDL_FALSE;
static SDL_bool shutting_down = SDL_FALSE;
#if defined(HAVE_INOTIFY)
static int inotify_fd = -1;
#endif
#if defined(SDL_USE_LIBUDEV)
static const SDL_UDEV_Symbols * usyms = NULL;
#endif
static struct
{
SDL_bool m_bHaveDevicesChanged;
SDL_bool m_bCanGetNotifications;
Uint32 m_unLastDetect;
#if defined(__WIN32__)
SDL_threadID m_nThreadID;
WNDCLASSEXA m_wndClass;
HWND m_hwndMsg;
HDEVNOTIFY m_hNotify;
double m_flLastWin32MessageCheck;
#endif
#if defined(__MACOSX__)
IONotificationPortRef m_notificationPort;
mach_port_t m_notificationMach;
#endif
#if defined(SDL_USE_LIBUDEV)
struct udev *m_pUdev;
struct udev_monitor *m_pUdevMonitor;
int m_nUdevFd;
#endif
} SDL_HIDAPI_discovery;
#ifdef __WIN32__
struct _DEV_BROADCAST_HDR
{
DWORD dbch_size;
DWORD dbch_devicetype;
DWORD dbch_reserved;
};
typedef struct _DEV_BROADCAST_DEVICEINTERFACE_A
{
DWORD dbcc_size;
DWORD dbcc_devicetype;
DWORD dbcc_reserved;
GUID dbcc_classguid;
char dbcc_name[ 1 ];
} DEV_BROADCAST_DEVICEINTERFACE_A, *PDEV_BROADCAST_DEVICEINTERFACE_A;
typedef struct _DEV_BROADCAST_HDR DEV_BROADCAST_HDR;
#define DBT_DEVICEARRIVAL 0x8000 /* system detected a new device */
#define DBT_DEVICEREMOVECOMPLETE 0x8004 /* device was removed from the system */
#define DBT_DEVTYP_DEVICEINTERFACE 0x00000005 /* device interface class */
#define DBT_DEVNODES_CHANGED 0x0007
#define DBT_CONFIGCHANGED 0x0018
#define DBT_DEVICETYPESPECIFIC 0x8005 /* type specific event */
#define DBT_DEVINSTSTARTED 0x8008 /* device installed and started */
#include <initguid.h>
DEFINE_GUID(GUID_DEVINTERFACE_USB_DEVICE, 0xA5DCBF10L, 0x6530, 0x11D2, 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED);
static LRESULT CALLBACK ControllerWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message) {
case WM_DEVICECHANGE:
switch (wParam) {
case DBT_DEVICEARRIVAL:
case DBT_DEVICEREMOVECOMPLETE:
if (((DEV_BROADCAST_HDR*)lParam)->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
SDL_HIDAPI_discovery.m_bHaveDevicesChanged = SDL_TRUE;
}
break;
}
return TRUE;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
#endif /* __WIN32__ */
#if defined(__MACOSX__)
static void CallbackIOServiceFunc(void *context, io_iterator_t portIterator)
{
/* Must drain the iterator, or we won't receive new notifications */
io_object_t entry;
while ((entry = IOIteratorNext(portIterator)) != 0) {
IOObjectRelease(entry);
*(SDL_bool*)context = SDL_TRUE;
}
}
#endif /* __MACOSX__ */
#ifdef HAVE_INOTIFY
#ifdef HAVE_INOTIFY_INIT1
static int SDL_inotify_init1(void) {
return inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
}
#else
static int SDL_inotify_init1(void) {
int fd = inotify_init();
if (fd < 0) return -1;
fcntl(fd, F_SETFL, O_NONBLOCK);
fcntl(fd, F_SETFD, FD_CLOEXEC);
return fd;
}
#endif
static int
StrHasPrefix(const char *string, const char *prefix)
{
return (SDL_strncmp(string, prefix, SDL_strlen(prefix)) == 0);
}
static int
StrIsInteger(const char *string)
{
const char *p;
if (*string == '\0') {
return 0;
}
for (p = string; *p != '\0'; p++) {
if (*p < '0' || *p > '9') {
return 0;
}
}
return 1;
}
#endif
static void
HIDAPI_InitializeDiscovery()
{
SDL_HIDAPI_discovery.m_bHaveDevicesChanged = SDL_TRUE;
SDL_HIDAPI_discovery.m_bCanGetNotifications = SDL_FALSE;
SDL_HIDAPI_discovery.m_unLastDetect = 0;
#if defined(__WIN32__)
SDL_HIDAPI_discovery.m_nThreadID = SDL_ThreadID();
SDL_zero(SDL_HIDAPI_discovery.m_wndClass);
SDL_HIDAPI_discovery.m_wndClass.hInstance = GetModuleHandle(NULL);
SDL_HIDAPI_discovery.m_wndClass.lpszClassName = "SDL_HIDAPI_DEVICE_DETECTION";
SDL_HIDAPI_discovery.m_wndClass.lpfnWndProc = ControllerWndProc; /* This function is called by windows */
SDL_HIDAPI_discovery.m_wndClass.cbSize = sizeof(WNDCLASSEX);
RegisterClassExA(&SDL_HIDAPI_discovery.m_wndClass);
SDL_HIDAPI_discovery.m_hwndMsg = CreateWindowExA(0, "SDL_HIDAPI_DEVICE_DETECTION", NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL);
{
DEV_BROADCAST_DEVICEINTERFACE_A devBroadcast;
SDL_zero(devBroadcast);
devBroadcast.dbcc_size = sizeof( devBroadcast );
devBroadcast.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
devBroadcast.dbcc_classguid = GUID_DEVINTERFACE_USB_DEVICE;
/* DEVICE_NOTIFY_ALL_INTERFACE_CLASSES is important, makes GUID_DEVINTERFACE_USB_DEVICE ignored,
* but that seems to be necessary to get a notice after each individual usb input device actually
* installs, rather than just as the composite device is seen.
*/
SDL_HIDAPI_discovery.m_hNotify = RegisterDeviceNotification( SDL_HIDAPI_discovery.m_hwndMsg, &devBroadcast, DEVICE_NOTIFY_WINDOW_HANDLE | DEVICE_NOTIFY_ALL_INTERFACE_CLASSES );
SDL_HIDAPI_discovery.m_bCanGetNotifications = ( SDL_HIDAPI_discovery.m_hNotify != 0 );
}
#endif /* __WIN32__ */
#if defined(__MACOSX__)
SDL_HIDAPI_discovery.m_notificationPort = IONotificationPortCreate(kIOMasterPortDefault);
if (SDL_HIDAPI_discovery.m_notificationPort) {
{
io_iterator_t portIterator = 0;
io_object_t entry;
IOReturn result = IOServiceAddMatchingNotification(
SDL_HIDAPI_discovery.m_notificationPort,
kIOFirstMatchNotification,
IOServiceMatching(kIOHIDDeviceKey),
CallbackIOServiceFunc, &SDL_HIDAPI_discovery.m_bHaveDevicesChanged, &portIterator);
if (result == 0) {
/* Must drain the existing iterator, or we won't receive new notifications */
while ((entry = IOIteratorNext(portIterator)) != 0) {
IOObjectRelease(entry);
}
} else {
IONotificationPortDestroy(SDL_HIDAPI_discovery.m_notificationPort);
SDL_HIDAPI_discovery.m_notificationPort = nil;
}
}
{
io_iterator_t portIterator = 0;
io_object_t entry;
IOReturn result = IOServiceAddMatchingNotification(
SDL_HIDAPI_discovery.m_notificationPort,
kIOTerminatedNotification,
IOServiceMatching(kIOHIDDeviceKey),
CallbackIOServiceFunc, &SDL_HIDAPI_discovery.m_bHaveDevicesChanged, &portIterator);
if (result == 0) {
/* Must drain the existing iterator, or we won't receive new notifications */
while ((entry = IOIteratorNext(portIterator)) != 0) {
IOObjectRelease(entry);
}
} else {
IONotificationPortDestroy(SDL_HIDAPI_discovery.m_notificationPort);
SDL_HIDAPI_discovery.m_notificationPort = nil;
}
}
}
SDL_HIDAPI_discovery.m_notificationMach = MACH_PORT_NULL;
if (SDL_HIDAPI_discovery.m_notificationPort) {
SDL_HIDAPI_discovery.m_notificationMach = IONotificationPortGetMachPort(SDL_HIDAPI_discovery.m_notificationPort);
}
SDL_HIDAPI_discovery.m_bCanGetNotifications = (SDL_HIDAPI_discovery.m_notificationMach != MACH_PORT_NULL);
#endif // __MACOSX__
#if defined(SDL_USE_LIBUDEV)
if (linux_enumeration_method == ENUMERATION_LIBUDEV) {
SDL_HIDAPI_discovery.m_pUdev = NULL;
SDL_HIDAPI_discovery.m_pUdevMonitor = NULL;
SDL_HIDAPI_discovery.m_nUdevFd = -1;
usyms = SDL_UDEV_GetUdevSyms();
if (usyms) {
SDL_HIDAPI_discovery.m_pUdev = usyms->udev_new();
}
if (SDL_HIDAPI_discovery.m_pUdev) {
SDL_HIDAPI_discovery.m_pUdevMonitor = usyms->udev_monitor_new_from_netlink(SDL_HIDAPI_discovery.m_pUdev, "udev");
if (SDL_HIDAPI_discovery.m_pUdevMonitor) {
usyms->udev_monitor_enable_receiving(SDL_HIDAPI_discovery.m_pUdevMonitor);
SDL_HIDAPI_discovery.m_nUdevFd = usyms->udev_monitor_get_fd(SDL_HIDAPI_discovery.m_pUdevMonitor);
SDL_HIDAPI_discovery.m_bCanGetNotifications = SDL_TRUE;
}
}
}
else
#endif /* SDL_USE_LIBUDEV */
{
#if defined(HAVE_INOTIFY)
inotify_fd = SDL_inotify_init1();
if (inotify_fd < 0) {
SDL_LogWarn(SDL_LOG_CATEGORY_INPUT,
"Unable to initialize inotify, falling back to polling: %s",
strerror(errno));
return;
}
/* We need to watch for attribute changes in addition to
* creation, because when a device is first created, it has
* permissions that we can't read. When udev chmods it to
* something that we maybe *can* read, we'll get an
* IN_ATTRIB event to tell us. */
if (inotify_add_watch(inotify_fd, "/dev",
IN_CREATE | IN_DELETE | IN_MOVE | IN_ATTRIB) < 0) {
close(inotify_fd);
inotify_fd = -1;
SDL_LogWarn(SDL_LOG_CATEGORY_INPUT,
"Unable to add inotify watch, falling back to polling: %s",
strerror (errno));
return;
}
SDL_HIDAPI_discovery.m_bCanGetNotifications = SDL_TRUE;
#endif /* HAVE_INOTIFY */
}
}
static void
HIDAPI_UpdateDiscovery()
{
if (!SDL_HIDAPI_discovery.m_bCanGetNotifications) {
const Uint32 SDL_HIDAPI_DETECT_INTERVAL_MS = 3000; /* Update every 3 seconds */
Uint32 now = SDL_GetTicks();
if (!SDL_HIDAPI_discovery.m_unLastDetect || SDL_TICKS_PASSED(now, SDL_HIDAPI_discovery.m_unLastDetect + SDL_HIDAPI_DETECT_INTERVAL_MS)) {
SDL_HIDAPI_discovery.m_bHaveDevicesChanged = SDL_TRUE;
SDL_HIDAPI_discovery.m_unLastDetect = now;
}
return;
}
#if defined(__WIN32__)
#if 0 /* just let the usual SDL_PumpEvents loop dispatch these, fixing bug 4286. --ryan. */
/* We'll only get messages on the same thread that created the window */
if (SDL_ThreadID() == SDL_HIDAPI_discovery.m_nThreadID) {
MSG msg;
while (PeekMessage(&msg, SDL_HIDAPI_discovery.m_hwndMsg, 0, 0, PM_NOREMOVE)) {
if (GetMessageA(&msg, SDL_HIDAPI_discovery.m_hwndMsg, 0, 0) != 0) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
#endif
#endif /* __WIN32__ */
#if defined(__MACOSX__)
if (SDL_HIDAPI_discovery.m_notificationPort) {
struct { mach_msg_header_t hdr; char payload[ 4096 ]; } msg;
while (mach_msg(&msg.hdr, MACH_RCV_MSG | MACH_RCV_TIMEOUT, 0, sizeof(msg), SDL_HIDAPI_discovery.m_notificationMach, 0, MACH_PORT_NULL) == KERN_SUCCESS) {
IODispatchCalloutFromMessage(NULL, &msg.hdr, SDL_HIDAPI_discovery.m_notificationPort);
}
}
#endif
#if defined(SDL_USE_LIBUDEV)
if (linux_enumeration_method == ENUMERATION_LIBUDEV) {
if (SDL_HIDAPI_discovery.m_nUdevFd >= 0) {
/* Drain all notification events.
* We don't expect a lot of device notifications so just
* do a new discovery on any kind or number of notifications.
* This could be made more restrictive if necessary.
*/
for (;;) {
struct pollfd PollUdev;
struct udev_device *pUdevDevice;
PollUdev.fd = SDL_HIDAPI_discovery.m_nUdevFd;
PollUdev.events = POLLIN;
if (poll(&PollUdev, 1, 0) != 1) {
break;
}
pUdevDevice = usyms->udev_monitor_receive_device(SDL_HIDAPI_discovery.m_pUdevMonitor);
if (pUdevDevice) {
const char *action = NULL;
action = usyms->udev_device_get_action(pUdevDevice);
if (!action || SDL_strcmp(action, "add") == 0 || SDL_strcmp(action, "remove") == 0) {
SDL_HIDAPI_discovery.m_bHaveDevicesChanged = SDL_TRUE;
}
usyms->udev_device_unref(pUdevDevice);
}
}
}
}
else
#endif /* SDL_USE_LIBUDEV */
{
#if defined(HAVE_INOTIFY)
if (inotify_fd >= 0) {
union
{
struct inotify_event event;
char storage[4096];
char enough_for_inotify[sizeof (struct inotify_event) + NAME_MAX + 1];
} buf;
ssize_t bytes;
size_t remain = 0;
size_t len;
bytes = read(inotify_fd, &buf, sizeof (buf));
if (bytes > 0) {
remain = (size_t) bytes;
}
while (remain > 0) {
if (buf.event.len > 0 &&
!SDL_HIDAPI_discovery.m_bHaveDevicesChanged) {
if (StrHasPrefix(buf.event.name, "hidraw") &&
StrIsInteger(buf.event.name + strlen ("hidraw"))) {
SDL_HIDAPI_discovery.m_bHaveDevicesChanged = SDL_TRUE;
/* We found an hidraw change. We still continue to
* drain the inotify fd to avoid leaving old
* notifications in the queue. */
}
}
len = sizeof (struct inotify_event) + buf.event.len;
remain -= len;
if (remain != 0) {
memmove(&buf.storage[0], &buf.storage[len], remain);
}
}
}
#endif /* HAVE_INOTIFY */
}
}
static void
HIDAPI_ShutdownDiscovery()
{
#if defined(__WIN32__)
if (SDL_HIDAPI_discovery.m_hNotify)
UnregisterDeviceNotification(SDL_HIDAPI_discovery.m_hNotify);
if (SDL_HIDAPI_discovery.m_hwndMsg) {
DestroyWindow(SDL_HIDAPI_discovery.m_hwndMsg);
}
UnregisterClassA(SDL_HIDAPI_discovery.m_wndClass.lpszClassName, SDL_HIDAPI_discovery.m_wndClass.hInstance);
#endif
#if defined(__MACOSX__)
if (SDL_HIDAPI_discovery.m_notificationPort) {
IONotificationPortDestroy(SDL_HIDAPI_discovery.m_notificationPort);
}
#endif
#if defined(SDL_USE_LIBUDEV)
if (linux_enumeration_method == ENUMERATION_LIBUDEV &&
usyms) {
if (SDL_HIDAPI_discovery.m_pUdevMonitor) {
usyms->udev_monitor_unref(SDL_HIDAPI_discovery.m_pUdevMonitor);
}
if (SDL_HIDAPI_discovery.m_pUdev) {
usyms->udev_unref(SDL_HIDAPI_discovery.m_pUdev);
}
SDL_UDEV_ReleaseUdevSyms();
usyms = NULL;
}
#endif
}
void
HIDAPI_DumpPacket(const char *prefix, Uint8 *data, int size)
{
@@ -658,8 +201,7 @@ static void
HIDAPI_SetupDeviceDriver(SDL_HIDAPI_Device *device)
{
if (device->driver) {
/* Already setup */
return;
return; /* Already setup */
}
device->driver = HIDAPI_GetDeviceDriver(device);
@@ -681,8 +223,7 @@ static void
HIDAPI_CleanupDeviceDriver(SDL_HIDAPI_Device *device)
{
if (!device->driver) {
/* Already cleaned up */
return;
return; /* Already cleaned up */
}
/* Disconnect any joysticks */
@@ -767,17 +308,7 @@ HIDAPI_JoystickInit(void)
}
#endif
#if defined(__MACOSX__) || defined(__IPHONEOS__) || defined(__TVOS__)
/* The hidapi framwork is weak-linked on Apple platforms */
int HID_API_EXPORT HID_API_CALL hid_init(void) __attribute__((weak_import));
if (hid_init == NULL) {
SDL_SetError("Couldn't initialize hidapi, framework not available");
return -1;
}
#endif /* __MACOSX__ || __IPHONEOS__ || __TVOS__ */
if (hid_init() < 0) {
if (SDL_hid_init() < 0) {
SDL_SetError("Couldn't initialize hidapi");
return -1;
}
@@ -788,7 +319,6 @@ HIDAPI_JoystickInit(void)
}
SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI,
SDL_HIDAPIDriverHintChanged, NULL);
HIDAPI_InitializeDiscovery();
HIDAPI_JoystickDetect();
HIDAPI_UpdateDevices();
@@ -863,10 +393,13 @@ HIDAPI_ConvertString(const wchar_t *wide_string)
if (wide_string) {
string = SDL_iconv_string("UTF-8", "WCHAR_T", (char*)wide_string, (SDL_wcslen(wide_string)+1)*sizeof(wchar_t));
if (!string) {
if (sizeof(wchar_t) == sizeof(Uint16)) {
switch (sizeof(wchar_t)) {
case 2:
string = SDL_iconv_string("UTF-8", "UCS-2-INTERNAL", (char*)wide_string, (SDL_wcslen(wide_string)+1)*sizeof(wchar_t));
} else if (sizeof(wchar_t) == sizeof(Uint32)) {
break;
case 4:
string = SDL_iconv_string("UTF-8", "UCS-4-INTERNAL", (char*)wide_string, (SDL_wcslen(wide_string)+1)*sizeof(wchar_t));
break;
}
}
}
@@ -874,7 +407,7 @@ HIDAPI_ConvertString(const wchar_t *wide_string)
}
static void
HIDAPI_AddDevice(struct hid_device_info *info)
HIDAPI_AddDevice(struct SDL_hid_device_info *info)
{
SDL_HIDAPI_Device *device;
SDL_HIDAPI_Device *curr, *last = NULL;
@@ -1038,7 +571,7 @@ static void
HIDAPI_UpdateDeviceList(void)
{
SDL_HIDAPI_Device *device;
struct hid_device_info *devs, *info;
struct SDL_hid_device_info *devs, *info;
SDL_LockJoysticks();
@@ -1051,7 +584,7 @@ HIDAPI_UpdateDeviceList(void)
/* Enumerate the devices */
if (SDL_HIDAPI_numdrivers > 0) {
devs = hid_enumerate(0, 0);
devs = SDL_hid_enumerate(0, 0);
if (devs) {
for (info = devs; info; info = info->next) {
device = HIDAPI_GetJoystickByInfo(info->path, info->vendor_id, info->product_id);
@@ -1061,7 +594,7 @@ HIDAPI_UpdateDeviceList(void)
HIDAPI_AddDevice(info);
}
}
hid_free_enumeration(devs);
SDL_hid_free_enumeration(devs);
}
}
@@ -1202,11 +735,10 @@ static void
HIDAPI_JoystickDetect(void)
{
if (SDL_AtomicTryLock(&SDL_HIDAPI_spinlock)) {
HIDAPI_UpdateDiscovery();
if (SDL_HIDAPI_discovery.m_bHaveDevicesChanged) {
/* FIXME: We probably need to schedule an update in a few seconds as well */
Uint32 count = SDL_hid_device_change_count();
if (SDL_HIDAPI_change_count != count) {
HIDAPI_UpdateDeviceList();
SDL_HIDAPI_discovery.m_bHaveDevicesChanged = SDL_FALSE;
SDL_HIDAPI_change_count = count;
}
SDL_AtomicUnlock(&SDL_HIDAPI_spinlock);
}
@@ -1363,15 +895,15 @@ HIDAPI_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16
return result;
}
static SDL_bool
HIDAPI_JoystickHasLED(SDL_Joystick *joystick)
static Uint32
HIDAPI_JoystickGetCapabilities(SDL_Joystick *joystick)
{
SDL_bool result = SDL_FALSE;
Uint32 result = 0;
if (joystick->hwdata) {
SDL_HIDAPI_Device *device = joystick->hwdata->device;
result = device->driver->HasJoystickLED(device, joystick);
result = device->driver->GetJoystickCapabilities(device, joystick);
}
return result;
@@ -1470,17 +1002,8 @@ HIDAPI_JoystickQuit(void)
shutting_down = SDL_TRUE;
HIDAPI_ShutdownDiscovery();
SDL_HIDAPI_QuitRumble();
#if defined(HAVE_INOTIFY)
if (inotify_fd >= 0) {
close(inotify_fd);
inotify_fd = -1;
}
#endif
while (SDL_HIDAPI_devices) {
HIDAPI_DelDevice(SDL_HIDAPI_devices);
}
@@ -1495,7 +1018,7 @@ HIDAPI_JoystickQuit(void)
SDL_DelHintCallback(SDL_HINT_JOYSTICK_HIDAPI,
SDL_HIDAPIDriverHintChanged, NULL);
hid_exit();
SDL_hid_exit();
shutting_down = SDL_FALSE;
initialized = SDL_FALSE;
@@ -1520,7 +1043,7 @@ SDL_JoystickDriver SDL_HIDAPI_JoystickDriver =
HIDAPI_JoystickOpen,
HIDAPI_JoystickRumble,
HIDAPI_JoystickRumbleTriggers,
HIDAPI_JoystickHasLED,
HIDAPI_JoystickGetCapabilities,
HIDAPI_JoystickSetLED,
HIDAPI_JoystickSendEffect,
HIDAPI_JoystickSetSensorsEnabled,

View File

@@ -27,7 +27,7 @@
#include "SDL_mutex.h"
#include "SDL_joystick.h"
#include "SDL_gamecontroller.h"
#include "../../hidapi/hidapi/hidapi.h"
#include "SDL_hidapi.h"
#include "../usb_ids.h"
/* This is the full set of HIDAPI drivers available */
@@ -70,7 +70,7 @@ typedef struct _SDL_HIDAPI_Device
struct _SDL_HIDAPI_DeviceDriver *driver;
void *context;
SDL_mutex *dev_lock;
hid_device *dev;
SDL_hid_device *dev;
SDL_atomic_t rumble_pending;
int num_joysticks;
SDL_JoystickID *joysticks;
@@ -88,6 +88,7 @@ typedef struct _SDL_HIDAPI_DeviceDriver
{
const char *hint;
SDL_bool enabled;
SDL_bool enabled_default;
SDL_bool (*IsSupportedDevice)(const char *name, SDL_GameControllerType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol);
const char *(*GetDeviceName)(Uint16 vendor_id, Uint16 product_id);
SDL_bool (*InitDevice)(SDL_HIDAPI_Device *device);
@@ -97,7 +98,7 @@ typedef struct _SDL_HIDAPI_DeviceDriver
SDL_bool (*OpenJoystick)(SDL_HIDAPI_Device *device, SDL_Joystick *joystick);
int (*RumbleJoystick)(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble);
int (*RumbleJoystickTriggers)(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble);
SDL_bool (*HasJoystickLED)(SDL_HIDAPI_Device *device, SDL_Joystick *joystick);
Uint32 (*GetJoystickCapabilities)(SDL_HIDAPI_Device *device, SDL_Joystick *joystick);
int (*SetJoystickLED)(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue);
int (*SendJoystickEffect)(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, const void *data, int size);
int (*SetJoystickSensorsEnabled)(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, SDL_bool enabled);

View File

@@ -23,6 +23,43 @@
#pragma pack(1)
#define HID_FEATURE_REPORT_BYTES 64
// Header for all host <==> target messages
typedef struct
{
unsigned char type;
unsigned char length;
} FeatureReportHeader;
// Generic controller attribute structure
typedef struct
{
unsigned char attributeTag;
uint32_t attributeValue;
} ControllerAttribute;
// Generic controller settings structure
typedef struct
{
ControllerAttribute attributes[ ( HID_FEATURE_REPORT_BYTES - sizeof( FeatureReportHeader ) ) / sizeof( ControllerAttribute ) ];
} MsgGetAttributes;
// This is the only message struct that application code should use to interact with feature request messages. Any new
// messages should be added to the union. The structures defined here should correspond to the ones defined in
// ValveDeviceCore.cpp.
//
typedef struct
{
FeatureReportHeader header;
union
{
MsgGetAttributes getAttributes;
} payload;
} FeatureReportMsg;
// Roll this version forward anytime that you are breaking compatibility of existing
// message types within ValveInReport_t or the header itself. Hopefully this should
// be super rare and instead you shoudl just add new message payloads to the union,