owned this note
owned this note
Published
Linked with GitHub
# Keeb TKL Protocol
11/7/2023
Keeb's protocol includes the following functions:
1. Set Keeb Settings
1. Get Keeb Settings
1. Set Key Assignments
1. Get Key Assignments
1. Set Current Profiles
1. Get Current Profiles
1. Set Macros
1. Get Macros
2. Dual Roller Software Mode Index Callback
3. Key Matrix Index Callback
4. Software Key Callback
5. Get Device Info
6. LED Streaming
![](https://hackmd.io/_uploads/rJCAKz0-a.png)
Keeb includes a total of:
* 93 Keys (includes 87 keys + 5 media keys + 1 button between the rotary encoders)
* 2 Dual Rollers (rotary encoders)
* 155 qRGB Pixels (includes 87 keys + 4 for the space bar + 5 media keys + 9 for the Dual Rollers + 50 on the bottom)
---
## 1. Set Keeb Settings
Keeb Settings include:
* Firmware Animation (6 types)
* Game Mode
* Dual Roller Settings
**Firmware Animations**
| Type | Brightness | Speed | Select Color | Direction |
| -------- | ---------- | ----- | ------------ | --- |
| Static | Yes | No | Yes | No |
| Breathing | Yes | Yes | Yes | No |
| Rainbow | Yes | Yes | No (preset rainbow) | No |
| Wave | Yes | Yes | No (preset rainbow) | Yes |
| Flow | Yes | Yes | Yes | Yes |
| PingPong | Yes | Yes | Yes | Yes|
Set Feature (USB)
| Byte 0 | Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 | Byte 6 | Byte 7 |
| ------ | ------ | ------ | --- | --- | --- | --- | --- |
| 0x21 | 09h | 00h | 03h | 02h | 00h | 08h | 00h |
Set Feature (*need to send 9 bytes, the first byte is 0x00 (byte 5)*)
| Byte 0 | Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 | Byte 6 | Byte 7 |
| ------ | ------ | ------ | --- | --- | --- | --- | --- |
| 0x04 | 0x06 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 |
EP6 out (write) (1 page (65 bytes))
| Byte 0 | Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 | Byte 6 | Byte 7 | Byte 8 | Byte 9 | Byte 10 |
| ------------------- | -------------- | ------------ | -------------- | --------- | --------- | ------------- | -------- | -------- | -------- | --- |
| Debounce (reserved) | Game Mode | FW Animation | LED Brightness | LED Speed | LED Color Index | LED Direction | reserved | reserved | reserved | reserved |
**Byte 1: Game Mode**
Bit 0: Windows Key on/off (1: off, 0: on)
Bit 1: Shift + Tab on/off (1: off, 0: on)
Bit 2: Alt + F4 on/off (1: off, 0: on)
Bit 3: Alt + Tab on/off (1: off, 0: on)
Bit 4: LED on/off (1: on, 0: off)
| Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 |
| -------- | -------- | -------- | --- | --- | --- | --- | --- |
| 0 | 0 | 0 | LED | Alt + Tab | Alt + F4 | Shift + Tab | Windows Key |
Example: If Windows Key is off (1), and others are on (0), and LED is off(0) = 0000 0001 -> 1
**Byte 2: Firmware Animation**
0x01: Static
0x02: Breathing
0x03: Breathing Rainbow
0x04: Rainbow Wave
0x05: Color Flow
0x06: PingPong
**Byte 3: LED Brightness**
Brightness goes from 0 - 255 (dll should be %)
**Byte 4: LED Speed**
Speed goes from 1 - 5 (1 is fastest, 5 is slowest)
**Byte 5: LED Color Index**
You can store 8 colors in FW
Index range is from 0 - 8
For static color, select one color to show from the color list (use index 0 - 7)
For other animations, use index 8 for multiple colors
**Byte 6: LED Direction**
0x00: Left to Right
0x01: Right to Left
0x02: Top to Bottom
0x03: Bottom to Top
| Byte 11 | Byte 12 | Byte 13 | Byte 14 | Byte 15 | Byte 16 | Byte 17 | Byte 18 | Byte 19 | Byte 20 | Byte 21 | Byte 22 | Byte 23 | Byte 24 | Byte 25 | Byte 26 | Byte 27 | Byte 28 | Byte 29 | Byte 30 | Byte 31 | Byte 32 | Byte 33 | Byte 34 |
| -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- |
| color1_r | color1_g | color1_b | color2_r | color2_g | color2_b | color3_r | color3_g | color3_b | color4_r | color4_g | color4_b | color5_r | color5_g | color5_b | color6_r | color6_g | color6_b | color7_r | color7_g | color7_b | color8_r | color8_g | color8_b |
**Byte 11 - 34 (8 Colors)**
8 color RGB array
| Byte 35 | Byte 36 | Byte 37 | Byte 38 | Byte 39 | Byte 40 | Byte 41 | Byte 42 | Byte 43 | Byte 44 | ... | Byte 63 |
| ------------------------ | ------------------ | ------------------ | ------------------ | ------------------ | ------------------- | ------------------- | ------------------- | -------- | --- | --- | -------- |
| Rotary Encoder Control Mode | Right Encoder Code_0 | Right Encoder Code_1 | Right Encoder Code_2 | Right Encoder Code_3 | Left Encoder Code_0 | Left Encoder Code_1 | Left Encoder Code_2 | Left Encoder Code_3 | reserved | ... | reserved |
**Byte 35: Rotary Encoder Control Mode**
0x10: Firmware
0x11: Software
**Byte 36 - 39: Left Encoder**
| Byte 36 | Byte 37 | Byte 38 | Byte 39 |
| ------- | ------- | ------- | --- |
| Code 0 | Code 1 | Code 2 | Code 3 |
**Byte 40 - 43: Right Encoder**
| Byte 40 | Byte 41 | Byte 42 | Byte 43 |
| ------- | ------- | ------- | --- |
| Code 0 | Code 1 | Code 2 | Code 3 |
KeyCode Document
## 2. Get Keeb Settings
Set Feature (USB)
| Byte 0 | Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 | Byte 6 | Byte 7 |
| ------ | ------ | ------ | --- | --- | --- | --- | --- |
| 0x21 | 09h | 00h | 03h | 02h | 00h | 08h | 00h |
Set Feature (*need to send 9 bytes, the first byte is 0x00 (byte 5)*)
| Byte 0 | Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 | Byte 6 | Byte 7 |
| ------ | ------ | ------ | --- | --- | --- | --- | --- |
| 0x84 | 0x06 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 |
EP6 in (read) (1 page (65 bytes))
| Byte 0 | Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 | Byte 6 | Byte 7 | Byte 8 | Byte 9 | Byte 10 |
| ------------------- | -------------- | ------------ | -------------- | --------- | --------- | ------------- | -------- | -------- | -------- | --- |
| Debounce (reserved) | Special Option | FW Animation | LED Brightness | LED Speed | LED Color | LED Direction | reserved | reserved | reserved | reserved |
| Byte 11 | Byte 12 | Byte 13 | Byte 14 | Byte 15 | Byte 16 | Byte 17 | Byte 18 | Byte 19 | Byte 20 | Byte 21 | Byte 22 | Byte 23 | Byte 24 | Byte 25 | Byte 26 | Byte 27 | Byte 28 | Byte 29 | Byte 30 | Byte 31 | Byte 32 | Byte 33 | Byte 34 |
| -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- |
| color1_r | color1_g | color1_b | color2_r | color2_g | color2_b | color3_r | color3_g | color3_b | color4_r | color4_g | color4_b | color5_r | color5_g | color5_b | color6_r | color6_g | color6_b | color7_r | color7_g | color7_b | color8_r | color8_g | color8_b |
| Byte 35 | Byte 36 | Byte 37 | Byte 38 | Byte 39 | Byte 40 | Byte 41 | Byte 42 | Byte 43 | Byte 44 | ... | Byte 63 |
| ------------------------ | ------------------ | ------------------ | ------------------ | ------------------ | ------------------- | ------------------- | ------------------- | -------- | --- | --- | -------- |
| Rotary Encoder Control Mode | Right Encoder Code_0 | Right Encoder Code_1 | Right Encoder Code_2 | Right Encoder Code_3 | Left Encoder Code_0 | Left Encoder Code_1 | Left Encoder Code_2 | Left Encoder Code_3 | reserved | ... | reserved |
## 3. Set Key Assignments
Set Feature (USB)
| Byte 0 | Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 | Byte 6 | Byte 7 |
| ------ | ------ | ------ | --- | --- | --- | --- | --- |
| 0x21 | 09h | 00h | 03h | 02h | 00h | 08h | 00h |
Set Feature (*need to send 9 bytes, the first byte is 0x00 (byte 5)*)
| Byte 0 | Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 | Byte 6 | Byte 7 |
| ------ | ------ | ------ | --- | --- | --- | --- | --- |
| 0x04 | 0xF2 | Profile Index | Layer Index | 0x00 | 0x00 | 0x00 | 0x00 |
**Byte 2: Profile Index**
Profile 0 or 1
**Byte 3: Layer Index**
Layer from 0 - 3 (4 layers)
EP6 out (write) (8 page (65 bytes/page))
Keeb matrix is reserved for the full keyboard -> 6*21 switches
Each key contains 4 bytes
*Note: button between Dual Rollers uses M1 (2)*
![](https://hackmd.io/_uploads/HJJoADPMa.png)
| Byte 0 | Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 | Byte 6 | Byte 7 | Byte 8 | ... | Byte 63 |
| ------------------- | -------------- | ------------ | -------------- | --------- | --------- | ------------- | -------- | -------- | -------- | --- |
| Key_1 KeyCode_0 | Key_1 KeyCode_1 | Key_1 KeyCode_2 | Key_1 KeyCode_3 | Key_2 KeyCode_0 | Key_2 KeyCode_1 | Key_2 KeyCode_2 | Key_2 KeyCode_3 | Key_3 KeyCode_0 | ... | Key_N KeyCode_3 |
## 4. Get Key Assignments
**Set Feature** (USB)
| Byte 0 | Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 | Byte 6 | Byte 7 |
| ------ | ------ | ------ | --- | --- | --- | --- | --- |
| 0x21 | 09h | 00h | 03h | 02h | 00h | 08h | 00h |
**Set Feature** (*need to send 9 bytes, the first byte is 0x00 (byte 5)*)
| Byte 0 | Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 | Byte 6 | Byte 7 |
| ------ | ------ | ------ | --- | --- | --- | --- | --- |
| 0x84 | 0xF2 | Profile Index | Layer Index | 0x00 | 0x00 | 0x00 | 0x00 |
**EP6 in (read) (8 page (65 bytes/page))**
Keeb matrix is reserved for the full keyboard -> 6*21 switches
Each key contains 4 bytes
*Note: button between Dual Rollers uses M1 (2)*
| Byte 0 | Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 | Byte 6 | Byte 7 | Byte 8 | ... | Byte 63 |
| ------------------- | -------------- | ------------ | -------------- | --------- | --------- | ------------- | -------- | -------- | -------- | --- |
| Key_1 KeyCode_0 | Key_1 KeyCode_1 | Key_1 KeyCode_2 | Key_1 KeyCode_3 | Key_2 KeyCode_0 | Key_2 KeyCode_1 | Key_2 KeyCode_2 | Key_2 KeyCode_3 | Key_3 KeyCode_0 | ... | Key_N KeyCode_3 |
## 5. Set Current Profiles
**Set Feature** (USB)
| Byte 0 | Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 | Byte 6 | Byte 7 |
| ------ | ------ | ------ | --- | --- | --- | --- | --- |
| 0x21 | 09h | 00h | 03h | 02h | 00h | 08h | 00h |
**Set Feature** (*need to send 9 bytes, the first byte is 0x00 (byte 5)*)
| Byte 0 | Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 | Byte 6 | Byte 7 |
| ------ | ------ | ------ | --- | --- | --- | --- | --- |
| 0x04 | 0x02 | Profile Index | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 |
**Byte 2: Profile Index**
Profile 0 or 1
## 6. Get Current Profiles
**Set Feature** (*need to send 9 bytes, the first byte is 0x00 (byte 5)*)
| Byte 0 | Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 | Byte 6 | Byte 7 |
| ------ | ------ | ------ | --- | --- | --- | --- | --- |
| 0x84 | 0x02 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 |
**EP2 in** (Read (8 bytes))
| Byte 0 | Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 | Byte 6 | Byte 7 |
| ------ | ------ | ------ | --- | --- | --- | --- | --- |
| 0x05 | 0x02 | Profile Index | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 |
**Byte 2: Profile Index**
Profile 0 or 1
## 7. Set Macros
**Set Feature** (*need to send 9 bytes, the first byte is 0x00 (byte 5)*)
| Byte 0 | Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 | Byte 6 | Byte 7 |
| ------ | ------ | ------ | --- | --- | --- | --- | --- |
| 0x04 | 0xF3 | 0x00 | Macro Index | 0x00 | 0x00 | 0x00 | 0x00 |
**Byte 3: Macro Index**
Macro index goes from 0 - 31 (16 macros per profile)
**EP6 out (write) (4 page (65 bytes/page))**
Each macro can save up to 256 bytes
The first 2 bytes are **repeat count** and every successive **2 bytes is an action**.
When both bytes are **00**, it means the macro is finished.
* Delays in between press and release are defined in **milliseconds**
| Byte 0 | Byte 1 | Byte 2 | Byte 3 | ... | Byte 5 | Byte 6 |
| -------- | -------- | ----------- | --------- | --- | ----------- | --------- |
| Repeat_L | Repeat_H | Attribute 1 | KeyCode 1 | ... | Attribute n | KeyCode n |
**Byte 0 & 1: Repeat**
Provide a range of values from 1 - 65535 for the repeat count
**Byte 2: Attribute**
Includes **key press/release** and **delay time**
| Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 |
| ------------- | ---------- | ---------- | ---------- | ---------- | ---------- | ---------- | ---------- |
| Press/Release | Delay Time | Delay Time | Delay Time | Delay Time | Delay Time | Delay Time | Delay Time |
**Bit 7: Press/Release**
Press: 0
Release: 1
**Bit 0 - 6: Delay Time**
Range goes from 0.01 - 1.27 s (1 - 127 * 10 ms)
If the delay is equal to 0 then go to the next action
If the delay is equal to 7F(127) then the next action (2 bytes) is a delay.
The delay can be up to 65.535s
## 8. Get Macros
**Set Feature** (*need to send 9 bytes, the first byte is 0x00 (byte 5)*)
| Byte 0 | Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 | Byte 6 | Byte 7 |
| ------ | ------ | ------ | --- | --- | --- | --- | --- |
| 0x84 | 0xF3 | 0x00 | Macro Index | 0x00 | 0x00 | 0x00 | 0x00 |
**Byte 3: Macro Index**
Macro index goes from 0 - 31 (16 macros per profile)
**EP6 in (read) (4 page (65 bytes/page))**
Each macro can save up to 256 bytes
| Byte 0 | ... | Byte 64 |
| ------ | --- | --- |
| | | |
## 9. Dual Roller Software Mode Index Callback
**EP2 in** (read)
**Right Encoder UP**
| Byte 0 | Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 | Byte 6 | Byte 7 |
| ------ | ------ | ------ | ------ | ------ | ------ | ------ | ------ |
| 0x05 | 0x09 | 0x20 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 |
**Right Encoder Down**
| Byte 0 | Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 | Byte 6 | Byte 7 |
| ------ | ------ | ------ | ------ | ------ | ------ | ------ | ------ |
| 0x05 | 0x09 | 0x40 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 |
**Left Encoder UP**
| Byte 0 | Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 | Byte 6 | Byte 7 |
| ------ | ------ | ------ | ------ | ------ | ------ | ------ | ------ |
| 0x05 | 0x09 | 0x00 | 0x20 | 0x00 | 0x00 | 0x00 | 0x00 |
**Left Encoder UP**
| Byte 0 | Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 | Byte 6 | Byte 7 |
| ------ | ------ | ------ | ------ | ------ | ------ | ------ | ------ |
| 0x05 | 0x09 | 0x00 | 0x40 | 0x00 | 0x00 | 0x00 | 0x00 |
**Dual Roller Middle Button Click**
| Byte 0 | Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 | Byte 6 | Byte 7 |
| ------ | ------ | ------ | ------ | ------ | ------ | ------ | ------ |
| 0x05 | 0x09 | 0x00 | 0x10 | 0x00 | 0x00 | 0x00 | 0x00 |
## 10. Key Matrix Index Callback
**EP2 in** (read)
| Byte 0 | Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 | Byte 6 | Byte 7 |
| ------ | ------ | ------ | ------ | ------ | ------ | ------ | ------ |
| 0x05 | 0xFA | Row | Column | 0x00 | 0x00 | 0x00 | 0x00 |
Row goes from 0 - 5
Column goes from 0 - 20
## 11. Software Key Callback
**EP2 in** (read)
| Byte 0 | Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 | Byte 6 | Byte 7 |
| ------ | ------ | ------ | ------ | ------ | ------ | ------ | ------ |
| 0x05 | 0xF1 | AP_Code | Action | 0x00 | 0x00 | 0x00 | 0x00 |
**Byte 2: AP_Code**
0 - FF
**Byte 3: Action**
0x01: Click
0x00: Release
## 12. Get Device Info
**Set Feature** (*need to send 9 bytes, the first byte is 0x00 (byte 5)*)
| Byte 0 | Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 | Byte 6 | Byte 7 |
| ------ | ------ | ------ | ------ | ------ | ------ | ------ | ------ |
| 0x84 | 0x05 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 |
**EP5 in** (read 65 bytes)
| Byte 0 | Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 | Byte 6 | ... | Byte 63 |
| ------ | ------ | ------ | ------ | --------- | --------- | ------ | --- | --- |
| VID_L | VID_H | PID_L | PID_H | version_L | version_H | Layout | ... | |
**byte 6: Layout**
0x01: ISO
0x02: ANSI (US)
## 13. LED Streaming
LED streaming will stop firmware animations
Keyboard RGB
**Set Feature** (*need to send 9 bytes, the first byte is 0x00 (byte 5)*)
| Byte 0 | Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 | Byte 6 | Byte 7 |
| ------ | ------ | ------ | ------ | ------ | ------ | ------ | ------ |
| 0x04 | 0xF0 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 |
**EP6 out** Write (6 page (65 bytes/page))
| Byte 0 | Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 | Byte 6 | ... | Byte 63 |
| ------- | ------- | ------- | ------- | ------- | ------- | ------- | --- | ------- |
| LED_1_R | LED_1_G | LED_1_B | LED_2_R | LED_2_G | LED_2_B | LED_3_R | ... | |
Surround RGB
**Set Feature** (*need to send 9 bytes, the first byte is 0x00 (byte 5)*)
| Byte 0 | Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 | Byte 6 | Byte 7 |
| ------ | ------ | ------ | ------ | ------ | ------ | ------ | ------ |
| 0x04 | 0xF1 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 |
**EP6 out** Write (3 page (65 bytes/page))
*Surround RGB lighting starts from 127*
| Byte 0 | Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 | Byte 6 | ... | Byte 63 |
| ------- | ------- | ------- | ------- | ------- | ------- | ------- | --- | ------- |
| LED_127_R | LED_127_G | LED_127_B | LED_128_R | LED_128_G | LED_128_B | LED_129_R | ... | |
---
The HYTE Keeb TKL Protocol is provided under the terms of the GNU General Public License version 2.