47 lines
2.3 KiB
Python
47 lines
2.3 KiB
Python
#!/usr/bin/env python3
|
|
"""Decode an iwlwifi host-command trace captured from Linux on the same adapter.
|
|
|
|
Linux drives this exact firmware successfully, so its host commands are ground
|
|
truth for what the firmware expects -- far more reliable than reading struct
|
|
definitions out of a kernel tree and hoping the version matches.
|
|
|
|
Capture on a Linux box with the adapter, as root:
|
|
|
|
trace-cmd record -e iwlwifi_dev_hcmd -o /tmp/iwl.dat \
|
|
sh -c 'nmcli radio wifi off; sleep 2; nmcli radio wifi on; sleep 20'
|
|
|
|
Then run this against /tmp/iwl.dat. dump_iwl_cmds.py prints full payload hex
|
|
for each command instead of a decoded summary.
|
|
|
|
Copyright (c) 2026 Daniel Hammer
|
|
"""
|
|
import re, subprocess
|
|
out = subprocess.run(['trace-cmd','report','-R','-i','/tmp/iwl.dat'],
|
|
capture_output=True, text=True).stdout
|
|
ACT={0:'STUB',1:'ADD',2:'MODIFY',3:'REMOVE'}
|
|
def u32(p,o): return p[o]|(p[o+1]<<8)|(p[o+2]<<16)|(p[o+3]<<24)
|
|
rows=[]
|
|
for line in out.splitlines():
|
|
m=re.search(r'hcmd=ARRAY\[(.*?)\]',line); t=re.search(r'\s(\d+\.\d+):',line)
|
|
if not m: continue
|
|
b=[int(x,16) for x in m.group(1).split(', ')]
|
|
if len(b)<8: continue
|
|
grp,op=b[1],b[0]; ln=b[4]|(b[5]<<8); p=b[8:8+ln]; ts=float(t.group(1)) if t else 0
|
|
if (grp,op)==(3,0x08) and ln>=52:
|
|
rows.append((ts,f"MAC_CONFIG action={ACT.get(u32(p,4)):6} id={u32(p,0)} is_assoc={p[36]} aid={p[40]|p[41]<<8} filter=0x{u32(p,20):x}"))
|
|
elif (grp,op)==(3,0x09) and ln>=208:
|
|
rows.append((ts,f"LINK_CONFIG action={ACT.get(u32(p,0)):6} link={u32(p,4)} mac={u32(p,8)} phy={u32(p,12)} mask=0x{u32(p,24):02x} active={p[28]} bi={u32(p,136)}"))
|
|
elif (grp,op)==(3,0x0a) and ln>=96:
|
|
rows.append((ts,f"STA_CONFIG sta={u32(p,0)} link={u32(p,4)} type={u32(p,24)} aid={u32(p,28)}"))
|
|
elif (grp,op)==(1,0x08) and ln>=32:
|
|
rows.append((ts,f"PHY_CONTEXT action={ACT.get(u32(p,4)):6} id={u32(p,0)} chan={u32(p,8)} band={p[12]} width={p[13]}"))
|
|
elif (grp,op)==(3,0x05):
|
|
rows.append((ts,f"SESSION_PROT action={ACT.get(u32(p,4)):6} conf_id={u32(p,8)} dur={u32(p,12)}"))
|
|
elif (grp,op)==(5,0x17):
|
|
rows.append((ts,f"SCD_QUEUE_CFG op={u32(p,0)}"))
|
|
elif (grp,op)==(3,0x0c):
|
|
rows.append((ts,"STA_REMOVE"))
|
|
rows.sort(); base=rows[0][0]
|
|
for ts,s in rows:
|
|
if ts-base > 2.3: print(f"{ts-base:7.3f} {s}")
|