From 667028037dd40f294bc279979bb1554035de6b00 Mon Sep 17 00:00:00 2001 From: girlglock <178796756+girlglock@users.noreply.github.com> Date: Sun, 19 Apr 2026 08:38:40 +0200 Subject: [PATCH 1/6] add actuated to active_keys pushes --- AnalogSense.js | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/AnalogSense.js b/AnalogSense.js index c90c240..0ad8df6 100644 --- a/AnalogSense.js +++ b/AnalogSense.js @@ -334,7 +334,7 @@ class AsProvider const active_keys = []; for (const [scancode, value] of Object.entries(this.buffer)) { - active_keys.push({ scancode, value }); + active_keys.push({ scancode, value, actuated: null }); } return active_keys; } @@ -361,7 +361,7 @@ class AsProviderWootingV1 extends AsProvider const scancode = (event.data.getUint8(i++) << 8) | event.data.getUint8(i++); if (scancode == 0) break; const value = event.data.getUint8(i++); - active_keys.push({ scancode, value: value / 255 }); + active_keys.push({ scancode, value: value / 255, actuated: null }); } handler(active_keys); }; @@ -396,6 +396,7 @@ class AsProviderWootingV2 extends AsProvider const packed = data.getUint8(i + 2); const value_hi = data.getUint8(i + 3); + const actuated = packed & 0x1; const keyNamespace = (packed >> 2) & 0xf; const value_lo = (packed >> 6) & 0x3; @@ -405,7 +406,7 @@ class AsProviderWootingV2 extends AsProvider if (scancode === 0) break; if (value === 0) continue; - active_keys.push({ scancode, value: value / 1023 }); + active_keys.push({ scancode, value: value / 1023, actuated }); } handler(active_keys); }; @@ -442,7 +443,8 @@ class AsProviderRazerHuntsman extends AsProvider const value = event.data.getUint8(i++); active_keys.push({ scancode: analogsense.razerScancodeToHidScancode(scancode), - value: value / 255 + value: value / 255, + actuated: null }); } handler(active_keys); @@ -483,7 +485,8 @@ class AsProviderRazerHuntsmanV3 extends AsProvider i++; // unclear, might be something like "priority." active_keys.push({ scancode: analogsense.razerScancodeToHidScancode(scancode), - value: value / 255 + value: value / 255, + actuated: null }); } handler(active_keys); @@ -575,7 +578,8 @@ class AsProviderDrunkdeer extends AsProvider { this.active_keys.push({ scancode: analogsense.drunkdeerIndexToHidScancode((n * (64 - 5)) + (i - 4)), - value: value / 40 + value: value / 40, + actuated: null }); } } From cf50e435c644d5d552d1adb73c35d2b79f2aecf5 Mon Sep 17 00:00:00 2001 From: girlglock <178796756+girlglock@users.noreply.github.com> Date: Sun, 19 Apr 2026 08:39:01 +0200 Subject: [PATCH 2/6] showcase actuation state in the demo --- demo.html | 1 + 1 file changed, 1 insertion(+) diff --git a/demo.html b/demo.html index 33e61c8..ddeaeda 100644 --- a/demo.html +++ b/demo.html @@ -48,6 +48,7 @@

const bar = document.createElement("div"); bar.className = "progress-bar"; bar.style.width = (key.value * 100) + "%"; + bar.style.backgroundColor = key.actuated ? "#7e28bf" : ""; bar.textContent = analogsense.scancodeToString(key.scancode); div.appendChild(bar); } From ca064feec07d2a4d0400062a1f9af86924bcad40 Mon Sep 17 00:00:00 2001 From: girlglock <178796756+girlglock@users.noreply.github.com> Date: Sun, 19 Apr 2026 08:39:07 +0200 Subject: [PATCH 3/6] update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 770ecaa..293717f 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ Once loaded, the following global functions become available: - `analogsense.scancodeToString(scancode: number): string` A device instance has the following members: -- `startListening(handler: function)` +- `startListening(handler: function)` - `stopListening()` - `getProductName(): string` - `forget()` From cb52ddf593c4d13aa2d8e11e3809bb6a376feddf Mon Sep 17 00:00:00 2001 From: girlglock <178796756+girlglock@users.noreply.github.com> Date: Sun, 26 Apr 2026 19:39:01 +0200 Subject: [PATCH 4/6] add socd and rs indicators --- AnalogSense.js | 42 +++++++++++++++++++++++++++++++----------- demo.html | 4 +++- 2 files changed, 34 insertions(+), 12 deletions(-) diff --git a/AnalogSense.js b/AnalogSense.js index 0ad8df6..6bf0c14 100644 --- a/AnalogSense.js +++ b/AnalogSense.js @@ -386,28 +386,48 @@ class AsProviderWootingV2 extends AsProvider this.dev.oninputreport = function(event) { const active_keys = []; + const features_by_pos = {}; const data = event.data; //each entry is 4 bytes (pos, keycode, namespace + analog lo, analog depth //namespace 0 are regular hid keys, non zero are media keys //analog value is 10bit 0 to 1023 + // + //namespace 6 are `advanced keys` (like socd dks etc etc) + //with which we can check if the user has configured eg socd on them or nah for (let i = 0; i + 4 <= data.byteLength; i += 4) { - const keycode = data.getUint8(i + 1); - const packed = data.getUint8(i + 2); - const value_hi = data.getUint8(i + 3); + const matrix_pos = data.getUint8(i + 0); + const keycode = data.getUint8(i + 1); + const packed = data.getUint8(i + 2); + const value_hi = data.getUint8(i + 3); - const actuated = packed & 0x1; - const keyNamespace = (packed >> 2) & 0xf; - const value_lo = (packed >> 6) & 0x3; + const actuated = (packed & 0x1) !== 0; + const key_namespace = (packed >> 2) & 0xf; + const value_lo = (packed >> 6) & 0x3; + const value = (value_hi << 2) | value_lo; - const scancode = (keyNamespace << 8) | keycode; - const value = (value_hi << 2) | value_lo; - - if (scancode === 0) break; + if (matrix_pos === 0 && keycode === 0) break; if (value === 0) continue; - active_keys.push({ scancode, value: value / 1023, actuated }); + if (key_namespace === 6) + { + if (!features_by_pos[matrix_pos]) features_by_pos[matrix_pos] = {}; + //if (keycode === 0x01) features_by_pos[matrix_pos].dks = true; //needs different handling + //if (keycode === 0x02) features_by_pos[matrix_pos].mod_tap = true; //needs different handling + //if (keycode === 0x03) features_by_pos[matrix_pos].toggle = true; //needs different handling + if (keycode === 0x04) features_by_pos[matrix_pos].rapid_snappy = true; + if (keycode === 0x05) features_by_pos[matrix_pos].socd = true; + } + else if (key_namespace === 0) + { + active_keys.push({ + scancode: keycode, + value: value / 1023, + extra: { actuated, ...features_by_pos[matrix_pos] }, + }); + } } + handler(active_keys); }; } diff --git a/demo.html b/demo.html index ddeaeda..f8b693c 100644 --- a/demo.html +++ b/demo.html @@ -48,8 +48,10 @@

const bar = document.createElement("div"); bar.className = "progress-bar"; bar.style.width = (key.value * 100) + "%"; - bar.style.backgroundColor = key.actuated ? "#7e28bf" : ""; + bar.style.backgroundColor = key.extra?.actuated ? "#7e28bf" : ""; bar.textContent = analogsense.scancodeToString(key.scancode); + if (key.extra?.socd) bar.textContent += " (socd enabled)"; + if (key.extra?.rapid_snappy) bar.textContent += " (rapid snappy enabled)"; div.appendChild(bar); } document.getElementById("active-keys").appendChild(div); From 37f03feb438d0c978e4c183a8ad3f71e784196e9 Mon Sep 17 00:00:00 2001 From: girlglock <178796756+girlglock@users.noreply.github.com> Date: Sun, 26 Apr 2026 19:41:19 +0200 Subject: [PATCH 5/6] update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 293717f..a1b5dab 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ Once loaded, the following global functions become available: - `analogsense.scancodeToString(scancode: number): string` A device instance has the following members: -- `startListening(handler: function)` +- `startListening(handler: function)` - `stopListening()` - `getProductName(): string` - `forget()` From 74d94ee93d680e9b621336431e5486003854f2db Mon Sep 17 00:00:00 2001 From: girlglock <178796756+girlglock@users.noreply.github.com> Date: Sun, 26 Apr 2026 19:41:50 +0200 Subject: [PATCH 6/6] fix typo --- AnalogSense.js | 2 +- demo.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/AnalogSense.js b/AnalogSense.js index 6bf0c14..363f0e4 100644 --- a/AnalogSense.js +++ b/AnalogSense.js @@ -415,7 +415,7 @@ class AsProviderWootingV2 extends AsProvider //if (keycode === 0x01) features_by_pos[matrix_pos].dks = true; //needs different handling //if (keycode === 0x02) features_by_pos[matrix_pos].mod_tap = true; //needs different handling //if (keycode === 0x03) features_by_pos[matrix_pos].toggle = true; //needs different handling - if (keycode === 0x04) features_by_pos[matrix_pos].rapid_snappy = true; + if (keycode === 0x04) features_by_pos[matrix_pos].rappy_snappy = true; if (keycode === 0x05) features_by_pos[matrix_pos].socd = true; } else if (key_namespace === 0) diff --git a/demo.html b/demo.html index f8b693c..91fbf0d 100644 --- a/demo.html +++ b/demo.html @@ -51,7 +51,7 @@

bar.style.backgroundColor = key.extra?.actuated ? "#7e28bf" : ""; bar.textContent = analogsense.scancodeToString(key.scancode); if (key.extra?.socd) bar.textContent += " (socd enabled)"; - if (key.extra?.rapid_snappy) bar.textContent += " (rapid snappy enabled)"; + if (key.extra?.rappy_snappy) bar.textContent += " (rappy snappy enabled)"; div.appendChild(bar); } document.getElementById("active-keys").appendChild(div);