diff --git a/src/joystick/hidapi/SDL_hidapi_flydigi.c b/src/joystick/hidapi/SDL_hidapi_flydigi.c index a36b022834..73b185becf 100644 --- a/src/joystick/hidapi/SDL_hidapi_flydigi.c +++ b/src/joystick/hidapi/SDL_hidapi_flydigi.c @@ -81,7 +81,9 @@ enum typedef struct { + SDL_HIDAPI_Device *device; Uint8 deviceID; + bool available; bool has_cz; bool has_lmrm; bool wireless; @@ -173,9 +175,31 @@ static bool HIDAPI_DriverFlydigi_InitControllerV1(SDL_HIDAPI_Device *device) } } } + ctx->available = true; + return true; } +static void HIDAPI_DriverFlydigi_SetAvailable(SDL_HIDAPI_Device* device, bool available) +{ + SDL_DriverFlydigi_Context *ctx = (SDL_DriverFlydigi_Context *)device->context; + + if (available == ctx->available) { + return; + } + + if (available) { + if (device->num_joysticks == 0) { + HIDAPI_JoystickConnected(device, NULL); + } + } else { + if (device->num_joysticks > 0) { + HIDAPI_JoystickDisconnected(device, device->joysticks[0]); + } + } + ctx->available = available; +} + static bool GetReply(SDL_HIDAPI_Device* device, Uint8 command, Uint8* data, size_t length) { for (int i = 0; i < 100; ++i) { @@ -218,12 +242,12 @@ static bool SDL_HIDAPI_Flydigi_SendAcquireRequest(SDL_HIDAPI_Device *device, boo return true; } -static bool HIDAPI_DriverFlydigi_HandleAcquireResponse(Uint8 *data, int size) +static void HIDAPI_DriverFlydigi_HandleAcquireResponse(SDL_HIDAPI_Device *device, Uint8 *data, int size) { if (data[5] != 1 && data[6] == 0) { - return SDL_SetError("Controller acquiring has been disabled"); + // Controller acquiring failed or has been disabled + HIDAPI_DriverFlydigi_SetAvailable(device, false); } - return true; } static bool HIDAPI_DriverFlydigi_InitControllerV2(SDL_HIDAPI_Device *device) @@ -267,13 +291,14 @@ static bool HIDAPI_DriverFlydigi_InitControllerV2(SDL_HIDAPI_Device *device) if (!GetReply(device, FLYDIGI_V2_GET_STATUS_COMMAND, data, sizeof(data))) { return SDL_SetError("Couldn't get controller status"); } - if (data[10] != 1) { + if (data[10] == 1) { + ctx->available = true; + } else { #ifdef SDL_PLATFORM_WINDOWS // Click "Allow third-party apps to take over mappings" in the FlyDigi Space Station app - return SDL_SetError("Controller acquiring is disabled"); #else // The FlyDigi Space Station app isn't available, we need to enable this ourselves - Uint8 enable_acquire[32] = { + Uint8 enable_acquire[] = { FLYDIGI_V2_CMD_REPORT_ID, FLYDIGI_V2_MAGIC1, FLYDIGI_V2_MAGIC2, @@ -419,6 +444,8 @@ static bool HIDAPI_DriverFlydigi_InitDevice(SDL_HIDAPI_Device *device) if (!ctx) { return false; } + ctx->device = device; + device->context = ctx; bool initialized; @@ -433,7 +460,12 @@ static bool HIDAPI_DriverFlydigi_InitDevice(SDL_HIDAPI_Device *device) HIDAPI_DriverFlydigi_UpdateDeviceIdentity(device); - return HIDAPI_JoystickConnected(device, NULL); + if (ctx->available) { + return HIDAPI_JoystickConnected(device, NULL); + } else { + // We'll connect it once it becomes available + return true; + } } static int HIDAPI_DriverFlydigi_GetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id) @@ -657,15 +689,16 @@ static void HIDAPI_DriverFlydigi_HandleStatePacketV1(SDL_Joystick *joystick, SDL SDL_memcpy(ctx->last_state, data, SDL_min(size, sizeof(ctx->last_state))); } -static bool HIDAPI_DriverFlydigi_HandlePacketV1(SDL_Joystick *joystick, SDL_DriverFlydigi_Context *ctx, Uint8 *data, int size) +static void HIDAPI_DriverFlydigi_HandlePacketV1(SDL_Joystick *joystick, SDL_DriverFlydigi_Context *ctx, Uint8 *data, int size) { if (data[0] != 0x04 || data[1] != 0xFE) { // We don't know how to handle this report, ignore it - return true; + return; } - HIDAPI_DriverFlydigi_HandleStatePacketV1(joystick, ctx, data, size); - return true; + if (joystick) { + HIDAPI_DriverFlydigi_HandleStatePacketV1(joystick, ctx, data, size); + } } static void HIDAPI_DriverFlydigi_HandleStatePacketV2(SDL_Joystick *joystick, SDL_DriverFlydigi_Context *ctx, Uint8 *data, int size) @@ -792,7 +825,18 @@ static void HIDAPI_DriverFlydigi_HandleStatePacketV2(SDL_Joystick *joystick, SDL SDL_memcpy(ctx->last_state, data, SDL_min(size, sizeof(ctx->last_state))); } -static bool HIDAPI_DriverFlydigi_HandlePacketV2(SDL_Joystick *joystick, SDL_DriverFlydigi_Context *ctx, Uint8 *data, int size) +static void HIDAPI_DriverFlydigi_HandleStatusUpdate(SDL_HIDAPI_Device *device, Uint8 *data, int size) +{ + if (data[9] == 1) { + // We can now acquire the controller + HIDAPI_DriverFlydigi_SetAvailable(device, true); + } else { + // We can no longer acquire the controller + HIDAPI_DriverFlydigi_SetAvailable(device, false); + } +} + +static void HIDAPI_DriverFlydigi_HandlePacketV2(SDL_Joystick *joystick, SDL_DriverFlydigi_Context *ctx, Uint8 *data, int size) { if (size > 0 && data[0] != 0x5A) { // If first byte is not 0x5A, it must be REPORT_ID, we need to remove it. @@ -801,23 +845,25 @@ static bool HIDAPI_DriverFlydigi_HandlePacketV2(SDL_Joystick *joystick, SDL_Driv } if (size < 31 || data[0] != FLYDIGI_V2_MAGIC1 || data[1] != FLYDIGI_V2_MAGIC2) { // We don't know how to handle this report, ignore it - return true; + return; } switch (data[2]) { case FLYDIGI_V2_ACQUIRE_CONTROLLER_COMMAND: - if (!HIDAPI_DriverFlydigi_HandleAcquireResponse(data, size)) { - return false; - } + HIDAPI_DriverFlydigi_HandleAcquireResponse(ctx->device, data, size); break; case FLYDIGI_V2_INPUT_REPORT: - HIDAPI_DriverFlydigi_HandleStatePacketV2(joystick, ctx, data, size); + if (joystick) { + HIDAPI_DriverFlydigi_HandleStatePacketV2(joystick, ctx, data, size); + } + break; + case FLYDIGI_V2_SET_STATUS_COMMAND: + HIDAPI_DriverFlydigi_HandleStatusUpdate(ctx->device, data, size); break; default: // We don't recognize this command, ignore it break; } - return true; } static bool HIDAPI_DriverFlydigi_UpdateDevice(SDL_HIDAPI_Device *device) @@ -845,20 +891,10 @@ static bool HIDAPI_DriverFlydigi_UpdateDevice(SDL_HIDAPI_Device *device) #endif ctx->last_packet = now; - if (!joystick) { - continue; - } - if (device->vendor_id == USB_VENDOR_FLYDIGI_V1) { - if (!HIDAPI_DriverFlydigi_HandlePacketV1(joystick, ctx, data, size)) { - HIDAPI_JoystickDisconnected(device, device->joysticks[0]); - return false; - } + HIDAPI_DriverFlydigi_HandlePacketV1(joystick, ctx, data, size); } else { - if (!HIDAPI_DriverFlydigi_HandlePacketV2(joystick, ctx, data, size)) { - HIDAPI_JoystickDisconnected(device, device->joysticks[0]); - return false; - } + HIDAPI_DriverFlydigi_HandlePacketV2(joystick, ctx, data, size); } } diff --git a/src/joystick/hidapi/SDL_hidapijoystick.c b/src/joystick/hidapi/SDL_hidapijoystick.c index 7b83ffba7f..137822b4ad 100644 --- a/src/joystick/hidapi/SDL_hidapijoystick.c +++ b/src/joystick/hidapi/SDL_hidapijoystick.c @@ -1305,6 +1305,11 @@ bool HIDAPI_IsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, */ SDL_LockJoysticks(); for (device = SDL_HIDAPI_devices; device; device = device->next) { + if (device->vendor_id == USB_VENDOR_FLYDIGI_V2) { + // Ignore the Apex 5, as it can dynamically switch between Xbox and HIDAPI mode + continue; + } + if (device->driver && HIDAPI_IsEquivalentToDevice(vendor_id, product_id, device)) { result = true;