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