@@ -314,6 +314,8 @@ typedef struct GIP_Quirks
314
314
Uint32 extra_in_system [8 ];
315
315
Uint32 extra_out_system [8 ];
316
316
GIP_AttachmentType device_type ;
317
+ Uint8 extra_buttons ;
318
+ Uint8 extra_axes ;
317
319
} GIP_Quirks ;
318
320
319
321
static const GIP_Quirks quirks [] = {
@@ -348,6 +350,12 @@ static const GIP_Quirks quirks[] = {
348
350
.filtered_features = GIP_FEATURE_MOTOR_CONTROL ,
349
351
.device_type = GIP_TYPE_ARCADE_STICK },
350
352
353
+ { USB_VENDOR_THRUSTMASTER , USB_PRODUCT_THRUSTMASTER_T_FLIGHT_HOTAS_ONE , 0 ,
354
+ .filtered_features = GIP_FEATURE_MOTOR_CONTROL ,
355
+ .device_type = GIP_TYPE_FLIGHT_STICK ,
356
+ .extra_buttons = 5 ,
357
+ .extra_axes = 3 },
358
+
351
359
{0 },
352
360
};
353
361
@@ -451,6 +459,10 @@ typedef struct GIP_Attachment
451
459
Uint8 share_button_idx ;
452
460
Uint8 paddle_idx ;
453
461
int paddle_offset ;
462
+
463
+ Uint8 extra_button_idx ;
464
+ int extra_buttons ;
465
+ int extra_axes ;
454
466
} GIP_Attachment ;
455
467
456
468
typedef struct GIP_Device
@@ -658,6 +670,9 @@ static void GIP_HandleQuirks(GIP_Attachment *attachment)
658
670
attachment -> metadata .device .in_system_messages [j ] |= quirks [i ].extra_in_system [j ];
659
671
attachment -> metadata .device .out_system_messages [j ] |= quirks [i ].extra_out_system [j ];
660
672
}
673
+
674
+ attachment -> extra_buttons = quirks [i ].extra_buttons ;
675
+ attachment -> extra_axes = quirks [i ].extra_axes ;
661
676
break ;
662
677
}
663
678
}
@@ -1168,6 +1183,10 @@ static bool GIP_SendInitSequence(GIP_Attachment *attachment)
1168
1183
GIP_SendVendorMessage (attachment , GIP_CMD_INITIAL_REPORTS_REQUEST , 0 , (const Uint8 * )& request , sizeof (request ));
1169
1184
}
1170
1185
1186
+ if (GIP_SupportsVendorMessage (attachment , GIP_CMD_DEVICE_CAPABILITIES , false)) {
1187
+ GIP_SendVendorMessage (attachment , GIP_CMD_DEVICE_CAPABILITIES , 0 , NULL , 0 );
1188
+ }
1189
+
1171
1190
if (!attachment -> joystick ) {
1172
1191
return HIDAPI_JoystickConnected (attachment -> device -> device , & attachment -> joystick );
1173
1192
}
@@ -1833,6 +1852,67 @@ static void GIP_HandleArcadeStickReport(
1833
1852
}
1834
1853
}
1835
1854
1855
+ static void GIP_HandleFlightStickReport (
1856
+ GIP_Attachment * attachment ,
1857
+ SDL_Joystick * joystick ,
1858
+ Uint64 timestamp ,
1859
+ const Uint8 * bytes ,
1860
+ int num_bytes )
1861
+ {
1862
+ Sint16 axis ;
1863
+ int i ;
1864
+
1865
+ if (num_bytes < 19 ) {
1866
+ return ;
1867
+ }
1868
+
1869
+ if (attachment -> last_input [2 ] != bytes [2 ]) {
1870
+ /* Fire 1 and 2 */
1871
+ SDL_SendJoystickButton (timestamp , joystick , SDL_GAMEPAD_BUTTON_LEFT_STICK , ((bytes [2 ] & 0x01 ) != 0 ));
1872
+ SDL_SendJoystickButton (timestamp , joystick , SDL_GAMEPAD_BUTTON_RIGHT_STICK , ((bytes [2 ] & 0x02 ) != 0 ));
1873
+ }
1874
+ for (i = 0 ; i < attachment -> extra_buttons ;) {
1875
+ if (attachment -> last_input [i / 8 + 3 ] != bytes [i / 8 + 3 ]) {
1876
+ for (; i < attachment -> extra_buttons ; i ++ ) {
1877
+ SDL_SendJoystickButton (timestamp ,
1878
+ joystick ,
1879
+ (Uint8 ) (attachment -> extra_button_idx + i ),
1880
+ ((bytes [i / 8 + 3 ] & (1u << i )) != 0 ));
1881
+ }
1882
+ } else {
1883
+ i += 8 ;
1884
+ }
1885
+ }
1886
+
1887
+ /* Roll, pitch and yaw are signed. Throttle and any extra axes are unsigned. All values are full-range. */
1888
+ axis = bytes [11 ];
1889
+ axis |= bytes [12 ] << 8 ;
1890
+ SDL_SendJoystickAxis (timestamp , joystick , SDL_GAMEPAD_AXIS_LEFTX , axis );
1891
+
1892
+ axis = bytes [13 ];
1893
+ axis |= bytes [14 ] << 8 ;
1894
+ SDL_SendJoystickAxis (timestamp , joystick , SDL_GAMEPAD_AXIS_LEFTY , axis );
1895
+
1896
+ axis = bytes [15 ];
1897
+ axis |= bytes [16 ] << 8 ;
1898
+ SDL_SendJoystickAxis (timestamp , joystick , SDL_GAMEPAD_AXIS_RIGHTX , axis );
1899
+
1900
+ /* There are no more signed values, so skip RIGHTY */
1901
+
1902
+ axis = (bytes [18 ] << 8 ) - 0x8000 ;
1903
+ axis |= bytes [17 ];
1904
+ SDL_SendJoystickAxis (timestamp , joystick , SDL_GAMEPAD_AXIS_LEFT_TRIGGER , axis );
1905
+
1906
+ for (i = 0 ; i < attachment -> extra_axes ; i ++ ) {
1907
+ if (20 + i * 2 >= num_bytes ) {
1908
+ return ;
1909
+ }
1910
+ axis = (bytes [20 + i * 2 ] << 8 ) - 0x8000 ;
1911
+ axis |= bytes [19 + i * 2 ];
1912
+ SDL_SendJoystickAxis (timestamp , joystick , (Uint8 ) (SDL_GAMEPAD_AXIS_RIGHT_TRIGGER + i ), axis );
1913
+ }
1914
+ }
1915
+
1836
1916
static bool GIP_HandleLLInputReport (
1837
1917
GIP_Attachment * attachment ,
1838
1918
const GIP_Header * header ,
@@ -1875,6 +1955,9 @@ static bool GIP_HandleLLInputReport(
1875
1955
case GIP_TYPE_ARCADE_STICK :
1876
1956
GIP_HandleArcadeStickReport (attachment , joystick , timestamp , bytes , num_bytes );
1877
1957
break ;
1958
+ case GIP_TYPE_FLIGHT_STICK :
1959
+ GIP_HandleFlightStickReport (attachment , joystick , timestamp , bytes , num_bytes );
1960
+ break ;
1878
1961
}
1879
1962
1880
1963
if ((attachment -> features & GIP_FEATURE_ELITE_BUTTONS ) &&
@@ -2395,8 +2478,17 @@ static bool HIDAPI_DriverGIP_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystic
2395
2478
attachment -> share_button_idx = (Uint8 ) joystick -> nbuttons ;
2396
2479
joystick -> nbuttons ++ ;
2397
2480
}
2481
+ if (attachment -> extra_buttons > 0 ) {
2482
+ attachment -> extra_button_idx = (Uint8 ) joystick -> nbuttons ;
2483
+ joystick -> nbuttons += attachment -> extra_buttons ;
2484
+ }
2398
2485
2399
2486
joystick -> naxes = SDL_GAMEPAD_AXIS_COUNT ;
2487
+ if (attachment -> attachment_type == GIP_TYPE_FLIGHT_STICK ) {
2488
+ /* Flight sticks have at least 4 axes, but only 3 are signed values, so we leave RIGHTY unused */
2489
+ joystick -> naxes += attachment -> extra_axes - 1 ;
2490
+ }
2491
+
2400
2492
joystick -> nhats = 1 ;
2401
2493
2402
2494
return true;
0 commit comments