add USB logging (#38186)

* usb logging

* fix test

* discover by PID

* hardwared, add counters

* edit msg

* add manufacturer

* reorder

* rm portli

* rm this
This commit is contained in:
Daniel Koepping
2026-06-30 16:17:26 -07:00
committed by GitHub
parent 8196b743af
commit e1e9efb965
3 changed files with 87 additions and 1 deletions
+18
View File
@@ -414,6 +414,10 @@ struct CanData {
struct DeviceState @0xa4d8b5af2aa492eb {
deviceType @45 :InitData.DeviceType;
# usb
chestnutPresent @51 :Bool;
usbState @52 :UsbState;
networkType @22 :NetworkType;
networkInfo @31 :NetworkInfo;
networkStrength @24 :NetworkStrength;
@@ -684,6 +688,20 @@ struct PeripheralState {
}
}
struct UsbState {
devices @0 :List(Device);
struct Device {
busnum @0 :UInt8;
devnum @1 :UInt8;
vendorId @2 :UInt16;
productId @3 :UInt16;
speedMbps @4 :UInt16;
manufacturer @6 :Text;
product @5 :Text;
}
}
struct RadarState @0x9a185389d6fdd05f {
mdMonoTime @6 :UInt64;
carStateMonoTime @11 :UInt64;
+63
View File
@@ -0,0 +1,63 @@
from pathlib import Path
CHESTNUT_VENDOR_ID = 0xADD1
CHESTNUT_PRODUCT_ID = 0x0001
USB_DEVICES_PATH = Path("/sys/bus/usb/devices")
def read(path: Path) -> str | None:
try:
return path.read_text().strip()
except OSError:
return None
def read_int(path: Path, base: int = 10) -> int:
try:
return int(path.read_text(), base)
except (OSError, ValueError):
return 0
def usb_devices() -> list[Path]:
try:
devices = (d for d in USB_DEVICES_PATH.glob("*") if (d / "idVendor").exists())
return sorted(devices, key=lambda p: p.name)
except OSError:
return []
def get_usb_state() -> list[dict]:
devices = []
for device in usb_devices():
vendor_id = read_int(device / "idVendor", 16)
product_id = read_int(device / "idProduct", 16)
devices.append({
"busnum": read_int(device / "busnum"),
"devnum": read_int(device / "devnum"),
"vendorId": vendor_id,
"productId": product_id,
"speedMbps": read_int(device / "speed"),
"manufacturer": read(device / "manufacturer") or "",
"product": read(device / "product") or "",
})
return devices
def set_usb_state(device_state, devices: list[dict]) -> None:
entries = device_state.usbState.init('devices', len(devices))
chestnut_present = False
for entry, device in zip(entries, devices, strict=True):
entry.busnum = device["busnum"]
entry.devnum = device["devnum"]
entry.vendorId = device["vendorId"]
entry.productId = device["productId"]
entry.speedMbps = device["speedMbps"]
entry.manufacturer = device["manufacturer"]
entry.product = device["product"]
if (entry.vendorId, entry.productId) == (CHESTNUT_VENDOR_ID, CHESTNUT_PRODUCT_ID):
chestnut_present = True
device_state.chestnutPresent = chestnut_present
+6 -1
View File
@@ -18,6 +18,7 @@ from openpilot.common.params import Params
from openpilot.common.realtime import DT_HW
from openpilot.selfdrive.selfdrived.alertmanager import set_offroad_alert
from openpilot.common.hardware import HARDWARE, TICI, PC
from openpilot.common.hardware.usb import get_usb_state, set_usb_state
from openpilot.system.loggerd.config import get_available_percent
from openpilot.common.swaglog import cloudlog
from openpilot.system.hardware.power_monitoring import PowerMonitoring
@@ -36,7 +37,7 @@ ONROAD_CYCLE_TIME = 1 # seconds to wait offroad after requesting an onroad cycl
ThermalBand = namedtuple("ThermalBand", ['min_temp', 'max_temp'])
HardwareState = namedtuple("HardwareState", ['network_type', 'network_info', 'network_strength', 'network_stats',
'network_metered', 'modem_temps'])
'network_metered', 'modem_temps', 'usb_state'])
# List of thermal bands. We will stay within this region as long as we are within the bounds.
# When exiting the bounds, we'll jump to the lower or higher band. Bands are ordered in the dict.
@@ -124,6 +125,7 @@ def hw_state_thread(end_event, hw_queue):
network_stats={'wwanTx': tx, 'wwanRx': rx},
network_metered=HARDWARE.get_network_metered(network_type),
modem_temps=modem_temps,
usb_state=get_usb_state(),
)
try:
@@ -166,6 +168,7 @@ def hardware_thread(end_event, hw_queue) -> None:
network_strength=NetworkStrength.unknown,
network_stats={'wwanTx': -1, 'wwanRx': -1},
modem_temps=[],
usb_state=[],
)
all_temp_filter = FirstOrderFilter(0., TEMP_TAU, DT_HW, initialized=False)
@@ -246,6 +249,8 @@ def hardware_thread(end_event, hw_queue) -> None:
msg.deviceState.screenBrightnessPercent = HARDWARE.get_screen_brightness()
set_usb_state(msg.deviceState, last_hw_state.usb_state)
# this subset is only used for offroad
temp_sources = [
msg.deviceState.memoryTempC,