Jump to content

Precision Touchpad (how many fingers on pad, position of each finger, etc)


Recommended Posts

Global Const $user32 = DllOpen("user32.dll")
GUIRegisterMsg(0x00FF,WM_INPUT)
Local $struct = DllStructCreate('struct;ushort UsagePage;ushort Usage;dword Flags;hwnd Target;endstruct')
$struct.UsagePage=0x0D
$struct.Usage=0x05
$struct.Flags=0x00000100
$struct.Target=GUICreate('')
DllCall('user32.dll', 'bool', 'RegisterRawInputDevices', 'struct*', $struct, 'uint', 1, 'uint', DllStructGetSize(DllStructCreate('struct;ushort UsagePage;ushort Usage;dword Flags;hwnd Target;endstruct')))

GUICreate('')
Global $hLog = GUICtrlCreateLabel('',0,0,400,400)
GUISetState()

Do
Until GUIGetMsg()=-3

Func WM_INPUT($hWnd, $uMsg, $wParam, $lParam)
     Local Static $HEAD = 'struct;dword Type;dword Size;handle hDevice;wparam wParam;endstruct;' , _
                  $HEADSIZE = DllStructGetSize(DllStructCreate($HEAD)) , _
                  $PREFIX = $HEAD & 'dword SizeHid;dword Count;'
     Local $size = DllCall($user32,'uint','GetRawInputData','handle',$lParam,'uint',0x10000003,'struct*',Null,'uint*',Null,'uint',$HEADSIZE)[4]
     Local $raw = DllCall ( $user32, _
                            'uint' , 'GetRawInputData', _
                          'handle' , $lParam, _
                            'uint' , 0x10000003, _
                         'struct*' , DllStructCreate('byte[' & $size & ']'), _
                           'uint*' , $size, _
                            'uint' , $HEADSIZE )[3]
     Local $ptr = DllStructGetPtr($raw)
     Local $tag = $PREFIX, $info = DllStructCreate($PREFIX,$ptr), $size = DllStructGetData($info,'SizeHid'), $count = DllStructGetData($info,'Count')
     For $i=0 to $count-1
         $tag &= 'byte input' & $i & '[' & $size & '];'
     Next
     Local $input = DllStructCreate($tag, $ptr)
     Local $fingerPos = [ _ 
       [ DllStructGetData($input,'input0', 3)+256*DllStructGetData($input,'input0', 4) , DllStructGetData($input,'input0', 5)+256*DllStructGetData($input,'input0', 6) ] , _
       [ DllStructGetData($input,'input0', 8)+256*DllStructGetData($input,'input0', 9) , DllStructGetData($input,'input0',10)+256*DllStructGetData($input,'input0',11) ] , _
       [ DllStructGetData($input,'input0',13)+256*DllStructGetData($input,'input0',14) , DllStructGetData($input,'input0',15)+256*DllStructGetData($input,'input0',16) ] , _
       [ DllStructGetData($input,'input0',18)+256*DllStructGetData($input,'input0',19) , DllStructGetData($input,'input0',20)+256*DllStructGetData($input,'input0',21) ] , _
       [ DllStructGetData($input,'input0',23)+256*DllStructGetData($input,'input0',24) , DllStructGetData($input,'input0',25)+256*DllStructGetData($input,'input0',26) ]   _
     ]
     GUICtrlSetData($hLog,'?unknown: ' & DllStructGetData($input,'input0', 1) & @CRLF _
                        & 'finger1: (' & DllStructGetData($input,'input0', 2) & ') ' & $fingerPos[0][0] & ',' & $fingerPos[0][1] & @CRLF _
                        & 'finger2: (' & DllStructGetData($input,'input0', 7) & ') ' & $fingerPos[1][0] & ',' & $fingerPos[1][1] & @CRLF _
                        & 'finger3: (' & DllStructGetData($input,'input0',12) & ') ' & $fingerPos[2][0] & ',' & $fingerPos[2][1] & @CRLF _
                        & 'finger4: (' & DllStructGetData($input,'input0',17) & ') ' & $fingerPos[3][0] & ',' & $fingerPos[3][1] & @CRLF _
                        & 'finger5: (' & DllStructGetData($input,'input0',22) & ') ' & $fingerPos[4][0] & ',' & $fingerPos[4][1] & @CRLF _
                        & '?unknown: ' & DllStructGetData($input,'input0',27) & @CRLF _
                        & 'report no.' & DllStructGetData($input,'input0',28) & @CRLF _
                        & 'fingers: '  & DllStructGetData($input,'input0',29) & @CRLF _
                        & 'click: '    & DllStructGetData($input,'input0',30) )
EndFunc

 

 

Only tested on the Precision Touchpad of the Surface Pro 4 Type Cover, could anyone else check their precision touchpad as well?

 

 

image.png.5baeae37640b355b58d3770b4b505155.png

Edited by AutoXenon
Link to post
Share on other sites
  • AutoXenon changed the title to Number of fingers on touchpad

FWIW, this displays a "random" value (appears to be in the range of 20 - 40) on my Dell XPS laptop.

Edit: Seems to be working somewhat better with the revised code.

Edit2: Did you try using the predefined structures from winapisys.au3 with _WinAPI_RegisterRawInputDevices and _WinAPI_GetRawInputData?

Edited by Danp2
Link to post
Share on other sites
  • AutoXenon changed the title to Precision Touchpad (how many fingers on pad, position of each finger, etc)

@turbobaby @Danp2 Can you guys try this version and report what the raw data format looks like?

 

#NoTrayIcon
Opt('GUIOnEventMode',1)
Global Const $user32 = DllOpen("user32.dll")
Global Const $HEAD = 'struct;dword Type;dword Size;handle hDevice;wparam wParam;endstruct;' , _
             $HEADSIZE = DllStructGetSize(DllStructCreate($HEAD)) , _
             $PREFIX = $HEAD & 'dword SizeHid;dword Count;'
GUIRegisterMsg(0x00FF,WM_INPUT)
Local $struct = DllStructCreate('struct;ushort UsagePage;ushort Usage;dword Flags;hwnd Target;endstruct')
$struct.UsagePage=0x0D
$struct.Usage=0x05
$struct.Flags=0x00000100
$struct.Target=GUICreate('')
DllCall('user32.dll', 'bool', 'RegisterRawInputDevices', 'struct*', $struct, 'uint', 1, 'uint', DllStructGetSize(DllStructCreate('struct;ushort UsagePage;ushort Usage;dword Flags;hwnd Target;endstruct')))

GUICreate('')
Global $hLog = GUICtrlCreateLabel('',0,0,400,400), $currentData=DllStructCreate($PREFIX), $stateString = '', $lastString = ''
GUISetState()
GUISetOnEvent(-3,Quit)

While Sleep(10)
      $stateString = ParseData($currentData)
      If $stateString = $lastString Then ContinueLoop
      $lastString = $stateString
      GUICtrlSetData($hLog,$stateString)
WEnd

Func Quit()
     Exit
EndFunc

Func WM_INPUT($hWnd, $uMsg, $wParam, $lParam)
     Local $size = DllCall($user32,'uint','GetRawInputData','handle',$lParam,'uint',0x10000003,'struct*',Null,'uint*',Null,'uint',$HEADSIZE)[4]
     $currentData = DllCall ( $user32 , _
                               'uint' , 'GetRawInputData', _
                             'handle' , $lParam, _
                               'uint' , 0x10000003, _
                            'struct*' , DllStructCreate('byte[' & $size & ']'), _
                              'uint*' , $size, _
                               'uint' , $HEADSIZE )[3]
EndFunc

Func ParseData($raw)
     Local $ptr = DllStructGetPtr($raw)
     Local $tag = $PREFIX, $info = DllStructCreate($PREFIX,$ptr), $size = DllStructGetData($info,'SizeHid'), $count = DllStructGetData($info,'Count')
     For $i=0 to $count-1
         $tag &= 'byte input' & $i & '[' & $size & '];'
     Next
     Local $input = DllStructCreate($tag, $ptr), $output=''
     For $i=0 to $count-1
         $output = $output & 'input' & $i & ' = '
         For $j=1 to $size
             $output = $output & Hex(DllStructGetData($input,'input' & $i,$j),2) & ' '
         Next
         $output = $output & @CRLF
     Next
     Return $output
EndFunc

 

Edited by AutoXenon
Link to post
Share on other sites
On 11/25/2022 at 7:05 AM, AutoXenon said:

@turbobaby @Danp2 Can you guys try this version and report what the raw data format looks like?

#NoTrayIcon
Opt('GUIOnEventMode',1)
Global Const $user32 = DllOpen("user32.dll")
Global Const $HEAD = 'struct;dword Type;dword Size;handle hDevice;wparam wParam;endstruct;' , _
             $HEADSIZE = DllStructGetSize(DllStructCreate($HEAD)) , _
             $PREFIX = $HEAD & 'dword SizeHid;dword Count;'
GUIRegisterMsg(0x00FF,WM_INPUT)
Local $struct = DllStructCreate('struct;ushort UsagePage;ushort Usage;dword Flags;hwnd Target;endstruct')
$struct.UsagePage=0x0D
$struct.Usage=0x05
$struct.Flags=0x00000100
$struct.Target=GUICreate('')
DllCall('user32.dll', 'bool', 'RegisterRawInputDevices', 'struct*', $struct, 'uint', 1, 'uint', DllStructGetSize(DllStructCreate('struct;ushort UsagePage;ushort Usage;dword Flags;hwnd Target;endstruct')))

GUICreate('')
Global $hLog = GUICtrlCreateLabel('',0,0,400,400), $currentData=DllStructCreate($PREFIX), $stateString = '', $lastString = ''
GUISetState()
GUISetOnEvent(-3,Quit)

While Sleep(10)
      $stateString = ParseData($currentData)
      If $stateString = $lastString Then ContinueLoop
      $lastString = $stateString
      GUICtrlSetData($hLog,$stateString)
WEnd

Func Quit()
     Exit
EndFunc

Func WM_INPUT($hWnd, $uMsg, $wParam, $lParam)
     Local $size = DllCall($user32,'uint','GetRawInputData','handle',$lParam,'uint',0x10000003,'struct*',Null,'uint*',Null,'uint',$HEADSIZE)[4]
     $currentData = DllCall ( $user32 , _
                               'uint' , 'GetRawInputData', _
                             'handle' , $lParam, _
                               'uint' , 0x10000003, _
                            'struct*' , DllStructCreate('byte[' & $size & ']'), _
                              'uint*' , $size, _
                               'uint' , $HEADSIZE )[3]
EndFunc

Func ParseData($raw)
     Local $ptr = DllStructGetPtr($raw)
     Local $tag = $PREFIX, $info = DllStructCreate($PREFIX,$ptr), $size = DllStructGetData($info,'SizeHid'), $count = DllStructGetData($info,'Count')
     For $i=0 to $count-1
         $tag &= 'byte input' & $i & '[' & $size & '];'
     Next
     Local $input = DllStructCreate($tag, $ptr), $output=''
     For $i=0 to $count-1
         $output = $output & 'input' & $i & ' = '
         For $j=1 to $size
             $output = $output & Hex(DllStructGetData($input,'input' & $i,$j),2) & ' '
         Next
         $output = $output & @CRLF
     Next
     Return $output
EndFunc

 

No, it is always remains empty and gives nothing back

grafik.png.745881c6f2da00791772aed1bbf6038b.png

Link to post
Share on other sites

The API retrieves reports with an embedded byte stream, the size and format of which depends on the specific device.

The code specifically asks Windows for reports from the "Generic Desktop - Digitizer" Usage (0x0D05) and so @turbobaby's plain-old touchpad, most likely registered to Windows as a plain ps/2 mouse, doesn't really send any data as a Digitizer.

I suppose it can be generalized to automatically retrieve the Preparsed Data describing the input format, but Microsoft's documentation isn't very clear on how to use it to actually interpret the data once retrieved.

Edited by AutoXenon
Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...