Load UHK layout automatically based on focused window (or talking to the firmware from Windows in general)

I’d like to have the UHK60 switch layouts automatically based on the currently focused window.

I could use autohotkey to detect the window. Ahk should be able to talk to the firmware via USB to actually switch the layout (or even change any settings)

But how do I do that? There has to be some kind of interface. Is there any documentation about that?

Any help would be appreciated :blush:

See the end of firmware/doc-dev/user-guide.md at master · UltimateHackingKeyboard/firmware · GitHub

TL;DR:

  • you can execute macro commands over usb
  • you can execute certain “native” actions over usb, like switching keymaps, using a set of scripts

How:

  • via scritps that can be found in agent/packages/usb
  • directly via raw hid.

Thanks, that’s a good start.

This does seem like serious programming work. Without any experience on usb devices that’s probably a couple of days, right?

There isn’t by chance some super easy thing like calling agent with some commandline paramers or something like that? I’m lazy, sorry :smiley:

I wouldn’t rate it for a few days or serious peogramming work. You just need to do one of these things:

  • figure out how to write a sequence of raw bytes to hid in your systems commandline
  • figure out if the scripts are packed with Agent builds (it may be as easy as decompressing the archive; or not, I have no idea)
  • build Agent locally to get access to the scripts

So that should be only one call with the correct bytes to change a layout for example?

I there’s even a script for setting layouts. I guess I have to just get the bytes from there and some of the usb classes.

Seems not so hard indeed. Thanks.

So that should be only one call with the correct bytes to change a layout for example?

Yes, once you know which hid interface to use.

#!/bin/bash
# find the first hid belonging to UHK 60
hidraw="hidraw`grep 'UHK 60' /sys/class/hidraw/hidraw*/device/uevent | sed -nE 's/.*hidraw([0-9]+)\/.*/\1/p' | sort -rn | head -n 1`"
# now send the command to uhk. `\x14` is the macro command. The rest is a normal string taken from the argument.
echo -e "\x14$*" > "/dev/$hidraw"

I there’s even a script for setting layouts. I guess I have to just get the bytes from there and some of the usb classes.

Yes. usb_protocol_handler will tell you what the bytes are.

Cool, this seems like easy mode now. Thanks alot :grin:

We’ll eventually implement Adaptive mode · Issue #555 · UltimateHackingKeyboard/agent · GitHub, but it’s a low priority. This issue may contain useful information.

@mlac can you coment on this?:

There isn’t by chance some super easy thing like calling agent with some commandline paramers or something like that?

The Adaptive mode has been on “will eventually implement” for ages without any progress.

We should provide some user friendly integration api in the meanwhile.

2 Likes

We’ll expose device protocol commands via a JavaScript API and command line, but a more integrated solution is justified.

agent/uhk-operations leaves me to believe the command for switching keymap should be something like
echo -e "\x11 3 71 65 77" > "/dev/$hidraw" (tried also echo -e "\x113 71 65 77" > "/dev/$hidraw")
for a “GAM” keymap:

'GAM'.split('').map(c => c.charCodeAt(0))
Array(3) [ 71, 65, 77 ]

yet it errors out. What am I missing?

Edit: agent prints “Usb protocol command 17 failed with: 3

I suspect the first byte needs to be something like interface id. Not sure if it is constant though - it used to be, but there was couple of changes in the last year.

I.e., try to prefix the message by a small integer (1 byte, less than 10).

Sorry, forgotten about this detail.

edit: eeeh, the echo syntax is wrong. This sends a string, not a list of bytes. Anyways, will look into it later.

1 Like

Good news: the additional id isn’t needed, which means that either of the following should work:

Either use a macro (recommended for general macro user-friendliness).

echo -e "\x14switchKeymap GAM"

Or the native command:

echo -e "\x11\x03GAM"

Full command I am using these days is:

#!/bin/bash

hidraw=`grep 'UHK 60' /sys/class/hidraw/hidraw*/device/uevent | grep -o 'hidraw[0-9][0-9]*' | grep -o '[0-9][0-9]*' | LC_ALL=C sort -rh | head -n 1`
DEVICE="/dev/hidraw$hidraw"

echo "Using device $DEVICE"
echo -e "\x14$*" > $DEVICE

For a quick test with uhk60, I would call it as:

uhkcmd "setLedTxt 1000 ABC"

(and observe “ABC” on the segment display for one second)

2 Likes

This is what I use to send macro commands to the UHK:

$ cat uhk-cmd.sh 
#!/bin/bash
hidraw=`grep 'UHK 60' /sys/class/hidraw/hidraw*/device/uevent | LC_ALL=C sort -rh | head -n 1 | grep -o 'hidraw[0-9][0-9]*'`
echo -e "\x14$*" | tee "/dev/$hidraw"

Sweet, thank you.

This is just the “ETX/end of text” separator right?

It is the length of the string to come.

(Parse error: probably yes.)