Lenovo Legion M7 · WebHID Driver

USB VID 0x17EF · PID 0x6168(wired) / 0x6166(wireless dongle) · Control interface usagePage 0xFF02 · Feature reports 520B · protocol reverse-engineered from the official LenovoAPI_M7 DLL
Not connected

DPI Stages cmd 0x44 read / 0x04 write

DPI choices: 50–10000 (step 50), 10200–26000 (step 200). Device code = DPI/50 − 1; "Off" is written as 200 (0xC8). Writes use read → modify → write-back; both arrays (active/backup) stay in sync.
About the 800 vs 750 difference:Official driver/firmware mapping is (code+1)×50(code 0x0F = true 800 DPI, exact across the full 50–26000 range); while the official LEGION EDGE app's readout display uses code×50 convention (shows 750) — exactly one 50-DPI step apart. This page shows the firmware-true value and annotates the official-app reading on each stage for cross-check.

Polling Rate config block payload[2] low nibble · cmd 0x04 write

Encoding (from the official driver LNV_SetParam reverse-engineering): 1 = 125 Hz, 2 = 250 Hz, 3 = 500 Hz, 4 = 1000 Hz; stored in the config block payload[2] low nibble (both record copies updated together). Read → modify → write-back.

Lift-Off Distance (LOD) config block payload[4] low nibble · cmd 0x04 write

The official device UI for M7 offers 1 mm / 2 mm (device-UI XML: mouse_check_LOD_1/2 checkboxes; default 1 mm). Encoding = millimetres, stored in payload[4] low nibble (both record copies synced). Read-modify-write.

Wheel Scroll Speed config block payload[5] low nibble · cmd 0x04 write

The official "Parameters" page slider (1–10). Stored in payload[5] low nibble (both record copies synced): speeds 1–9 are written as-is; speed 10 = write 0 (factory default = fastest). Verified on hardware: after 10 → 1 the wheel became noticeably slower.

⚠ Important:When the official LEGION EDGE app is opened it pushes its saved configuration back to the mouse(observed: it resets manually-changed LOD / polling rate to its saved values, e.g. LOD back to 1 mm, rate back to 1000 Hz). After changing values here, avoid opening the official app — or set the same values inside it. Values written here stay stable while the app is closed.

Button / Key Mapping (20 slots) cmd 0x41 read / 0x01 write

Double-check mappings before writing. Export a backup under "Raw Data / Backup" first; use the default preset below to restore factory buttons.
#ActionRaw value (hex)

Known values: 0 = unset; 0x10101/0x10201/0x10301/0x10401/0x10501 = mouse buttons 1–5(left/right/middle/back/forward, inferred from the default layout); 0x801 / 0x901、0x32ff0601 / 0x32ff0701 = special functions (DPI± etc., not individually verified). For other actions use the raw hex field.

Lighting Data (read-only) inside the 0x44 config block

The lighting structure is not fully decoded yet; this tab shows the raw bytes plus a colour preview. To modify, use the Raw Data tab (back up first!).

Raw lighting bytes (record offset 0x40–0x80)

—

Config Block (400 bytes) 0x44 / 0x04

Hex (editable, 32 bytes per line). Click write after editing. ⚠ Wrong values can change mouse behaviour — export a backup first.

Key Mapping Block (80 bytes) 0x41 / 0x01

Backup / Restore

Backup contains the full config block + key block + device info + timestamp. Restoring only takes effect on the device after you click a write button.

Manual Command

payload hex (optional; truncated by len and placed from offset 8):

Wire Log 0


    

Live Input Reports

Waiting for events… (battery changes, device status reports, etc.)
Protocol Reference (reverse-engineering summary)
ItemValue
Control interfaceUsagePage 0xFF02 / Usage 0x0002, feature length 520, input length 8 (MI_01 COL05)
Feature reportReport ID = 0x09; total 520 bytes
Packet header[0]=09 report id · [1]=checksum · [2]=command · [3]=sub-index · [4]=01 · [5]=seq · [6..7]=length (LE) · [8..]=payload
Checksum[1] = sum([2..519]) & 0xFF
Commands0x44=read config (400B) · 0x04=write config · 0x41=read keys (80B) · 0x01=write keys
Polling ratepayload[2] low nibble: 1=125Hz · 2=250Hz · 3=500Hz · 4=1000Hz (from LNV_SetParam; verified 0x04→0x03)
Lift-Off Distancepayload[4] low nibble: 1=1mm · 2=2mm (only two options in the M7 UI; verified 0x01→0x02)
Scroll speedpayload[5] low nibble: speeds 1–9 as-is; 10 (fastest, default) = 0 (official slider 1–10; verified 10→1 slower)
Read transactionSetFeature(request, len field = expected byte count) → wait ~120 ms → GetFeature(report 9) reads the response (command echoed at [2])
Response lengthVariable: the device returns exactly 8 + declared-length bytes (config 408B / keys 88B); the driver zero-pads to 520 before parsing
Write transactionRead the whole block → modify → write the whole block back (read-modify-write)
Config block layout400B = record (256B) + copy of its first 144B; record: DPI stage byte [3]=(active+1)<<4|count, active stage-code array (offset 7, u16x8), backup array (+0x14), lighting area ~[0x40..]
Input reports8B: [1]=0x0A event marker; [2]=subtype (5 = battery, [3]=battery %)
Official driverLenovoAPI_M7_20240522.dll (CDevG5MS class; feature R/W + 0xFF02 matching)

All of the above was verified on real hardware (reads, writes, read-back checks and restores).