Files
linux-voice-assistant/linux_voice_assistant
imonlinux 7305a289a0 Add files via upload
What’s in it:

Xvf3800RuntimeConfig – simple dataclass for VID/PID, timeouts, etc.

Xvf3800Controller(EventHandler) – structured very similar to your other controllers:

On init:

Checks enabled and hid availability.

Uses hid.enumerate() to find the XVF3800 by VID/PID.

Opens the first HID interface (non-blocking).

Starts a background thread _poll_loop().

_poll_loop():

Reads HID reports (read(64, timeout_ms=...)).

For each non-empty report:

Calls _parse_hw_mute_from_report(report) → Optional[bool].

If it returns True/False and the value changed, it publishes:

self.loop.call_soon_threadsafe(
    self.event_bus.publish,
    "set_mic_mute",
    {"state": new_state},
)


Exits cleanly when self._running is false or state.shutdown is true.

@subscribe def set_mic_mute(self, data: dict):

Listens to the same set_mic_mute event MQTT and ButtonController use.

Updates _last_hw_mute_state.

Calls _send_hw_mute_state(desired) to push mute+LED down to hardware.

Placeholders:

def _parse_hw_mute_from_report(self, report: bytes) -> Optional[bool]:
    # TODO: implement once we know the report layout
    _LOGGER.debug("XVF3800 HID report (len=%d): %s", len(report), report.hex())
    return None

def _send_hw_mute_state(self, muted: bool) -> None:
    # TODO: implement once we know output report format
    _LOGGER.debug("(stub) Would send HID command to set XVF3800 mute=%s", muted)
2025-12-06 18:34:54 -08:00
..
2025-08-26 09:30:58 -05:00
2025-11-29 23:42:24 -08:00
2025-11-18 15:15:46 -08:00
2025-11-20 20:01:13 -08:00
2025-11-17 17:42:40 -08:00
2025-11-30 12:31:34 -08:00
2025-11-29 23:40:16 -08:00
2025-10-12 10:09:45 -07:00
2025-11-17 21:50:53 -08:00
2025-11-21 16:59:04 -08:00
2025-11-29 14:38:13 -08:00
2025-11-21 11:00:03 -08:00
2025-11-29 14:38:52 -08:00
2025-11-29 23:43:08 -08:00
2025-11-21 17:17:56 -08:00
2025-12-06 18:34:54 -08:00
2025-11-19 18:46:05 -08:00