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);