From 20923d1495a098afe482dd537df9c615632f94e0 Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Mon, 30 Mar 2026 10:32:25 +0800 Subject: [PATCH 1/7] Add --pdports-cypd The regular --pdports command does not return useful data on our systems because it uses the chrome PD subsystem instead of the cypress PD subsystem that we use. Signed-off-by: Daniel Schaefer --- framework_lib/src/chromium_ec/command.rs | 2 + framework_lib/src/chromium_ec/commands.rs | 27 ++++ framework_lib/src/commandline/clap_std.rs | 5 + framework_lib/src/commandline/mod.rs | 5 + framework_lib/src/commandline/uefi.rs | 4 + framework_lib/src/power.rs | 145 ++++++++++++++++++ .../completions/bash/framework_tool | 2 +- .../completions/fish/framework_tool.fish | 1 + .../completions/zsh/_framework_tool | 1 + 9 files changed, 191 insertions(+), 1 deletion(-) diff --git a/framework_lib/src/chromium_ec/command.rs b/framework_lib/src/chromium_ec/command.rs index 5e7351a..5436d45 100644 --- a/framework_lib/src/chromium_ec/command.rs +++ b/framework_lib/src/chromium_ec/command.rs @@ -110,6 +110,8 @@ pub enum EcCommands { GetGpuPcie = 0x3E1E, /// Set gpu bay serial and program structure ProgramGpuEeprom = 0x3E1F, + /// Get PD port state from Cypress PD controller + GetPdPortState = 0x3E23, /// Read board ID of specific ADC channel ReadBoardId = 0x3E26, } diff --git a/framework_lib/src/chromium_ec/commands.rs b/framework_lib/src/chromium_ec/commands.rs index 2a22b89..cc04d33 100644 --- a/framework_lib/src/chromium_ec/commands.rs +++ b/framework_lib/src/chromium_ec/commands.rs @@ -1247,6 +1247,33 @@ impl EcRequest<_EcResponseReadPdVersionV1> for EcRequestReadPdVersionV1 { } } +#[repr(C, packed)] +pub struct EcRequestGetPdPortState { + pub port: u8, +} + +#[repr(C, packed)] +pub struct EcResponseGetPdPortState { + pub c_state: u8, + pub pd_state: u8, + pub power_role: u8, + pub data_role: u8, + pub vconn: u8, + pub epr_active: u8, + pub epr_support: u8, + pub cc_polarity: u8, + pub voltage: u16, + pub current: u16, + pub active_port: u8, + pub pd_alt_mode_status: u8, +} + +impl EcRequest for EcRequestGetPdPortState { + fn command_id() -> EcCommands { + EcCommands::GetPdPortState + } +} + #[repr(C, packed)] pub struct EcRequestPrivacySwitches {} diff --git a/framework_lib/src/commandline/clap_std.rs b/framework_lib/src/commandline/clap_std.rs index f435f8c..4b44142 100644 --- a/framework_lib/src/commandline/clap_std.rs +++ b/framework_lib/src/commandline/clap_std.rs @@ -78,6 +78,10 @@ struct ClapCli { #[arg(long)] pdports: bool, + /// Show CYPD PD port state (Framework-specific) + #[arg(long)] + pdports_cypd: bool, + /// Show info from SMBIOS (Only on UEFI) #[arg(long)] info: bool, @@ -475,6 +479,7 @@ pub fn parse(args: &[String]) -> Cli { fansetrpm, autofanctrl: args.autofanctrl, pdports: args.pdports, + pdports_cypd: args.pdports_cypd, pd_info: args.pd_info, pd_reset: args.pd_reset, pd_disable: args.pd_disable, diff --git a/framework_lib/src/commandline/mod.rs b/framework_lib/src/commandline/mod.rs index ea2b99b..b7681d1 100644 --- a/framework_lib/src/commandline/mod.rs +++ b/framework_lib/src/commandline/mod.rs @@ -171,6 +171,7 @@ pub struct Cli { pub fansetrpm: Option<(Option, u32)>, pub autofanctrl: Option>, pub pdports: bool, + pub pdports_cypd: bool, pub privacy: bool, pub pd_info: bool, pub pd_reset: Option, @@ -260,6 +261,7 @@ pub fn parse(args: &[String]) -> Cli { // fansetrpm // autofanctrl pdports: cli.pdports, + pdports_cypd: cli.pdports_cypd, privacy: cli.privacy, pd_info: cli.version, // pd_reset @@ -1550,6 +1552,8 @@ pub fn run_with_args(args: &Cli, _allupdate: bool) -> i32 { print_err(ec.autofanctrl(None)); } else if args.pdports { power::get_and_print_pd_info(&ec); + } else if args.pdports_cypd { + power::get_and_print_cypd_pd_info(&ec); } else if args.info { smbios_info(); } else if let Some(dump_path) = &args.meinfo { @@ -1841,6 +1845,7 @@ Options: --fansetrpm Set fan RPM (limited by EC fan table max RPM) --autofanctrl []Turn on automatic fan speed control (optionally provide fan index) --pdports Show information about USB-C PD ports + --pdports-cypd Show CYPD PD port state (Framework-specific) --info Show info from SMBIOS (Only on UEFI) --meinfo [] Show Intel ME information (from SMBIOS type 0xDB) --pd-info Show details about the PD controllers diff --git a/framework_lib/src/commandline/uefi.rs b/framework_lib/src/commandline/uefi.rs index fc8467e..6ab9382 100644 --- a/framework_lib/src/commandline/uefi.rs +++ b/framework_lib/src/commandline/uefi.rs @@ -46,6 +46,7 @@ pub fn parse(args: &[String]) -> Cli { fansetrpm: None, autofanctrl: None, pdports: false, + pdports_cypd: false, pd_info: false, pd_reset: None, pd_disable: None, @@ -224,6 +225,9 @@ pub fn parse(args: &[String]) -> Cli { } else if arg == "--pdports" { cli.pdports = true; found_an_option = true; + } else if arg == "--pdports-cypd" { + cli.pdports_cypd = true; + found_an_option = true; } else if arg == "--allupdate" { cli.allupdate = true; found_an_option = true; diff --git a/framework_lib/src/power.rs b/framework_lib/src/power.rs index 679d2d6..5dc50f0 100644 --- a/framework_lib/src/power.rs +++ b/framework_lib/src/power.rs @@ -718,6 +718,151 @@ pub fn get_pd_info(ec: &CrosEc, ports: u8) -> Vec> { info } +#[derive(Debug)] +enum CypdTypeCState { + Nothing, + Sink, + Source, + Debug, + Audio, + PoweredAccessory, + Unsupported, + Invalid, +} + +impl From for CypdTypeCState { + fn from(v: u8) -> Self { + match v { + 0 => CypdTypeCState::Nothing, + 1 => CypdTypeCState::Sink, + 2 => CypdTypeCState::Source, + 3 => CypdTypeCState::Debug, + 4 => CypdTypeCState::Audio, + 5 => CypdTypeCState::PoweredAccessory, + 6 => CypdTypeCState::Unsupported, + _ => CypdTypeCState::Invalid, + } + } +} + +#[derive(Debug)] +enum CypdPdPowerRole { + Sink, + Source, + Unknown, +} + +impl From for CypdPdPowerRole { + fn from(v: u8) -> Self { + match v { + 0 => CypdPdPowerRole::Sink, + 1 => CypdPdPowerRole::Source, + _ => CypdPdPowerRole::Unknown, + } + } +} + +#[derive(Debug)] +enum CypdPdDataRole { + Ufp, + Dfp, + Disconnected, + Unknown, +} + +impl From for CypdPdDataRole { + fn from(v: u8) -> Self { + match v { + 0 => CypdPdDataRole::Ufp, + 1 => CypdPdDataRole::Dfp, + 2 => CypdPdDataRole::Disconnected, + _ => CypdPdDataRole::Unknown, + } + } +} + +pub fn get_and_print_cypd_pd_info(ec: &CrosEc) { + let fl16 = Some(PlatformFamily::Framework16) == smbios::get_family(); + let ports = 4u8; + + for port in 0..ports { + println!( + "USB-C Port {} ({}):", + port, + match port { + 0 => "Right Front", + 1 => + if fl16 { + "Right Middle" + } else { + "Right Back" + }, + 2 => + if fl16 { + "Left Middle" + } else { + "Left Back" + }, + 3 => "Left Front", + _ => "??", + } + ); + + let result = EcRequestGetPdPortState { port }.send_command(ec); + match result { + Ok(info) => { + let c_state = CypdTypeCState::from(info.c_state); + let power_role = CypdPdPowerRole::from(info.power_role); + let data_role = CypdPdDataRole::from(info.data_role); + let voltage = { info.voltage }; + let current = { info.current }; + let watts_mw = voltage as u32 * current as u32 / 1000; + + println!(" Type-C State: {:?}", c_state); + println!( + " PD Contract: {}", + if info.pd_state != 0 { "Yes" } else { "No" } + ); + println!(" Power Role: {:?}", power_role); + println!(" Data Role: {:?}", data_role); + println!( + " VCONN: {}", + if info.vconn != 0 { "On" } else { "Off" } + ); + println!( + " Voltage: {}.{:03} V", + voltage / 1000, + voltage % 1000 + ); + println!(" Current: {} mA", current); + println!(" Power: {}.{} W", watts_mw / 1000, watts_mw % 1000); + println!( + " EPR: {}{}", + if info.epr_active != 0 { + "Active" + } else { + "Inactive" + }, + if info.epr_support != 0 { + " (Supported)" + } else { + "" + } + ); + println!(" CC Polarity: CC{}", info.cc_polarity + 1); + println!( + " Active Port: {}", + if info.active_port != 0 { "Yes" } else { "No" } + ); + println!(" Alt Mode: 0x{:02X}", info.pd_alt_mode_status); + } + Err(e) => { + print_err::<()>(Err(e)); + } + } + } +} + pub fn get_and_print_pd_info(ec: &CrosEc) { let fl16 = Some(PlatformFamily::Framework16) == smbios::get_family(); let ports = 4; // All our platforms have 4 PD ports so far diff --git a/framework_tool/completions/bash/framework_tool b/framework_tool/completions/bash/framework_tool index 968a93c..1072370 100755 --- a/framework_tool/completions/bash/framework_tool +++ b/framework_tool/completions/bash/framework_tool @@ -23,7 +23,7 @@ _framework_tool() { case "${cmd}" in framework_tool) - opts="-v -q -t -f -h --flash-gpu-descriptor --verbose --quiet --versions --version --features --esrt --device --compare-version --power --thermal --sensors --fansetduty --fansetrpm --autofanctrl --pdports --info --meinfo --pd-info --pd-reset --pd-disable --pd-enable --dp-hdmi-info --dp-hdmi-update --audio-card-info --privacy --pd-bin --ec-bin --capsule --dump --h2o-capsule --dump-ec-flash --flash-full-ec --flash-ec --flash-ro-ec --flash-rw-ec --intrusion --inputdeck --inputdeck-mode --expansion-bay --charge-limit --charge-current-limit --charge-rate-limit --get-gpio --fp-led-level --fp-brightness --kblight --remap-key --rgbkbd --ps2-enable --tablet-mode --touchscreen-enable --stylus-battery --console --reboot-ec --ec-hib-delay --uptimeinfo --s0ix-counter --hash --driver --pd-addrs --pd-ports --test --test-retimer --boardid --force --dry-run --flash-gpu-descriptor-file --dump-gpu-descriptor-file --nvidia --host-command --generate-completions --help" + opts="-v -q -t -f -h --flash-gpu-descriptor --verbose --quiet --versions --version --features --esrt --device --compare-version --power --thermal --sensors --fansetduty --fansetrpm --autofanctrl --pdports --pdports-cypd --info --meinfo --pd-info --pd-reset --pd-disable --pd-enable --dp-hdmi-info --dp-hdmi-update --audio-card-info --privacy --pd-bin --ec-bin --capsule --dump --h2o-capsule --dump-ec-flash --flash-full-ec --flash-ec --flash-ro-ec --flash-rw-ec --intrusion --inputdeck --inputdeck-mode --expansion-bay --charge-limit --charge-current-limit --charge-rate-limit --get-gpio --fp-led-level --fp-brightness --kblight --remap-key --rgbkbd --ps2-enable --tablet-mode --touchscreen-enable --stylus-battery --console --reboot-ec --ec-hib-delay --uptimeinfo --s0ix-counter --hash --driver --pd-addrs --pd-ports --test --test-retimer --boardid --force --dry-run --flash-gpu-descriptor-file --dump-gpu-descriptor-file --nvidia --host-command --generate-completions --help" if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 diff --git a/framework_tool/completions/fish/framework_tool.fish b/framework_tool/completions/fish/framework_tool.fish index 7ae87da..ac51168 100644 --- a/framework_tool/completions/fish/framework_tool.fish +++ b/framework_tool/completions/fish/framework_tool.fish @@ -81,6 +81,7 @@ complete -c framework_tool -l power -d 'Show current power status of battery and complete -c framework_tool -l thermal -d 'Print thermal information (Temperatures and Fan speed)' complete -c framework_tool -l sensors -d 'Print sensor information (ALS, G-Sensor)' complete -c framework_tool -l pdports -d 'Show information about USB-C PD ports' +complete -c framework_tool -l pdports-cypd -d 'Show CYPD PD port state (Framework-specific)' complete -c framework_tool -l info -d 'Show info from SMBIOS (Only on UEFI)' complete -c framework_tool -l pd-info -d 'Show details about the PD controllers' complete -c framework_tool -l dp-hdmi-info -d 'Show details about connected DP or HDMI Expansion Cards' diff --git a/framework_tool/completions/zsh/_framework_tool b/framework_tool/completions/zsh/_framework_tool index aeeedb7..270c653 100644 --- a/framework_tool/completions/zsh/_framework_tool +++ b/framework_tool/completions/zsh/_framework_tool @@ -72,6 +72,7 @@ _framework_tool() { '--thermal[Print thermal information (Temperatures and Fan speed)]' \ '--sensors[Print sensor information (ALS, G-Sensor)]' \ '--pdports[Show information about USB-C PD ports]' \ +'--pdports-cypd[Show CYPD PD port state (Framework-specific)]' \ '--info[Show info from SMBIOS (Only on UEFI)]' \ '--pd-info[Show details about the PD controllers]' \ '--dp-hdmi-info[Show details about connected DP or HDMI Expansion Cards]' \ From 424060ff5f3c27a018f73ba2794255ea5c1eab28 Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Mon, 30 Mar 2026 11:07:20 +0800 Subject: [PATCH 2/7] --pdports: Hide CC if not connected It's not meaningful if no cable/device is connected Signed-off-by: Daniel Schaefer --- framework_lib/src/power.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/framework_lib/src/power.rs b/framework_lib/src/power.rs index 5dc50f0..3e22a1a 100644 --- a/framework_lib/src/power.rs +++ b/framework_lib/src/power.rs @@ -812,6 +812,7 @@ pub fn get_and_print_cypd_pd_info(ec: &CrosEc) { match result { Ok(info) => { let c_state = CypdTypeCState::from(info.c_state); + let connected = !matches!(c_state, CypdTypeCState::Nothing); let power_role = CypdPdPowerRole::from(info.power_role); let data_role = CypdPdDataRole::from(info.data_role); let voltage = { info.voltage }; @@ -849,7 +850,18 @@ pub fn get_and_print_cypd_pd_info(ec: &CrosEc) { "" } ); - println!(" CC Polarity: CC{}", info.cc_polarity + 1); + if connected { + println!( + " CC Polarity: {}", + match info.cc_polarity { + 0 => "CC1", + 1 => "CC2", + 2 => "CC1 (Debug)", + 3 => "CC2 (Debug)", + _ => "Unknown", + } + ); + } println!( " Active Port: {}", if info.active_port != 0 { "Yes" } else { "No" } From 77699ab2bb83edb7ecb17bfcab8d9431cc9876b7 Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Mon, 30 Mar 2026 11:07:52 +0800 Subject: [PATCH 3/7] --pdports: Show V,A,W as negotiated Misleading previously, because it's not instantenous measurements. Signed-off-by: Daniel Schaefer --- framework_lib/src/power.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/framework_lib/src/power.rs b/framework_lib/src/power.rs index 3e22a1a..f55f5a2 100644 --- a/framework_lib/src/power.rs +++ b/framework_lib/src/power.rs @@ -831,12 +831,13 @@ pub fn get_and_print_cypd_pd_info(ec: &CrosEc) { if info.vconn != 0 { "On" } else { "Off" } ); println!( - " Voltage: {}.{:03} V", + " Negotiated: {}.{:03} V, {} mA, {}.{} W", voltage / 1000, - voltage % 1000 + voltage % 1000, + current, + watts_mw / 1000, + watts_mw % 1000, ); - println!(" Current: {} mA", current); - println!(" Power: {}.{} W", watts_mw / 1000, watts_mw % 1000); println!( " EPR: {}{}", if info.epr_active != 0 { From 7bc597c75be6c2666b77e585ed2955da6f511002 Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Mon, 30 Mar 2026 11:08:17 +0800 Subject: [PATCH 4/7] --pdports: Decode DP alt mode bits Signed-off-by: Daniel Schaefer --- framework_lib/src/power.rs | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/framework_lib/src/power.rs b/framework_lib/src/power.rs index f55f5a2..84de225 100644 --- a/framework_lib/src/power.rs +++ b/framework_lib/src/power.rs @@ -867,7 +867,35 @@ pub fn get_and_print_cypd_pd_info(ec: &CrosEc) { " Active Port: {}", if info.active_port != 0 { "Yes" } else { "No" } ); - println!(" Alt Mode: 0x{:02X}", info.pd_alt_mode_status); + let alt = info.pd_alt_mode_status; + if connected && alt != 0 { + let mut modes = vec![]; + if alt & 0x01 != 0 { + modes.push("DFP_D Connected"); + } + if alt & 0x02 != 0 { + modes.push("UFP_D Connected"); + } + if alt & 0x04 != 0 { + modes.push("Power Low"); + } + if alt & 0x08 != 0 { + modes.push("Enabled"); + } + if alt & 0x10 != 0 { + modes.push("Multi-Function"); + } + if alt & 0x20 != 0 { + modes.push("USB Config"); + } + if alt & 0x40 != 0 { + modes.push("Exit Request"); + } + if alt & 0x80 != 0 { + modes.push("HPD High"); + } + println!(" DP Alt Mode: {} (0x{:02X})", modes.join(", "), alt); + } } Err(e) => { print_err::<()>(Err(e)); From 159f0b20ce89027a078502940e2d062d11e96aa1 Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Mon, 30 Mar 2026 11:17:21 +0800 Subject: [PATCH 5/7] Rename --pdports and add --pdports-chromebook Signed-off-by: Daniel Schaefer --- EXAMPLES.md | 2 +- framework_lib/src/commandline/clap_std.rs | 8 ++++---- framework_lib/src/commandline/mod.rs | 12 ++++++------ framework_lib/src/commandline/uefi.rs | 6 +++--- framework_tool/completions/bash/framework_tool | 2 +- framework_tool/completions/fish/framework_tool.fish | 4 ++-- framework_tool/completions/zsh/_framework_tool | 4 ++-- 7 files changed, 19 insertions(+), 19 deletions(-) diff --git a/EXAMPLES.md b/EXAMPLES.md index eda71ae..2ca3876 100644 --- a/EXAMPLES.md +++ b/EXAMPLES.md @@ -40,7 +40,7 @@ Options: --autofanctrl Turn on automatic fan speed control --pdports - Show information about USB-C PD ports + Show USB-C PD port state --info Show info from SMBIOS (Only on UEFI) --pd-info diff --git a/framework_lib/src/commandline/clap_std.rs b/framework_lib/src/commandline/clap_std.rs index 4b44142..829b27d 100644 --- a/framework_lib/src/commandline/clap_std.rs +++ b/framework_lib/src/commandline/clap_std.rs @@ -74,13 +74,13 @@ struct ClapCli { #[arg(long)] autofanctrl: Option>, - /// Show information about USB-C PD ports + /// Show USB-C PD port state #[arg(long)] pdports: bool, - /// Show CYPD PD port state (Framework-specific) + /// Show PD port info (generic Chromium EC) #[arg(long)] - pdports_cypd: bool, + pdports_chromebook: bool, /// Show info from SMBIOS (Only on UEFI) #[arg(long)] @@ -479,7 +479,7 @@ pub fn parse(args: &[String]) -> Cli { fansetrpm, autofanctrl: args.autofanctrl, pdports: args.pdports, - pdports_cypd: args.pdports_cypd, + pdports_chromebook: args.pdports_chromebook, pd_info: args.pd_info, pd_reset: args.pd_reset, pd_disable: args.pd_disable, diff --git a/framework_lib/src/commandline/mod.rs b/framework_lib/src/commandline/mod.rs index b7681d1..d965b67 100644 --- a/framework_lib/src/commandline/mod.rs +++ b/framework_lib/src/commandline/mod.rs @@ -171,7 +171,7 @@ pub struct Cli { pub fansetrpm: Option<(Option, u32)>, pub autofanctrl: Option>, pub pdports: bool, - pub pdports_cypd: bool, + pub pdports_chromebook: bool, pub privacy: bool, pub pd_info: bool, pub pd_reset: Option, @@ -261,7 +261,7 @@ pub fn parse(args: &[String]) -> Cli { // fansetrpm // autofanctrl pdports: cli.pdports, - pdports_cypd: cli.pdports_cypd, + pdports_chromebook: cli.pdports_chromebook, privacy: cli.privacy, pd_info: cli.version, // pd_reset @@ -1551,9 +1551,9 @@ pub fn run_with_args(args: &Cli, _allupdate: bool) -> i32 { } else if let Some(None) = args.autofanctrl { print_err(ec.autofanctrl(None)); } else if args.pdports { - power::get_and_print_pd_info(&ec); - } else if args.pdports_cypd { power::get_and_print_cypd_pd_info(&ec); + } else if args.pdports_chromebook { + power::get_and_print_pd_info(&ec); } else if args.info { smbios_info(); } else if let Some(dump_path) = &args.meinfo { @@ -1844,8 +1844,8 @@ Options: --fansetduty Set fan duty cycle (0-100%) --fansetrpm Set fan RPM (limited by EC fan table max RPM) --autofanctrl []Turn on automatic fan speed control (optionally provide fan index) - --pdports Show information about USB-C PD ports - --pdports-cypd Show CYPD PD port state (Framework-specific) + --pdports Show USB-C PD port state + --pdports-chromebook Show PD port info (generic Chromium EC) --info Show info from SMBIOS (Only on UEFI) --meinfo [] Show Intel ME information (from SMBIOS type 0xDB) --pd-info Show details about the PD controllers diff --git a/framework_lib/src/commandline/uefi.rs b/framework_lib/src/commandline/uefi.rs index 6ab9382..e86c517 100644 --- a/framework_lib/src/commandline/uefi.rs +++ b/framework_lib/src/commandline/uefi.rs @@ -46,7 +46,7 @@ pub fn parse(args: &[String]) -> Cli { fansetrpm: None, autofanctrl: None, pdports: false, - pdports_cypd: false, + pdports_chromebook: false, pd_info: false, pd_reset: None, pd_disable: None, @@ -225,8 +225,8 @@ pub fn parse(args: &[String]) -> Cli { } else if arg == "--pdports" { cli.pdports = true; found_an_option = true; - } else if arg == "--pdports-cypd" { - cli.pdports_cypd = true; + } else if arg == "--pdports-chromebook" { + cli.pdports_chromebook = true; found_an_option = true; } else if arg == "--allupdate" { cli.allupdate = true; diff --git a/framework_tool/completions/bash/framework_tool b/framework_tool/completions/bash/framework_tool index 1072370..8a3d515 100755 --- a/framework_tool/completions/bash/framework_tool +++ b/framework_tool/completions/bash/framework_tool @@ -23,7 +23,7 @@ _framework_tool() { case "${cmd}" in framework_tool) - opts="-v -q -t -f -h --flash-gpu-descriptor --verbose --quiet --versions --version --features --esrt --device --compare-version --power --thermal --sensors --fansetduty --fansetrpm --autofanctrl --pdports --pdports-cypd --info --meinfo --pd-info --pd-reset --pd-disable --pd-enable --dp-hdmi-info --dp-hdmi-update --audio-card-info --privacy --pd-bin --ec-bin --capsule --dump --h2o-capsule --dump-ec-flash --flash-full-ec --flash-ec --flash-ro-ec --flash-rw-ec --intrusion --inputdeck --inputdeck-mode --expansion-bay --charge-limit --charge-current-limit --charge-rate-limit --get-gpio --fp-led-level --fp-brightness --kblight --remap-key --rgbkbd --ps2-enable --tablet-mode --touchscreen-enable --stylus-battery --console --reboot-ec --ec-hib-delay --uptimeinfo --s0ix-counter --hash --driver --pd-addrs --pd-ports --test --test-retimer --boardid --force --dry-run --flash-gpu-descriptor-file --dump-gpu-descriptor-file --nvidia --host-command --generate-completions --help" + opts="-v -q -t -f -h --flash-gpu-descriptor --verbose --quiet --versions --version --features --esrt --device --compare-version --power --thermal --sensors --fansetduty --fansetrpm --autofanctrl --pdports --pdports-chromebook --info --meinfo --pd-info --pd-reset --pd-disable --pd-enable --dp-hdmi-info --dp-hdmi-update --audio-card-info --privacy --pd-bin --ec-bin --capsule --dump --h2o-capsule --dump-ec-flash --flash-full-ec --flash-ec --flash-ro-ec --flash-rw-ec --intrusion --inputdeck --inputdeck-mode --expansion-bay --charge-limit --charge-current-limit --charge-rate-limit --get-gpio --fp-led-level --fp-brightness --kblight --remap-key --rgbkbd --ps2-enable --tablet-mode --touchscreen-enable --stylus-battery --console --reboot-ec --ec-hib-delay --uptimeinfo --s0ix-counter --hash --driver --pd-addrs --pd-ports --test --test-retimer --boardid --force --dry-run --flash-gpu-descriptor-file --dump-gpu-descriptor-file --nvidia --host-command --generate-completions --help" if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 diff --git a/framework_tool/completions/fish/framework_tool.fish b/framework_tool/completions/fish/framework_tool.fish index ac51168..47df44a 100644 --- a/framework_tool/completions/fish/framework_tool.fish +++ b/framework_tool/completions/fish/framework_tool.fish @@ -80,8 +80,8 @@ complete -c framework_tool -l esrt -d 'Display the UEFI ESRT table' complete -c framework_tool -l power -d 'Show current power status of battery and AC (Add -vv for more details)' complete -c framework_tool -l thermal -d 'Print thermal information (Temperatures and Fan speed)' complete -c framework_tool -l sensors -d 'Print sensor information (ALS, G-Sensor)' -complete -c framework_tool -l pdports -d 'Show information about USB-C PD ports' -complete -c framework_tool -l pdports-cypd -d 'Show CYPD PD port state (Framework-specific)' +complete -c framework_tool -l pdports -d 'Show USB-C PD port state' +complete -c framework_tool -l pdports-chromebook -d 'Show PD port info (generic Chromium EC)' complete -c framework_tool -l info -d 'Show info from SMBIOS (Only on UEFI)' complete -c framework_tool -l pd-info -d 'Show details about the PD controllers' complete -c framework_tool -l dp-hdmi-info -d 'Show details about connected DP or HDMI Expansion Cards' diff --git a/framework_tool/completions/zsh/_framework_tool b/framework_tool/completions/zsh/_framework_tool index 270c653..cb3230d 100644 --- a/framework_tool/completions/zsh/_framework_tool +++ b/framework_tool/completions/zsh/_framework_tool @@ -71,8 +71,8 @@ _framework_tool() { '--power[Show current power status of battery and AC (Add -vv for more details)]' \ '--thermal[Print thermal information (Temperatures and Fan speed)]' \ '--sensors[Print sensor information (ALS, G-Sensor)]' \ -'--pdports[Show information about USB-C PD ports]' \ -'--pdports-cypd[Show CYPD PD port state (Framework-specific)]' \ +'--pdports[Show USB-C PD port state]' \ +'--pdports-chromebook[Show PD port info (generic Chromium EC)]' \ '--info[Show info from SMBIOS (Only on UEFI)]' \ '--pd-info[Show details about the PD controllers]' \ '--dp-hdmi-info[Show details about connected DP or HDMI Expansion Cards]' \ From 5ef3c163cc3b0c275198d980e6e463e32bca7be3 Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Mon, 30 Mar 2026 11:31:17 +0800 Subject: [PATCH 6/7] --pdports: Add examples Signed-off-by: Daniel Schaefer --- EXAMPLES.md | 107 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) diff --git a/EXAMPLES.md b/EXAMPLES.md index 2ca3876..be79a3c 100644 --- a/EXAMPLES.md +++ b/EXAMPLES.md @@ -719,3 +719,110 @@ It's not controlled by the EC, use https://keyboard.frame.work. Mostly for debugging firmware. See [EXAMPLES_ADVANCED.md](EXAMPLES_ADVANCED.md) + +## PD Ports + +### Power Adapters + +A 240W EPR (Framework) power adapter connected. +Alongside a 65W SDR adapter - which is not active, because the EC firmware switches to the higher power adapter. + +``` +USB-C Port 0 (Right Back): + Type-C State: Source + PD Contract: Yes + Power Role: Sink + Data Role: Dfp + VCONN: Off + Negotiated: 48.000 V, 5000 mA, 240.0 W + EPR: Active (Supported) + CC Polarity: CC1 + Active Port: Yes +USB-C Port 1 (Right Middle): + Type-C State: Source + PD Contract: Yes + Power Role: Sink + Data Role: Ufp + VCONN: Off + Negotiated: 20.000 V, 3000 mA, 60.0 W + EPR: Inactive + CC Polarity: CC1 + Active Port: No +``` + +A 100W SDR power adapter connected: + +``` +USB-C Port 0 (Right Back): + Type-C State: Source + PD Contract: Yes + Power Role: Sink + Data Role: Ufp + VCONN: Off + Negotiated: 20.000 V, 5000 mA, 100.0 W + EPR: Inactive + CC Polarity: CC1 + Active Port: Yes +``` + +A 65W (Framework) power adapter connected: + +``` +USB-C Port 0 (Right Back): + Type-C State: Source + PD Contract: Yes + Power Role: Sink + Data Role: Dfp + VCONN: On + Negotiated: 20.000 V, 3250 mA, 65.0 W + EPR: Inactive + CC Polarity: CC2 + Active Port: Yes +``` + +### Devices + +A USB2/3 device connected (even USB-A Expansion Card): + +``` +USB-C Port 2 (Left Middle): + Type-C State: Sink + PD Contract: No + Power Role: Source + Data Role: Dfp + VCONN: Off + Negotiated: 5.000 V, 3000 mA, 15.0 W + EPR: Inactive + CC Polarity: CC1 + Active Port: No +``` + +A Display connected through Framework DisplayPort Expansion card: + +``` +USB-C Port 1 (Right Middle): + Type-C State: Sink + PD Contract: Yes + Power Role: Source + Data Role: Dfp + VCONN: On + Negotiated: 5.000 V, 410 mA, 2.50 W + EPR: Inactive + CC Polarity: CC1 + Active Port: No + DP Alt Mode: DFP_D Connected, HPD High (0x81) +``` + +Nothing connected (or Type-C Expansion Card): + +``` +USB-C Port 3 (Left Back): + Type-C State: Nothing + PD Contract: No + Power Role: Sink + Data Role: Ufp + VCONN: Off + Negotiated: 0.000 V, 0 mA, 0.0 W + EPR: Inactive + Active Port: No +``` From 3f593a1e23cf52fbdd02b5d92a21bbf53faeaf73 Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Mon, 30 Mar 2026 11:32:16 +0800 Subject: [PATCH 7/7] --pdports: Only show alt mode bits if DP is active I noticed that the HPD bit was set even on some adapters Signed-off-by: Daniel Schaefer --- framework_lib/src/power.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/framework_lib/src/power.rs b/framework_lib/src/power.rs index 84de225..7219ee7 100644 --- a/framework_lib/src/power.rs +++ b/framework_lib/src/power.rs @@ -868,7 +868,9 @@ pub fn get_and_print_cypd_pd_info(ec: &CrosEc) { if info.active_port != 0 { "Yes" } else { "No" } ); let alt = info.pd_alt_mode_status; - if connected && alt != 0 { + // Bits 0-1 indicate DP alt mode is active (bit 0 = DFP_D/TBT, + // bit 1 = UFP_D). Only show when actually in DP alt mode. + if connected && (alt & 0x03) != 0 { let mut modes = vec![]; if alt & 0x01 != 0 { modes.push("DFP_D Connected");