XINPUT hat das Problem, das nur XBOX-Controller abgefragt werden können und nicht bspw. PS4- Controller.
Ich hab jetzt 1 1/2 Lösungen. Eine über die RAW-DATA-Routinen von Windows, die klappt wunderbar in 32Bit und 64Bit.
Jetzt wollte ich noch den Schritt machen und direkt auf abfrage abzufragen, das klappt aber überhaupt nicht.
HIDD_GetInputReport funktioniert nicht und liefert nie eine brauchbare Information.
Hat jemand brauchbaren Code, wie man die Buttons und Achsen nur mittels HID abfragen kann?
Code: Alles auswählen
;https://www.codeproject.com/Articles/185522/Using-the-Raw-Input-API-to-Process-Joystick-Input
;https://docs.microsoft.com/en-us/windows/desktop/winprog/windows-data-types
;https://www.codeproject.com/Articles/192941/HID-Application-Class-for-Easy-Reading-of-Joystick
;https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf
;https://katyscode.wordpress.com/2013/08/30/xinput-tutorial-part-1-adding-gamepad-support-to-your-windows-game/
DeclareModule joy
EnableExplicit
#HIDID_PS4 = $09CC0000054C
#HIDID_XBOXONE = $02FF0000045E
#HIDID_XBOX360 = $028E0000045E
Structure _Axis_Info
exist.i
value.i
EndStructure
Structure _Axis
x._Axis_Info
y._Axis_Info
z._Axis_Info
rx._Axis_Info
ry._Axis_Info
rz._Axis_Info
Slider._Axis_info
Dial._Axis_Info
Wheel._Axis_Info
EndStructure
Structure _DPad
exist.i
x.i
y.i
EndStructure
Structure _Button
Number.i
Value.l
EndStructure
Structure _HID
VendorId.l
ProductId.l
EndStructure
Structure sJoystick
Name.s
StructureUnion
HID._HID
HIDID.Q
EndStructureUnion
StructureUnion
Axis._Axis
AxisNb._Axis_Info[9]
EndStructureUnion
DPad._DPad
Button._Button
EndStructure
Declare init()
Declare exit()
Declare scan();Search for devices
Declare Register(WindowNb,without_focus=#False)
Declare CheckEvent(WindowEvent)
Declare EnableRemapPS4(flag)
Declare Enumerate(List Handle.i())
Declare LastState(handle);return *joystick.joystick
Declare Examine(hDevice)
EndDeclareModule
Module Joy
Procedure.s ShowError ()
Protected error, *MemoryID,length,e$
error = GetLastError_ ()
If error
*MemoryID = AllocateMemory (255)
length = FormatMessage_ (#FORMAT_MESSAGE_FROM_SYSTEM, #Null, error, 0, *MemoryID, 255, #Null)
If length > 1 ; Some error messages are "" + Chr (13) + Chr (10)... stoopid M$... :(
e$ = PeekS (*MemoryID, length - 2)
Else
e$ = "Unknown error!"
EndIf
FreeMemory (*MemoryID)
ProcedureReturn ""+error+" "+e$
Else
ProcedureReturn "No error has occurred!"
EndIf
EndProcedure
Declare Parse(*PreparseData,hDevice,*report,reportLen,hidhandle=0)
Global DLLuser32, DLLhid
Global PS4Remap
;
; Case $30: *axis=Joysticks()\Joystick\Axis\x
; Case $31: *axis=Joysticks()\Joystick\Axis\y
; Case $32: *axis=Joysticks()\Joystick\Axis\z
; Case $33: *axis=Joysticks()\Joystick\Axis\rx
; Case $34: *axis=Joysticks()\Joystick\Axis\ry
; Case $35: *axis=Joysticks()\Joystick\Axis\rz
; Case $36: *axis=Joysticks()\Joystick\Axis\Slider
Macro PS4AxisRemap(d)
If ps4remap
If d=$32
d=$33
ElseIf d=$33
d=$32
ElseIf d=$35
d=$34
ElseIf d=$34
d=$35
EndIf
EndIf
EndMacro
Macro PS4ButtonRemap(d)
If ps4remap
Select d
Case 1:d=0
Case 2:d=1
;3=3
Case 0:d=2
Case 9:d=7
Case 13:d=6
Case 11:d=9
Case 10:d=8
;4=4
;5=5
Case 6:d=$FF
Case 7:d=$FF
Case 8:d=13
EndSelect
EndIf
EndMacro
;{ HID-Prototype
Prototype.l prot_GetRawInputDeviceList (pRawInputDeviceList.i,puiNumDevices.i,cbSize.l)
Prototype.l prot_GetRawInputDeviceInfoW (hDevice.i,uiCommand.l,pData.i,pcbSize.i)
Prototype.l prot_RegisterRawInputDevices (pRawInputDevices.i,uiNumDevices.l,cbSize.l)
Prototype.l prot_GetRawInputData (hRawInput.i,uiCommand.l,pdata.i,pcbSize.i,cbSizeHeader.l)
Prototype.l prot_HidP_GetCaps (pPreparsedData.i,pCapabilities.i)
Prototype.l prot_HidP_GetButtonCaps (ReportType.l, pButtonCaps.i, puiButtonCapsLength.i, pPreparsedData.i)
Prototype.l prot_HidP_GetValueCaps (ReportType.l, pValueCaps.i , puiValueCapsLength.i , pPreparsedData.i)
Prototype.l prot_HidP_GetUsages (ReportType.l, wUsagePage.w , uLinkCollection.u, pUsageList.i, plUsageLength.i, pPreparsedData.i, pcReport.i, lReportLength.l)
Prototype.l prot_HidP_GetUsageValue (ReportType.l, wUsagePage.w , ULinkCollection.u, wUsage.w, pulValue.i, pPreparsedData.i, pcReport.i, lReportLength.l)
Prototype.l prot_HidP_GetScaledUsageValue (ReportType.l, wUsagePage.w , ULinkCollection.u, wUsage.w, pulValue.i, pPreparsedData.i, pcReport.i, lReportLength.l)
Prototype.l prot_HidP_InitializeReportForID (ReportType.l,ReportID.a,pPreparsedData.i, pcReport.i, lReportLength.l)
Prototype.b prot_HidD_GetProductString (HidDeviceObject.i, pBuffer.i, BufferLength.l)
Prototype.b prot_HidD_GetPreparsedData (HidDeviceObject.i, pPreparsedData.i)
Prototype.b prot_HidD_FreePreparsedData (PreparsedData.i)
Prototype.b prot_HidD_GetInputReport (HidDeviceObject.i, pReportBuffer.i, lReportBufferLength.l)
Global GetRawInputDeviceList.prot_GetRawInputDeviceList
Global GetRawInputDeviceInfo.prot_GetRawInputDeviceInfoW
Global RegisterRawInputDevices.prot_RegisterRawInputDevices
Global GetRawInputData.prot_GetRawInputData
Global HidP_InitializeReportForID.prot_HidP_InitializeReportForID
Global HidP_GetCaps.prot_HidP_GetCaps
Global HidP_GetButtonCaps.prot_HidP_GetButtonCaps
Global HidP_GetValueCaps.prot_HidP_GetValueCaps
Global HidP_GetUsages.prot_HidP_GetUsages
Global HidP_GetUsageValue.prot_HidP_GetUsageValue
Global HidP_GetScaledUsageValue.prot_HidP_GetScaledUsageValue
Global HidD_GetProductString.prot_HidD_GetProductString
Global HidD_GetPreparsedData.prot_HidD_GetPreparsedData
Global HidD_FreePreparsedData.prot_HidD_FreePreparsedData
Global HidD_GetInputReport.prot_HidD_GetInputReport
;}
#HID_Error=$10000000
#Buf256Size=256*2;widechar
Global *buf256
;{ HID-Structures
Structure RAWINPUTDEVICELIST_ Align #PB_Structure_AlignC
hDevice.i
dwType.l
EndStructure
Macro RAWINPUTDEVICELIST:RAWINPUTDEVICELIST_:EndMacro
Structure RID_DEVICE_INFO_HID_ Align #PB_Structure_AlignC
dwVendorId.l
dwProductId.l
dwVersionNumber.l
usUsagePage.w
usUsage.w
EndStructure
Macro RID_DEVICE_INFO_HID:RID_DEVICE_INFO_HID_:EndMacro
Structure RID_DEVICE_INFO_KEYBOARD_ Align #PB_Structure_AlignC
dwType.l
dwSubType.l
dwKeyboardMode.l
dwNumberOfFunctionKeys.l
dwNumberOfIndicators.l
dwNumberOfKeysTotal.l
EndStructure
Macro RID_DEVICE_INFO_KEYBOARD:RID_DEVICE_INFO_KEYBOARD_:EndMacro
Structure RID_DEVICE_INFO_MOUSE_ Align #PB_Structure_AlignC
dwId.l
dwNumberOfButtons.l
dwSampleRate.l
fHasHorizontalWheel.l
EndStructure
Macro RID_DEVICE_INFO_MOUSE:RID_DEVICE_INFO_MOUSE_:EndMacro
Structure RID_DEVICE_INFO_ Align #PB_Structure_AlignC
cbSize.l
dwType.l
StructureUnion
mouse.RID_DEVICE_INFO_MOUSE_
keyboard.RID_DEVICE_INFO_KEYBOARD_
hid.RID_DEVICE_INFO_HID_
EndStructureUnion
EndStructure
Macro RID_DEVICE_INFO:RID_DEVICE_INFO_:EndMacro
Structure RAWINPUTDEVICE_ Align #PB_Structure_AlignC
usUsagePage.w
usUsage.w
dwFlags.l
hwndTarget.i
EndStructure
Macro RAWINPUTDEVICE:RAWINPUTDEVICE_:EndMacro
Structure RAWINPUTHEADER_ Align #PB_Structure_AlignC
dwType.l
dwSize.l
hDevice.i
wParam.i
EndStructure
Macro RAWINPUTHEADER:RAWINPUTHEADER_:EndMacro
Structure RAWMOUSE_BUTTON_ Align #PB_Structure_AlignC
usButtonFlags.w
usButtonData.w
EndStructure
Macro RAWMOUSE_BUTTON:RAWMOUSE_BUTTON_:EndMacro
Structure RAWMOUSE_ Align #PB_Structure_AlignC
usFlags.w
StructureUnion
ulButtons.l
usButton.RAWMOUSE_BUTTON
EndStructureUnion
ulRawButtons.l
lLastX.l
lLastY.l
ulExtraInformation.l
EndStructure
Macro RAWMOUSE:RAWMOUSE_:EndMacro
Structure RAWKEYBOARD_ Align #PB_Structure_AlignC
MakeCode.w
Flags.w
Reserved.w
VKey.w
Message.l
ExtraInformation.l
EndStructure
Macro RAWKEYBOARD:RAWKEYBOARD_:EndMacro
Structure RAWHID_ Align #PB_Structure_AlignC
dwSizeHid.l
dwCount.l
bRawData.b[1]
EndStructure
Macro RAWHID:RAWHID_:EndMacro
Structure RAWINPUT_ Align #PB_Structure_AlignC
header.RAWINPUTHEADER
StructureUnion
mouse.RAWMOUSE
keyboard.RAWKEYBOARD
hid.RAWHID
EndStructureUnion
EndStructure
Macro RAWINPUT:RAWINPUT_:EndMacro
Structure HIDP_CAPS Align #PB_Structure_AlignC
UsagePage.w
Usage.w
InputReportByteLength.u
OutputReportByteLength.u
FeatureReportByteLength.u
Reserved.u[17]
NumberLinkCollectionNodes.u
NumberInputButtonCaps.u
NumberInputValueCaps.u
NumberInputDataIndices.u
NumberOutputButtonCaps.u
NumberOutputValueCaps.u
NumberOutputDataIndices.u
NumberFeatureButtonCaps.u
NumberFeatureValueCaps.u
NumberFeatureDataIndices.u
EndStructure
Structure _HIDP_CAPS_Range Align #PB_Structure_AlignC
UsageMin.w
UsageMax.w
StringMin.u
StringMax.u
DesignatorMin.u
DesignatorMax.u
DataIndexMin.u
DataIndexMax.u
EndStructure
Structure _HIDP_CAPS_NotRange Align #PB_Structure_AlignC
Reserved1.w
Usage.w
StringIndex.u
Reserved2.u
DesignatorIndex.u
Reserved3.u
DataIndex.u
Reserved4.u
EndStructure
Structure HIDP_BUTTON_CAPS Align #PB_Structure_AlignC
UsagePage.w;
ReportID.a ;
IsAlias.b ;
BitField.u ;
LinkCollection.u;
LinkUsage.w ;
LinkUsagePage.w ;
IsRange.b ;
IsStringRange.b ;
IsDesignatorRange.b;
IsAbsolute.b ;
Reserved.l[10] ;
StructureUnion
Range._HIDP_CAPS_Range
NotRange._HIDP_CAPS_NotRange
EndStructureUnion
EndStructure
Structure HIDP_VALUE_CAPS Align #PB_Structure_AlignC
UsagePage.w;
ReportID.a ;
IsAlias.b ;
BitField.u ;
LinkCollection.u;
LinkUsage.w ;
LinkUsagePage.w ;
IsRange.b ;
IsStringRange.b ;
IsDesignatorRange.b;
IsAbsolute.b ;
HasNull.b ;
Reserved.a ;
BitSize.u
ReportCount.u ;
Reserved2.u[5] ;
UnitsExp.l ;
Units.l ;
LogicalMin.l
LogicalMax.l ;
PhysicalMin.l ;
PhysicalMax.l ;
StructureUnion
Range._HIDP_CAPS_Range
NotRange._HIDP_CAPS_NotRange
EndStructureUnion
EndStructure
;}
;{ Constants
#RIDI_DEVICENAME=$20000007
#RIDI_DEVICEINFO=$2000000b
#RIDI_PREPARSEDDATA=$20000005
#RIM_TYPEHID=2
#RIM_TYPEKEYBOARD=1
#RIM_TYPEMOUSE=0
#RID_HEADER=$10000005
#RID_INPUT=$10000003
#RIDEV_INPUTSINK=$00000100
#HIDP_STATUS_SUCCESS=$110000
Enumeration HIDP_REPORT_TYPE
#HidP_Input
#HidP_Output
#HidP_Feature
EndEnumeration
;}
Procedure init()
If DLLuser32<>0
ProcedureReturn #False
EndIf
DLLuser32=OpenLibrary(#PB_Any,"user32.dll")
DLLhid=OpenLibrary(#PB_Any,"hid.dll")
GetRawInputDeviceList= GetFunction(DLLuser32, "GetRawInputDeviceList")
GetRawInputDeviceInfo = GetFunction(DLLuser32, "GetRawInputDeviceInfoW")
RegisterRawInputDevices = GetFunction(DLLuser32, "RegisterRawInputDevices")
GetRawInputData = GetFunction(DLLuser32, "GetRawInputData")
HidP_GetCaps = GetFunction(DLLhid, "HidP_GetCaps")
HidP_GetButtonCaps = GetFunction(DLLhid, "HidP_GetButtonCaps")
HidP_GetValueCaps = GetFunction(DLLhid, "HidP_GetValueCaps")
HidP_GetUsages = GetFunction(DLLhid, "HidP_GetUsages")
HidP_GetUsageValue = GetFunction(DLLhid, "HidP_GetUsageValue")
HidP_InitializeReportForID = GetFunction(DLLhid, "HidP_InitializeReportForID")
HidD_GetProductString = GetFunction(DLLhid, "HidD_GetProductString")
HidD_GetPreparsedData = GetFunction(DllHid, "HidD_GetPreparsedData")
HidD_FreePreparsedData = GetFunction(DLLhid, "HidD_FreePreparsedData")
HidD_GetInputReport = GetFunction(DLLhid, "HidD_GetInputReport")
*buf256=AllocateMemory(#Buf256Size)
ProcedureReturn scan()
EndProcedure
Procedure exit()
If DLLuser32=0
ProcedureReturn #False
EndIf
CloseLibrary(DLLuser32)
CloseLibrary(DLLhid)
DLLuser32=0
DLLhid=0
GetRawInputDeviceList= 0
GetRawInputDeviceInfo = 0
RegisterRawInputDevices = 0
GetRawInputData = 0
HidP_GetCaps = 0
HidP_GetButtonCaps = 0
HidP_GetValueCaps = 0
HidP_GetUsages = 0
HidP_GetUsageValue = 0
HidP_GetScaledUsageValue = 0
HidP_InitializeReportForID = 0
HidD_GetProductString = 0
HidD_GetPreparsedData = 0
HidD_FreePreparsedData = 0
HidD_GetInputReport = 0
FreeMemory(*buf256)
*buf256=0
EndProcedure
Procedure EnableRemapPS4(flag)
PS4Remap=flag
EndProcedure
Structure _sJoysticks_caps
InputReportByteLength.u
NumberInputButtonCaps.u
NumberInputValueCaps.u
EndStructure
Structure _sJoysticks_Hid
hDevice.i
DevicePath.s
Usage.u
UsagePage.u
EndStructure
Structure sJoysticks
Hid._sJoysticks_Hid
Caps._sJoysticks_caps
Joystick.sJoystick
EndStructure
Global NewList Joysticks.sJoysticks()
Procedure ClearJoysticks()
ClearList( joysticks() )
EndProcedure
Procedure Enumerate(List handle.i())
ClearList(handle())
ForEach joysticks()
AddElement(handle())
handle()=Joysticks()\Hid\hDevice
Next
ProcedureReturn ListSize(joysticks())
EndProcedure
Procedure scan()
Protected size.u,count.u,i,hidHandle
Protected DeviceInfo.RID_DEVICE_INFO
Protected caps.HIDP_CAPS
Protected PD.i,*ButtonCaps.HIDP_BUTTON_CAPS,capsLength.u,pos
ClearJoysticks()
If GetRawInputDeviceList(#Null,@count,SizeOf (RAWINPUTDEVICELIST) )>#HID_Error Or count=0
ProcedureReturn #False
EndIf
Dim Devices.RAWINPUTDEVICELIST(count-1)
If GetRawInputDeviceList(@devices(),@count,SizeOf(RAWINPUTDEVICELIST))>#HID_Error
ProcedureReturn #False
EndIf
For pos=0 To count-1
If Devices(pos)\dwType=#RIM_TYPEHID
size.u=SizeOf(rid_device_info)
If GetRawInputDeviceInfo(devices(pos)\hDevice,#RIDI_DEVICEINFO,@DeviceInfo,@size)>#HID_Error
ClearStructure(DeviceInfo,RID_DEVICE_INFO)
EndIf
If DeviceInfo\hid\usUsagePage=$1 And (DeviceInfo\hid\usUsage=4 Or DeviceInfo\hid\usUsage=5)
AddElement(joysticks())
joysticks()\hid\hDevice = devices(pos)\hDevice
joysticks()\Joystick\HID\VendorId = DeviceInfo\hid\dwVendorId
joysticks()\Joystick\hid\ProductId = DeviceInfo\hid\dwProductId
joysticks()\hid\Usage = DeviceInfo\hid\usUsage
joysticks()\hid\UsagePage = DeviceInfo\hid\usUsagePage
;Device Path
size.u=#Buf256Size
If GetRawInputDeviceInfo(devices(pos)\hDevice,#RIDI_DEVICENAME,*buf256,@size)<#HID_Error
joysticks()\hid\DevicePath=PeekS(*buf256)
hidHandle=CreateFile_(*buf256,#GENERIC_READ|#GENERIC_WRITE,#FILE_SHARE_READ|#FILE_SHARE_WRITE,#Null,#OPEN_EXISTING,#Null,#Null)
If hidHandle
If HidD_GetProductString(hidHandle,*buf256,#Buf256Size)
joysticks()\Joystick\Name=PeekS(*buf256)
EndIf
If HidD_GetPreparsedData(hidHandle,@pd)
If HidP_GetCaps(pd, @caps)=#HIDP_STATUS_SUCCESS
joysticks()\Caps\InputReportByteLength = caps\InputReportByteLength
joysticks()\Caps\NumberInputButtonCaps = caps\NumberInputButtonCaps
joysticks()\Caps\NumberInputValueCaps = caps\NumberInputValueCaps
EndIf
;Number of Buttons
*ButtonCaps=AllocateMemory(SizeOf(HIDP_BUTTON_CAPS) * caps\NumberInputButtonCaps)
capsLength.u = Caps\NumberInputButtonCaps
If HidP_GetButtonCaps(#HidP_Input, *ButtonCaps, @capsLength,pd) = #HIDP_STATUS_SUCCESS
If *ButtonCaps\IsRange And *ButtonCaps\IsAbsolute And *ButtonCaps\UsagePage=$09
Joysticks()\Joystick\Button\Number = *ButtonCaps\Range\UsageMax - *ButtonCaps\range\UsageMin+1
EndIf
EndIf
FreeMemory(*ButtonCaps)
;Axis
Dim ValueCaps.HIDP_VALUE_CAPS(caps\NumberInputValueCaps-1)
capsLength.u = caps\NumberInputValueCaps
If HidP_GetValueCaps( #HidP_Input,@ValueCaps(), @capsLength,pd) = #HIDP_STATUS_SUCCESS
For i=0 To caps\NumberInputValueCaps-1
If ValueCaps(i)\IsAbsolute And ValueCaps(i)\IsRange=#False And ValueCaps(i)\UsagePage=1 And (ValueCaps(i)\NotRange\Usage=>$30 And ValueCaps(i)\NotRange\Usage<=$39)
If ValueCaps(i)\NotRange\Usage=$39
joysticks()\Joystick\DPad\exist=#True
Else
If joysticks()\Joystick\HIDid=#HIDID_PS4
PS4AxisRemap(ValueCaps(i)\NotRange\Usage)
EndIf
joysticks()\Joystick\AxisNb[ ValueCaps(i)\NotRange\Usage -$30 ]\exist=#True
EndIf
EndIf
Next
EndIf
HidD_FreePreparsedData(pd)
pd=0
EndIf
CloseHandle_(hidHandle)
EndIf
EndIf
EndIf
EndIf
Next
Protected json
json=CreateJSON(#PB_Any)
If json
InsertJSONList(JSONValue(json), joysticks())
Debug ComposeJSON(json, #PB_JSON_PrettyPrint)
FreeJSON(json)
EndIf
ProcedureReturn ListSize(joysticks())
EndProcedure
Procedure Register(WindowNb,without_focus=#False)
Dim rid.RAWINPUTDEVICE(1)
rid(0)\usUsagePage=1
rid(0)\usUsage=5
rid(0)\hwndTarget=WindowID(WindowNb)
rid(0)\dwFlags=#RIDEV_DEVNOTIFY
rid(1)\usUsagePage=1
rid(1)\usUsage=4
rid(1)\hwndTarget=WindowID(WindowNb)
rid(1)\dwFlags=#RIDEV_DEVNOTIFY
If without_focus
rid(0)\dwFlags | #RIDEV_INPUTSINK
rid(1)\dwFlags | #RIDEV_INPUTSINK
EndIf
ProcedureReturn registerrawinputdevices(rid(),2,SizeOf(RAWINPUTDEVICE))
EndProcedure
Macro _FreeWMInput()
If *rawinput
FreeMemory(*rawinput):*rawinput=0
EndIf
If *PreparseData
FreeMemory(*PreparseData):*PreparseData=0
EndIf
EndMacro
Procedure Parse_WM_Input()
Protected size.u,ret
Protected hDevice,*report,reportLen
Protected *Rawinput.RAWINPUT,*PreparseData,buffersize.u
;Get size
If GetRawInputData(EventlParam(),#RID_INPUT,#Null,@size,SizeOf(RAWINPUTHEADER))<>0
ProcedureReturn #False
EndIf
;Allocate Memory
*Rawinput=AllocateMemory(size)
If *Rawinput=0
_FreeWMInput()
ProcedureReturn #False
EndIf
;Get *RawInput
If GetRawInputData(EventlParam(),#RID_INPUT,*Rawinput,@size,SizeOf(RAWINPUTHEADER))<>size
_FreeWMInput()
ProcedureReturn #False
EndIf
hDevice=*Rawinput\header\hDevice
*report = @ *Rawinput\hid\bRawData
reportLen = *Rawinput\hid\dwSizeHid
Protected ok
;Find Joystick
ForEach Joysticks()
If hDevice= Joysticks()\hid\hDevice
ok=#True
Break
EndIf
Next
If ok=#False
_FreeWMInput()
ProcedureReturn #False
EndIf
;Get BUffersize
If GetRawInputDeviceInfo( hDevice, #RIDI_PREPARSEDDATA ,#Null, @buffersize)<>0
_FreeWMInput()
ProcedureReturn #False
EndIf
;Allocate
*PreparseData=AllocateMemory(buffersize)
If *PreparseData=0
_FreeWMInput()
ProcedureReturn #False
EndIf
;Get PreparseData
If GetRawInputDeviceInfo( hDevice, #RIDI_PREPARSEDDATA ,*PreparseData,@buffersize)<>buffersize
_FreeWMInput()
ProcedureReturn #False
EndIf
ret=Parse(*PreparseData,hDevice,*report,reportLen)
_FreeWMInput()
ProcedureReturn ret
EndProcedure
Procedure GetReport(HidDeviceObject.i, Type.i, id.a, *report.ascii, reportLen.l, *PreparseData)
Debug ""+HidDeviceObject+" "+type+" "+id+" "+ *report +" "+reportLen+" "+*PreparseData
If HidP_InitializeReportForID(type,id,*PreparseData,*report,reportLen) <> #HIDP_STATUS_SUCCESS
Debug "inital-error"
ProcedureReturn #False
EndIf
If HidD_GetInputReport(HidDeviceObject,*report,reportLen-1) = 0
Debug "input-Report-error"
ProcedureReturn #False
EndIf
ProcedureReturn #True
EndProcedure
Procedure Examine(hDevice)
Protected ok,hidHandle,pd,*ret,*report
;Find Joystick
ForEach Joysticks()
If hDevice= Joysticks()\hid\hDevice
ok=#True
Break
EndIf
Next
If ok=#False
ProcedureReturn #False
EndIf
*report=AllocateMemory(joysticks()\Caps\InputReportByteLength+2)
If *report
hidHandle=CreateFile_(joysticks()\Hid\DevicePath,#GENERIC_READ|#GENERIC_WRITE,#FILE_SHARE_READ|#FILE_SHARE_WRITE,#Null,#OPEN_EXISTING,#FILE_FLAG_OVERLAPPED,#Null)
If hidHandle=#INVALID_HANDLE_VALUE
hidHandle=0
EndIf
Debug "HidHandle:"+hidHandle
If hidHandle
Debug "ok"
If HidD_GetPreparsedData(hidHandle,@pd)
Protected hidcaps.HIDP_CAPS
If parse(pd,hDevice,*report,joysticks()\Caps\InputReportByteLength,hidHandle)
*ret=joysticks()\Joystick
EndIf
HidD_FreePreparsedData(pd)
pd=0
EndIf
CloseHandle_(hidHandle)
EndIf
FreeMemory(*report)
EndIf
ProcedureReturn *ret
EndProcedure
Macro _freeParse()
EndMacro
Procedure Parse(*PreparseData,hDevice,*report,reportLen,hidhandle=0); Joysticks() must be set!
Protected capsLength.u,usageLength.l,i,value.l,bitmask.l,half.i
; Check Buttons
;Get ButtonCaps
capsLength.u = joysticks()\Caps\NumberInputButtonCaps
Dim ButtonCaps.HIDP_BUTTON_CAPS( capsLength-1 )
If HidP_GetButtonCaps(#HidP_Input, @ButtonCaps(0), @capsLength,*PreparseData) <> #HIDP_STATUS_SUCCESS
ProcedureReturn #False
EndIf
;Get Buttons
If ButtonCaps(0)\IsRange And ButtonCaps(0)\IsAbsolute And ButtonCaps(0)\UsagePage=$09
If hidhandle And GetReport(hidhandle,#HidP_Input,buttoncaps(0)\ReportID,*report,reportLen,*PreparseData)=#False
Debug "GetReportError"
;ProcedureReturn #False
EndIf
usageLength.l=ButtonCaps(0)\Range\UsageMax - ButtonCaps(0)\range\UsageMin+1
Dim usage.u(usageLength)
joysticks()\Joystick\Button\Value=0
If HidP_GetUsages( #HidP_Input, ButtonCaps(0)\UsagePage, #Null, @usage(), @usageLength, *PreparseData, *report, reportLen) = #HIDP_STATUS_SUCCESS
For i=0 To usageLength-1
usage(i) - ButtonCaps(0)\Range\UsageMin
If joysticks()\Joystick\HIDid=#HIDID_PS4
PS4ButtonRemap(usage(i))
EndIf
If usage(i)<32
joysticks()\Joystick\Button\Value | (1 << usage(i))
EndIf
Next
EndIf
EndIf
;Get ValueCaps
capsLength.u = joysticks()\caps\NumberInputValueCaps
Dim ValueCaps.HIDP_VALUE_CAPS( capsLength-1 )
If HidP_GetValueCaps( #HidP_Input, @ValueCaps(0), @capsLength,*PreparseData) <> #HIDP_STATUS_SUCCESS
ProcedureReturn #False
EndIf
;Get Values
For i=0 To joysticks()\Caps\NumberInputValueCaps-1
If ValueCaps(i)\IsAbsolute And ValueCaps(i)\IsRange=#False And ValueCaps(i)\UsagePage=1 And (ValueCaps(i)\NotRange\Usage=>$30 And ValueCaps(i)\NotRange\Usage<=$39)
If hidhandle And GetReport(hidhandle,#HidP_Input,ValueCaps(i)\ReportID,*report,reportLen,*PreparseData)=#False
;ProcedureReturn #False
EndIf
If HidP_GetUsageValue( #HidP_Input, ValueCaps(i)\UsagePage, #Null, ValueCaps(i)\NotRange\Usage, @value.l,*PreparseData, *report, reportLen)= #HIDP_STATUS_SUCCESS
If ValueCaps(i)\NotRange\Usage=$39
;Debug ""+Joysticks()\Joystick\nb+" "+ValueCaps(i)\HasNull+" "+ValueCaps(i)\LogicalMin+" - "+ValueCaps(i)\LogicalMax
joysticks()\Joystick\DPad\x=0
joysticks()\Joystick\DPad\y=0
Select value-ValueCaps(i)\LogicalMin
Case 7,0,1:joysticks()\Joystick\DPad\y=-1
Case 5,4,3:joysticks()\Joystick\DPad\y=1
EndSelect
Select value-ValueCaps(i)\LogicalMin
Case 7,6,5:joysticks()\Joystick\DPad\x=-1
Case 1,2,3:joysticks()\Joystick\DPad\x=1
EndSelect
Else
If joysticks()\Joystick\HIDid=#HIDID_PS4
PS4AxisRemap(ValueCaps(i)\NotRange\Usage)
EndIf
bitmask= (1 << ValueCaps(i)\BitSize)-1
ValueCaps(i)\LogicalMin & bitmask
ValueCaps(i)\LogicalMax & bitmask
value & bitmask
value - ValueCaps(i)\LogicalMin
half = (ValueCaps(i)\LogicalMax- ValueCaps(i)\LogicalMin)/2
joysticks()\Joystick\AxisNb[ ValueCaps(i)\NotRange\Usage-$30 ]\value=(value-half)*100/half
EndIf
EndIf
EndIf
Next
ProcedureReturn #True
EndProcedure
Procedure CheckEvent(WindowEvent)
Protected ret=0
Select WindowEvent
Case #WM_INPUT
If Parse_WM_Input()
ret=joysticks()\Joystick
Else
ret=0
EndIf
Case #WM_INPUT_DEVICE_CHANGE
scan()
ret=0
EndSelect
ProcedureReturn ret
EndProcedure
Procedure LastState(handle)
Protected *ret=#Null
ForEach joysticks()
If joysticks()\Hid\hDevice=handle
*ret=joysticks()\Joystick
Break
EndIf
Next
ProcedureReturn *ret
EndProcedure
EndModule
CompilerSelect 2;- example 1=rawinput, 2=examine
CompilerCase 1
;Rawinput-version
Procedure FillEditor()
Protected ii, *joy.joy::sJoystick
NewList handles()
joy::Enumerate(handles())
a$=""
ForEach handles()
*joy=joy::LastState(handles())
If *joy
a$+"----------------"+ handles() +#CRLF$
a$+"Name: "+ *joy\Name +#CRLF$
a$+"Product: "+Hex( *joy\HIDID) +#CRLF$
a$+"--"+#CRLF$
a$+"Buttons:"+*joy\Button\Number + #CRLF$
a$+"Buttonmap:"+Right("000000000000000000000000000000"+Bin( *joy\Button\Value ),*joy\Button\Number)+" "+*joy\Button\Value+#CRLF$
For ii=0 To *joy\Button\Number-1
If (*joy\Button\Value >> ii) &1
a$+"nr:"+ii+#CRLF$
EndIf
Next
a$+"--"+#CRLF$
If *joy\Axis\x\exist
a$+"X:"+ *joy\axis\x\value+#CRLF$
EndIf
If *joy\Axis\y\exist
a$+"Y:"+ *joy\axis\y\value+#CRLF$
EndIf
If *joy\Axis\z\exist
a$+"Z:"+ *joy\axis\z\value+#CRLF$
EndIf
a$+"--"+#CRLF$
If *joy\Axis\rx\exist
a$+"rx:"+ *joy\axis\rx\value+#CRLF$
EndIf
If *joy\Axis\ry\exist
a$+"ry:"+ *joy\axis\ry\value+#CRLF$
EndIf
If *joy\Axis\rz\exist
a$+"rZ:"+ *joy\axis\rz\value+#CRLF$
EndIf
a$+"--"+#CRLF$
If *joy\Axis\Slider\exist
a$+"Slider:"+ *joy\axis\Slider\value+#CRLF$
EndIf
a$+"--"+#CRLF$
If *joy\DPad\exist
a$+"DigiPad X:"+ *joy\DPad\x +#CRLF$
a$+"DigiPad y:"+ *joy\DPad\y +#CRLF$
EndIf
EndIf
Next
If GetGadgetText(0)<> a$
SetGadgetText(0,a$)
EndIf
EndProcedure
count=joy::init()
Debug count
joy::EnableRemapPS4(#True)
If OpenWindow(0, 100, 200, 800, 600, "PureBasic Window", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget)
joy::Register(0,#True)
EditorGadget(0,0,0,WindowWidth(0),WindowHeight(0))
FillEditor()
Repeat
Event = WaitWindowEvent()
Select event
Case #PB_Event_CloseWindow ; If the user has pressed on the close button
Quit = 1
Default
If joy::CheckEvent(event)<> -1
FillEditor()
EndIf
EndSelect
Until Quit = 1
EndIf
CompilerCase 2
;examine-version
Procedure FillEditor()
Protected ii, *joy.joy::sJoystick
NewList handles()
joy::Enumerate(handles())
a$="Start"+#CRLF$
ForEach handles()
*joy=joy::Examine(handles())
If *joy
a$+"----------------"+ handles() +#CRLF$
a$+"Name: "+ *joy\Name +#CRLF$
a$+"Product: "+Hex( *joy\HIDID) +#CRLF$
a$+"--"+#CRLF$
a$+"Buttons:"+*joy\Button\Number + #CRLF$
a$+"Buttonmap:"+Right("000000000000000000000000000000"+Bin( *joy\Button\Value ),*joy\Button\Number)+" "+*joy\Button\Value+#CRLF$
For ii=0 To *joy\Button\Number-1
If (*joy\Button\Value >> ii) &1
a$+"nr:"+ii+#CRLF$
EndIf
Next
a$+"--"+#CRLF$
If *joy\Axis\x\exist
a$+"X:"+ *joy\axis\x\value+#CRLF$
EndIf
If *joy\Axis\y\exist
a$+"Y:"+ *joy\axis\y\value+#CRLF$
EndIf
If *joy\Axis\z\exist
a$+"Z:"+ *joy\axis\z\value+#CRLF$
EndIf
a$+"--"+#CRLF$
If *joy\Axis\rx\exist
a$+"rx:"+ *joy\axis\rx\value+#CRLF$
EndIf
If *joy\Axis\ry\exist
a$+"ry:"+ *joy\axis\ry\value+#CRLF$
EndIf
If *joy\Axis\rz\exist
a$+"rZ:"+ *joy\axis\rz\value+#CRLF$
EndIf
a$+"--"+#CRLF$
If *joy\Axis\Slider\exist
a$+"Slider:"+ *joy\axis\Slider\value+#CRLF$
EndIf
a$+"--"+#CRLF$
If *joy\DPad\exist
a$+"DigiPad X:"+ *joy\DPad\x +#CRLF$
a$+"DigiPad y:"+ *joy\DPad\y +#CRLF$
EndIf
EndIf
Next
If GetGadgetText(0)<> a$
SetGadgetText(0,a$)
EndIf
EndProcedure
count=joy::init()
Debug count
joy::EnableRemapPS4(#True)
If OpenWindow(0, 100, 200, 800, 600, "PureBasic Window", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget)
EditorGadget(0,0,0,WindowWidth(0),WindowHeight(0))
AddWindowTimer(0,1,1000/30);30fps
FillEditor()
Repeat
Event = WaitWindowEvent()
Select event
Case #PB_Event_Timer
FillEditor()
Case #PB_Event_CloseWindow ; If the user has pressed on the close button
Quit = 1
Default
If joy::CheckEvent(event)<> -1
FillEditor()
EndIf
EndSelect
Until Quit = 1
EndIf
CompilerEndSelect