Unofficial, independent research notes and tools about the internals of the Logitech G560 LIGHTSYNC gaming speaker
(USB 046d:0a78): which chips it contains, how they talk to each other, how the firmware images are structured,
where the startup volume comes from, how to turn off the startup lighting animation, and what is (not) possible over Bluetooth.
Not affiliated with Logitech, Conexant, Synaptics, STMicroelectronics or Texas Instruments. All trademarks belong to their owners. No proprietary firmware is included in this repository — only notes, hashes of the official downloads, and tools you run on files you download yourself. No firmware was ever modified. Apart from read-only requests, the only writes to the speaker were standard HID++ lighting settings (
0x8070: persistent LED effects and the startup-animation flag) and, once, the 2-byte startup-volume word in the Conexant EEPROM (0x120). See what was not done.
Confidence tags: [V] verified on a real G560 · [C] observed directly in firmware code or data · [I] inference / hypothesis.
- Architecture — USB host → Conexant CX2070x-family audio chip (65C02-based, USB + DSP) → I²C → STM32L100 microcontroller → two TI TAS5731M class-D amplifiers (and the LED driving). [C][V] → docs/architecture.md
- Firmware images — the Windows updater contains two images: a Conexant EEPROM image (Motorola S-record) and an STM32 image (
Muse_DfuImg, U-Boot-like header, CRC-16/XMODEM, no signature at that layer). [C] - The device exposes the Conexant HID "memory access" interface (report
0x04OUT 36 B /0x05IN 32 B — the same onefwupd'ssynaptics-cxaudioplugin uses). We dumped the full 32 KiB EEPROM and 36 KiB of ROM with it; the EEPROM is byte-identical to the 122.3.23 image in the updater. [V] → docs/conexant-cx2070x.md - Startup volume — the chip powers up at a gain of
0xE5A7(−26.35 dB, curve index 10), stored at EEPROM0x120. A USB host overwrites it within ~0.13 s; the MCU's own default (index 25) is only live for ~2 s. On the tested speaker these 2 bytes were changed to index 25 (−13.98 dB) and the next cold boot started there. [V] for the power-on gain, timings and the change, [I] for the Bluetooth-only consequence → docs/startup-volume.md - Startup lighting animation — the ~10 s colour cycle at power-on is controlled by one persistent MCU flag, exposed over HID++
0x8070function 4 (get) / 5 (set), setting id 1. Writing2turns it off without any firmware change; done and verified by power-cycling a real G560. [V][C] → docs/startup-animation.md - Bluetooth — the speaker publishes only an A2DP sink over SDP (no AVRCP/HFP/SPP). No Bluetooth-related strings, registers or peripherals were found in either firmware (the Conexant ROM was dumped but not fully disassembled). No Bluetooth control channel was found; the vendor's BT updater library speaks Airoha RACE, which belongs to a different hardware variant. [V][C] → docs/bluetooth.md
- Volume curve changes between firmware 122.2.22 and 122.3.23 are in the MCU's amplifier tables, not in the Conexant image. [C] → docs/mcu-stm32.md
- Risks & recovery for modifying the startup volume: researched, then the change was carried out once with a no-op write first and full-dump diffs. The Conexant ROM checks only marker bytes, no checksum. The deeper recovery steps were never needed and are untested → docs/risks-and-recovery.md
| Path | Contents |
|---|---|
docs/ |
Findings, by topic (architecture, Conexant, MCU, Bluetooth, startup volume, startup animation, risks, how to reproduce) |
docs/tr/NOTES.tr.md |
The original chronological working notes, in Turkish |
tools/ |
Python/Swift tools. Offline analysers (no device needed) and a small number of read-only device tools |
LICENSE |
MIT — code |
LICENSE-DOCS.md |
CC BY 4.0 — documentation |
Offline (work on files you obtain from the vendor — see docs/reproduce.md):
| Tool | Purpose |
|---|---|
pe_extract.py |
Pull the embedded FIRMWARE resources out of the Windows updater .exe |
s37_decode.py |
Motorola S-record → flat binary (also verifies record checksums) |
uimg.py |
Validate/unpack the Muse_DfuImg header (CRC-16/XMODEM) |
mcu_dis.py |
Thumb-2 disassembler + cross-references for the STM32 image |
cx_dis.py |
65C02 recursive-descent disassembler for the Conexant patch (address map, hook table) |
pe_func.py, pe_strxref.py |
x86-64 helpers for the vendor's Windows DLLs |
Host-side, read-only (macOS): hid_report_descriptor.py (reads the cached HID descriptor from ioreg), sdp_dump.py (SDP query),
g560_db.swift / g560_volume.swift (CoreAudio volume read).
Device tools:
| Tool | Notes |
|---|---|
cx_hid_read.py |
Read-only Conexant memory reader. The only code path that talks to the device refuses any packet with the write bit set. |
cx_boot_watch.py |
Watches the device disappear/reappear and samples a few RAM words at boot (read-only) |
rfcomm_scan.py |
Tries to open RFCOMM channels 1–30 (opens data channels; sends nothing) |
probe_hidpp.py, watch_hidpp.py |
Read-only HID++ 2.0 feature enumeration / polling |
g560.py |
python3 -m venv .venv && . .venv/bin/activate
pip install -r requirements.txt # hidapi, capstone, pefile (+ pyobjc on macOS for Bluetooth tools)
python3 -I tools/hid_report_descriptor.py # no device I/O: shows the report IDs the speaker declares
python3 -I tools/cx_hid_read.py --dry-run ram 1000 9 # prints the packet that WOULD be sent; sends nothing
python3 -I tools/cx_hid_read.py ram 1000 9 # real read: CX RAM 0x1000..0x1008 (firmware version etc.)Tested on macOS (Apple silicon). The HID tools use hidapi, so Linux/Windows should work in principle but are untested.
g560.py, probe_hidpp.py and watch_hidpp.py import each other, so run those three from inside tools/.
- No firmware was modified. The only writes were the HID++ lighting settings and the 2-byte startup-volume word mentioned above (plus the firmware's own "park" flag in RAM during that write). The write tool used for it is not published; the packets are documented in
docs/risks-and-recovery.md. Its recovery ladder beyond "write the old bytes back" was never exercised. - The STM32 firmware update protocol and the speaker's Bluetooth module firmware were not analysed (the latter is not in the vendor package for this hardware variant).
- The CX ROM was dumped and its EEPROM boot checks were read, but it was not fully analysed (the CPU has non-standard extended instructions that common disassemblers mis-decode).
- The startup-volume claim for Bluetooth-only use is an inference: with a USB host attached, the host overwrites the value too quickly to observe it.
- The startup animation can be switched off but not changed: its effect is a constant in the MCU firmware, and the firmware was not modified. The rest of the LED effect engine was analysed only as far as needed.
Corrections are very welcome — most hypotheses here are tagged [I] for a reason. Particularly useful:
- A second G560 (or another hardware revision) to compare EEPROM dumps and the BT module.
- Someone with a Linux box:
sdptool browse <addr>/bluetoothctlagainst the speaker would settle whether a hidden RFCOMM service exists (macOS cannot tell "refused" from "not permitted"). - The extended 65C02 instruction set of the Conexant core (
B2/C2/D2/E2/F2 …). - Datasheet-level confirmation of the TAS5731M volume register scale.
Writing to the Conexant EEPROM or the MCU can brick the speaker. There is no official recovery procedure, and Logitech states that its firmware tools are no longer supported. Nothing here is advice to do so. If you experiment, dump and keep your own EEPROM backup first.