Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion examples/rt685s-evk/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 29 additions & 0 deletions src/asynchronous/embassy/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,14 @@ impl<'a, M: RawMutex, B: I2c> Tps6699x<'a, M, B> {
inner.set_sx_app_config(port, state).await
}

/// Get the discovered SVIDs on a port returned from `Discover SVIDs REQ` messages.
pub async fn get_discovered_svids(
&mut self,
port: LocalPortId,
) -> Result<registers::discovered_svids::DiscoveredSvids, Error<B::Error>> {
self.lock_inner().await.get_discovered_svids(port).await
}

/// Get Rx ADO
pub async fn get_rx_ado(
&mut self,
Expand Down Expand Up @@ -706,6 +714,22 @@ impl<'a, M: RawMutex, B: I2c> Tps6699x<'a, M, B> {
self.lock_inner().await.modify_tx_identity(port, f).await
}

/// Get the latest received SOP identity data
pub async fn get_received_sop_identity_data(
&mut self,
port: LocalPortId,
) -> Result<registers::received_sop_identity_data::ReceivedSopIdentityData, Error<B::Error>> {
self.lock_inner().await.get_received_sop_identity_data(port).await
}

/// Get the latest received SOP Prime identity data
pub async fn get_received_sop_prime_identity_data(
&mut self,
port: LocalPortId,
) -> Result<registers::received_sop_prime_identity_data::ReceivedSopPrimeIdentityData, Error<B::Error>> {
self.lock_inner().await.get_received_sop_prime_identity_data(port).await
}

/// Get DP config
pub async fn get_dp_config(
&mut self,
Expand Down Expand Up @@ -740,6 +764,11 @@ impl<'a, M: RawMutex, B: I2c> Tps6699x<'a, M, B> {
self.execute_command(port, Command::Drst, None, None).await
}

/// Execute the [`Command::HRST`] command.
pub async fn execute_hrst(&mut self, port: LocalPortId) -> Result<ReturnValue, Error<B::Error>> {
self.execute_command(port, Command::HRST, None, None).await
}

/// Get Rx discovered custom modes
pub async fn execute_gcdm(
&mut self,
Expand Down
55 changes: 55 additions & 0 deletions src/asynchronous/internal/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -598,6 +598,25 @@ impl<B: I2c> Tps6699x<B> {
.await
}

/// Get the discovered SVIDs on a port returned from `Discover SVIDs REQ` messages.
pub async fn get_discovered_svids(
&mut self,
port: LocalPortId,
) -> Result<registers::discovered_svids::DiscoveredSvids, Error<B::Error>> {
let mut buf = [0u8; registers::discovered_svids::LEN];
self.borrow_port(port)?
.into_registers()
.interface()
.read_register(
registers::discovered_svids::ADDR,
(registers::discovered_svids::LEN * 8) as u32,
&mut buf,
)
.await?;

Ok(buf.into())
}

/// Get Rx ADO
pub async fn get_rx_ado(&mut self, port: LocalPortId) -> Result<registers::field_sets::RxAdo, Error<B::Error>> {
self.borrow_port(port)?.into_registers().rx_ado().read_async().await
Expand Down Expand Up @@ -753,6 +772,42 @@ impl<B: I2c> Tps6699x<B> {
self.set_tx_identity(port, reg.clone()).await?;
Ok(reg)
}

/// Get the latest received SOP identity data
pub async fn get_received_sop_identity_data(
&mut self,
port: LocalPortId,
) -> Result<registers::received_sop_identity_data::ReceivedSopIdentityData, Error<B::Error>> {
let mut buf = [0u8; registers::received_sop_identity_data::LEN];
self.borrow_port(port)?
.into_registers()
.interface()
.read_register(
registers::received_sop_identity_data::ADDR,
(registers::received_sop_identity_data::LEN * 8) as u32,
&mut buf,
)
.await?;
Ok(buf.into())
}

/// Get the latest received SOP Prime identity data
pub async fn get_received_sop_prime_identity_data(
&mut self,
port: LocalPortId,
) -> Result<registers::received_sop_prime_identity_data::ReceivedSopPrimeIdentityData, Error<B::Error>> {
let mut buf = [0u8; registers::received_sop_prime_identity_data::LEN];
self.borrow_port(port)?
.into_registers()
.interface()
.read_register(
registers::received_sop_prime_identity_data::ADDR,
(registers::received_sop_prime_identity_data::LEN * 8) as u32,
&mut buf,
)
.await?;
Ok(buf.into())
}
}

#[cfg(test)]
Expand Down
2 changes: 1 addition & 1 deletion src/command/gcdm.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//! Get custom discovered modes command
use embedded_usb_pd::vdm::Svid;
use embedded_usb_pd::vdm::structured::Svid;

/// Input data length
pub const INPUT_LEN: usize = 3;
Expand Down
12 changes: 12 additions & 0 deletions src/command/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,15 @@ pub enum Command {
/// [`ReturnValue`]
Drst = u32_from_str(*b"DRST"),

/// Hard Reset
///
/// # Input
/// None
///
/// # Output
/// [`ReturnValue`]
HRST = u32_from_str(*b"HRST"),

/// Send VDM.
///
/// # Input
Expand Down Expand Up @@ -170,6 +179,8 @@ impl TryFrom<u32> for Command {
Ok(Command::Muxr)
} else if Command::Drst == value {
Ok(Command::Drst)
} else if Command::HRST == value {
Ok(Command::HRST)
} else if Command::VDMs == value {
Ok(Command::VDMs)
} else if Command::Ucsi == value {
Expand Down Expand Up @@ -718,6 +729,7 @@ mod test {
assert_eq!(Command::try_from(Command::Dbfg as u32).unwrap(), Command::Dbfg);
assert_eq!(Command::try_from(Command::Muxr as u32).unwrap(), Command::Muxr);
assert_eq!(Command::try_from(Command::Drst as u32).unwrap(), Command::Drst);
assert_eq!(Command::try_from(Command::HRST as u32).unwrap(), Command::HRST);
assert_eq!(Command::try_from(Command::VDMs as u32).unwrap(), Command::VDMs);
assert_eq!(Command::try_from(Command::Ucsi as u32).unwrap(), Command::Ucsi);
assert_eq!(Command::try_from(0xFFFFFFFFu32), Err(PdError::InvalidParams));
Expand Down
210 changes: 210 additions & 0 deletions src/registers/discovered_svids.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
//! Discovered SVIDs register (`0x21`).
//!
//! This register's size exceeds the maximum supported length by the [`device_driver`] crate.
//!
//! This register contains the SVID information returned from `Discover SVIDs REQ` messages.

use bitfield::bitfield;
use embedded_usb_pd::vdm::structured::Svid;

/// The address of the `Discovered SVIDs` register.
pub const ADDR: u8 = 0x21;

/// The length of the `Discovered SVIDs` register, in bytes.
///
/// This exceeds the maximum supported length by the [`device_driver`] crate.
pub const LEN: usize = 264 / 8;

bitfield! {
/// Discovered SVIDs register.
#[derive(Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
struct Raw([u8]);
impl Debug;
Comment thread
asasine marked this conversation as resolved.

/// Number of SVIDs discovered on SOP.
pub u8, number_sop_svids, set_number_sop_svids: 3, 0;
/// Number of SVIDs discovered on SOP'.
pub u8, number_sop_prime_svids, set_number_sop_prime_svids: 7, 4;

/// First SVID supported by SOP port partner.
pub u16, svid_sop0, set_svid_sop0: 23, 8;

/// Second SVID supported by SOP port partner.
pub u16, svid_sop1, set_svid_sop1: 39, 24;

/// Third SVID supported by SOP port partner.
pub u16, svid_sop2, set_svid_sop2: 55, 40;

/// Fourth SVID supported by SOP port partner.
pub u16, svid_sop3, set_svid_sop3: 71, 56;

/// Fifth SVID supported by SOP port partner.
pub u16, svid_sop4, set_svid_sop4: 87, 72;

/// Sixth SVID supported by SOP port partner.
pub u16, svid_sop5, set_svid_sop5: 103, 88;

/// Seventh SVID supported by SOP port partner.
pub u16, svid_sop6, set_svid_sop6: 119, 104;

/// Eighth SVID supported by SOP port partner.
pub u16, svid_sop7, set_svid_sop7: 135, 120;

/// First SVID supported by SOP' cable plug
pub u16, svid_sop_prime0, set_svid_sop_prime0: 151, 136;

/// Second SVID supported by SOP' cable plug
pub u16, svid_sop_prime1, set_svid_sop_prime1: 167, 152;

/// Third SVID supported by SOP' cable plug
pub u16, svid_sop_prime2, set_svid_sop_prime2: 183, 168;

/// Fourth SVID supported by SOP' cable plug
pub u16, svid_sop_prime3, set_svid_sop_prime3: 199, 184;

/// Fifth SVID supported by SOP' cable plug
pub u16, svid_sop_prime4, set_svid_sop_prime4: 215, 200;

/// Sixth SVID supported by SOP' cable plug
pub u16, svid_sop_prime5, set_svid_sop_prime5: 231, 216;

/// Seventh SVID supported by SOP' cable plug
pub u16, svid_sop_prime6, set_svid_sop_prime6: 247, 232;

/// Eighth SVID supported by SOP' cable plug
pub u16, svid_sop_prime7, set_svid_sop_prime7: 263, 248;
}

/// Discovered SVIDs register, containing the SVID information returned from `Discover SVIDs REQ` messages.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct DiscoveredSvids(Raw<[u8; LEN]>);

impl DiscoveredSvids {
pub const DEFAULT: Self = Self(Raw([0; LEN]));

/// Returns the number of SVIDs discovered on the SOP port partner.
pub fn number_sop_svids(&self) -> usize {
self.0.number_sop_svids() as usize
}
Comment thread
asasine marked this conversation as resolved.

/// Returns an iterator over the SVIDs discovered on the SOP port partner.
///
/// This will return at most 8 SVIDs, even if [`Self::number_sop_svids`] returns
/// a larger number. Neither the data sheet nor the USB PD specification explicitly
/// state that there can be at most 8 SVIDs, but the register only has space
/// for 8.
pub fn svid_sop(&self) -> impl ExactSizeIterator<Item = Svid> {
[
self.0.svid_sop0(),
self.0.svid_sop1(),
self.0.svid_sop2(),
self.0.svid_sop3(),
self.0.svid_sop4(),
self.0.svid_sop5(),
self.0.svid_sop6(),
self.0.svid_sop7(),
]
.into_iter()
.take(self.number_sop_svids())
.map(Svid)
}

/// Returns the number of SVIDs discovered on the SOP' cable plug.
pub fn number_sop_prime_svids(&self) -> usize {
self.0.number_sop_prime_svids() as usize
Comment thread
asasine marked this conversation as resolved.
}

/// Returns an iterator over the SVIDs discovered on the SOP' cable plug.
///
/// This will return at most 8 SVIDs, even if [`Self::number_sop_prime_svids`]
/// returns a larger number. Neither the data sheet nor the USB PD specification
/// explicitly state that there can be at most 8 SVIDs, but the register only
/// has space for 8.
pub fn svid_sop_prime(&self) -> impl ExactSizeIterator<Item = Svid> {
[
self.0.svid_sop_prime0(),
self.0.svid_sop_prime1(),
self.0.svid_sop_prime2(),
self.0.svid_sop_prime3(),
self.0.svid_sop_prime4(),
self.0.svid_sop_prime5(),
self.0.svid_sop_prime6(),
self.0.svid_sop_prime7(),
]
.into_iter()
.take(self.number_sop_prime_svids())
.map(Svid)
}
}

impl Default for DiscoveredSvids {
fn default() -> Self {
Self::DEFAULT
}
}

impl From<[u8; LEN]> for DiscoveredSvids {
fn from(raw: [u8; LEN]) -> Self {
Self(Raw(raw))
}
}

#[cfg(test)]
mod tests {
use super::*;
extern crate std;
use std::vec;
use std::vec::Vec;

#[test]
fn impl_iterators() {
let mut reg = DiscoveredSvids::default();

reg.0.set_number_sop_svids(3);
reg.0.set_svid_sop0(0x1234);
reg.0.set_svid_sop1(0x5678);
reg.0.set_svid_sop2(0x9ABC);

reg.0.set_number_sop_prime_svids(2);
reg.0.set_svid_sop_prime0(0xDEF0);
reg.0.set_svid_sop_prime1(0xFFFF);

assert_eq!(reg.number_sop_svids(), 3);
assert_eq!(
reg.svid_sop().collect::<Vec<_>>(),
vec![Svid(0x1234), Svid(0x5678), Svid(0x9ABC)]
);

assert_eq!(reg.number_sop_prime_svids(), 2);
assert_eq!(
reg.svid_sop_prime().collect::<Vec<_>>(),
vec![Svid(0xDEF0), Svid(0xFFFF)]
);
}

#[test]
fn default_has_no_svids() {
let reg = DiscoveredSvids::default();
assert_eq!(reg.number_sop_svids(), 0);
assert_eq!(reg.svid_sop().len(), 0);

assert_eq!(reg.number_sop_prime_svids(), 0);
assert_eq!(reg.svid_sop_prime().len(), 0);
}

/// There's only space fo r8 SVIDs in the register but the number of SVIDs could
/// be larger, so the iterators should clamp to 8.
#[test]
fn iterators_clamp_to_8() {
let mut reg = DiscoveredSvids::default();

reg.0.set_number_sop_svids(9);
reg.0.set_number_sop_prime_svids(10);
assert_eq!(reg.number_sop_svids(), 9);
assert_eq!(reg.number_sop_prime_svids(), 10);
assert_eq!(reg.svid_sop().len(), 8);
assert_eq!(reg.svid_sop_prime().len(), 8);
}
}
3 changes: 3 additions & 0 deletions src/registers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ use crate::Mode;

pub mod autonegotiate_sink;
pub mod boot_flags;
pub mod discovered_svids;
pub mod dp_status;
pub mod port_config;
pub mod received_sop_identity_data;
pub mod received_sop_prime_identity_data;
pub mod rx_caps;
pub mod rx_other_vdm;
pub mod tx_identity;
Expand Down
Loading
Loading