An Example of USB Power Delivery
Let's take a look at what it takes to get almost 100W of power for a USB-C Easy Bake Oven. In this post, I'll go through the detail of the transactions on the Configuration Channel (CC) when I plug in my oven.
I borrowed a fancy Teledyne LeCroy Mercury T2C USB HS/PD Protocol Analyzer to capture the traffic. You can follow along for free with their software and my saved session. Here is the .usbraw file as well. Once you have everything installed and open the file, you should see this.
The Left device is the Apple MacBook Pro charger. The Right device is my USB-C breakout board. The first packets are from when I plugged in each of the cables. The charger identifies as a Source with a Rp pull-up on CC1. Then my board identifies as a Sink with a Rd pull-down on CC1. Once the connection is established, the charger modulates its current on CC1 to advertised USB Type-C Current at 1.5 Amp. At this point, my board is allowed to draw 1.5 A at 5 V. To get a different voltage requires some transactions using USB Power Delivery.
The charger starts by sending unsolicited Source_Capabilities messages to inform my device about its capabilities as a power source. My firmware ignores these messages, and sends a Get_Source_Cap (packet 86) to request the same information. When the charger sends it again, my board replies with a Request message (90) for the highest available power, which in this case is 5V, 2.4A. The charger sends an Accept message, then a few milliseconds later sends a PS_Ready message to let my board know it can now draw up to 2.4A. Note that every message is followed up with a GoodCRC message.
After that is all settled, one of the devices starts interrogating the cable plug (packets 96-100). SOP' is the start of packet symbol to address the cable plug. All the packets until now have been one device to another using the SOP symbol. As for which device is talking to the cable, it must be the charger. The two devices have an explicit USB PD contract, so only the Source is allowed to communicate with SOP' and SOP'', as noted in Section 4.9 of the Type-C spec. The cable responds with a Structured Vendor Defined Message (VDM). The data objects describe its vendor name, cert status, product ID, USB SuperSpeed support, max Vbus current, latency, and few other miscellaneous bits of data.
Now that the charger knows that the cable can support 5 Amps, it sends a new Source_Capabilities message. In addition to 5V, 2.4A, it now includes 9V, 3A and 20V, 4.3A. Note that the 5V fixed supply is first, as required by the spec. Then all other options are listed in increasing order of voltage, in this case, 27W then 86W. Upon receiving the new capabilities, my board requests the highest possible power. Just like before, the charger sends an Accept message followed by a PS_Ready message.
Finally, the charger sends a Structured VDM to find out more about the device it's charging. Unfortunately, I haven't implemented that part of my firmware, so there's no reply.
That's the end of the transactions. After this point, the Easy Bake oven has the power it needs to run the heater. The Arduino inside is using its on-board regulator to convert the 20V down to 5V to power its microcontroller. In this system, there is no need for further communication. In a more complex version, the oven could send a request for less power when it knows it doesn't need to run the heater. This would allow the source to reallocate that power to other devices. This charger has only one USB-C receptacle and is only connected to my board and the wall, so there's no need for anything like that.
If you want to learn more, I recommend going through the captured transactions with the USB Power Delivery spec open. If you right-click on the Packet number, you will see an option to inspect the raw data. You can select between looking at the 5-bit data that was transmitted on the wire, or the 4-bit nibbles it represents. In 4b mode, you can go through each bit of each message and compare it against the tables in Section 6 of the USB PD spec.
If you want to play around with USB-C yourself, you can buy one of my board on Tindie. My firmware libraries are on github for the FUSB302 and USB PD. Please feel free to contribute pull requests or suggestions. I'm always open to help making USB-C more accessible.