Updated controller support

Got an idea for enhancing PureBasic? New command(s) you'd like to see?
coco2
Enthusiast
Enthusiast
Posts: 467
Joined: Mon Nov 25, 2013 5:38 am
Location: Australia

Updated controller support

Post by coco2 »

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.
miso
Enthusiast
Enthusiast
Posts: 525
Joined: Sat Oct 21, 2023 4:06 pm
Location: Hungary

Re: Updated controller support

Post by miso »

All sticks and trigger also available. Try the pad optional parameter. They will be there.
coco2
Enthusiast
Enthusiast
Posts: 467
Joined: Mon Nov 25, 2013 5:38 am
Location: Australia

Re: Updated controller support

Post by coco2 »

Thanks for the tip, I didn't know that pad meant access to all of the controls.
User avatar
kenmo
Addict
Addict
Posts: 2066
Joined: Tue Dec 23, 2003 3:54 am

Re: Updated controller support

Post by kenmo »

Hi coco2, I agree the Joystick library could use a major update. It would be nice if all PB platforms used SDL and its gamepad mappings. If I knew how to make PureLibraries I would contribute!

We last discussed SDL2 in 2023 :) I thought I should mention that major SDL3 released this year and I've written a brand new SDL3 wrapper for PureBasic, also I use it on both Windows and Linux now. You might be interested.

Here's the project. See SDL3.pbi
https://github.com/kenmo-pb/SDLx

Try the JoystickProperties and GamepadInput examples.
Actually, looking at them right now, I'd like to simplify them even more!
coco2
Enthusiast
Enthusiast
Posts: 467
Joined: Mon Nov 25, 2013 5:38 am
Location: Australia

Re: Updated controller support

Post by coco2 »

Hi Kenmo,
I still have the SDL2 wrapper but I would prefer if PureBasic had a good library built in, because I'm not so good at working with external libraries. I will take a look at your SDL3 wrapper, thank you.
miso
Enthusiast
Enthusiast
Posts: 525
Joined: Sat Oct 21, 2023 4:06 pm
Location: Hungary

Re: Updated controller support

Post by miso »

@coco2

I could not agree more. I have a controller module on hold, I return to finish it and post in the gamedev section today or tomorrow, as I have time today.
The controller problems are present everywhere (even in sdl, unity, etc) as the problem lies in the drivers and the non standardized hardware architectures. (drivers and/or hardware part like bluetooth can cause duplicate entries in controller list, and the layouts vary with product to product even with same manufacturers)
coco2
Enthusiast
Enthusiast
Posts: 467
Joined: Mon Nov 25, 2013 5:38 am
Location: Australia

Re: Updated controller support

Post by coco2 »

I tried working with SDL2 but I couldn't get it to read the GUID of the controller. If I had the GUID I could remember configurations every time the controller is connected. But I couldn't work out how to do that.
miso
Enthusiast
Enthusiast
Posts: 525
Joined: Sat Oct 21, 2023 4:06 pm
Location: Hungary

Re: Updated controller support

Post by miso »

The new hid lib implemented in the current beta can retreive extra data.
miso
Enthusiast
Enthusiast
Posts: 525
Joined: Sat Oct 21, 2023 4:06 pm
Location: Hungary

Re: Updated controller support

Post by miso »

The GUID in SDL is not a GUID. (It would not help.) It is a composition if VID, PID, BUS, DRIVER VERSION, PADDING and HASH. (I'm not shouting, seemed fine to capitol these.)

To identify a device, the first 3 is enough, the last 3 is reserved and not needed even to search the sdl database txt for layout mappings.
(I'm not sure of hats, as I think in windows its mapped as buttons or axis by driver, I'm no expert.)

This code works with the latest beta (6.30 beta4 !), but can compose the first (searchable) part of the sdl guid for gamepads and joysticks.

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()
Edit:

Clarification for the SDL GUIDs:
The SDL guid is different after sdl 2.1.

The first 4 bytes (8 character in the guid (windows)) is not important. 03000000 or 05000000 means the bus.

The next 2 bytes will be the the vendor ID like 5E04.
The next 2 bytes will be 0000

The next two bytes will be the product ID like 8E02.
The rest is not important.

Beware, the SDL guid has these bytes as big endian, so PB Hid gives back vendor 045E (Microsoft) in little endian, and it will be 5E04 (reversed) in the SDL GUID text format. (Regardless of OS)
coco2
Enthusiast
Enthusiast
Posts: 467
Joined: Mon Nov 25, 2013 5:38 am
Location: Australia

Re: Updated controller support

Post by coco2 »

When connecting an Xbox One controller via bluetooth it's seen as two controllers:

Code: Select all

Initialise: number of joysticks: 2
  Joystick 0: Bluetooth LE XINPUT compatible input device
  Joystick 1: XBox 360 controller 1
How do we fix that?
miso
Enthusiast
Enthusiast
Posts: 525
Joined: Sat Oct 21, 2023 4:06 pm
Location: Hungary

Re: Updated controller support

Post by miso »

Driver error. The new hid lib (beta4 6.30) finds my xbox controller only as 1 entry, while xinput based pb joystick lib finds it as 2 entry. (1 is virtual)
I managed to draw the raw data (with hidlib) from the controller. That way I already can identify same type controllers with hidpath. ( that way when one of them disconnects, I know which one has been removed from the two)

Can handle all the sticks, buttons, triggers, buttons, dpads ( as hats, never found dpad configured as dpad yet.) I could not manage motors (forcefeedback) though. None of my devices' descriptor had physical reports for them.
coco2
Enthusiast
Enthusiast
Posts: 467
Joined: Mon Nov 25, 2013 5:38 am
Location: Australia

Re: Updated controller support

Post by coco2 »

Why does SDL2 correctly detect one controller with the correct name "Xbox One S Controller"?
miso
Enthusiast
Enthusiast
Posts: 525
Joined: Sat Oct 21, 2023 4:06 pm
Location: Hungary

Re: Updated controller support

Post by miso »

I'ts just a guess, as I'm not familiar with SDL. I guess they get the devices via raw hid data, and display that. The virtual entries does not produce inputs.
I'm a beginner with all of these, so most things are getting figured out just now, on the fly for me, while I learn.
Post Reply