Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate

Native HID support


  • Please log in to reply
25 replies to this topic
MrB
  • Guests
  • Last active:
  • Joined: --
So how would you integrate these HID raw data outputs - once you found them - into your autohotkey.ini?
The focus should be on an easy and simple integration for non-advanced users.

Lexikos
  • Administrators
  • 9844 posts
  • AutoHotkey Foundation
  • Last active:
  • Joined: 17 Oct 2006
How I would integrate raw input and the easier/simpler method for non-advanced users are entirely different. For instance, this is "optimized" for the chat button on my mouse (since it's the only button I need to detect):
DetectHiddenWindows, On
    Process, Exist
    Script_Hwnd := WinExist("ahk_class AutoHotkey ahk_pid " ErrorLevel)
    DetectHiddenWindows, Off
;...
    RegisterRawInputDevice(1, 12, Script_Hwnd)
;....
    return
;...
RegisterRawInputDevice(Usage, UsagePage, hwnd)
{
    VarSetCapacity(dev, 12, 0)
    NumPut(UsagePage,   dev, 0, "UShort")
    NumPut(Usage,       dev, 2, "UShort")
    NumPut(0x100,       dev, 4) ; dwFlags = RIDEV_INPUTSINK (don't require foreground)
    NumPut(hwnd,        dev, 8)
    
    if DllCall("RegisterRawInputDevices"
        , "uint", &dev  ; pRawInputDevices (pointer to an array of RAWINPUTDEVICE)
        , "uint", 1     ; uiNumDevices
        , "uint", 12)   ; cbSize (size of a RAWINPUTDEVICE structure)
        OnMessage(0xFF, "WM_INPUT")
}

WM_INPUT(wParam, lParam)
{
    Static HoldingChat=0
    
    Critical
    
    ; Get required buffer size.
    DllCall("GetRawInputData", "uint", lParam, "uint", 0x10000003
        , "uint", 0, "uint*", size, "uint", 16)

    VarSetCapacity(raw, size, 0)
    
    ; Get raw input data from handle (lParam)
    ret := DllCall("GetRawInputData", "uint", lParam, "uint", 0x10000003
        , "uint", &raw, "uint*", size, "uint", 16, "int")
    
    if (ErrorLevel or ret = -1)
        return

    type := NumGet(raw)
    
    if type = 2  ; RIM_TYPEHID
    {
        if (NumGet(raw, 20) < 1) ; dwCount
            return
        if (NumGet(raw, 16) < 3) ; dwSizeHid - should be 5 for my device.
            return
        
        if (NumGet(raw, 25, "UShort") = 0x1BC) ; Chat button.
        {
            if (!HoldingChat) {
                gosub ActivateLastFlashingWindow
                HoldingChat = 1
            }
        }
        else if (HoldingChat)
            HoldingChat = 0
    }
}
As you can see, there's barely any separation of implementation from the assigned action, so it isn't user-other-than-me-friendly.

What I want to know is: how would you like to integrate raw input within your scripts? For instance,
hid:chat::msgbox chat pressed
would be the most abstract, but obviously won't work since it doesn't say which device, or what "chat" is.

Perhaps something like this?:
OnRawHid( Usage, UsagePage, Pattern, Label [, DeviceIndex=Any ] )
Pattern could be a regular expression, or a simple string such as "030000E200" (which would be my mute button.) I suppose for readability, optional spaces could be included: "03 00 00 E2 00".

"Why use a regular expression?" -- If I press mute while holding chat, I get the message "03 BC 01 E2 00", which is a combination of chat (BC 01) and mute (E2). So, for instance, I could say "^.{6}E2.{2}$" and that would match "030000E200" (mute), "03BC01E200" (chat+mute, or mute+chat), etc.

I suppose regular expressions aren't for "non-advanced users," though.

MrB
  • Guests
  • Last active:
  • Joined: --
Hi lexikos, sorry for the delayed answer, I was out of town for the last days.

What I want to know is: how would you like to integrate raw input within your scripts?

:idea:
First of all, taking up Micha's comment, there should be a switch to turn HID support of, if not needed - to reduce the space autohotkey needs at runtime. There should also be a switch to set the HID-device to listen to or disable input from certain devices. Perhaps like this:
#DisableHIDSupport                                ;enabled by default
#OpenHIDforInput(Devicename, Usage, UsagePage)    ;listen to all devices by default
Second, I would prefer to keep the syntax that autohotkey uses for keys and use it accordingly for HID devices. Something like this:
030000E200:: Msgbox, Mute was pressed
To facilitate the learning process for the user, the section "key history and skript info" of autohotkey should contain 1) the necessary HID strings (in this case 030000E200)and 2) the device the string was obtained from.


Would be great if we could get this working and our comments find their way into the program...

Lexikos
  • Administrators
  • 9844 posts
  • AutoHotkey Foundation
  • Last active:
  • Joined: 17 Oct 2006
Since I posted, I've been working on a RawInput function-library script, which I will use to make a (hopefully) user-friendly method of accepting raw input in a script. It won't be as easy as "hotkey::", but perhaps as easy as the hotkey command. (It'll need to be called from the auto-execute section to associate devices/data with labels.)

To test the functions, I wrote a GUI script (which will also be useful in determining what data a device sends.)
Posted Image
That shows all of the ways a device can be identified (atm.)

#OpenHIDforInput(Devicename, Usage, UsagePage)

Unfortunately, it isn't easy to get a (useful) readable device name. Of some use, the Device Name shown on the GUI (and by Micha's script) contains a hint to a registry path. For instance,
Device Name: \\?\[color=green]HID#VID_046D&PID_C518&MI_01&Col01#7&231d2277&0&0000[/color]#{4d1e55b2-f16f-11cf-88cb-001111000030}
The registry key for this device can be found at
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\[color=green]HID\VID_046D&PID_C518&MI_01&Col01\7&231d2277&0&0000[/color]
Unfortunately the only "readable name" I see is "HID-compliant consumer control device." Not very useful.

The Vendor ID (VID) and Product ID (PID) identify the device (in this case as a Logitech MX610.) To get a list of handles to matching devices, I can do:
list := RawInput_FilterDevices("VID_046D PID_C518")
This gets the top three devices in the screenshot above. To identify the specific device I am after, I can do one of:
hDevice := RawInput_FilterDevices("VID_046D PID_C518 #3")
; or
hDevice := RawInput_FilterDevices("UP12 U1") ; UsagePage 0x000C = 12, Usage 1
; or a combination

First of all, taking up Micha's comment, there should be a switch to turn HID support of, if not needed

#DisableHIDSupport seems redundant, since OpenHIDforInput() would be required to tell AutoHotkey to register a device.

- to reduce the space autohotkey needs at runtime.

I'm not sure exactly what space would be used, other than the space for each HID-hotkey, and the memory used by the raw input code itself.

Heh, it just occurred to me that while
030000E200::
is not a valid hotkey (at least, "doesn't exist in the current keyboard layout"),
030000E200:
; and even
hid:12-1-3:030000E200:
are valid labels. Still, I think it would be best to include some indication of which device should trigger the HID-hotkey/label. (That is, if it were automatic/built-in.)

The level-of-ease I'm eventually aiming for is something like:[*:1qx50nxf]Open the GUI.
[*:1qx50nxf]Select a device (or all devices.)
[*:1qx50nxf]Press a button. Assuming it triggers an input event,
[*:1qx50nxf]Click the input event. This should generate code for quick insertion into a script, and possibly more specific details, like a filter to identify the device, and the data string alone.Example code:
RawInput_Map("VID_046D PID_C518 UP12 U1", "03BC010000", "ClickedChatButton")
; or the easier-but-more-likely-to-eventually-conflict-with-something:
RawInput_Map("#3", "030000E200", "ClickedMuteButton")
;...
ClickedChatButton:
    WinActivate, - Online
return
ClickedMuteButton:
    Send {Volume_Mute}  ; undo the button's native function
    Send {Media_Play_Pause}
return
I'd use OnRawInput(), but that wouldn't be function-library compliant.

What has been delaying the script is this: a string like "030000E200" doesn't seem like a generic enough way of identifying a button. Additionally, it doesn't seem to provide much benefit over the existing scripts. For instance, where does the script you mentioned earlier fall short?

  • Guests
  • Last active:
  • Joined: --

raw HID data is sent as a blob of binary data. For instance, one of the devices associated with my mouse sends "03 00 00 E2 00" for mute, "03 00 00 E9 00" for volume up, but "03 BC 01 E9 00" if I was already holding the chat button. It's not a simple "pressed/released this button" message, so adding generic support for it to AutoHotkey would be difficult.

I have been playing with Raw Devices today, using my USB keyboard. I managed a limited success - I can get a list of HID devices, I can intercept (using WM_INPUT) any of them, and I can capture events for many keys on my keyboard. Unfortunatelly, AutoHotKey is able to capture those keys as well. I couldn't get a single "real raw" input from my keyboard (that is, a sequence of bytes similar to that you listed above) - all WM_INPUT messages came in the form of "slightly translated" RIM_TYPEKEYBOARD, none as "real raw" RIM_TYPEHID. Unfortunatelly, it doesn't seem like I can capture the extra keys - not even when I intercept the whole UsagePage 1 :-(

I hope I will have a better luck with my MX1000 (when I come back home where it sits). If I could capture at least SOME of the extra keys, it would be nice.

tyxiang
  • Members
  • 12 posts
  • Last active: Sep 12 2009 07:53 AM
  • Joined: 26 Nov 2008
I used Lexikos's script for my remote control.
The remote control add a HID and a JoyStick in my PC. The script can get code from Joystick (Usage=5 and UsagePage=1).
But it can not get code from the HID (Usage=0 and UsagePage=65280).

Posted Image

Can you help me?

Thank you a lot.

argitoth
  • Members
  • 23 posts
  • Last active: Jan 02 2014 04:54 AM
  • Joined: 10 Dec 2013
Whatever happened to this?

I'd like to map my logitech keyboard keys. I'm still a noob, but since this thread was calling for syntax implementation, here's my idea for syntax, just making up numbers here:

; declare HID, special keys, syntax: HID Identifier, SymbolicAssignment
; Indentifier: The thing that shows up in autohotkey key history
; SymbolicAssignment: How you want to refer to the HID key.

#HID 409734598347593, Fn
#HID 485604957630945, FnF1
#HID 402634858262976, FnF2

FnF2::do script

^z::
Send {FnF1}

; Fn key plus 'A'
Fna::do script

..etc.

rhr
  • Members
  • 217 posts
  • Last active: Feb 13 2015 02:41 AM
  • Joined: 28 Jun 2012

Does work AHK 64-bits?


ЯHR

 

 

 

 

 


nnnik
  • Members
  • 1625 posts
  • Last active: Jan 24 2019 02:19 PM
  • Joined: 28 Jul 2012
Yes the AHK_64 bit Version can be found here:
www.ahkscript.org

Visit the new forum ahkscript.org.

http://ahkscript.org


rhr
  • Members
  • 217 posts
  • Last active: Feb 13 2015 02:41 AM
  • Joined: 28 Jun 2012

@nnnik,  no no .. I have AHK 64-bit alrady  but script will work 64-bit and 32-bit? because some script will not work 64-bit


ЯHR

 

 

 

 

 


nnnik
  • Members
  • 1625 posts
  • Last active: Jan 24 2019 02:19 PM
  • Joined: 28 Jul 2012
The last post doesn't work at all.

Visit the new forum ahkscript.org.

http://ahkscript.org