Skip to content

Commit a82e8a7

Browse files
committed
Allow dynamically switching mode of the Apex 5 controller
The controller can be in XInput mode or enhanced mode, so it will always show up as an XInput controller, and the enhanced mode controller will come and go as enhanced mode is enabled or disabled in the FlyDigi Space Station app.
1 parent 28849fd commit a82e8a7

File tree

2 files changed

+71
-30
lines changed

2 files changed

+71
-30
lines changed

src/joystick/hidapi/SDL_hidapi_flydigi.c

Lines changed: 66 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,9 @@ enum
8181

8282
typedef struct
8383
{
84+
SDL_HIDAPI_Device *device;
8485
Uint8 deviceID;
86+
bool available;
8587
bool has_cz;
8688
bool has_lmrm;
8789
bool wireless;
@@ -173,9 +175,31 @@ static bool HIDAPI_DriverFlydigi_InitControllerV1(SDL_HIDAPI_Device *device)
173175
}
174176
}
175177
}
178+
ctx->available = true;
179+
176180
return true;
177181
}
178182

183+
static void HIDAPI_DriverFlydigi_SetAvailable(SDL_HIDAPI_Device* device, bool available)
184+
{
185+
SDL_DriverFlydigi_Context *ctx = (SDL_DriverFlydigi_Context *)device->context;
186+
187+
if (available == ctx->available) {
188+
return;
189+
}
190+
191+
if (available) {
192+
if (device->num_joysticks == 0) {
193+
HIDAPI_JoystickConnected(device, NULL);
194+
}
195+
} else {
196+
if (device->num_joysticks > 0) {
197+
HIDAPI_JoystickDisconnected(device, device->joysticks[0]);
198+
}
199+
}
200+
ctx->available = available;
201+
}
202+
179203
static bool GetReply(SDL_HIDAPI_Device* device, Uint8 command, Uint8* data, size_t length)
180204
{
181205
for (int i = 0; i < 100; ++i) {
@@ -218,12 +242,12 @@ static bool SDL_HIDAPI_Flydigi_SendAcquireRequest(SDL_HIDAPI_Device *device, boo
218242
return true;
219243
}
220244

221-
static bool HIDAPI_DriverFlydigi_HandleAcquireResponse(Uint8 *data, int size)
245+
static void HIDAPI_DriverFlydigi_HandleAcquireResponse(SDL_HIDAPI_Device *device, Uint8 *data, int size)
222246
{
223247
if (data[5] != 1 && data[6] == 0) {
224-
return SDL_SetError("Controller acquiring has been disabled");
248+
// Controller acquiring failed or has been disabled
249+
HIDAPI_DriverFlydigi_SetAvailable(device, false);
225250
}
226-
return true;
227251
}
228252

229253
static bool HIDAPI_DriverFlydigi_InitControllerV2(SDL_HIDAPI_Device *device)
@@ -267,13 +291,14 @@ static bool HIDAPI_DriverFlydigi_InitControllerV2(SDL_HIDAPI_Device *device)
267291
if (!GetReply(device, FLYDIGI_V2_GET_STATUS_COMMAND, data, sizeof(data))) {
268292
return SDL_SetError("Couldn't get controller status");
269293
}
270-
if (data[10] != 1) {
294+
if (data[10] == 1) {
295+
ctx->available = true;
296+
} else {
271297
#ifdef SDL_PLATFORM_WINDOWS
272298
// Click "Allow third-party apps to take over mappings" in the FlyDigi Space Station app
273-
return SDL_SetError("Controller acquiring is disabled");
274299
#else
275300
// The FlyDigi Space Station app isn't available, we need to enable this ourselves
276-
Uint8 enable_acquire[32] = {
301+
Uint8 enable_acquire[] = {
277302
FLYDIGI_V2_CMD_REPORT_ID,
278303
FLYDIGI_V2_MAGIC1,
279304
FLYDIGI_V2_MAGIC2,
@@ -419,6 +444,8 @@ static bool HIDAPI_DriverFlydigi_InitDevice(SDL_HIDAPI_Device *device)
419444
if (!ctx) {
420445
return false;
421446
}
447+
ctx->device = device;
448+
422449
device->context = ctx;
423450

424451
bool initialized;
@@ -433,7 +460,12 @@ static bool HIDAPI_DriverFlydigi_InitDevice(SDL_HIDAPI_Device *device)
433460

434461
HIDAPI_DriverFlydigi_UpdateDeviceIdentity(device);
435462

436-
return HIDAPI_JoystickConnected(device, NULL);
463+
if (ctx->available) {
464+
return HIDAPI_JoystickConnected(device, NULL);
465+
} else {
466+
// We'll connect it once it becomes available
467+
return true;
468+
}
437469
}
438470

439471
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
657689
SDL_memcpy(ctx->last_state, data, SDL_min(size, sizeof(ctx->last_state)));
658690
}
659691

660-
static bool HIDAPI_DriverFlydigi_HandlePacketV1(SDL_Joystick *joystick, SDL_DriverFlydigi_Context *ctx, Uint8 *data, int size)
692+
static void HIDAPI_DriverFlydigi_HandlePacketV1(SDL_Joystick *joystick, SDL_DriverFlydigi_Context *ctx, Uint8 *data, int size)
661693
{
662694
if (data[0] != 0x04 || data[1] != 0xFE) {
663695
// We don't know how to handle this report, ignore it
664-
return true;
696+
return;
665697
}
666698

667-
HIDAPI_DriverFlydigi_HandleStatePacketV1(joystick, ctx, data, size);
668-
return true;
699+
if (joystick) {
700+
HIDAPI_DriverFlydigi_HandleStatePacketV1(joystick, ctx, data, size);
701+
}
669702
}
670703

671704
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
792825
SDL_memcpy(ctx->last_state, data, SDL_min(size, sizeof(ctx->last_state)));
793826
}
794827

795-
static bool HIDAPI_DriverFlydigi_HandlePacketV2(SDL_Joystick *joystick, SDL_DriverFlydigi_Context *ctx, Uint8 *data, int size)
828+
static void HIDAPI_DriverFlydigi_HandleStatusUpdate(SDL_HIDAPI_Device *device, Uint8 *data, int size)
829+
{
830+
if (data[9] == 1) {
831+
// We can now acquire the controller
832+
HIDAPI_DriverFlydigi_SetAvailable(device, true);
833+
} else {
834+
// We can no longer acquire the controller
835+
HIDAPI_DriverFlydigi_SetAvailable(device, false);
836+
}
837+
}
838+
839+
static void HIDAPI_DriverFlydigi_HandlePacketV2(SDL_Joystick *joystick, SDL_DriverFlydigi_Context *ctx, Uint8 *data, int size)
796840
{
797841
if (size > 0 && data[0] != 0x5A) {
798842
// 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
801845
}
802846
if (size < 31 || data[0] != FLYDIGI_V2_MAGIC1 || data[1] != FLYDIGI_V2_MAGIC2) {
803847
// We don't know how to handle this report, ignore it
804-
return true;
848+
return;
805849
}
806850

807851
switch (data[2]) {
808852
case FLYDIGI_V2_ACQUIRE_CONTROLLER_COMMAND:
809-
if (!HIDAPI_DriverFlydigi_HandleAcquireResponse(data, size)) {
810-
return false;
811-
}
853+
HIDAPI_DriverFlydigi_HandleAcquireResponse(ctx->device, data, size);
812854
break;
813855
case FLYDIGI_V2_INPUT_REPORT:
814-
HIDAPI_DriverFlydigi_HandleStatePacketV2(joystick, ctx, data, size);
856+
if (joystick) {
857+
HIDAPI_DriverFlydigi_HandleStatePacketV2(joystick, ctx, data, size);
858+
}
859+
break;
860+
case FLYDIGI_V2_SET_STATUS_COMMAND:
861+
HIDAPI_DriverFlydigi_HandleStatusUpdate(ctx->device, data, size);
815862
break;
816863
default:
817864
// We don't recognize this command, ignore it
818865
break;
819866
}
820-
return true;
821867
}
822868

823869
static bool HIDAPI_DriverFlydigi_UpdateDevice(SDL_HIDAPI_Device *device)
@@ -845,20 +891,10 @@ static bool HIDAPI_DriverFlydigi_UpdateDevice(SDL_HIDAPI_Device *device)
845891
#endif
846892
ctx->last_packet = now;
847893

848-
if (!joystick) {
849-
continue;
850-
}
851-
852894
if (device->vendor_id == USB_VENDOR_FLYDIGI_V1) {
853-
if (!HIDAPI_DriverFlydigi_HandlePacketV1(joystick, ctx, data, size)) {
854-
HIDAPI_JoystickDisconnected(device, device->joysticks[0]);
855-
return false;
856-
}
895+
HIDAPI_DriverFlydigi_HandlePacketV1(joystick, ctx, data, size);
857896
} else {
858-
if (!HIDAPI_DriverFlydigi_HandlePacketV2(joystick, ctx, data, size)) {
859-
HIDAPI_JoystickDisconnected(device, device->joysticks[0]);
860-
return false;
861-
}
897+
HIDAPI_DriverFlydigi_HandlePacketV2(joystick, ctx, data, size);
862898
}
863899
}
864900

src/joystick/hidapi/SDL_hidapijoystick.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1305,6 +1305,11 @@ bool HIDAPI_IsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version,
13051305
*/
13061306
SDL_LockJoysticks();
13071307
for (device = SDL_HIDAPI_devices; device; device = device->next) {
1308+
if (device->vendor_id == USB_VENDOR_FLYDIGI_V2) {
1309+
// Ignore the Apex 5, as it can dynamically switch between Xbox and HIDAPI mode
1310+
continue;
1311+
}
1312+
13081313
if (device->driver &&
13091314
HIDAPI_IsEquivalentToDevice(vendor_id, product_id, device)) {
13101315
result = true;

0 commit comments

Comments
 (0)