[Protocol] 0x8127 DUAL_CLUTCH: bite point and button assignment decoded on a G923 Xbox edition (046d:c26e)
Hi, I'm working on a similar project, but for Xbox.
FEATURE_MATRIX.md lists 0x8127 as present but not implemented, with a note that settling it
would need a G HUB capture of the bite-point control. There may be a cheaper route: the wheel
configures this feature itself from on-wheel button combinations and then reports the result over
HID++, so the layout can be read by listening on the feature index while a person works the wheel -
no G HUB session needed. Here is what was recorded from the wheel on the bench, in case it is useful.
Device and provenance
|
|
| Device |
Logitech G923 Racing Wheel for Xbox One and PC |
| USB ID |
046d:c26e (PC mode; same wheel enumerates as 046d:c26d in Xbox mode) |
| Firmware |
139.2.50 as G HUB reports it = HID++ 0x0003 entity 0 U1 v57.2 build 80 |
| G HUB |
not running during these runs. Installed build is 2021.3.9205 |
0x8127 runtime index |
0x11 |
| Host |
Windows, hidapi over the two FF43 HID++ collections |
fn2 reads the dual-clutch state
fn2 reply [0] = 0x01 configured / enabled
[1] = button 0x00 = RSB, 0x01 = LSB
[2] = bite point, 0..100 (0x00..0x64)
fn2 looks to be a read. Writes to fn2 and fn3 are acknowledged and change nothing; twenty such writes in an earlier session and eight in this one all came back successful with no state change. Sharing that mainly so the next person does not spend the same time on it: on this feature page an acknowledged write does not appear to be an applied one.
The wheel emits an event on every change
Unsolicited, on feature index 0x11, carrying the same fields plus a mode byte:
12 ff 11 00 | 01 <button> <bitepoint> 00 <mode> <n>
mode = 0x02 in setting mode
0x00 on exit/save
How the feature is driven
All on the wheel, with no host involvement:
|
Sequence |
LED confirmation |
| Enter setup |
Hold both gear paddles + LSB + RSB, ~2 s |
RPM LEDs blue, flashing slowly |
| Assign the button |
press LSB or RSB — the only valid choices |
LEDs flash red |
| Set the bite point |
clutch + accelerator down, then + / - |
one event per press |
| Exit and save |
Select, the centre of the dial |
LEDs flash green-to-blue |
| Reset |
both paddles + X |
all RPM LEDs on, then off in sequence |
What each part rests on
| Claim |
How we got it |
| Byte 2 is the bite point |
It tracked the - button 1:1 across ten presses, 0x64 → 0x5a, and fn2 read 01:00:64 before the sequence and 01:00:5a after |
| 100 looks like the ceiling |
~6 + presses while already at 100 each emitted an event and the value stayed 0x64 |
| Byte 1 is the assigned button |
Two runs with one variable changed: run 1 assigned RSB → 0x00, run 2 assigned LSB → 0x01. We wrote that prediction into the log before run 2 so it could fail visibly |
| The page does not seem to touch the rev LEDs |
0x807A fn2 GET_STATE and fn7 GetDetails were unchanged across every 0x8127 read and all eight writes, with a known pattern lit on the bar throughout |
Run 1, the - button being pressed, one event each:
+31.79s 12:ff:11:00:01:00:64:00:02:01 100
+32.24s 12:ff:11:00:01:00:63:00:02:01 99
+32.59s 12:ff:11:00:01:00:62:00:02:01 98
... (one per press)
+35.74s 12:ff:11:00:01:00:5a:00:02:01 90
+38.38s 12:ff:11:00:01:00:5a:00:00:01 byte 4: 02 -> 00, exit/save
Run 2, LSB assigned instead of RSB — byte 1 moves and nothing else does:
+ 9.22s 12:ff:11:00:01:01:64:00:02:01
fn2 before 01:00:64 fn2 after 01:01:64
What was not decoded
Listing these so this is not mistaken for a complete decode:
fn1 has two zones (zone 2 and above return INVALID_ARGUMENT 0x02), reading 00:09:00:09
and 00:09:00:0a. Those have never moved for us — not through setup, a bite point change, a
button reassignment, a reset, or 28 writes across two sessions. We guessed it held the button
assignment and were wrong; that turned out to be fn2 byte 1.
fn0 returns a single byte 0x02 and has not moved.
fn3 accepts 0x00 and 0x01; 0x02 and 0x03 return INVALID_ARGUMENT 0x02. Looks like
a two-state selector, but no write to it changed anything we could observe.
- Whether the saved bite point persists. It read 90 at the end of one run and 100 at the start
of the next with nothing sent in between, so either the Select exit does not commit it or
re-entering setup resets to 100. We have not tested across a power cycle, so we would treat the
save as unconfirmed rather than durable.
- All of this is one wheel on one firmware.
0x8127 is listed on the RS50 and c266 as well and we
have neither, so we cannot say whether any of it carries across.
The approach, in case it helps elsewhere
The three remaining functions did not respond to anything we sent, which fits the same pattern
fn2 showed — the wheel writes them and the host can only read. What eventually worked was to stop
writing, listen for unsolicited reports on the feature index, and have someone perform a real
on-device action, then diff the registers before and after. Two sessions of writing gave us nothing;
one session of listening gave us the layout above. It may be worth a try on other pages that look
inert.
Attachments
Redacted for host name and wheel serial, otherwise unmodified.
| File |
What it is |
8127_run1_assign_RSB_bitepoint_100_to_90.log |
The main run. RSB assigned, bite point walked 100 → 90 |
8127_run2_assign_LSB.log |
The paired run that identified the button field, including the prediction written before it ran |
8127_protocol_function_map_and_writes.log |
The function map (fn4–fn15 → INVALID_FUNCTION_ID, zones 2+ → INVALID_ARGUMENT) and the eight writes that changed nothing |
Log format is +<monotonic s> TAB <utc> TAB <type> TAB <message>. TX/RX are HID++ report bytes,
OBS is a human observation, and a NOTE containing PREDICTION was written before the payload it
refers to was sent.
Happy to run further tests on this wheel if any of it would be useful to you.
8127_protocol_function_map_and_writes.log
8127_run1_assign_RSB_bitepoint_100_to_90.log
8127_run2_assign_LSB.log
[Protocol]
0x8127DUAL_CLUTCH: bite point and button assignment decoded on a G923 Xbox edition (046d:c26e)Hi, I'm working on a similar project, but for Xbox.
FEATURE_MATRIX.mdlists0x8127as present but not implemented, with a note that settling itwould need a G HUB capture of the bite-point control. There may be a cheaper route: the wheel
configures this feature itself from on-wheel button combinations and then reports the result over
HID++, so the layout can be read by listening on the feature index while a person works the wheel -
no G HUB session needed. Here is what was recorded from the wheel on the bench, in case it is useful.
Device and provenance
046d:c26e(PC mode; same wheel enumerates as046d:c26din Xbox mode)0x0003entity 0U1v57.2 build 800x8127runtime index0x11FF43HID++ collectionsfn2reads the dual-clutch statefn2looks to be a read. Writes tofn2andfn3are acknowledged and change nothing; twenty such writes in an earlier session and eight in this one all came back successful with no state change. Sharing that mainly so the next person does not spend the same time on it: on this feature page an acknowledged write does not appear to be an applied one.The wheel emits an event on every change
Unsolicited, on feature index
0x11, carrying the same fields plus a mode byte:How the feature is driven
All on the wheel, with no host involvement:
+/-What each part rests on
-button 1:1 across ten presses,0x64→0x5a, andfn2read01:00:64before the sequence and01:00:5aafter+presses while already at 100 each emitted an event and the value stayed0x640x00, run 2 assigned LSB →0x01. We wrote that prediction into the log before run 2 so it could fail visibly0x807Afn2GET_STATE andfn7GetDetails were unchanged across every0x8127read and all eight writes, with a known pattern lit on the bar throughoutRun 1, the
-button being pressed, one event each:Run 2, LSB assigned instead of RSB — byte 1 moves and nothing else does:
What was not decoded
Listing these so this is not mistaken for a complete decode:
fn1has two zones (zone 2 and above returnINVALID_ARGUMENT 0x02), reading00:09:00:09and
00:09:00:0a. Those have never moved for us — not through setup, a bite point change, abutton reassignment, a reset, or 28 writes across two sessions. We guessed it held the button
assignment and were wrong; that turned out to be
fn2byte 1.fn0returns a single byte0x02and has not moved.fn3accepts0x00and0x01;0x02and0x03returnINVALID_ARGUMENT 0x02. Looks likea two-state selector, but no write to it changed anything we could observe.
of the next with nothing sent in between, so either the Select exit does not commit it or
re-entering setup resets to 100. We have not tested across a power cycle, so we would treat the
save as unconfirmed rather than durable.
0x8127is listed on the RS50 andc266as well and wehave neither, so we cannot say whether any of it carries across.
The approach, in case it helps elsewhere
The three remaining functions did not respond to anything we sent, which fits the same pattern
fn2showed — the wheel writes them and the host can only read. What eventually worked was to stopwriting, listen for unsolicited reports on the feature index, and have someone perform a real
on-device action, then diff the registers before and after. Two sessions of writing gave us nothing;
one session of listening gave us the layout above. It may be worth a try on other pages that look
inert.
Attachments
Redacted for host name and wheel serial, otherwise unmodified.
8127_run1_assign_RSB_bitepoint_100_to_90.log8127_run2_assign_LSB.log8127_protocol_function_map_and_writes.logfn4–fn15→INVALID_FUNCTION_ID, zones 2+ →INVALID_ARGUMENT) and the eight writes that changed nothingLog format is
+<monotonic s> TAB <utc> TAB <type> TAB <message>.TX/RXare HID++ report bytes,OBSis a human observation, and aNOTEcontainingPREDICTIONwas written before the payload itrefers to was sent.
Happy to run further tests on this wheel if any of it would be useful to you.
8127_protocol_function_map_and_writes.log
8127_run1_assign_RSB_bitepoint_100_to_90.log
8127_run2_assign_LSB.log