Updated controller support
Posted: Tue Nov 25, 2025 8:30 am
The current controller/joystick support reads 3 analogue axes, but all modern controllers have 6 (left stick, right stick and triggers). Also there are more buttons I think.
http://www.purebasic.com
https://www.purebasic.fr/english/
Code: Select all
;USAGE_PAGES=============================================================================================
Global Dim usagepages.s($FF)
#UPA_UNDEFINED = $00 : usagepages(#UPA_UNDEFINED) = "Undefined"
#UPA_GENERIC = $01 : usagepages(#UPA_GENERIC) = "Generic Desktop Controls" ;mouses, joysticks, gamepad, pointers, axes, dpad
#UPA_SIMCONTROLS = $02 : usagepages(#UPA_SIMCONTROLS) = "Simulation Controls" ;simulator devices, fly, race,joystick,pedal,rudder,throttle
#UPA_VR = $03 : usagepages(#UPA_VR) = "VR Controls" ;motion tracking, vr input devices
#UPA_SPORT = $04 : usagepages(#UPA_SPORT) = "Sport Controls" ;fitness specific devices, like bicycle-ergometer
#UPA_GAME_CONTROLS = $05 : usagepages(#UPA_GAME_CONTROLS) = "Game Controls" ;Not the modern, more likely arcade, wheel, or other game input
#UPA_GENERIC_DEV = $06 : usagepages(#UPA_GENERIC_DEV) = "Generic Device" ;other, not necessarily input devices
#UPA_KEYBOARD = $07 : usagepages(#UPA_KEYBOARD) = "Keyboard / Keypad"
#UPA_LED = $08 : usagepages(#UPA_LED) = "LEDs" ;keyboard leds for example (output)
#UPA_BUTTON = $09 : usagepages(#UPA_BUTTON) = "Buttons" ;Any buttons on keyboard, gamepad, joystick
#UPA_ORDINAL = $0A : usagepages(#UPA_ORDINAL) = "Ordinal" ;very rare and special
#UPA_TELEPHONY = $0B : usagepages(#UPA_TELEPHONY) = "Telephony" ;I/O for telephon specific like volume, call receive
#UPA_CONSUMER = $0C : usagepages(#UPA_CONSUMER) = "Consumer" ;rare, multimedia remote handle, audio/video play/pause
#UPA_DIGITIZERS = $0D : usagepages(#UPA_DIGITIZERS) = "Digitizer" ;graphic tablets, stylus pressure, pen, touchpad, touchscreen
#UPA_RESERVED = $0E : usagepages(#UPA_RESERVED) = "Reserved" ;originally force-feedback, but too many reserved, few uses
#UPA_PID = $0F : usagepages(#UPA_PID) = "Physical interface" ;mainly force feedback
#UPA_UNICODE = $10 : usagepages(#UPA_UNICODE) = "Unicode" ;rare, unicode encoded I/O
#UPA_ALPHANUMERIC = $14 : usagepages(#UPA_ALPHANUMERIC) = "Alphanumeric Display";LCD panel, text displays
#UPA_MEDICAL = $40 : usagepages(#UPA_MEDICAL) = "Medical Instument"
#UPA_BARCODE_SCANNER = $8C : usagepages(#UPA_BARCODE_SCANNER) = "Barcode Scanner"
#UPA_SCALES = $8D : usagepages(#UPA_SCALES) = "Scale" ;weight measuring
;========================================================================================================
Global Dim genpages.s($FF)
;USAGE_GENERIC===========================================================================================
#GUS_UNDEFINED = $00 : genpages(#GUS_UNDEFINED) = "Undefined"
#GUS_POINTER = $01 : genpages(#gus_Pointer) = "Pointer"
#GUS_MOUSE = $02 : genpages(#GUS_MOUSE) = "Mouse"
#GUS_JOYSTICK = $04 : genpages(#GUS_JOYSTICK) = "Joystick"
#GUS_GAMEPAD = $05 : genpages(#GUS_GAMEPAD) = "GamePad"
#GUS_KEYBOARD = $06 : genpages(#GUS_KEYBOARD) = "Keyboard"
#GUS_KEYPAD = $07 : genpages(#GUS_KEYPAD) = "Keypad"
#GUS_MULTI_AXIS_CONTROLLER = $08 : genpages(#GUS_MULTI_AXIS_CONTROLLER) = "Multi Axis Controller"
#GUS_X_AXIS = $30 : genpages(#GUS_X_AXIS) = "X Axis"
#GUS_Y_AXIS = $31 : genpages(#GUS_Y_AXIS) = "Y Axis"
#GUS_Z_AXIS = $32 : genpages(#GUS_Z_AXIS) = "Z Axis"
#GUS_RX = $33 : genpages(#GUS_RX) = "Rotation X" ;joystick rotation x
#GUS_RY = $34 : genpages(#GUS_RY) = "Rotation Y"
#GUS_RZ = $35 : genpages(#GUS_RZ) = "Rotation Z";rotation z, rudder
#GUS_SLIDER = $36 : genpages(#GUS_SLIDER) = "Slider"
#GUS_DIAL = $37 : genpages(#GUS_DIAL) = "Dial"
#GUS_WHEEL = $38 : genpages(#GUS_WHEEL) = "Wheel"
#GUS_HAT_SWITCH = $39 : genpages(#GUS_HAT_SWITCH) = "Hat Switch"
#GUS_START = $3D : genpages(#GUS_START) = "Start"
#GUS_SELECT = $3E : genpages(#gus_Select) = "Select"
;========================================================================================================
;USAGE_SIM===============================================================================================
#SIM_FLIGHT = $01 ;flight simulation device
#SIM_DRIVE = $02 ;automobile simulation device
#SIM_RUDDER = $20
#SIM_THROTTLE = $21
#SIM_STEERING = $22
#SIM_ACCELERATOR = $23
#SIM_BRAKE = $24
#SIM_CLUTCH = $25
;========================================================================================================
;USAGE BUTTONS===========================================================================================
; $01-$FF , Button 1 ... Button 255
;beware, in raw input data it is usually bitmapped to 1-2 bytes (8-16 buttons)
;========================================================================================================
Global Dim bustypes.s($FF)
;BUSES===================================================================================================
#BUS_USB = $01 : bustypes(#BUS_USB) = "USB"
#BUS_BLUETOOTH = $02 : bustypes(#BUS_BLUETOOTH) = "BlueTooth"
#BUS_VIRTUAL = $03 : bustypes(#BUS_VIRTUAL) = "Virtual / HIDProxy" ;Virtual controller, software HID
#BUS_PCI = $04 : bustypes(#BUS_PCI) = "PCI" ;Rare, mostly inbuilt device
#BUS_I2C = $05 : bustypes(#BUS_I2C) = "I2C" ;Inter integrated circuit, inlayed systems like tablets sensors and touchpads
#BUS_SPI = $06 : bustypes(#BUS_SPI) = "Serial Peripheral Interface" ; these are just for completion, not needed for us, gamedevs
#BUS_UNKNOWN = $07 : bustypes(#BUS_UNKNOWN) = "Default/Unknown" ;HIDBUS/Unknown
;========================================================================================================
Global Dim Strr.s(12)
Global Dim Stra.s(12)
stra(1)="HID PATH"
stra(2)="Vendor ID"
stra(3)="Product ID"
stra(4)="Serial Number"
stra(5)="ReleaseNumber"
stra(6)="HID Manufacturer"
stra(7)="HID Product"
stra(8)="UsagePage"
stra(9)="Usage"
stra(10)="Interface num"
stra(11)="BusType"
OpenConsole("")
EnableGraphicalConsole(1)
ExamineHIDs()
Global upg.i
While NextHID()
For x = 1 To 11
strr(x) = HIDInfo(x)
Select x
Case #PB_HID_UsagePage
upg.i=Val(HIDInfo(x))
PrintN(stra(x)+" : "+usagepages(upg))
Case #PB_HID_Usage
u.I = Val(HIDInfo(x))
If upg = #UPA_GENERIC
PrintN(stra(x)+" : "+genpages(u))
Else
PrintN(stra(x)+" : "+Str(u))
EndIf
Case #PB_HID_BusType
u.I = Val(HIDInfo(x))
PrintN(stra(x)+" : "+bustypes(u))
Default
PrintN(stra(x)+" : "+Strr(x))
EndSelect
Next
If HIDInfo(#PB_HID_UsagePage) = Str(#UPA_GENERIC)
If HIDInfo(#PB_HID_Usage)=Str(#GUS_GAMEPAD) Or HIDInfo(#PB_HID_Usage)=Str(#GUS_JOYSTICK)
part1.s = RSet(Hex(Val(HIDInfo(#PB_HID_VendorId))),4,"0")
part2.s = RSet(Hex(Val(HIDInfo(#PB_HID_ProductId))),4,"0")
part3.s = RSet(Hex(Val(HIDInfo(#PB_HID_BusType))),2,"0")
sdlguid.s = part1+part2+part3
PrintN("")
PrintN("SDL GUID:"+sdlguid)
PrintN("")
PrintN("(the remaining part would be driver version, padding/hash and reserved, )")
PrintN("(the first part is enough to identify a controller in the SDL database)")
PrintN("(to select a mapping.)")
EndIf
EndIf
PrintN("")
PrintN("======")
PrintN("")
Wend
Input()Code: Select all
Initialise: number of joysticks: 2
Joystick 0: Bluetooth LE XINPUT compatible input device
Joystick 1: XBox 360 controller 1