Skip to content

feat(devices): add alternate product IDs listed by Options+ - #179

Merged
mmaher88 merged 1 commit into
masterfrom
feat/options-plus-alt-pids
Nov 10, 2026
Merged

mmaher88 merged 1 commit into
masterfrom
feat/options-plus-alt-pids

Conversation

@mmaher88

@mmaher88 mmaher88 commented Nov 9, 2026

Copy link
Copy Markdown
Owner

Summary

Logitech Options+ ships these product IDs for devices Logitune already supports, but our descriptors don't list them:

Descriptor Added PID Options+ entry
mx-master-3s 0xb043 model 2b043, a second "MX Master 3S" revision. Same depot, CIDs 0x52/0x53/0x56/0xC3/0xC4, DPI 200–8000 step 50
mx-master-3s-for-business 0xb044 model 2b044, same capabilities as b035
mx-master-2s 0x4069 Unifying WPID. Model 6b019 lists 046d_b019 and 046d_4069
mx-vertical 0xc08a USB cable. Model eb020 lists 046d_407b, 046d_b020, 046d_c08a

Why it matters: DeviceManager::probeDevice only opens a session for a non-receiver hidraw node when findByPid() matches. A 3S reporting b043 over Bluetooth was never probed. Receiver-paired devices fall back to name matching, so they were less affected, but that fallback can't separate the 3S from the 3S For Business when the firmware name is ambiguous.

Wired MX Vertical (0xc08a): connection label is wrong

With this change, a cable-connected MX Vertical goes through probeDevice like this:

  1. The HID++ report-ID check (0x85 0x11) passes on the HID++ interface.
  2. 0xc08a is not a receiver PID, so it takes the direct branch, and findByPid(0xc08a) now matches.
  3. deviceIndex = 0xFF (kDeviceIndexDirect). That's correct for a wired HID++ 2.0 device; Solaar uses 0xFF for both USB and Bluetooth direct connections.
  4. connType is hard-coded to "Bluetooth" (DeviceManager.cpp, direct branch). This is wrong for USB. BatteryChip shows the Bluetooth icon and the Easy-Switch page says "Connected via Bluetooth" while the mouse is on its cable.

This PR doesn't fix the label. The fix needs the HID bus type. HIDIOCGRAWINFO already returns bustype (BUS_USB vs BUS_BLUETOOTH), but HidrawDevice::DeviceInfo drops it. It's a small follow-up: keep bustype and label the direct branch from it. Device identity isn't affected, because sessions merge by HID++ serial, not by PID or label.

0xc08a is only added to mx-vertical, which matches Options+ (it has no separate For Business model). A wired MX Vertical for Business would therefore resolve to the "MX Vertical" descriptor. The two descriptors differ only in hotspot positions.

The MX Vertical 0xFD button is intentionally left out. It needs hotspot coordinates.

Tests

  • A DeviceSpec entry for each new PID (MX_Master_2S_4069, MX_Master_3S_b043, MX_Master_3S_For_Business_b044, MX_Vertical_c08a). Each one runs the full parameterized suite against its descriptor: controls, DPI, hotspots, gestures and features.
  • The parameterized test names now end in the PID (…/MX_Master_3S_b034). Without that, two entries for one descriptor would produce duplicate gtest names.
  • DeviceRegistry.FindByPidAndNameResolvesMxMaster3sRevisions: b034/b043 resolve to MX Master 3S and b035/b044 resolve to MX Master 3S For Business. That holds even when the reported name points at the sibling descriptor.
  • I checked that the new cases fail when 0xb043 is removed from the descriptor (7 failures).

All of these pass locally on f6b1431: logitune-tests 836/836, logitune-tray-tests 9/9, logitune-qml-tests 72/72, generate-readme-devices.py --check (the table has no PID column, so README is unchanged), and generate_package_deps.py --check. Only descriptor JSON and tests change, so no hardware smoke test.

🤖 Generated with Claude Code

Logitech Options+ ships these PIDs for devices Logitune already
supports, but our descriptors did not list them:

- MX Master 3S: 0xb043, a second hardware revision (Options+ model
  2b043, same CIDs and 200-8000 DPI range as 0xb034).
- MX Master 3S For Business: 0xb044 (model 2b044, same capabilities
  as 0xb035).
- MX Master 2S: 0x4069, its Unifying WPID.
- MX Vertical: 0xc08a, its PID over the USB cable.

DeviceManager only opens a session for a non-receiver hidraw node when
findByPid() matches, so a 3S reporting 0xb043 over Bluetooth was never
probed. Receiver-paired devices fell back to name matching, which
could not tell the 3S and 3S For Business apart if the firmware name
was ambiguous.

Tests: a DeviceSpec entry per new PID, so each one is checked against
the full descriptor (controls, DPI, hotspots, gestures, features). The
parameterized test names now carry the PID to stay unique when one
descriptor has several entries. A findByPidAndName case checks that
0xb043 and 0xb044 resolve to their own descriptor regardless of the
reported name.
@mmaher88
mmaher88 merged commit 480c45f into master Nov 10, 2026
6 checks passed
@mmaher88
mmaher88 deleted the feat/options-plus-alt-pids branch November 10, 2026 13:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant