Jump to content

Monitoring WACOM Digitizing tablet and pen (HID and RawInput help)


Recommended Posts

I'm trying to use AutoIt to monitor outputs from a Wacom digitizer tablet.

Running the _WinAPI_EnumRawInputDevices demo produces the following output relevant to the tablet (I think this will be mouse, pen, eraser, touchpad, +??)

\\?\HID#VID_056A&PID_0314&Col01#6&1a48d70e&0&0000#{378de44c-56ef-11d1-bc8c-00a0c91405dd}
\\?\HID#VID_056A&PID_0314&Col05#6&1a48d70e&0&0004#{4d1e55b2-f16f-11cf-88cb-001111000030}
\\?\HID#VID_056A&PID_0314&Col04#6&1a48d70e&0&0003#{4d1e55b2-f16f-11cf-88cb-001111000030}
\\?\HID#VID_056A&PID_0314&Col03#6&1a48d70e&0&0002#{4d1e55b2-f16f-11cf-88cb-001111000030}
\\?\HID#VID_056A&PID_0314&Col02#6&1a48d70e&0&0001#{4d1e55b2-f16f-11cf-88cb-001111000030}
 

Attached is a file with linux wacom driver info which would seem like a good start for constants etc

http://www.usb.org/developers/hidpage/Hut1_12v2.pdf page 103 lists the Digitiser page for HID devices as 0D, with various devices, but I can't figure out which is relevant to the tablet.

(I also looked at (HID) Human Interface Device Communications in XP but this was a post from 2009 and seems to have been superseded by updates to AutoIt, and basically just does the same as the _WinAPI_EnumRawInputDevices demo)

This is my most current code which registers HID devices and consoleWrites out the raw input information.

There are still some problems -

1. It doesn't label all the extracted raw data

2. Some of the information from the Tablet can be seen using HIDTrace.exe, but I can't extract it with this current code (eg the touchring and hotkeys):-

#include <APISysConstants.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WinAPIGdi.au3>
#include <WinAPIMisc.au3>
#include <WinAPISys.au3>
#include <WindowsConstants.au3>

; NB The following tags are a hack due to typos in the autoit core code (in WinAPISys.au3)
$atagRID_DEVICE_INFO_MOUSE = 'struct;dword Id;dword NumberOfButtons;dword SampleRate;int HasHorizontalWheel;endstruct'
$atagRID_DEVICE_INFO_KEYBOARD = 'struct;dword KbType;dword KbSubType;dword KeyboardMode;dword NumberOfFunctionKeys;dword NumberOfIndicators;dword NumberOfKeysTotal;endstruct'
$atagRID_DEVICE_INFO_HID = 'struct;dword VendorId;dword ProductId;dword VersionNumber;ushort UsagePage;ushort Usage;endstruct'

$atagRID_INFO_MOUSE = 'dword Size;dword Type;' & $atagRID_DEVICE_INFO_MOUSE & ';dword Unused[2];'
$atagRID_INFO_KEYBOARD = 'dword Size;dword Type;' & $atagRID_DEVICE_INFO_KEYBOARD
$atagRID_INFO_HID = 'dword Size;dword Type;' & $atagRID_DEVICE_INFO_HID & ';dword Unused[2]'


Opt('TrayAutoPause', 0)

;RID = Raw Input Data

; Create GUI
Global $g_hForm = GUICreate('Test ' & StringReplace(@ScriptName, '.au3', '()'), 160, 212, @DesktopWidth - 179, @DesktopHeight - 283, BitOR($WS_CAPTION, $WS_POPUP, $WS_SYSMENU), $WS_EX_TOPMOST)




;ConsoleWrite($tagRAWINPUTDEVICE & @CRLF)           ; struct;ushort UsagePage;ushort Usage;dword Flags;hwnd hTarget;endstruct

; Digitizer pen works correctly





; Now iterate through all HID devices and register them
; To obtain the values of "UsagePage" and "Usage" members of this structure read HID Usage Tables documentation
; www.usb.org/developers/hidpage/Hut1_12v2.pdf

Local $tRID = DllStructCreate($tagRAWINPUTDEVICE)
DllStructSetData($tRID, 'Flags', $RIDEV_INPUTSINK)
DllStructSetData($tRID, 'hTarget', $g_hForm)

#cs
\\?\HID#VID_056A&PID_0314&Col05#6&1a48d70e&0&0004#{4d1e55b2-f16f-11cf-88cb-001111000030}
Device Info:-
VendorId: 056A
ProductId: 0314
VersionNumber: 256
UsagePage: 00
Usage: 0B
\\?\HID#VID_056A&PID_0314&Col04#6&1a48d70e&0&0003#{4d1e55b2-f16f-11cf-88cb-001111000030}
Device Info:-
VendorId: 056A
ProductId: 0314
VersionNumber: 256
UsagePage: 0D
Usage: 01
\\?\HID#VID_056A&PID_0314&Col03#6&1a48d70e&0&0002#{4d1e55b2-f16f-11cf-88cb-001111000030}
Device Info:-
VendorId: 056A
ProductId: 0314
VersionNumber: 256
UsagePage: 0D
Usage: 02
\\?\HID#VID_056A&PID_0314&Col02#6&1a48d70e&0&0001#{4d1e55b2-f16f-11cf-88cb-001111000030}
Device Info:-
VendorId: 056A
ProductId: 0314
VersionNumber: 256
UsagePage: 00
Usage: 0A
\\?\HID#VID_056A&PID_0314&Col01#6&1a48d70e&0&0000#{378de44c-56ef-11d1-bc8c-00a0c91405dd}
Mouse Info:-
Id: 256
NumberOfButtons: 5
SampleRate: 0
HasHorizontalWheel: 0
#ce

; Register tablet mouse
DllStructSetData($tRID, 'UsagePage', 0x01) ; Generic Desktop Controls
DllStructSetData($tRID, 'Usage', 0x02) ; Mouse
_WinAPI_RegisterRawInputDevices($tRID)

; Register keyboard
DllStructSetData($tRID, 'UsagePage', 0x01) ; Generic Desktop Controls
DllStructSetData($tRID, 'Usage', 0x06) ; Keyboard
_WinAPI_RegisterRawInputDevices($tRID)

; Register tablet digitizer
DllStructSetData($tRID, 'UsagePage', 0x0D) ; Digitizers
DllStructSetData($tRID, 'Usage', 0x01) ; Digitizer
_WinAPI_RegisterRawInputDevices($tRID)

; Register tablet ??
DllStructSetData($tRID, 'UsagePage', 0x00) ; Undefined
DllStructSetData($tRID, 'Usage', 0x0B) ; ??
_WinAPI_RegisterRawInputDevices($tRID)

; Register tablet pen
DllStructSetData($tRID, 'UsagePage', 0x0D) ; Digitizers
DllStructSetData($tRID, 'Usage', 0x02) ; Pen
_WinAPI_RegisterRawInputDevices($tRID)

; Register tablet ??
DllStructSetData($tRID, 'UsagePage', 0x00) ; Undefined
DllStructSetData($tRID, 'Usage', 0x0A) ;
_WinAPI_RegisterRawInputDevices($tRID)




#cs
; Now iterate to find other devices
Local $tText, $aData = _WinAPI_EnumRawInputDevices()
If IsArray($aData) Then
    ReDim $aData[$aData[0][0] + 1][3]
    $tText = DllStructCreate('wchar[256]')
    For $i = 1 To $aData[0][0]
        If _WinAPI_GetRawInputDeviceInfo($aData[$i][0], $tText, 256, $RIDI_DEVICENAME) Then
            $aData[$i][2] = DllStructGetData($tText, 1)
            ConsoleWrite ($aData[$i][2] & @CRLF)
        Else
            $aData[$i][2] = ''
        EndIf

        If $aData[$i][1] = $RIM_TYPEHID Then
            $devInf = DllStructCreate($atagRID_INFO_HID)

            If _WinAPI_GetRawInputDeviceInfo($aData[$i][0], $devInf, DllStructGetSize($devInf), $RIDI_DEVICEINFO ) Then
                If DllStructGetData($devInf, 'VendorId') = 0x056A And DllStructGetData($devInf, 'ProductId') = 0x0314 then
                    ConsoleWrite ("Device Info:-" & @CRLF)

                    ; see http://www.usb.org/developers/hidpage/Hut1_12v2.pdf for UsagePage and UsageID
                    ConsoleWrite ('VendorId: ' & Hex(DllStructGetData($devInf, 'VendorId'),4) & @CRLF)
                    ConsoleWrite ('ProductId: ' & Hex(DllStructGetData($devInf, 'ProductId'),4) & @CRLF)
                    ConsoleWrite ('VersionNumber: ' & DllStructGetData($devInf, 'VersionNumber') & @CRLF)
                    ConsoleWrite ('UsagePage: ' & Hex(DllStructGetData($devInf, 'UsagePage'),2) & @CRLF)
                    ConsoleWrite ('Usage: ' & Hex(DllStructGetData($devInf, 'Usage'),2) & @CRLF)

                    DllStructSetData($tRID, 'UsagePage', DllStructGetData($devInf, 'UsagePage'))
                    DllStructSetData($tRID, 'Usage', DllStructGetData($devInf, 'Usage'))
                    _WinAPI_RegisterRawInputDevices($tRID)
                EndIf
            EndIf
        EndIf
    Next
EndIf



#ce


; Register WM_INPUT message
GUIRegisterMsg($WM_INPUT, 'WM_INPUT')

GUISetState(@SW_SHOW)





;   ConsoleWrite($structWACOM_HID_DATA & @CRLF)

;   ConsoleWrite("W" & @CRLF)
;   ConsoleWrite($hWnd & @CRLF)
;   ConsoleWrite($iMsg & @CRLF)
;   ConsoleWrite($wParam & @CRLF)
;   ConsoleWrite($lParam & @CRLF)    ;lParam has the handle to the RAWINPUT structure, not a pointer to it. To get the raw data, use the handle in the call to GetRawInputData.

;   ConsoleWrite($tagRAWINPUTMOUSE & @CRLF)             ; struct;dword Type;dword Size;handle hDevice;wparam wParam;endstruct;ushort Flags;ushort Alignment;ushort ButtonFlags;ushort ButtonData;ulong RawButtons;long LastX;long LastY;ulong ExtraInformation;
;   ConsoleWrite($tagRAWINPUTHID & @CRLF)               ; struct;dword Type;dword Size;handle hDevice;wparam wParam;endstruct;dword SizeHid;dword Count;


; from https://raw.githubusercontent.com/torvalds/linux/master/drivers/hid/wacom_wac.c
;static const struct wacom_features wacom_features_0x314 = { "Wacom Intuos Pro S", 31496, 19685, 2047, 63, INTUOSPS, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 7, .touch_max = 16, .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };


; from https://raw.githubusercontent.com/torvalds/linux/master/drivers/hid/wacom_wac.h
Global $nameArr[45]
$nameArr[1] = "dword Type; (mouse=0,keyboard=1,HID=2)"
$nameArr[2] = "dword Size; (entire packet bytes, incl headers)"
$nameArr[3] = "handle hDevice;"
$nameArr[4] = "wparam wParam;"
$nameArr[5] = "dword dwSizeHid (in bytes);"
$nameArr[6] = "dword dwCount; (num of HID inputs for device)"
for $i = 0 to 37
    $nameArr[$i+7] = $i
Next


;local $nameArr[35] = ["", "dword Type; (mouse=0,keyboard=1,HID=2)", "dword Size; (entire packet bytes, incl headers)", "handle hDevice;", "wparam wParam;", "dword dwSizeHid (in bytes);", "dword dwCount; (num of HID inputs for device)", "ubyte bRawData; (as arr of bytes)", "SHORT inputmode;", "SHORT inputmode_index;", "BOOL sense_state;", "BOOL inrange_state;", "BOOL invert_state;", "BOOL tipswitch;", "INT x;", "INT y;", "INT pressure;", "INT width;", "INT height;", "INT id;", "INT cc_report;", "INT cc_index;", "INT cc_value_index;", "INT last_slot_field;", "INT num_expected;", "INT num_received;", "INT bat_status;", "INT battery_capacity;", "INT bat_charging;", "INT bat_connected;", "INT ps_connected;", "BOOL pad_input_event_flag;" ]

$nameArr[8] = "penvsEraser: 30+p=2,e=6   pen=32,bl=33,bs=35,Eraser=36,bl=44,bs=46"
$nameArr[9] = "x (5080lpi, 6.2 inches = 32768 = 15 bits)"
$nameArr[10] = "y (5080lpi, 3.9 inches)"
$nameArr[11] = "proximity (1024)"
$nameArr[12] = "pressure (2048)"
$nameArr[34] = "tilt(buttonaxis) [+/- 60]"
$nameArr[36] = "tilt(noaxis) [+/- 60]"

Global $structHID_DATA = "struct;" & _
    "dword Type;" & _
    "dword Size;" & _
    "handle hDevice;" & _
    "wparam wParam;" & _
    "dword dwSizeHid;" & _
    "dword dwCount;" & _
    "endstruct;"


Global $structWACOM_PEN_DATA = "struct;" & _
    "dword Type;" & _
    "dword Size;" & _
    "handle hDevice;" & _
    "wparam wParam;" & _
    "dword dwSizeHid;" & _
    "dword dwCount;" & _
    "ubyte bRawData00;" & _
    "ubyte penvsEraser;" & _
    "word x;" & _
    "word y;" & _
    "word proximity;" & _
    "word pressure;" & _
    "ubyte bRawData09;" & _
    "ubyte bRawData10;" & _
    "ubyte bRawData11;" & _
    "ubyte bRawData12;" & _
    "ubyte bRawData13;" & _
    "ubyte bRawData14;" & _
    "ubyte bRawData15;" & _
    "ubyte bRawData16;" & _
    "ubyte bRawData17;" & _
    "ubyte bRawData18;" & _
    "ubyte bRawData19;" & _
    "ubyte bRawData20;" & _
    "ubyte bRawData21;" & _
    "ubyte bRawData22;" & _
    "ubyte bRawData23;" & _
    "ubyte bRawData24;" & _
    "ubyte bRawData25;" & _
    "ubyte bRawData26;" & _
    "ubyte bRawData27;" & _
    "ubyte bRawData28;" & _
    "ubyte bRawData29;" & _
    "ubyte bRawData30;" & _
    "ubyte bRawData31;" & _
    "ubyte bRawData32;" & _
    "ubyte bRawData33;" & _
    "ubyte tilt_ba;" & _
    "ubyte bRawData35;" & _
    "ubyte tilt_na;" & _
    "ubyte bRawData37;" & _
    "endstruct;"



;Global $tRIM = DllStructCreate($structWACOM_PEN_DATA)
;  Local $tRIM = DllStructCreate($structRAW_HID_DATA)

Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE

Func WM_INPUT($hWnd, $iMsg, $wParam, $lParam)
    #forceref $iMsg, $wParam


    Switch $hWnd
        Case $g_hForm
            ConsoleWrite("*** New WM_INPUT Recieved ***" & @CRLF)

            ; Retrieve the device header information
            Local $tRIM = DllStructCreate($tagRAWINPUTHEADER)
            If _WinAPI_GetRawInputData($lParam, $tRIM, DllStructGetSize($tRIM), $RID_HEADER) Then       ; Retrieves the raw input from the specified device
                $devType = DllStructGetData($tRIM, 'Type')
                $devSize = DllStructGetData($tRIM, 'Size')
            Else
                ConsoleWrite ("Device Header Retrieval Failed" & @CRLF)
                Return
            EndIf

            ; Now use the handle to the device to get it's name
            ; The tablet seems to spoof the keyboard or the mouse for some of it's functions, in which case there is no device name available
            Local $tText = DllStructCreate('wchar[256]')
            If _WinAPI_GetRawInputDeviceInfo(DllStructGetData($tRIM, 'hDevice'), $tText, 256, $RIDI_DEVICENAME) Then
                $devName = DllStructGetData($tText, 1)
                ConsoleWrite ($devName & @CRLF)
            Else
                ConsoleWrite ("Device Name Retrieval Failed" & @CRLF)
            EndIf

            ConsoleWrite ('Raw Input Device Type: ' & $devType & @CRLF)
            ConsoleWrite ('Input Packet Size (bytes): ' & $devSize  & @CRLF)

            if $devType = $RIM_TYPEMOUSE Then
                ;$tagRAWINPUTMOUSE = 'struct;dword Type;dword Size;handle hDevice;wparam wParam;endstruct;ushort Flags;ushort Alignment;ushort ButtonFlags;ushort ButtonData;ulong RawButtons;long LastX;long LastY;ulong ExtraInformation;'

                Local $tRIM = DllStructCreate($tagRAWINPUTMOUSE)

                If _WinAPI_GetRawInputData($lParam, $tRIM, DllStructGetSize($tRIM), $RID_INPUT) Then        ; Retrieves the raw input from the specified device
                    ConsoleWrite ("Mouse Info:-" & @CRLF)

                    ConsoleWrite ('Flags: ' & DllStructGetData($tRIM, 'Flags') & @CRLF)
                    ConsoleWrite ('Alignment: ' & DllStructGetData($tRIM, 'Alignment') & @CRLF)
                    ConsoleWrite ('ButtonFlags: ' & DllStructGetData($tRIM, 'ButtonFlags') & @CRLF)
                    ConsoleWrite ('ButtonData: ' & DllStructGetData($tRIM, 'ButtonData') & @CRLF)
                    ConsoleWrite ('RawButtons: ' & DllStructGetData($tRIM, 'RawButtons') & @CRLF)
                    ConsoleWrite ('LastX: ' & DllStructGetData($tRIM, 'LastX') & @CRLF)
                    ConsoleWrite ('LastY: ' & DllStructGetData($tRIM, 'LastY') & @CRLF)
                    ConsoleWrite ('ExtraInformation: ' & DllStructGetData($tRIM, 'ExtraInformation') & @CRLF)
                EndIf
            EndIf

            if $devType = $RIM_TYPEKEYBOARD Then
                ;$tagRAWINPUTMOUSE = 'struct;dword Type;dword Size;handle hDevice;wparam wParam;endstruct;ushort MakeCode;ushort Flags;ushort Reserved;ushort VKey;ushort;uint Message;ulong ExtraInformation;'

                Local $tRIM = DllStructCreate($tagRAWINPUTKEYBOARD)

                If _WinAPI_GetRawInputData($lParam, $tRIM, DllStructGetSize($tRIM), $RID_INPUT) Then        ; Retrieves the raw input from the specified device
                    ConsoleWrite ("Keyboard Info:-" & @CRLF)

                    ConsoleWrite ('MakeCode: ' & DllStructGetData($tRIM, 'MakeCode') & "    MakeCode = The scan code from the key depression." & @CRLF)
                    ConsoleWrite ('Flags: ' & DllStructGetData($tRIM, 'Flags') & @CRLF)
                    ConsoleWrite ('VKey: ' & DllStructGetData($tRIM, 'VKey') & "    VKey = Windows message compatible virtual-key code." & @CRLF)
                    ConsoleWrite ('Message: ' & DllStructGetData($tRIM, 'Message') & @CRLF)
                    ConsoleWrite ('ExtraInformation: ' & DllStructGetData($tRIM, 'ExtraInformation') & @CRLF)
                EndIf
            EndIf

            if $devType = $RIM_TYPEHID Then

                $tRIM = DllStructCreate($structWACOM_PEN_DATA)

    ;            If _WinAPI_GetRawInputDeviceInfo($lParam, $tRIM, DllStructGetSize($tRIM), $RID_INPUT) Then     ; Retrieves the raw input from the specified device

                If _WinAPI_GetRawInputData($lParam, $tRIM, DllStructGetSize($tRIM), $RID_INPUT) Then        ; Retrieves the raw input from the specified device
                    ConsoleWrite ("HID Info:-" & @CRLF)

                    ; Print out all possible variables
;                   for $i = 1 to UBound($nameArr)-1
;                       ConsoleWrite($i & ":" & $nameArr[$i] & ": " & DllStructGetData($tRIM, $i) & "                 @@@: " & @error & @CRLF)
;                   Next

                    ; Print out identified variables
                    For $i = 8 to 12
                        ConsoleWrite($i & ":" & $nameArr[$i] & ": " & DllStructGetData($tRIM, $i) & @CRLF)
                    Next
                    ConsoleWrite(34 & ":" & $nameArr[34] & ": " & DllStructGetData($tRIM, 34) & @CRLF)
                    ConsoleWrite(36 & ":" & $nameArr[36] & ": " & DllStructGetData($tRIM, 36) & @CRLF)
                EndIf
            EndIf

    EndSwitch
    sleep(500)
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_INPUT

 

 

 

 

wacom_wac.c

Edited by dgm5555
Link to comment
Share on other sites

  • 2 weeks later...

I'm not an expert in your problem but I want to say:

This is nice that you share your knowlege.
Thanks.

 

Signature beginning:
Please remember: "AutoIt"..... *  Wondering who uses AutoIt and what it can be used for ? * Forum Rules *
ADO.au3 UDF * POP3.au3 UDF * XML.au3 UDF * IE on Windows 11 * How to ask ChatGPT for AutoIt Codefor other useful stuff click the following button:

Spoiler

Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind. 

My contribution (my own projects): * Debenu Quick PDF Library - UDF * Debenu PDF Viewer SDK - UDF * Acrobat Reader - ActiveX Viewer * UDF for PDFCreator v1.x.x * XZip - UDF * AppCompatFlags UDF * CrowdinAPI UDF * _WinMergeCompare2Files() * _JavaExceptionAdd() * _IsBeta() * Writing DPI Awareness App - workaround * _AutoIt_RequiredVersion() * Chilkatsoft.au3 UDF * TeamViewer.au3 UDF * JavaManagement UDF * VIES over SOAP * WinSCP UDF * GHAPI UDF - modest begining - comunication with GitHub REST APIErrorLog.au3 UDF - A logging Library * Include Dependency Tree (Tool for analyzing script relations) * Show_Macro_Values.au3 *

 

My contribution to others projects or UDF based on  others projects: * _sql.au3 UDF  * POP3.au3 UDF *  RTF Printer - UDF * XML.au3 UDF * ADO.au3 UDF SMTP Mailer UDF * Dual Monitor resolution detection * * 2GUI on Dual Monitor System * _SciLexer.au3 UDF * SciTE - Lexer for console pane

Useful links: * Forum Rules * Forum etiquette *  Forum Information and FAQs * How to post code on the forum * AutoIt Online Documentation * AutoIt Online Beta Documentation * SciTE4AutoIt3 getting started * Convert text blocks to AutoIt code * Games made in Autoit * Programming related sites * Polish AutoIt Tutorial * DllCall Code Generator * 

Wiki: Expand your knowledge - AutoIt Wiki * Collection of User Defined Functions * How to use HelpFile * Good coding practices in AutoIt * 

OpenOffice/LibreOffice/XLS Related: WriterDemo.au3 * XLS/MDB from scratch with ADOX

IE Related:  * How to use IE.au3  UDF with  AutoIt v3.3.14.x * Why isn't Autoit able to click a Javascript Dialog? * Clicking javascript button with no ID * IE document >> save as MHT file * IETab Switcher (by LarsJ ) * HTML Entities * _IEquerySelectorAll() (by uncommon) * IE in TaskSchedulerIE Embedded Control Versioning (use IE9+ and HTML5 in a GUI) * PDF Related:How to get reference to PDF object embeded in IE * IE on Windows 11

I encourage you to read: * Global Vars * Best Coding Practices * Please explain code used in Help file for several File functions * OOP-like approach in AutoIt * UDF-Spec Questions *  EXAMPLE: How To Catch ConsoleWrite() output to a file or to CMD *

I also encourage you to check awesome @trancexx code:  * Create COM objects from modules without any demand on user to register anything. * Another COM object registering stuffOnHungApp handlerAvoid "AutoIt Error" message box in unknown errors  * HTML editor

winhttp.au3 related : * https://www.autoitscript.com/forum/topic/206771-winhttpau3-download-problem-youre-speaking-plain-http-to-an-ssl-enabled-server-port/

"Homo sum; humani nil a me alienum puto" - Publius Terentius Afer
"Program are meant to be read by humans and only incidentally for computers and execute" - Donald Knuth, "The Art of Computer Programming"
:naughty:  :ranting:, be  :) and       \\//_.

Anticipating Errors :  "Any program that accepts data from a user must include code to validate that data before sending it to the data store. You cannot rely on the data store, ...., or even your programming language to notify you of problems. You must check every byte entered by your users, making sure that data is the correct type for its field and that required fields are not empty."

Signature last update: 2023-04-24

Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...