6161#define SENSOR_INTERVAL_APEX5_WIRED_RATE_HZ 970
6262#define SENSOR_INTERVAL_APEX5_WIRED_NS (SDL_NS_PER_SECOND / SENSOR_INTERVAL_APEX5_WIRED_RATE_HZ)
6363
64+ #define FLYDIGI_ACQUIRE_CONTROLLER_HEARTBEAT_TIME 1000 * 60
65+
6466#define FLYDIGI_V1_CMD_REPORT_ID 0x05
6567#define FLYDIGI_V1_HAPTIC_COMMAND 0x0F
6668#define FLYDIGI_V1_GET_INFO_COMMAND 0xEC
7173#define FLYDIGI_V2_GET_INFO_COMMAND 0x01
7274#define FLYDIGI_V2_HAPTIC_COMMAND 0x12
7375#define FLYDIGI_V2_ACQUIRE_CONTROLLER_COMMAND 0x1c
74- #define FLYDIGI_ACQUIRE_CONTROLLER_HEARTBEAT_TIME 1000 * 60
76+
7577#define LOAD16 (A , B ) (Sint16)((Uint16)(A) | (((Uint16)(B)) << 8))
7678
7779typedef struct
7880{
79- bool enabled ;
8081 Uint8 deviceID ;
8182 bool has_cz ;
8283 bool has_lmrm ;
@@ -88,11 +89,8 @@ typedef struct
8889 Uint64 sensor_timestamp_step_ns ; // Based on observed rate of receipt of IMU sensor packets.
8990 float accelScale ;
9091 float gyroScale ;
92+ Uint64 last_heartbeat ;
9193 Uint8 last_state [USB_PACKET_LENGTH ];
92-
93- bool stop_thread ;
94- SDL_Thread * thread ;
95- char thread_name_buf [256 ];
9694} SDL_DriverFlydigi_Context ;
9795
9896
@@ -198,26 +196,23 @@ static bool GetReply(SDL_HIDAPI_Device* device, Uint8 command, Uint8* data, size
198196 return false;
199197}
200198
201- static int SDLCALL SDL_HIDAPI_Flydigi_ThreadFunction (SDL_HIDAPI_Device * device )
199+ static bool SDL_HIDAPI_Flydigi_SendHeartbeat (SDL_HIDAPI_Device * device )
202200{
203- SDL_DriverFlydigi_Context * ctx = (SDL_DriverFlydigi_Context * )device -> context ;
204- while (true) {
205- if (ctx -> stop_thread ) {
206- return 0 ;
207- }
208-
209- const Uint8 acquireControllerCmd [] = { FLYDIGI_V2_CMD_REPORT_ID , FLYDIGI_V2_MAGIC1 , FLYDIGI_V2_MAGIC2 , FLYDIGI_V2_ACQUIRE_CONTROLLER_COMMAND , 23 , 1 , 83 , 68 , 76 , 0 };
210- if (SDL_hid_write (device -> dev , acquireControllerCmd , sizeof (acquireControllerCmd )) < 0 ) {
211- return SDL_SetError ("Couldn't enable input reports" );
212- }
213- Uint8 acquireControllerData [USB_PACKET_LENGTH ];
201+ const Uint8 acquireControllerCmd [] = { FLYDIGI_V2_CMD_REPORT_ID , FLYDIGI_V2_MAGIC1 , FLYDIGI_V2_MAGIC2 , FLYDIGI_V2_ACQUIRE_CONTROLLER_COMMAND , 23 , 1 , 83 , 68 , 76 , 0 };
202+ if (SDL_hid_write (device -> dev , acquireControllerCmd , sizeof (acquireControllerCmd )) < 0 ) {
203+ return SDL_SetError ("Couldn't enable input reports" );
204+ }
214205
215- if (GetReply (device , FLYDIGI_V2_ACQUIRE_CONTROLLER_COMMAND , acquireControllerData , sizeof (acquireControllerData ))) {
216- ctx -> enabled = acquireControllerData [6 ] == 1 ;
217- }
218- SDL_Delay (FLYDIGI_ACQUIRE_CONTROLLER_HEARTBEAT_TIME );
206+ Uint8 acquireControllerData [USB_PACKET_LENGTH ];
207+ if (!GetReply (device , FLYDIGI_V2_ACQUIRE_CONTROLLER_COMMAND , acquireControllerData , sizeof (acquireControllerData ))) {
208+ return SDL_SetError ("Controller acquiring is not supported" );
209+ }
210+ if (acquireControllerData [6 ] != 1 ) {
211+ return SDL_SetError ("Controller acquiring is disabled" );
219212 }
213+ return true;
220214}
215+
221216static bool HIDAPI_DriverFlydigi_InitControllerV2 (SDL_HIDAPI_Device * device )
222217{
223218 SDL_DriverFlydigi_Context * ctx = (SDL_DriverFlydigi_Context * )device -> context ;
@@ -233,7 +228,6 @@ static bool HIDAPI_DriverFlydigi_InitControllerV2(SDL_HIDAPI_Device *device)
233228 ctx -> firmware_version = LOAD16 (data [17 ], data [16 ]);
234229
235230 switch (data [7 ]) {
236-
237231 case 1 :
238232 // Wired connection
239233 ctx -> wireless = false;
@@ -247,25 +241,9 @@ static bool HIDAPI_DriverFlydigi_InitControllerV2(SDL_HIDAPI_Device *device)
247241 }
248242 }
249243
250- const Uint8 acquireControllerCmd [] = { FLYDIGI_V2_CMD_REPORT_ID , FLYDIGI_V2_MAGIC1 , FLYDIGI_V2_MAGIC2 , FLYDIGI_V2_ACQUIRE_CONTROLLER_COMMAND , 23 , 1 , 83 , 68 , 76 , 0 };
251- if (SDL_hid_write (device -> dev , acquireControllerCmd , sizeof (acquireControllerCmd )) < 0 ) {
252- return SDL_SetError ("Couldn't enable input reports" );
253- }
254-
255- Uint8 acquireControllerData [USB_PACKET_LENGTH ];
256- if (GetReply (device , FLYDIGI_V2_ACQUIRE_CONTROLLER_COMMAND , acquireControllerData , sizeof (acquireControllerData ))) {
257- if (acquireControllerData [6 ] == 1 ) {
258- ctx -> enabled = true;
259- } else {
260- // the controller can not be acquired by third party app
261- ctx -> enabled = false;
262- }
263- }else {
264- // the controller does not support acquired by third party app
265- ctx -> enabled = false;
266- }
244+ ctx -> last_heartbeat = SDL_GetTicks ();
267245
268- return ctx -> enabled ;
246+ return SDL_HIDAPI_Flydigi_SendHeartbeat ( device ) ;
269247}
270248
271249static void HIDAPI_DriverFlydigi_UpdateDeviceIdentity (SDL_HIDAPI_Device * device )
@@ -457,20 +435,11 @@ static bool HIDAPI_DriverFlydigi_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joy
457435 SDL_PrivateJoystickAddSensor (joystick , SDL_SENSOR_GYRO , flSensorRate );
458436 SDL_PrivateJoystickAddSensor (joystick , SDL_SENSOR_ACCEL , flSensorRate );
459437 }
460- if (ctx -> enabled && device -> vendor_id == USB_VENDOR_FLYDIGI_V2 ) {
461-
462- SDL_snprintf (ctx -> thread_name_buf , sizeof (ctx -> thread_name_buf ), "SDL_hidapi_flydigi %d %04x:%04x" , SDL_GetJoystickID (device -> joysticks ), USB_VENDOR_FLYDIGI_V2 , ctx -> deviceID );
463-
464- ctx -> stop_thread = false;
465- ctx -> thread = SDL_CreateThread (SDL_HIDAPI_Flydigi_ThreadFunction , ctx -> thread_name_buf , device );
466- }
467438 return true;
468439}
469440
470441static bool HIDAPI_DriverFlydigi_RumbleJoystick (SDL_HIDAPI_Device * device , SDL_Joystick * joystick , Uint16 low_frequency_rumble , Uint16 high_frequency_rumble )
471442{
472- SDL_DriverFlydigi_Context * ctx = (SDL_DriverFlydigi_Context * )device -> context ;
473-
474443 if (device -> vendor_id == USB_VENDOR_FLYDIGI_V1 ) {
475444 Uint8 rumble_packet [] = { FLYDIGI_V1_CMD_REPORT_ID , FLYDIGI_V1_HAPTIC_COMMAND , 0x00 , 0x00 };
476445 rumble_packet [2 ] = low_frequency_rumble >> 8 ;
@@ -659,9 +628,6 @@ static void HIDAPI_DriverFlydigi_HandleStatePacketV2(SDL_Joystick *joystick, SDL
659628 Sint16 axis ;
660629 Uint64 timestamp = SDL_GetTicksNS ();
661630
662- if (!ctx -> enabled ) {
663- return ;
664- }
665631 if (size > 0 && data [0 ] != 0x5A ) {
666632 // If first byte is not 0x5A, it must be REPORT_ID, we need to remove it.
667633 ++ data ;
@@ -818,6 +784,18 @@ static bool HIDAPI_DriverFlydigi_UpdateDevice(SDL_HIDAPI_Device *device)
818784 }
819785 }
820786
787+ if (device -> vendor_id == USB_VENDOR_FLYDIGI_V2 ) {
788+ Uint64 now = SDL_GetTicks ();
789+ if (now >= (ctx -> last_heartbeat + FLYDIGI_ACQUIRE_CONTROLLER_HEARTBEAT_TIME )) {
790+ if (!SDL_HIDAPI_Flydigi_SendHeartbeat (device )) {
791+ // We can no longer acquire the device, mark it as disconnected
792+ HIDAPI_JoystickDisconnected (device , device -> joysticks [0 ]);
793+ return false;
794+ }
795+ ctx -> last_heartbeat = now ;
796+ }
797+ }
798+
821799 if (size < 0 ) {
822800 // Read error, device is disconnected
823801 HIDAPI_JoystickDisconnected (device , device -> joysticks [0 ]);
@@ -827,12 +805,8 @@ static bool HIDAPI_DriverFlydigi_UpdateDevice(SDL_HIDAPI_Device *device)
827805
828806static void HIDAPI_DriverFlydigi_CloseJoystick (SDL_HIDAPI_Device * device , SDL_Joystick * joystick )
829807{
830- SDL_DriverFlydigi_Context * ctx = (SDL_DriverFlydigi_Context * )device -> context ;
831- ctx -> stop_thread = true;
832808 const Uint8 acquireControllerCmd [] = { FLYDIGI_V2_CMD_REPORT_ID , FLYDIGI_V2_MAGIC1 , FLYDIGI_V2_MAGIC2 , FLYDIGI_V2_ACQUIRE_CONTROLLER_COMMAND , 23 , 0 , 83 , 68 , 76 , 0 };
833- if (SDL_hid_write (device -> dev , acquireControllerCmd , sizeof (acquireControllerCmd )) < 0 ) {
834- return SDL_SetError ("Couldn't enable input reports" );
835- }
809+ SDL_hid_write (device -> dev , acquireControllerCmd , sizeof (acquireControllerCmd ));
836810}
837811
838812static void HIDAPI_DriverFlydigi_FreeDevice (SDL_HIDAPI_Device * device )
0 commit comments