Debugging USB-PD Negotiation Failures
How CC-line PDO/RDO exchange, e-marker chips and TCPM state machines expose the exact point where USB-PD negotiation stalls or falls back to 5V.

In this guide
Table of Contents
Table of contents
A laptop connected to a certified 100W GaN charger that trickle-charges at 15W is not a charger fault, it is a protocol fault. The hardware is fine, the cable is fine, but the USB-PD negotiation exchange that establishes the voltage and current contract between source and sink has degraded silently to a fallback state. Most consumer troubleshooting guides tell you to “try a different cable,” which occasionally works, but understanding why it works requires looking at the actual state machine running on the CC line, not the marketing wattage printed on the brick.
#The Negotiation Surface: CC Lines, BMC Signalling and the Policy Engine
USB Power Delivery runs entirely over the two Configuration Channel (CC) pins in a USB-C connector, using Biphase Mark Coding (BMC) at 300 kbps. Before any PD packet is sent, the connector performs analogue role and orientation detection: the source presents a pull-up resistor (Rp) on CC1 or CC2, the sink presents a pull-down (Rd), and the resistance value advertises a default current tier (900 mA, 1.5 A or 3 A) even before a single PD message is exchanged. This is the fallback layer that keeps “dumb” USB-C devices charging at a sane minimum if PD never establishes.
Once Vbus and CC are stable, the source’s Policy Engine — implemented in Linux as the tcpm (Type-C Port Manager) driver — transmits a Source_Capabilities message containing an ordered array of 32-bit Power Data Objects (PDOs). Each PDO fixed-supply entry encodes voltage in 50 mV units and maximum current in 10 mA units, plus flags for dual-role power, USB suspend support and unconstrained power. The sink parses this array, selects the best-fit PDO, and replies with a Request message carrying a Requested Data Object (RDO) that references the PDO index and the operating current it wants. If the source can service that request it sends Accept, waits for the internal power supply rail to settle, then sends PS_RDY — only at that point does Vbus transition to the negotiated voltage.
Every failure symptom a user reports as “my charger doesn’t fast charge” maps to a specific point in this exchange collapsing, not to the charger’s rated wattage being wrong.
#Sequence of a Healthy USB-PD Negotiation
Rendering diagram...
#Implementation Logic: Where the Handshake Actually Breaks
In practice, three structural weak points account for the vast majority of negotiation failures observed in the field:

- Cable identity mismatch. Cables rated above 3 A / 60 W are required to carry an e-marker chip on the CC line, powered via Vconn, which responds to a Discover_Identity command addressed to SOP’ (Start of Packet Prime). If the e-marker CRC fails, or the cable has no e-marker at all, the source is contractually required to cap negotiation at the 3 A default tier regardless of the PDOs it advertises.
- PD revision truncation. A PD 3.0 source presenting Extended Source Capabilities to a PD 2.0-only sink that does not understand the extended message header will silently drop the message, wait out
tSenderResponse(24 ms), then re-transmit. After the retry counter is exhausted the Policy Engine issues a Soft Reset, and the contract falls back to a conservative default PDO — typically 5 V. - Signal integrity on cheap cable runs. BMC on the CC line tolerates modest capacitance, but long, thin, unshielded cables push rise/fall times past spec. CRC failures accumulate, each triggering a GoodCRC retry; once
nRetryCount(default 3) is exceeded, the state machine issues a Hard Reset, Vbus drops fortSrcRecover(~660 ms), and negotiation restarts from zero.
These three failure classes are why the same laptop, same charger and a different cable produce wildly different charging behaviour — the cable is not a passive wire in a PD system, it is an active participant in the negotiation.
#Diagnostic Tooling and Configuration
On Linux, the tcpm driver logs every state transition through the kernel ring buffer, which is the fastest way to confirm whether a Hard Reset or Soft Reset is occurring:
1$ sudo dmesg -w | grep -i tcpm
2[ 812.441203] tcpm tcpm-source-psy-usbpd0: CC1: 0 -> 1, CC2: 0 -> 0
3[ 812.443011] tcpm tcpm-source-psy-usbpd0: state change SRC_ATTACHED -> SRC_STARTUP
4[ 812.481902] tcpm tcpm-source-psy-usbpd0: PD_MSG: SRC_CAPABILITIES
5[ 812.502113] tcpm tcpm-source-psy-usbpd0: state change SNK_READY -> SNK_TRANSITION_SINK
6[ 813.104441] tcpm tcpm-source-psy-usbpd0: Hard resetThe Type-C class in sysfs exposes the negotiated contract without needing a bus analyser, which is enough to confirm whether the fallback tier was accepted or a full PD contract was reached:
1$ cat /sys/class/typec/port0/usb_power_delivery/source-capabilities/1:fixed_supply/voltage
25000000
3$ cat /sys/class/typec/port0/usb_power_delivery/source-capabilities/1:fixed_supply/maximum_current
43000000
5$ cat /sys/class/power_supply/ucsi-source-psy-USB0/current_now
6900000When kernel logs are insufficient — for instance to catch an e-marker Discover_Identity failure on SOP’ — a hardware PD sniffer such as a Twinkie or a Power-Z KM003C captures the raw CC traffic independently of the OS driver stack, which is the only reliable way to distinguish a source-side bug from a cable-side bug. The full state diagram and message definitions are formalised in the USB Power Delivery specification published by the USB Implementers Forum, and cross-referencing observed PDO byte values against that document is the fastest way to confirm whether a device is advertising capabilities correctly.
Anyone designing a device that negotiates power dynamically alongside other subsystem contracts should apply the same discipline used in broader architectural patterns for state machine design — explicit timeouts, bounded retries, and a deterministic fallback state prevent the negotiation layer from oscillating indefinitely under marginal signal conditions.

#Failure Modes and Edge Cases
Beyond the three structural weak points above, several edge cases only appear under sustained load or unusual topology:
| Symptom | Root Cause | Diagnostic Signal | Fix |
|---|---|---|---|
| Charges at 5 V/3 A only | No e-marker chip or CRC failure on cable | Discover_Identity on SOP’ times out | Replace with rated e-marked cable |
| Charging drops mid-session | Charger thermal foldback reduces advertised PDO | New Source_Capabilities mid-contract, renegotiation event | Improve charger airflow, lower ambient load |
| Repeated brief disconnects | Hard Reset loop from CRC accumulation | dmesg shows repeated Hard reset entries | Shorter/shielded cable, check connector wear |
| Device enumerates but stays at 5 V | PD revision mismatch truncates extended messages | Soft Reset after tSenderResponse timeout | Firmware update, force PD2.0 fallback mode |
| Voltage overshoot on PPS rail | Malformed RDO or spoofed PDO from compromised firmware | Vbus exceeds requested value momentarily | Enforce OVP at sink, PD3.1 authentication |
The last row is the one most engineers underestimate. Because USB-PD negotiation is a trust-based exchange — the sink largely believes what the source advertises — a compromised charger firmware (the class of attack documented publicly as BadPower) can advertise a PDO with a voltage the connected device was never designed to tolerate. The protocol has no mandatory cryptographic verification of PDO content in PD 2.0/3.0; PD 3.1 introduces an optional Authentication mechanism using Get_Digest/Get_Certificate/Challenge exchanges over SOP, but adoption in consumer silicon remains limited because it requires a secure element on both sides of the link.
#Scaling and Security Trade-offs
Every design decision in a USB-PD-capable product balances negotiation robustness against cost, latency and safety margin:
- E-marker inclusion: adds BOM cost per cable but is the only mechanism preventing a thin, unrated cable from being told to carry 5 A continuously.
- PPS granularity: 20 mV voltage steps in Programmable Power Supply mode improve thermal efficiency during fast charging but require more Request/Accept round trips, increasing negotiation latency under marginal signal conditions.
- Hard Reset recovery window: the mandated ~660 ms
tSrcRecoverfavours protocol correctness over user-perceived responsiveness; shortening it non-compliantly risks Vbus instability during role swap. - PD3.1 authentication: closes the PDO-spoofing gap but doubles silicon cost on low-margin charger SKUs, which is why it remains optional rather than mandatory in the specification.
- Multiple advertised PDOs: gives sinks more negotiation flexibility but extends the Source_Capabilities payload, marginally increasing enumeration time on every single plug event.
None of these trade-offs are theoretical. They are the direct explanation for why two devices carrying the same wattage rating on their packaging can behave completely differently once plugged into the same charger, and why a diagnostic approach rooted in the actual PD state machine — rather than cable swapping by trial and error — is the only reliable way to isolate whether the fault sits in the source, the cable, or the sink’s own policy engine implementation.
Evidence trail
Sources and verification
Primary documentation and external technical references used in this article.
Comments
Add a thoughtful note on Debugging USB-PD Negotiation Failures. Comments are checked for spam and held for moderation before appearing.
Related Engineering Labs
Calculator
SLO Budget Suite
Calculate exact error budgets, observed SLI and versioned multiwindow burn-rate alert thresholds without floating-point loss.
Calculator
CIDR Planner
Normalize IPv4/IPv6 networks, calculate exact ranges and audit batch allocations for containment, overlap, alignment and unused capacity.
Calculator
DB Pool Sizer
Calculate the exact, safe maximum connection pool size per pod to ensure the database is never exhausted during an autoscaling event.
Related articles
Tech Fundamentals
SLC Cache Exhaustion: Why Your SSD Slows Mid-Copy
Sustained NVMe writes collapse when pseudo-SLC cache empties; here's how controller design, fio logging and nvme-cli SMART data expose the exact cliff point.
Tech Fundamentals
Reading SMART Attribute Thresholds Before Failure
How smartctl's Reallocated_Sector_Ct, Pending_Sector and CRC_Error_Count values expose failing drives before a RAID rebuild turns risky.
Tech Fundamentals
Fixing UEFI Secure Boot Chain-of-Trust Failures
How PK, KEK, db, dbx, shim and MOK layers interact, and the mokutil, sbsign, and sbctl steps that repair a broken UEFI trust chain.
Tech Fundamentals
Diagnosing Laptop CPU Thermal Throttling
Intel RAPL power limits, MSR register polling and PL1/PL2 windows reveal why laptop CPUs throttle mid-task, with turbostat and powercap fixes.
Learn More About KBY
About KBY
Learn about our mission, editorial standards, and commitment to trusted engineering knowledge.
Why Trust KBY
Explore the processes and policies that ensure our publications are accurate, useful, and responsible.
Newsletter
Get our latest editorial publications, research and practical insights sent directly to your inbox.
Was this useful?
Engineering insights, direct to you.
Receive the latest Systems Engineering tutorials, production guides, Engineering Labs and operational best practices.