Skip to main content

usb-kernel-debug

Use when the Linux end of a USB link must explain itself — enumeration failures, "device descriptor read error", control STALLs, missing or short transfers, ISO dropouts, port-reset storms, xHCI errors. usbmon URB capture to pcapng, kernel dynamic debug on host or gadget.

معلومات المصدر

المستودع
hathach/agentrc
آخر نشاط في المصدر
٧ أكتوبر ٢٠٢٦ في ٠٦:٠٩
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
١
التفرعات
٢

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

مستكشف الملفات
3 ملفات

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
name
usb-kernel-debug
description
Use when the Linux end of a USB link must explain itself — enumeration failures, "device descriptor read error", control STALLs, missing or short transfers, ISO dropouts, port-reset storms, xHCI errors. usbmon URB capture to pcapng, kernel dynamic debug on host or gadget.
# usb-kernel-debug — what the Linux side of the link saw Two kernel facilities, by the role Linux plays in the link: | Linux is the … | usbmon URB capture (`usbcap.py`) | dynamic debug (`usb_dyndbg.sh`) | |----------------|----------------------------------|------------------------------------------| | PC host | yes — what the host exchanged | yes — why the host driver acted | | gadget peer | no — a UDC has no usbmon | yes — `dwc2`/`dwc3` + `udc_core` + `libcomposite` | Neither sees inside the device's firmware or the wire itself: pair this with a wire sniffer (the `usb-sniffer` skill, if installed) and target-side debugging (GDB on the MCU) for those. ## usbmon — capture (host role) `usbmon` records host-side **URBs** — control / bulk / interrupt / isochronous transfers, descriptors, class requests, STALLs, short packets — i.e. exactly what the host exchanged with a device. Requires `usbmon` loaded and `/dev/usbmon*` readable by your user (`wireshark` group); the script says so when `tshark` cannot open the interface — a fresh group membership needs a new login or `sg wireshark -c '...'`. Never `sudo` it: the script refuses root, whose `dumpcap` drops its capabilities and then cannot write an outfile under a mode-0700 home. Reading a finished `.pcapng` needs no group. ```bash S=<skill dir>/scripts $S/usbcap.py 1a86:55d4 10 # the bus of that plugged-in device, 10 s; --help for selectors and defaults $S/usbcap.py 3 10 cap.pcapng --snaplen 64 # bus 3, URB headers only ``` Capture the device's own bus. A selector matching devices on several buses (`1a86:` with two adapters plugged in) is refused with the matches listed: pass the bus, or `auto` when you really want every bus. Full payloads by default; `--snaplen 64` keeps only the 64-byte usbmon record (URB type, endpoint, status, lengths) for long or high-throughput captures, and `128` adds the first 64 bytes of payload, enough for setup packets and descriptor heads. An existing output file is refused, never overwritten. A capture with no packets exits 1 and keeps the file: wrong bus, or nothing happened. To catch enumeration, start the capture, then replug or reset the device. ## usbmon — analyze ```bash tshark -r cap.pcapng # one line per URB tshark -r cap.pcapng -V | less # full dissection (descriptors decoded) tshark -r cap.pcapng -Y 'usb.device_address==26' # filter to one device ``` ### Filter (`-Y '<expr>'`) | Goal | Expression | |--------------------------------------------------|-------------------------------------------------------------| | One device / endpoint | `usb.device_address==26` / `usb.endpoint_address==0x81` | | IN (to host) / OUT (from host) | `usb.endpoint_address.direction==1` / `==0` | | Submit / Complete event | `usb.urb_type=='S'` / `=='C'` (char literal: single quotes) | | Control / bulk / interrupt / iso | `usb.transfer_type==2` / `3` / `1` / `0` | | Only transfers carrying data | `usb.data_len>0` | | GET_DESCRIPTOR / SET_ADDRESS / SET_CONFIGURATION | `usb.setup.bRequest==6` / `5` / `9` | | SET_INTERFACE / CLEAR_FEATURE (clear-halt) | `usb.setup.bRequest==11` / `1` | | Descriptor type DEVICE/CONFIG/STRING/HID-report | `usb.bDescriptorType==1` / `2` / `3` / `0x22` | | Class / vendor requests | `usb.bmRequestType.type!=0` | | STALLs / errors | `usb.urb_status!=0 && usb.urb_status!=-115` | Combine with `&&` — e.g. one endpoint's data: `usb.endpoint_address==0x02 && usb.data_len>0`. **`usb.urb_status` codes** (errno): `0` success · `-115` `-EINPROGRESS` (every Submit) · `-71` `-EPROTO` (transaction error — device answered wrong or didn't service in time, after the HC's retries) · `-32` `-EPIPE` (STALL) · `-110` `-ETIMEDOUT` · `-75` `-EOVERFLOW` (babble). A **control** transfer completing `-71` ≠ a STALL: the device mis-/under-served it (e.g. EP0 starved under load), not a deliberate STALL from its control handler. **Decoding class requests:** the plain `-e usb.setup.bRequest` field is often blank for class requests (CDC `SET_LINE_CODING` 0x20 / `SET_CONTROL_LINE_STATE` 0x22, `bmRequestType==0x21`) — Wireshark routes them to class fields. Use `-V` on the Submit frame to get the request name + `wValue` (for `SET_CONTROL_LINE_STATE`, `wValue` bit0=DTR, bit1=RTS). **Hard limit — usbmon is URB-level, not wire-level.** It cannot show data toggle (DATA0/DATA1) or NAKs. A device-side stall and a toggle desync both look identical: Submits on an endpoint with no Completes. To tell them apart, pair usbmon with a wire sniffer, or with GDB on the device: read the endpoint control register (response/toggle bits) and the device stack's endpoint state at the moment of the hang. ## Dynamic debug (either role) Kernel **dynamic debug** shows the Linux side's *reasoning* that capture can't: port resets and their causes, enumeration retries, address (re)assignment, EP halts, xHCI ring/command errors. `scripts/usb_dyndbg.sh` (`--help` lists the allowlisted modules; run with `sudo`) flips the print flag for those USB modules only: ```bash sudo $S/usb_dyndbg.sh on usbcore xhci_hcd # then reproduce while following `sudo dmesg -w` sudo $S/usb_dyndbg.sh status # what is switched on right now sudo $S/usb_dyndbg.sh off usbcore xhci_hcd # ALWAYS: left on, it floods the log and skews timing ``` `on`/`off` read the flags back and say how many of the module's print sites took (`N of N sites print`); a module that is not loaded, or built without dynamic debug, is an error rather than a quiet success. Module choice by role: on a host, `usbcore` for enumeration/hub logic plus the controller driver `lsusb -t` shows for the bus; on a gadget peer, `dwc2` (or `dwc3`) + `udc_core` + `libcomposite`, run on the peer itself (the script is self-contained, copy it over). Best for **re-enumerates / enumeration stalls / port-reset storms**, where usbmon shows the resets but not the host's reason. ## Reading a capture Candidate causes and the check that tells them apart, not verdicts: - **Not recognized / re-enumerates:** is `GET DESCRIPTOR (DEVICE)` answered, `bMaxPacketSize0` sane? Repeated SET_ADDRESS or resets: a device too slow to respond is one candidate, a marginal link or power another; dynamic debug on `usbcore` and the controller driver gives the host's own reset reason. - **Enumeration stalls:** find the last good control transfer; the next request, often CONFIG, a string, or the first class request, is the first suspect: compare the device's answer to it (`-V`) with what it should return, or look at the wire when there is no answer at all. - **Control STALL:** a control URB completing `-32` (`-EPIPE`) is a STALL from the device's control handler, usually an unhandled `bRequest` (decode it with `-V`). `-71` is not a STALL, see the errno list. - **Bulk / interrupt missing or short:** on the endpoint, do Submits get Completes? An unexpected short (`usb.data_len < wMaxPacketSize`) suggests a length bug; no completions can be the device never writing, a stalled endpoint or a toggle desync, which usbmon cannot separate. - **A CDC read hangs with the IN endpoint idle:** check EP0 first. Did `SET_CONTROL_LINE_STATE` complete `0` or fail `-71`? If it failed, the device never saw DTR and may stop sourcing data by design. - **ISO / audio dropouts:** ISO URB cadence (~1/ms at full speed) and payload lengths; zero-length frames are consistent with the device starving the endpoint; confirm on the target (what the class fed, and when) before blaming it. - **Wrong descriptors:** `-V` decodes them; check `bLength` / `wTotalLength` against what the device is meant to return.
عرض على GitHub