HID Descriptor Tool

Everything else that doesn't fall into one of the other PB categories.
miso
Enthusiast
Enthusiast
Posts: 630
Joined: Sat Oct 21, 2023 4:06 pm
Location: Hungary

Re: HID Descriptor Tool

Post by miso »

Accessing memory with Peek... would be easier and correct.
@Peter:

I would have made these mistakes with peek also. If this starts to work correctly, I plan to clean every unnecessary protoype remains, and add a binary version too. (I'm aware, it's not you who will profit from those) (I'm also glad that I got help from you in these discoveries. I jumped into this totally blindfolded. )
miso
Enthusiast
Enthusiast
Posts: 630
Joined: Sat Oct 21, 2023 4:06 pm
Location: Hungary

Re: HID Descriptor Tool

Post by miso »

Upgraded the code pages to work with pb 6.30 Beta 6.
Quickly updated again for a small correction.
miso
Enthusiast
Enthusiast
Posts: 630
Joined: Sat Oct 21, 2023 4:06 pm
Location: Hungary

Re: HID Descriptor Tool

Post by miso »

Upgraded the code.
- Added a number as version
- Displays the hex value of the entries
- Displays the scope (main,global local)
- Added decimal representation of the values.
- Displaying flag 0 meanings too with input/feature, etc.
- Added support for multi-entry, multi collection devices such as keyboards, special mice, tablet+stylus digitalizers with multiple repors.

Got some pages list upgrade from Infratec, that does not applied yet, but will be. I also think that the usages should be expanded a bit more.
(mostly for the range that is above 0x00FF)

A simple mouse outputs something like this:

Code: Select all

HID Product: USB Optical Mouse
HID Manufacturer: Logitech
HID Path: \\?\HID#VID_046D&PID_C077#6&896db25&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}
HID VID: 046D
HID PID: C077


========== Parsed Version ==========

    (0x05), (Global) Usage Page....................(Generic Desktop Page,GD_
    (0x09), (Local) Usage....................(0x02) Mouse,CA,
    (0xA1), (Main) Collection....................(0x01) Application
            (0x09), (Local) Usage....................(0x01) Pointer,CP,
            (0xA1), (Main) Collection....................(0x00) Physical
                    (0x05), (Global) Usage Page....................(Button Page,BTN_
                    (0x19), (Local) Usage Minimum....................(0x01)..............................[1]
                    (0x29), (Local) Usage Maximum....................(0x03)..............................[3]
                    (0x15), (Global) Logical Minimum*....................(0x00)..............................[0]
                    (0x25), (Global) Logical Maximum*....................(0x01)..............................[1]
                    (0x75), (Global) Report Size....................(0x01)..............................[1]
                    (0x95), (Global) Report Count....................(0x08)..............................[8]
                    (0x81), (Main) Input....................(0x02) Data, --[Variable]--, Absolute, No Wrap, Linear, Preferred State, No Null Position, 
                    (0x05), (Global) Usage Page....................(Generic Desktop Page,GD_
                    (0x09), (Local) Usage....................(0x30) X,DV,
                    (0x09), (Local) Usage....................(0x31) Y,DV,
                    (0x09), (Local) Usage....................(0x38) Wheel,DV,
                    (0x15), (Global) Logical Minimum*....................(0x81)..............................[-127]
                    (0x25), (Global) Logical Maximum*....................(0x7F)..............................[127]
                    (0x75), (Global) Report Size....................(0x08)..............................[8]
                    (0x95), (Global) Report Count....................(0x03)..............................[3]
                    (0x81), (Main) Input....................(0x06) Data, --[Variable]--, --[Relative]--, No Wrap, Linear, Preferred State, No Null Position, 
            End Collection
    End Collection
User avatar
minimy
Addict
Addict
Posts: 817
Joined: Mon Jul 08, 2013 8:43 pm
Location: off world

Re: HID Descriptor Tool

Post by minimy »

Hey miso! Thanks for share!
I will download the last beta to test.
If translation=Error: reply="Sorry, Im Spanish": Endif
miso
Enthusiast
Enthusiast
Posts: 630
Joined: Sat Oct 21, 2023 4:06 pm
Location: Hungary

Re: HID Descriptor Tool

Post by miso »

Your welcome.

Story time: I was not aware, that keyboards and mice are off limits on windows. No raw data, no reports, no inputs can be read. My gaming mouse has a vendor defined entry, but unfortunately that is not the duplicatio of the mouse controls. Controllers/joysticks works fine, also my wacom digitalizer stylus. I don't know about the other 2 OS.

Note: In the descriptor dump, the values that uses more than 1 byte are in big endian, while pb is little endian. (The output currently translates this data to little endian, to get the correct values)

When you read raw data from the HID, it will be also in big endian.
If its 8 bit data on a 16 bit field (that happens), one can skip the dummy byte, and can read only the needed one.
For true 16 bit data, it must be byteswapped.

For 16 bit (the only one I met till this day):

Code: Select all

Procedure.u swap16(u.u)
  ProcedureReturn (((u&$FF)<<8)|((u>>8)&$FF))
EndProcedure

udat.u = $FF00
Debug RSet(Hex(udat,#PB_Unicode),4,"0")
udat = swap16(udat)
Debug RSet(Hex(udat,#PB_Unicode),4,"0")
Last edited by miso on Thu Dec 25, 2025 10:54 pm, edited 2 times in total.
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5604
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: HID Descriptor Tool

Post by Kwai chang caine »

Thanks for shared, apparently that works here 8)
ImageThe happiness is a road...
Not a destination

PureBasic French Forum
User avatar
mk-soft
Always Here
Always Here
Posts: 6493
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: HID Descriptor Tool

Post by mk-soft »

For swapping ...

Code: Select all

;-TOP by mk-soft, v1.02.1, 27.08.2022

CompilerIf #PB_Compiler_Version < 600
  #PB_Backend_Asm = 0
  #PB_Backend_C = 1
  #PB_Compiler_Backend = 0
CompilerEndIf

Procedure bswap16(value.u)
  CompilerIf #PB_Compiler_Backend = #PB_Backend_C
    !return __builtin_bswap16(v_value);
  CompilerElse
    !xor eax,eax
    !mov ax, word [p.v_value]
    !rol ax, 8
    ProcedureReturn
  CompilerEndIf
EndProcedure

Procedure bswap32(value.l)
  CompilerIf #PB_Compiler_Backend = #PB_Backend_C
    !return __builtin_bswap32(v_value);
  CompilerElse
    !mov eax, dword [p.v_value]
    !bswap eax
    ProcedureReturn
  CompilerEndIf
EndProcedure

Procedure.q bswap64(value.q)
  CompilerIf #PB_Compiler_Backend = #PB_Backend_C
    !return __builtin_bswap64(v_value);
  CompilerElse
    CompilerIf #PB_Compiler_Processor=#PB_Processor_x64
      !mov rax, qword [p.v_value]
      !bswap rax
    CompilerElse
      !mov edx, dword [p.v_value]
      !mov eax, dword [p.v_value + 4]
      !bswap edx
      !bswap eax
    CompilerEndIf
    ProcedureReturn
  CompilerEndIf
EndProcedure
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
miso
Enthusiast
Enthusiast
Posts: 630
Joined: Sat Oct 21, 2023 4:06 pm
Location: Hungary

Re: HID Descriptor Tool

Post by miso »

mk-soft wrote: Thu Dec 25, 2025 6:40 pm For swapping ...
Thanks mk-soft! These are faster than my implementations, and will be useful to anyone who will use the PB hidlib!
miso
Enthusiast
Enthusiast
Posts: 630
Joined: Sat Oct 21, 2023 4:06 pm
Location: Hungary

Re: HID Descriptor Tool

Post by miso »

This one is an old equipment, but maybe in the future it might make someone happy. (At least I hope)
Example drawing snippet provided, you might need a driver to have a shared entry point for the device.

Code: Select all

;Driver for Wacom Intuos 3 PTZ-630 Release 1.2
;VID:056A (1386), PID:00B1 (177), RELEASE:0102 (258)

;Vendor defined descriptor reverse engineered, module written by miso, 2025.12.28
;Policy: 777, do what you please. No credit required.

;-=======MODULE Start===========================================================================
DeclareModule PTZ
  Declare Open()
  Declare Examine()
  Declare Close()
  Declare.i PenScreenX()
  Declare.i PenScreenY()
  Declare.u PenRawX()
  Declare.u PenRawY()
  Declare.i Getpressure()
  Declare.a PenInRange()
  Declare.a PenIsClose()
  Declare.a PenButton_1()
  Declare.a PenButton_2()
  Declare.i GetLeftSlider()
  Declare.i GetRightSlider()
  Declare.a Rightbutton_1()
  Declare.a Rightbutton_2()
  Declare.a Rightbutton_3()
  Declare.a Rightbutton_4()
  Declare.a Leftbutton_1()
  Declare.a Leftbutton_2()
  Declare.a Leftbutton_3()
  Declare.a Leftbutton_4()
EndDeclareModule


Module PTZ
  
Structure hstruct
  id.i
  iswacom.i
  path.s
  vid.s
  pid.s
  *buffer
  *buttons
  *pen
  lastsize.i
EndStructure

Global wacomptz.hstruct

Procedure.u swap16(u.u)
  ProcedureReturn (u<<8|((u>>8)&$FF))
EndProcedure


;=============================================================================================
;Open device Wacom Intuos 3 PTZ-630 Release 1.2 for use if exists, and an entry point is given
;allocates 3x10 bytes memory if succesful.
;=============================================================================================
  Procedure Open()
    ExamineHIDs()
    While NextHID()
      If HIDInfo(#PB_HID_VendorId) = "1386" And HIDInfo(#PB_HID_ProductId) = "177" And HIDInfo(#PB_HID_ReleaseNumber) = "258"
        If HIDInfo(#PB_HID_UsagePage) = "13" And HIDInfo(#PB_HID_Usage) = "1"
          wacomptz\id = OpenHIDPath(#PB_Any,HIDInfo(#PB_HID_Path))
          If IsHID(wacomptz\id)
            Debug "ok"
            wacomptz\buffer = AllocateMemory(10)
            wacomptz\pen = AllocateMemory(10)
            wacomptz\buttons = AllocateMemory(10)
          EndIf
        EndIf
      EndIf
    Wend
  EndProcedure
  
;=============================================================================================
;Closes device Wacom Intuos 3 PTZ-630 Release 1.2 for use if exists and previously opened.
;Deallocates 3x10 bytes memory.
;=============================================================================================  
  Procedure Close()
    If IsHID(wacomptz\id)
      FreeMemory(wacomptz\buffer)
      FreeMemory(wacomptz\pen)
      FreeMemory(wacomptz\buttons)
      CloseHID(wacomptz\id)
    EndIf
  EndProcedure
  
;=============================================================================================
;Examines device Wacom Intuos 3 PTZ-630 Release 1.2 for raw data if previously opened
;=============================================================================================  
  Procedure Examine()
    If IsHID(wacomptz\id)
      Repeat
        wacomptz\lastsize = ReadHIDData(wacomptz\id,wacomptz\buffer,10,1)
        If PeekA(wacomptz\buffer)=$0c
          CopyMemory(wacomptz\buffer,wacomptz\buttons,10)
        ElseIf PeekA(wacomptz\buffer)=$02
          CopyMemory(wacomptz\buffer,wacomptz\pen,10)
        EndIf
      Until wacomptz\lastsize = 0
    EndIf
  EndProcedure
  
;==============================================================================================
;Examines device Wacom Intuos 3 PTZ-630 Release 1.2 for pen screen x. Requires an opened screen
;============================================================================================== 
  Procedure.i PenScreenX()
    Protected u.u,f.f,out.i
    If IsHID(wacomptz\id)
      u = PeekU(wacomptz\pen+2)
      u = swap16(u)
      f.f = (ScreenWidth()/20320)*u
      out.i = Round(f.f,#PB_Round_Down)
      ProcedureReturn out.i
    EndIf
  EndProcedure

;==============================================================================================
;Examines device Wacom Intuos 3 PTZ-630 Release 1.2 for pen screen y. Requires an opened screen
;============================================================================================== 
  Procedure.i PenScreenY()
    Protected u.u,f.f,out.i
    If IsHID(wacomptz\id)
      u = PeekU(wacomptz\pen+4)
      u = swap16(u)
      f.f = (ScreenHeight()/15240)*u
      out.i = Round(f.f,#PB_Round_Down)
      ProcedureReturn out.i
    EndIf
  EndProcedure

;==============================================================================================
;Examines device Wacom Intuos 3 PTZ-630 Release 1.2 for device raw x. 0-20320
;============================================================================================== 
  Procedure.u PenRawX()
    Protected u.u,f.f,out.i
    If IsHID(wacomptz\id)
      ProcedureReturn swap16(PeekU(wacomptz\pen+2))
    EndIf
  EndProcedure

;==============================================================================================
;Examines device Wacom Intuos 3 PTZ-630 Release 1.2 for device raw y. 0-15240
;============================================================================================== 
  Procedure.u PenRawY()
    Protected u.u,f.f,out.i
    If IsHID(wacomptz\id)
      ProcedureReturn swap16(PeekU(wacomptz\pen+4))
    EndIf
  EndProcedure

;==============================================================================================
;Examines device Wacom Intuos 3 PTZ-630 Release 1.2 for pressure strength 0-255
;============================================================================================== 
  Procedure.i Getpressure()
    Protected out.i
    If Not IsHID(wacomptz\id) : ProcedureReturn 0 : EndIf
    out = PeekA(wacomptz\pen+6)
    ProcedureReturn out
  EndProcedure

;==============================================================================================
;Returns 1 if pen is in range, 0 otherwise
;============================================================================================== 
  Procedure.a PenInRange()
    If Not IsHID(wacomptz\id) : ProcedureReturn 0 : EndIf
    ProcedureReturn ((PeekA(wacomptz\pen+1))>>5)&%1
  EndProcedure

;==============================================================================================
;Returns 1 if pen is close, 0 otherwise
;============================================================================================== 
  Procedure.a PenIsClose()
    If Not IsHID(wacomptz\id) : ProcedureReturn 0 : EndIf
    ProcedureReturn ((PeekA(wacomptz\pen+1))>>6)&%1
  EndProcedure

;==============================================================================================
;0-1
;============================================================================================== 
  Procedure.a PenButton_1()
    If Not IsHID(wacomptz\id) : ProcedureReturn 0 : EndIf
    ProcedureReturn ((PeekA(wacomptz\pen+1))>>1)&%1
  EndProcedure

;==============================================================================================
;0-1
;============================================================================================== 
  Procedure.a PenButton_2()
    If Not IsHID(wacomptz\id) : ProcedureReturn 0 : EndIf
    ProcedureReturn ((PeekA(wacomptz\pen+1))>>2)&%1
  EndProcedure

;==============================================================================================
;0-13 , 0 = no touch, 1 = top 13= bottom
;============================================================================================== 
  Procedure.i GetLeftSlider()
    Protected u.u,i.i
    If Not IsHID(wacomptz\id) : ProcedureReturn 0 : EndIf
    u = swap16(PeekU(wacomptz\buttons+1))
    If u = 0 : ProcedureReturn 0:EndIf
    For i = 0 To 15
      If u>>i&%1 :ProcedureReturn i+1 : EndIf
    Next i
    ProcedureReturn 0
    
  EndProcedure

;==============================================================================================
;0-13 0 = no touch, 1 = top 13= bottom
;============================================================================================== 
  Procedure.i GetRightSlider()
    Protected u.u,i.i
    If Not IsHID(wacomptz\id) : ProcedureReturn 0 : EndIf
    u = swap16(PeekU(wacomptz\buttons+3))
    If u = 0 : ProcedureReturn 0:EndIf
    For i = 0 To 15
      If u>>i&%1 :ProcedureReturn i+1 : EndIf
    Next i
    ProcedureReturn 0
  EndProcedure

;==============================================================================================
;0-1
;============================================================================================== 
  Procedure.a Rightbutton_1()
    If Not IsHID(wacomptz\id) : ProcedureReturn 0 : EndIf
    ProcedureReturn ((PeekA(wacomptz\buttons+6)))&%1
  EndProcedure

;==============================================================================================
;0-1
;============================================================================================== 
  Procedure.a Rightbutton_2()
    If Not IsHID(wacomptz\id) : ProcedureReturn 0 : EndIf
    ProcedureReturn ((PeekA(wacomptz\buttons+6))>>1)&%1
  EndProcedure

;==============================================================================================
;0-1
;============================================================================================== 
  Procedure.a Rightbutton_3()
    If Not IsHID(wacomptz\id) : ProcedureReturn 0 : EndIf
    ProcedureReturn ((PeekA(wacomptz\buttons+6))>>2)&%1
  EndProcedure

;==============================================================================================
;0-1
;============================================================================================== 
  Procedure.a Rightbutton_4()
    If Not IsHID(wacomptz\id) : ProcedureReturn 0 : EndIf
    ProcedureReturn ((PeekA(wacomptz\buttons+6))>>3)&%1
  EndProcedure

;==============================================================================================
;0-1
;============================================================================================== 
  Procedure.a Leftbutton_1()
    If Not IsHID(wacomptz\id) : ProcedureReturn 0 : EndIf
    ProcedureReturn ((PeekA(wacomptz\buttons+5)))&%1
  EndProcedure

;==============================================================================================
;0-1
;============================================================================================== 
  Procedure.a Leftbutton_2()
    If Not IsHID(wacomptz\id) : ProcedureReturn 0 : EndIf
    ProcedureReturn ((PeekA(wacomptz\buttons+5))>>1)&%1
  EndProcedure

;==============================================================================================
;0-1
;============================================================================================== 
  Procedure.a Leftbutton_3()
    If Not IsHID(wacomptz\id) : ProcedureReturn 0 : EndIf
    ProcedureReturn ((PeekA(wacomptz\buttons+5))>>2)&%1
  EndProcedure

;==============================================================================================
;0-1
;============================================================================================== 
  Procedure.a Leftbutton_4()
    If Not IsHID(wacomptz\id) : ProcedureReturn 0 : EndIf
    ProcedureReturn ((PeekA(wacomptz\buttons+5))>>3)&%1
  EndProcedure
EndModule
;-=======MODULE END=============================================================================  








;-=======EXAMPLE START==========================================================================
DeclareModule petskii
EnableExplicit
;=======================================================================
;system font
;=======================================================================
  Declare LoadSyStemFont()
  Declare text(x,y,text.s,color.i,intensity.i=255)
  Declare centertext(x,y,text.s,color.i,intensity.i=255)
  Declare FreeSyStemFont()
EndDeclareModule

Module petskii
;======================================================
;System fonts  for displaying system messages on screen
;======================================================
  #USED_CHARACTERS="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()-_=+[{]};:',<.>/?"+Chr(34)
  Global Dim font(370):Global Dim fontimport.i(370)
  
  Procedure LoadSyStemFont()
    Protected x.i,i.i,j.i,sprline.a
    For i = 1 To Len(#USED_CHARACTERS):fontImport(Asc(Mid(#USED_CHARACTERS,i,1)))=1 : Next i 
    Restore sysfont
      For x= 1 To 370
        If fontimport(x)=1
          font(x)=CreateSprite(-1,8,12,#PB_Sprite_AlphaBlending)
          StartDrawing(SpriteOutput(font(x)))
          DrawingMode(#PB_2DDrawing_AllChannels)
          For j=0 To 11  
            Read.a sprline 
            For i=0 To 7
              If sprline&%1 :Plot(i,j,RGBA(255,255,255,255)): Else : Plot(i,j,RGBA(0,0,0,0)) : EndIf
              sprline>>1 
            Next i
          Next j
          StopDrawing()
          ZoomSprite(font(x),16,24)
        EndIf
      Next x
  EndProcedure
   
  Procedure text(x,y,text.s,color.i,intensity.i=255) : Protected.i textlength,i,character
    textlength.i = Len(text.s)
    For i = 1 To textlength.i
      character.i = Asc(Mid(text.s,i,1))
      If character.i>ArraySize(font()) : ProcedureReturn #Null : EndIf
      If IsSprite(font(character))
        DisplayTransparentSprite(font(character),(x+((i-1) * 16)),(y),intensity,color.i)
      EndIf
    Next i
  EndProcedure
  
  Procedure centertext(x,y,text.s,color.i,intensity=255)
    Protected textlength.i
    textlength.i = Len(text.s)
    x=x-(textlength*8) : y=y-8
    text(x,y,text.s,color,intensity)
  EndProcedure
  
 
  Procedure FreeSyStemFont()
    Protected i.i
    For i = 1 To Len(#USED_CHARACTERS)
      If IsSprite(font(i)) : FreeSprite(font(i)) : EndIf
    Next i
  EndProcedure
 DataSection
    sysfont:
    Data.q $3838383838380000,$EEEE000000003800,$00000000000000EE,$FFEEFFEEEEEE0000,$383800000000EEEE,$0000387EE07C0EFC,$1C3870EECECE0000,$7C7C00000000E6EE,$0000FCEEEE3C7CEE
    Data.q $00003870E0E00000,$7070000000000000,$000070381C1C1C38,$707070381C1C0000,$0000000000001C38,$000000EE7CFF7CEE,$38FE383800000000,$0000000000000038,$001C383800000000
    Data.q $00FE000000000000,$0000000000000000,$0000383800000000,$3870E0C000000000,$7C7C000000000E1C,$00007CEEEEFEFEEE,$38383C3838380000,$7C7C00000000FE38,$0000FE0E1C70E0EE
    Data.q $E078E0EE7C7C0000,$E0E0000000007CEE,$0000E0E0FEEEF8F0,$E0E07E0EFEFE0000,$7C7C000000007CEE,$00007CEEEE7E0EEE,$383870EEFEFE0000,$7C7C000000003838,$00007CEEEE7CEEEE
    Data.q $E0FCEEEE7C7C0000,$3838000000007CEE,$0000383800000038,$0000003838380000,$F0F00000001C3838,$0000F0381C0E1C38,$FE00FE0000000000,$1E1E000000000000,$00001E3870E07038
    Data.q $3870E0EE7C7C0000,$7C7C000000003800,$00007CCE0EFEFEEE,$EEFEEE7C38380000,$7E7E00000000EEEE,$00007EEEEE7EEEEE,$0E0E0EEE7C7C0000,$3E3E000000007CEE,$00003E7EEEEEEE7E
    Data.q $0E3E0E0EFEFE0000,$FEFE00000000FE0E,$00000E0E0E3E0E0E,$EEFE0EEE7C7C0000,$EEEE000000007CEE,$0000EEEEEEFEEEEE,$383838387C7C0000,$F8F8000000007C38,$00003C7E70707070
    Data.q $3E1E3E7EEEEE0000,$0E0E00000000EE7E,$0000FE0E0E0E0E0E,$CEFEFEFECECE0000,$EEEE00000000CECE,$0000EEEEFEFEFEFE,$EEEEEEEE7C7C0000,$7E7E000000007CEE,$00000E0E0E7EEEEE
    Data.q $EEEEEEEE7C7C0000,$7E7E00000000F07C,$0000EE7E3E7EEEEE,$E07C0EEE7C7C0000,$FEFE000000007CEE,$0000383838383838,$EEEEEEEEEEEE0000,$EEEE000000007CEE,$0000387CEEEEEEEE
    Data.q $FEFECECECECE0000,$EEEE00000000CEFE,$0000EEEE7C387CEE,$387CEEEEEEEE0000,$FEFE000000003838,$0000FE0E1C3870E0,$1C1C1C1C7C7C0000,$7C7C000000007C1C,$00007C7070707070
    Data.q $3838FE7C38380000,$0000000000003838,$0000FF0000000000,$FCE07C0000000000,$000000000000FCEE,$00007EEEEE7E0E0E,$0E0E7C0000000000,$0000000000007C0E,$0000FCEEEEFCE0E0
    Data.q $FEEE7C0000000000,$0000000000007C0E,$0000383838FC38F0,$EEEEFC0000000000,$0E0E0000007EE0FC,$0000EEEEEEEE7E0E,$38383C0038380000,$0000000000007C38,$003C707070700070
    Data.q $3E7E0E0E0E0E0000,$3C3C00000000EE7E,$00007C3838383838,$FEFEEE0000000000,$000000000000CEFE,$0000EEEEEEEE7E00,$EEEE7C0000000000,$0000000000007CEE,$000E0E7EEEEE7E00
    Data.q $EEEEFC0000000000,$0000000000E0E0FC,$00000E0E0EEE7E00,$7C0EFC0000000000,$0000000000007EE0,$0000F0383838FE38,$EEEEEE0000000000,$000000000000FCEE,$0000387CEEEEEE00
    Data.q $FEFECE0000000000,$000000000000FCFC,$0000EE7C387CEE00,$EEEEEE0000000000,$00000000003E70FC,$0000FE1C3870FE00,$381E3838F0F00000,$1E1E00000000F038,$00001E3838F03838
  EndDataSection
EndModule 

Global screenspr.i

InitSprite():InitKeyboard():InitMouse()

ExamineDesktops()
OpenWindow(0, 0,0, DesktopWidth(0)*0.8,DesktopHeight(0)*0.8, "Test",#PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(0), 0, 0, WindowWidth(0), WindowHeight(0), 0, 0, 0)
petskii::LoadSyStemFont()

screenspr = CreateSprite(#PB_Any,ScreenWidth(),ScreenHeight(),#PB_Sprite_AlphaBlending)
ptz::Open()
Repeat
  While WindowEvent():Wend
  ClearScreen(0)
	ExamineKeyboard()
	ExamineMouse()
	MouseDeltaX()
	ptz::Examine()
	
	If ptz::Getpressure()>0
	  StartDrawing(SpriteOutput(screenspr))
	  Circle(ptz::PenScreenX(),ptz::PenScreenY(),ptz::Getpressure()/20,$0000FF)
	  StopDrawing()
	EndIf
	DisplayTransparentSprite(screenspr,0,0)
	
	petskii::text(10,60,"Pen in range : "+ Str(ptz::PenInRange()),$00AA00)
	petskii::text(10,90,"Pen is close : "+ Str(ptz::PenIsClose()),$00AA00)
	
	petskii::text(10,130,"Pen Raw X   : "+ Str(ptz::PenRawX()),$00AA00)
	petskii::text(10,160,"Pen Raw Y   : "+ Str(ptz::PenRawY()),$00AA00)
	
	petskii::text(10,200,"Pen Screen X   : "+ Str(ptz::PenScreenX()),$00AA00)
	petskii::text(10,230,"Pen Screen Y   : "+ Str(ptz::PenScreenY()),$00AA00)
	
	petskii::text(10,270,"Pen Pressure   : "+ Str(ptz::Getpressure()),$00AA00)
	
	petskii::text(10,300,"Pen Button 1   : "+ Str(ptz::PenButton_1()),$00AA00)
	petskii::text(10,330,"Pen Button 2   : "+ Str(ptz::PenButton_2()),$00AA00)
	
	petskii::text(10,370,"Left Slider   : "+ Str(ptz::GetLeftSlider()),$00AA00)
	petskii::text(10,400,"Right Slider  : "+ Str(ptz::GetRightSlider()),$00AA00)
	
	petskii::text(10,450,"Left Button 1   : "+ Str(ptz::Leftbutton_1()),$00AA00)
	petskii::text(10,480,"Left Button 2   : "+ Str(ptz::Leftbutton_2()),$00AA00)
	petskii::text(10,510,"Left Button 3   : "+ Str(ptz::Leftbutton_3()),$00AA00)
	petskii::text(10,540,"Left Button 4   : "+ Str(ptz::Leftbutton_4()),$00AA00)
	
	petskii::text(410,450,"Right Button 1   : "+ Str(ptz::Rightbutton_1()),$00AA00)
	petskii::text(410,480,"Right Button 2   : "+ Str(ptz::Rightbutton_2()),$00AA00)
	petskii::text(410,510,"Right Button 3   : "+ Str(ptz::Rightbutton_3()),$00AA00)
	petskii::text(410,540,"Right Button 4   : "+ Str(ptz::Rightbutton_4()),$00AA00)
	
	
	If ptz::PenInRange() : petskii::text(ptz::PenScreenX(),ptz::PenScreenY(),"W",$0000FF) : EndIf
	
	FlipBuffers() : Delay(1)
Until KeyboardReleased(#PB_Key_Escape) Or MouseButton(3)
ptz::Close()

;-=======EXAMPLE END============================================================================
infratec
Always Here
Always Here
Posts: 7771
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: HID Descriptor Tool

Post by infratec »

I'm fighting with different headsets for telephony to avoid the installation of the original SDK stuff.
Sometimes USB is not as easy as it should be. :cry:
Last edited by infratec on Sun Dec 28, 2025 8:09 pm, edited 1 time in total.
PeDe
Enthusiast
Enthusiast
Posts: 338
Joined: Sun Nov 26, 2017 3:13 pm

Re: HID Descriptor Tool

Post by PeDe »

Hello miso,

thanks for the code for the Wacom tablet. My Intuos 4 now works with Raspberry Pi OS.

Peter
miso
Enthusiast
Enthusiast
Posts: 630
Joined: Sat Oct 21, 2023 4:06 pm
Location: Hungary

Re: HID Descriptor Tool

Post by miso »

PeDe wrote: Sun Dec 28, 2025 6:35 pm Hello miso,

thanks for the code for the Wacom tablet. My Intuos 4 now works with Raspberry Pi OS.

Peter
HI!

You say, that that layout works with intuos 4 too? If it does, would you kindly post full name vid pid and release to me? (So I will save this information for myself)
(Though I'm sure you had to modify it a bit)
PeDe
Enthusiast
Enthusiast
Posts: 338
Joined: Sun Nov 26, 2017 3:13 pm

Re: HID Descriptor Tool

Post by PeDe »

I only changed the VID/PID in your code, nothing else. Here are a few brief comments on what I noticed.

Peter


Tablet orientation buttons on the left

Left Slider - Round button in the ring-shaped slider: 0 or 1
Left Slider - shows values from 9 to 16 when in the ring-shaped slider
Right Slider - these are the 8 buttons with the values from top to bottom: 9 to 16
Left Button/Right Button 1-4 - does not display anything, always 0

- Detection of different pens is not displayed
- Pen tilt is not displayed
- Erasing with the pen upside down is not displayed

Code: Select all

@ lsusb
Bus 001 Device 006: ID 056a:00ba Wacom Co., Ltd PTK-840 [Intuos4 (8x13)]

@ usb-devices
T:  Bus=01 Lev=02 Prnt=03 Port=02 Cnt=01 Dev#=  6 Spd=12   MxCh= 0
D:  Ver= 1.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs=  1
P:  Vendor=056a ProdID=00ba Rev=01.04
S:  Manufacturer=Tablet
S:  Product=PTK-840
C:  #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=300mA
I:  If#= 0 Alt= 0 #EPs= 1 Cls=03(HID  ) Sub=01 Prot=02 Driver=usbhid
E:  Ad=81(I) Atr=03(Int.) MxPS=  10 Ivl=4ms

@ od -An -tx1 /sys/class/hidraw/hidraw6/device/report_descriptor | hidrd-convert -i hex -o spec
Usage Page (Desktop),               ; Generic desktop controls (01h)
Usage (Mouse),                      ; Mouse (02h, application collection)
Collection (Application),
    Report ID (1),
    Usage (Pointer),                ; Pointer (01h, physical collection)
    Collection (Physical),
        Usage Page (Button),        ; Button (09h)
        Usage Minimum (01h),
        Usage Maximum (03h),
        Logical Minimum (0),
        Logical Maximum (1),
        Report Count (3),
        Report Size (1),
        Input (Variable),
        Report Count (5),
        Input (Constant, Variable),
        Usage Page (Desktop),       ; Generic desktop controls (01h)
        Usage (X),                  ; X (30h, dynamic value)
        Usage (Y),                  ; Y (31h, dynamic value)
        Usage (Wheel),              ; Wheel (38h, dynamic value)
        Logical Minimum (-127),
        Logical Maximum (127),
        Report Size (8),
        Report Count (3),
        Input (Variable, Relative),
    End Collection,
End Collection,
Usage Page (Digitizer),             ; Digitizer (0Dh)
Usage (Digitizer),                  ; Digitizer (01h, application collection)
Collection (Application),
    Report ID (2),
    Usage (00h),
    Report Size (8),
    Report Count (9),
    Logical Minimum (0),
    Logical Maximum (255),
    Input (Variable),
    Report ID (2),
    Usage (Program Change Keys),    ; Program change keys (3Ah, logical collection)
    Logical Maximum (2),
    Report Count (1),
    Feature (Variable),
    Report ID (3),
    Usage (00h),
    Logical Maximum (255),
    Feature (Variable),
    Report ID (4),
    Usage (Program Change Keys),    ; Program change keys (3Ah, logical collection)
    Logical Maximum (1),
    Feature (Variable),
    Report ID (5),
    Usage (00h),
    Logical Maximum (255),
    Report Count (8),
    Feature (Variable),
    Report ID (6),
    Usage (00h),
    Feature (Variable),
    Report ID (7),
    Usage (00h),
    Report Count (6),
    Feature (Variable),
    Report ID (8),
    Usage (00h),
    Report Count (4),
    Feature (Variable),
    Report ID (9),
    Usage (00h),
    Report Count (1),
    Feature (Variable),
    Report ID (10),
    Usage (00h),
    Report Count (2),
    Feature (Variable),
    Report ID (11),
    Usage (00h),
    Report Count (1),
    Feature (Variable),
    Report ID (12),
    Usage (00h),
    Report Count (9),
    Input (Variable),
    Report ID (13),
    Usage (00h),
    Report Count (1),
    Feature (Variable),
    Report ID (14),
    Usage (00h),
    Report Count (5),
    Feature (Variable),
    Report ID (14),
    Usage (00h),
    Report Count (9),
    Input (Variable),
    Report ID (32),
    Usage (00h),
    Report Count (8),
    Feature (Variable),
    Report ID (33),
    Usage (00h),
    Report Count (1),
    Feature (Variable),
    Report ID (35),
    Usage (00h),
    Report Count (258),
    Feature (Variable),
    Report ID (36),
    Usage (00h),
    Report Count (1),
    Feature (Variable),
    Report ID (37),
    Usage (00h),
    Report Count (7),
    Feature (Variable),
    Report ID (38),
    Usage (00h),
    Report Count (7),
    Feature (Variable),
    Report ID (39),
    Usage (00h),
    Report Count (7),
    Feature (Variable),
End Collection
[code]
miso
Enthusiast
Enthusiast
Posts: 630
Joined: Sat Oct 21, 2023 4:06 pm
Location: Hungary

Re: HID Descriptor Tool

Post by miso »

PeDe wrote: Sun Dec 28, 2025 8:03 pm I only changed the VID/PID in your code, nothing else. Here are a few brief comments on what I noticed.

Peter


Tablet orientation buttons on the left

Left Slider - Round button in the ring-shaped slider: 0 or 1
Left Slider - shows values from 9 to 16 when in the ring-shaped slider
Right Slider - these are the 8 buttons with the values from top to bottom: 9 to 16
Left Button/Right Button 1-4 - does not display anything, always 0

- Detection of different pens is not displayed
- Pen tilt is not displayed
- Erasing with the pen upside down is not displayed
Yes. Seems like the layout is similar, but not the same. The two input report has the same ID (0x02 and 0x0c), but the offsets and positions are different. Without an Intuos 4, I cant detect where they should be, as the descriptor says nothing in detail. (only that the reports size is 9 bytes. + the report ID)

I displayed all the buffers or parts of it in hex and or bits, touched the tablet. Bitflags/values instantly revealed themselves. The descriptor is vendor defined. The sliders are strange too. With wacom intuos 3 it is in 2 bytes, all bits down, 1 bit up. The position of the 1 bit is the point where it is touched.
so real values looks like 0, 1, 2, 4, 8, 16, ....4096.

Raw x,y resolutions can be different too.

Edit: just for info: I found the tilt x, y bytes with wacom3 PTZ, I just did not implement it. That was hard, because I did not know, that PTZ had this feature, but it is there obviously at the end of the pen report. I did not find the eraser/tip flag. As those are very visible, I'd say those are not present normally, and might be get in a different way, I don't know. That is the only thing I did not find, but it may be there in the wacom 4 base reports. (my tipp would be a flag somewhere in the second byte in the pen buffer.)
Post Reply