Home
Projects
Blog
Toggle Cursor trail
LinkedIn
GitHub
Printables
Email Me
Switch to dark theme

Motospeed X6 Reverse engineering - Mouse Remapping

First Published: 2026-03-06

Last Updated: 2026-03-06

Motospeed X6 writeup part 3

Intro

This is the 3rd and final part of reverse engineering the Motospeed X6, where I am covering how it handles macros and how it fetches the mouse's current settings.

Fetching Settings from Mouse

The packet you send to request a settings packet is really simple, but has an enormous amount of padding (62 bytes for a 64 byte packet).
b3 06 00 00 00 00 ... 00
The settings packet you receive on the other hand is enormous and data-dense. (Note also padded to total of 64 bytes)
b4 06 00 22 22 02 90 01 20 03 b0 04 80 0c c0 12 0d 05 05 01 2e 00 00 00 00 00 ... 00 00
│        └┬─┘  │  └─┬─┘ └─┬─┘ └─┬─┘ └─┬─┘ └─┬─┘ │     │  │     └───── padding ... ────┘
│         │    │    └ 1   2     3     4   5 ┘   │     │  └ Sleep Time
│         │    │      └ DPI Slot Values ─┘      │     └ Debounce Time
│         │    └ Current DPI Slot               └ Settings Byte
│         └ Polling Rate
└ 0xb4 (Report ID)
The Settings byte's internal structure is as such (where 1 = On, 0 = Off)
0 0 0 1 1 1 1 0
│ │   │ │ │ └┬┘
│ │   │ │ │  └ Lift Off Distance (High:01, Low:10)
│ │   │ │ └ Motion Sync
│ │   │ └ Angle Snap
│ │   └ Ripple
│ └ Scroll Direction
└ Esports Mode
There were a couple of interesting things of note:
  • The polling rate uses two repeated bytes and the first 4 bits of each byte are used to communicate the Polling rate.
    It is the only setting that repeats its data.
  • Additionally, RGB settings are not transmitted, the official app apparently stores the last modified state in an internal database instead.
    What is strange is that this is a 64 byte packet, hence there looks like there is plenty of space to add it, but IDK, I'm not a firmware developer/chipset designer.

Remapping Controls

A quite interesting quirk about the Remapping packets, are that they are 64 bytes, larger than the standard 21 bytes of the other packets.
Quite interesting is that Remapping packets are unusally large, unlike with the data fetching packet where I could imagine that it needs a 64 byte packet as it needs a large return packet to hold all the data, the remapping packet and responses are quite small.

Key Remapping Packet

b3 52 03 00 01 02 00 00 00 00 00 00 00 ... 00 00
│  │  │     │  └──┬───┘  └──── padding ... ────┘
│  │  │     │     └─ Features codes
│  │  │     └ Feature to change
│  │  └ Key to remap
│  └ 0x52 (Remapping Command)
└ 0xb3 (Report ID)

Features + Feature Codes

These are dropdown menus, click/tap to see more info

Macro Packets

Heres where we get into the most complex feature of the mouse.
There are two different packet structures for small and large macros respectively and frankly, I don't still fully understand the large packet structure.

Short Packet

                                         Instructions
                                       ┌───┐       ┌───┐
b3 54 01 00 0e 00 01 01 40 00 00 02 00 81 04 00 00 01 04 00 00 00 00 00 ... 00 00
│  │  │     └─┬─┘ └─┬─┘ │  └─┬─┘ └─┬─┘                   └──── padding  ... ────┘
│  │  │       │     │   │    │     └ Instruction Count
│  │  │       │     │   │    └ Time Delay
│  │  │       │     │   └ Loop Type
│  │  │       │     └─ No. Loops
│  │  │       └ Payload Length
│  │  └ Key to remap
│  └ 0x54 (Remapping Macro Command)
└ 0xb3 (Report ID)

Large Packet (First of a multi-packet sequence)

                                                 Instructions
                                                ┌───┐       ┌───┐
B3 71 03 3A 54 03 00 B2 00 01 01 00 00 00 2B 00 81 17 00 00 0F 5E 00 00 ... D2 2F
│  │        └─┬─┘ └─┬─┘ │  └─┬─┘ └─┬─┘                                      └─┬─┘
│  │          │     │   │    │     └ Instruction Count? Always empty          └ End of Packet Indicator
│  │          │     │   │    └ Time Delay
│  │          │     │   └ Loop Type
│  │          │     └─ No. Loops
│  │          └ Payload Length
│  └ 0x71 (Remapping Large Macro Command)
└ 0xb3 (Report ID)

Instruction Structure

The instructions first start with a SubPacket header
  • 0x81: HID key up
  • 0x01: HID key down
  • 0x0f: Delay
  • 0x88: Mouse Down
  • 0x08: Mouse Up
  • 0x05: Mouse Scroll
  • 0x09: Mouse Move
and from there the payload depends on the subpacket type:

Subpacket payloads

Analysis

What generally makes the short packet different from the large packets is the headers, large packets forgo the instruction count and the byte that used to be the remap key seems to be used for something else.

What is notable about the packets is that after each instruction, they have 2 bytes of padding, and in large packets, since the end of packet indicator gets in the way of padding, the next packet's instruction area will start with two bytes of padding before continuing.

Conclusion

I apologise for the relatively short explanation and the lack of details.
Nearing the end of the large packet analysis, I started to lose a bit of steam as I started getting a bit bored and distracted, and had to take a break, and writing this article was rather difficult as I started finding it difficult to remember the fine details of my research .
It is really fascinating how they engineered the macros, but it is unfortunately really tedious to understand and reverse engineer it.

I may come back in the future and modify this blogpost with better information if I ever get the motivation to research this again, but I am quite tired of messing around with this mouse for now.
As an aside, I made a webHID utility based on this 3 part series, and it is available now here.

I really hope you try it out if you own this mouse.
I hope this series has been interesting and you learnt something from it.
This work is licensed under

CC BY 4.0

Creative Commons IconCreative Commons BY Icon
Profile Picture
linkedIn Profile LinkGitHub