diff --git a/src/lib.rs b/src/lib.rs index 5416bad..1cb58b3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,12 +3,24 @@ pub mod asynchronous; pub mod pdo; pub mod type_c; +pub mod ucsi; -/// Port ID new type +/// Port ID new type. +/// +/// This differs from [`GlobalPortId`] in that it refers to a port on a specific controller. If +/// there are multiple controllers, the same port ID may be used on different controllers. #[derive(Copy, Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct PortId(pub u8); +/// Global port ID, used to unique identify a port +/// +/// This differs from [`PortId`] in that it is not limited to the number of ports on a single +/// controller. If there are multiple controllers, each port should have a unique global port ID. +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub struct GlobalPortId(pub u8); + #[derive(Copy, Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] /// General PD-related errors diff --git a/src/ucsi/lpm.rs b/src/ucsi/lpm.rs new file mode 100644 index 0000000..adf5d36 --- /dev/null +++ b/src/ucsi/lpm.rs @@ -0,0 +1,33 @@ +use crate::{GlobalPortId, PdError}; + +/// Connector reset types +#[derive(Copy, Clone, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum ResetType { + Hard, + Data, +} + +/// LPM command data +#[derive(Copy, Clone, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum CommandData { + ConnectorReset(ResetType), +} + +/// LPM commands +#[derive(Copy, Clone, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub struct Command { + pub port: GlobalPortId, + pub operation: CommandData, +} + +/// LPM response data +#[derive(Copy, Clone, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum ResponseData { + Complete, +} + +pub type Response = Result; diff --git a/src/ucsi/mod.rs b/src/ucsi/mod.rs new file mode 100644 index 0000000..240d0b4 --- /dev/null +++ b/src/ucsi/mod.rs @@ -0,0 +1,83 @@ +//! Ucsi types, see spec at https://www.usb.org/document-library/usb-type-cr-connector-system-software-interface-ucsi-specification +#![allow(missing_docs)] + +use bitfield::bitfield; + +pub mod lpm; +pub mod ppm; + +/// Ucsi opcodes, see spec for more detail +#[repr(u8)] +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub enum UsciOpcode { + PpmReset = 0x01, + Cancel, + ConnectorReset, + AckCcCi, + SetNotificationEnable, + GetCapability, + GetConnectorCapability, + SetCcom, + SetUor, + SetPdm, + SetPdr, + GetAlternateModes, + GetCamSupported, + GetCurrentCam, + SetNewCam, + GetPdos, + GetCableProperty, + GetConnectorStatus, + GetErrorStatus, + SetPowerLevel, + GetPdMessage, + GetAttentionVdo, + GetCamCs = 0x18, + LpmFwUpdateRequest, + SecurityRequest, + SetRetimerMode, + SetSinkPath, + SetPdos, + ReadPowerLevel, + ChunkingSupport, + SetUsb = 0x21, + GetLpmPpmInfo, +} + +bitfield! { + /// Command status and connect change indicator, see spec for more details + #[derive(Copy, Clone)] + #[cfg_attr(feature = "defmt", derive(defmt::Format))] + pub struct Cci(u32); + impl Debug; + pub eom, set_eom: 0, 0; + pub port, set_port: 1, 7; + pub data_len, set_data_len: 8, 15; + pub vdm, set_vdm: 16, 16; + pub reserved, _: 17, 22; + pub security_req, set_security_req: 23, 23; + pub fw_update_req, set_fw_update_req: 24, 24; + pub not_supported, set_not_supported: 25, 25; + pub cancel_complete, set_cancel_complete: 26, 26; + pub reset_complete, set_reset_complete: 27, 27; + pub busy, set_busy: 28, 28; + pub ack_command, set_ack_command: 29, 29; + pub error, set_error: 30, 30; + pub cmd_complete, set_cmd_complete: 31, 31; +} + +/// UCSI commands +#[derive(Copy, Clone, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum Command { + PpmCommand(ppm::Command), + LpmCommand(lpm::Command), +} + +/// UCSI command responses +#[derive(Copy, Clone, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum Response { + PpmResponse(ppm::Response), + LpmResponse(lpm::Response), +} diff --git a/src/ucsi/ppm.rs b/src/ucsi/ppm.rs new file mode 100644 index 0000000..50d9e8f --- /dev/null +++ b/src/ucsi/ppm.rs @@ -0,0 +1,47 @@ +use bitfield::bitfield; + +use crate::PdError; + +bitfield! { + /// PPM notifications that can be enabled, see spec for more details + #[derive(Copy, Clone)] + #[cfg_attr(feature = "defmt", derive(defmt::Format))] + pub struct SetNotificationEnableData(u32); + impl Debug; + pub cmd_complete, set_cmd_complete: 0, 0; + pub external_supply_change, set_external_supply_change: 1, 1; + pub power_op_mode_change, set_power_op_mode_change: 2, 2; + pub attention, set_attention: 3, 3; + pub fw_update_req, set_fw_update_req: 4, 4; + pub provider_caps_change, set_provider_caps_change: 5, 5; + pub power_lvl_change, set_power_lvl_change: 6, 6; + pub pd_reset_complete, set_pd_reset_complete: 7, 7; + pub cam_change, set_cam_change: 8, 8; + pub battery_charge_change, set_battery_charge_change: 9, 9; + pub security_req, set_security_req: 10, 10; + pub connector_partner_change, set_connector_partner_change: 11, 11; + pub power_dir_change, set_power_dir_change: 12, 12; + pub set_retimer_mode, set_set_retimer_mode: 13, 13; + pub connect_change, set_connect_change: 14, 14; + pub error, set_error: 15, 15; + pub sink_path_change, set_sink_path_change: 16, 16; +} + +/// Commands that only affect the PPM level and don't need to be sent to an LPM +#[derive(Copy, Clone, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum Command { + Reset, + Cancel, + AckCcCi, + SetNotificationEnable(SetNotificationEnableData), +} + +/// PPM command response data +#[derive(Copy, Clone, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum ResponseData { + Complete, +} + +pub type Response = Result;