/**
******************************************************************************
* @file usbpd_vdm_user.c
* @author MCD Application Team
* @brief USBPD provider demo file
******************************************************************************
* @attention
*
*
© Copyright (c) 2018 STMicroelectronics.
* All rights reserved.
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "usbpd_core.h"
#include "usbpd_dpm_conf.h"
#include "usbpd_vdm_user.h"
#include "usbpd_dpm_user.h"
#if defined(_GUI_INTERFACE)
#include "gui_api.h"
#include "usbpd_gui_memmap.h"
#endif /* _GUI_INTERFACE */
#include "string.h"
#include "main.h"
/* Private define ------------------------------------------------------------*/
#define SVDM_DP_STATUS SVDM_SPECIFIC_1
#define SVDM_DP_CONFIG SVDM_SPECIFIC_2
#define MAX_SVID_USER 1
/*
* DP Pin assignement
*/
#define DP_PIN_ASSIGNMENT_NONE 0x00 /*!< De-select pin assignment. */
#define DP_PIN_ASSIGNMENT_A 0x01 /*!< Select Pin Assignment A */
#define DP_PIN_ASSIGNMENT_B 0x02 /*!< Select Pin Assignment B */
#define DP_PIN_ASSIGNMENT_C 0x04 /*!< Select Pin Assignment C */
#define DP_PIN_ASSIGNMENT_D 0x08 /*!< Select Pin Assignment D */
#define DP_PIN_ASSIGNMENT_E 0x10 /*!< Select Pin Assignment E */
#define DP_PIN_ASSIGNMENT_F 0x20 /*!< Select Pin Assignment F */
/* Pin configs B/D/F support multi-function */
#define MODE_DP_PIN_MF_MASK 0x2a
/* Pin configs A/B support BR2 signaling levels */
#define MODE_DP_PIN_BR2_MASK 0x3
/* Pin configs C/D/E/F support DP signaling levels */
#define MODE_DP_PIN_DP_MASK 0x3c
#define MODE_DP_V13 0x1
#define MODE_DP_GEN2 0x2
#define MODE_DP_NUMBER 1u
#define MODE_DP_MODE_SNK 0x1
#define MODE_DP_MODE_SRC 0x2
#define MODE_DP_MODE_BOTH 0x3
#define MODE_DP_STATUS_CONNECT_NO 0x0 /*!< no (DFP|UFP)_D is connected or disabled */
#define MODE_DP_STATUS_CONNECT_DFP_D 0x1 /*!< DFP_D connected */
#define MODE_DP_STATUS_CONNECT_UFP_D 0x2 /*!< UFP_D connected */
#define MODE_DP_STATUS_CONNECT_BOTH 0x3 /*!< DFP_D & UFP_D connected */
#define DISPLAY_PORT_SVID 0xFF01U /*!< SVID For Display Port */
#define PRODUCT_VDO 0xAAAAAAAAU /*!< Device version + USB Product ID */
/**
* @brief Type-C to Plug/Receptacle
* @{
*/
typedef enum {
CABLE_TO_PLUG = 0, /*0b0*/
CABLE_TO_RECEPTACLE = 1, /*0b1*/
} USBPD_CableToPR;
/**
* @}
*/
/* Private typedef -----------------------------------------------------------*/
/* GNU Compiler */
#if defined (__GNUC__)
/* ARM Compiler */
#elif defined (__CC_ARM)
#pragma anon_unions
/* IAR Compiler */
#elif defined (__ICCARM__)
#endif
/*
* DisplayPort modes capabilities
*/
typedef union
{
uint32_t d32;
struct
{
uint32_t SignalDirection : 2; /*!< signal direction ( 00b=rsv, 01b=sink, 10b=src 11b=both ) */
uint32_t Supports : 4; /*!< xxx1: Supports DPv1.3, xx1x Supports USB Gen 2 signaling
Other bits are reserved. */
uint32_t PlugOrRecept : 1; /*!< Plug | Receptacle (0b == plug, 1b == receptacle) */
uint32_t USB20 : 1; /*!< USB 2.0 signaling (0b=yes, 1b=no) */
uint32_t DFP_D_Pin : 8; /*!< DFP_D pin assignment supported */
uint32_t UFP_D_Pin : 8; /*!< UFP_D pin assignment supported */
uint32_t Reserved : 8; /*!< Reserved */
}d;
}USBPD_DPModeTypeDef;
/*
* Structure to SVID supported by the devices
*/
typedef struct {
uint32_t NumSVIDs;
uint16_t SVIDs[MAX_SVID_USER];
}USBPD_SVIDUSerInfo_TypeDef;
/* Private macro -------------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* List of callbacks for VDM layer */
static USBPD_StatusTypeDef USBPD_VDM_DiscoverIdentity(uint8_t PortNum, USBPD_DiscoveryIdentity_TypeDef *pIdentity);
static USBPD_StatusTypeDef USBPD_VDM_DiscoverSVIDs(uint8_t PortNum, uint16_t **p_SVID_Info, uint8_t *nb);
static USBPD_StatusTypeDef USBPD_VDM_DiscoverModes(uint8_t PortNum, uint16_t SVID, uint32_t **p_ModeInfo, uint8_t *nbMode);
static USBPD_StatusTypeDef USBPD_VDM_ModeEnter(uint8_t PortNum, uint16_t SVID, uint32_t ModeIndex);
static USBPD_StatusTypeDef USBPD_VDM_ModeExit(uint8_t PortNum, uint16_t SVID, uint32_t ModeIndex);
static void USBPD_VDM_InformIdentity(uint8_t PortNum, USBPD_SOPType_TypeDef SOPType, USBPD_VDM_CommandType_Typedef status, USBPD_DiscoveryIdentity_TypeDef *pIdentity);
static void USBPD_VDM_InformSVID(uint8_t PortNum, USBPD_SOPType_TypeDef SOPType, USBPD_VDM_CommandType_Typedef CommandStatus, USBPD_SVIDInfo_TypeDef *pListSVID);
static void USBPD_VDM_InformMode(uint8_t PortNum, USBPD_SOPType_TypeDef SOPType, USBPD_VDM_CommandType_Typedef CommandStatus, USBPD_ModeInfo_TypeDef *pModesInfo);
static void USBPD_VDM_InformModeEnter(uint8_t PortNum, USBPD_SOPType_TypeDef SOPType, USBPD_VDM_CommandType_Typedef CommandStatus, uint16_t SVID, uint32_t ModeIndex);
static void USBPD_VDM_SendAttention(uint8_t PortNum, uint8_t *NbData, uint32_t *VDO);
static void USBPD_VDM_ReceiveAttention(uint8_t PortNum, uint8_t NbData, uint32_t VDO);
static void USBPD_VDM_SendSpecific(uint8_t PortNum, USBPD_VDM_Command_Typedef VDMCommand, uint8_t *NbData, uint32_t *VDO);
static USBPD_StatusTypeDef USBPD_VDM_ReceiveSpecific(uint8_t PortNum, USBPD_VDM_Command_Typedef VDMCommand, uint8_t *NbData, uint32_t *VDO);
static void USBPD_VDM_InformSpecific(uint8_t PortNum, USBPD_VDM_Command_Typedef VDMCommand, uint8_t *NbData, uint32_t *VDO);
//static USBPD_StatusTypeDef HPD_Init(uint8_t PortNum);
/* Private variables ---------------------------------------------------------*/
USBPD_VDM_SettingsTypeDef DPM_VDM_Settings[USBPD_PORT_COUNT] =
{
{
.VDM_XID_SOP = 0x0000AAAAu, /*!< A decimal number assigned by USB-IF before certification */
.VDM_USB_VID_SOP = USBPD_VID, /*!< A decimal number assigned by USB-IF before certification */
.VDM_PID_SOP = 0xAAAAu, /*!< A unique number assigned by the Vendor ID holder identifying the product. */
.VDM_ModalOperation = MODAL_OPERATION_SUPPORTED, /*!< Product support Modes based on @ref USBPD_ModalOp_TypeDef */
.VDM_bcdDevice_SOP = 0xAAAAu, /*!< A unique number assigned by the Vendor ID holder containing identity information relevant to the release version of the product. */
.VDM_USBHostSupport = USB_NOTCAPABLE, /*!< Indicates whether the UUT is capable of enumerating USB Host */
.VDM_USBDeviceSupport = USB_NOTCAPABLE, /*!< Indicates whether the UUT is capable of enumerating USB Devices */
.VDM_ProductTypeUFPorCP = PRODUCT_TYPE_AMA, /*!< Product type UFP or CablePlug of the UUT based on @ref USBPD_ProductType_TypeDef */
.VDM_ProductTypeDFP = PRODUCT_TYPE_AMC, /*!< Product type DFP of the UUT based on @ref USBPD_ProductType_TypeDef */
}
};
const USBPD_VDM_Callbacks vdmCallbacks =
{
USBPD_VDM_DiscoverIdentity,
USBPD_VDM_DiscoverSVIDs,
USBPD_VDM_DiscoverModes,
USBPD_VDM_ModeEnter,
USBPD_VDM_ModeExit,
USBPD_VDM_InformIdentity,
USBPD_VDM_InformSVID,
USBPD_VDM_InformMode,
USBPD_VDM_InformModeEnter,
NULL,
USBPD_VDM_SendAttention,
USBPD_VDM_ReceiveAttention,
USBPD_VDM_SendSpecific,
USBPD_VDM_ReceiveSpecific,
USBPD_VDM_InformSpecific,
NULL,
NULL
};
uint8_t VDM_Mode_On[USBPD_PORT_COUNT];
extern USBPD_ParamsTypeDef DPM_Params[USBPD_PORT_COUNT];
USBPD_IDHeaderVDO_TypeDef IDHeaderVDO[USBPD_PORT_COUNT];
USBPD_DiscoveryIdentity_TypeDef sIdentity[USBPD_PORT_COUNT];
uint16_t Remote_CurrentSVID[USBPD_PORT_COUNT];
uint16_t Remote_SVID_Mode[USBPD_PORT_COUNT];
USBPD_SVIDUSerInfo_TypeDef SVIDInfo[USBPD_PORT_COUNT];
USBPD_ModeInfo_TypeDef sModesInfo[USBPD_PORT_COUNT];
const USBPD_DPModeTypeDef vdo_dp_modes[USBPD_PORT_COUNT][MODE_DP_NUMBER] =
{
{
{
.d.UFP_D_Pin = DP_PIN_ASSIGNMENT_NONE, /* UFP pin cfg supported : none */
.d.DFP_D_Pin = DP_PIN_ASSIGNMENT_C | DP_PIN_ASSIGNMENT_D, /* DFP pin cfg supported */
.d.USB20 = 1, /* USB2.0 signalling even in AMode */
.d.PlugOrRecept = CABLE_TO_PLUG, /* its a plug */
.d.Supports = MODE_DP_V13, /* DPv1.3 Support, no Gen2 */
.d.SignalDirection = MODE_DP_MODE_SNK /* Its a sink only */
},
#if MODE_DP_NUMBER==2u
{
.d.UFP_D_Pin = DP_PIN_ASSIGNMENT_NONE, /* UFP pin cfg supported : none */
.d.DFP_D_Pin = DP_PIN_ASSIGNMENT_C | DP_PIN_ASSIGNMENT_D, /* DFP pin cfg supported */
.d.USB20 = 0, /* USB2.0 signalling even in AMode */
.d.PlugOrRecept = CABLE_TO_RECEPTACLE,/* its a receptacle */
.d.Supports = MODE_DP_V13, /* DPv1.3 Support, no Gen2 */
.d.SignalDirection = MODE_DP_MODE_BOTH /* Its a sink / src */
}
#endif /* MODE_DP_NUMBER==2u */
}
};
USBPD_DPStatus_TypeDef sDP_Status[USBPD_PORT_COUNT] =
{
{
.d.Reserved = 0,
.d.IRQ_HPD = 0,
.d.HPDState = 0,
.d.ExitDPMode = 0,
.d.USBConfig = 0,
.d.MultiFunction = 1,
.d.Enable = 1,
.d.PowerLow = 0,
.d.ConnectStatus = MODE_DP_STATUS_CONNECT_DFP_D,
}
};
#if defined(_GUI_INTERFACE)
USBPD_DPConfig_TypeDef sDP_Config[USBPD_PORT_COUNT] =
{
{
.d.SelectConfiguration = MODE_DP_CONFIG_SELECT_UFP_U_AS_DFP_D,
.d.Signaling = MODE_DP_V13, /* Support of DPv1.3 */
.d.Reserved1 = 0,
.d.UFP_U_Pin = DP_PIN_ASSIGNMENT_C,
.d.Reserved2 = 0,
},
#if USBPD_PORT_COUNT == 2
{
.d.SelectConfiguration = MODE_DP_CONFIG_SELECT_USB,
.d.Signaling = 0,
.d.Reserved1 = 0,
.d.UFP_U_Pin = DP_PIN_ASSIGNMENT_NONE,
.d.Reserved2 = 0,
},
#endif /*USBPD_PORT_COUNT == 2*/
};
#endif /* _GUI_INTERFACE */
/* Private functions ---------------------------------------------------------*/
/**
* @brief VDM Discovery identity callback (answer to Discover Identity request message)
* @param PortNum current port number
* @param pIdentity Pointer on USBPD_DiscoveryIdentity_TypeDef structure
* @retval USBPD status
*/
static USBPD_StatusTypeDef USBPD_VDM_DiscoverIdentity(uint8_t PortNum, USBPD_DiscoveryIdentity_TypeDef *pIdentity)
{
IDHeaderVDO[PortNum].d32 = 0;
if (DPM_Params[PortNum].PE_SpecRevision > USBPD_SPECIFICATION_REV2)
{
IDHeaderVDO[PortNum].b30.VID = DPM_VDM_Settings[PortNum].VDM_USB_VID_SOP;
IDHeaderVDO[PortNum].b30.ModalOperation = DPM_VDM_Settings[PortNum].VDM_ModalOperation;
IDHeaderVDO[PortNum].b30.USBHostCapability = DPM_VDM_Settings[PortNum].VDM_USBHostSupport;
IDHeaderVDO[PortNum].b30.USBDevCapability = DPM_VDM_Settings[PortNum].VDM_USBDeviceSupport;
IDHeaderVDO[PortNum].b30.ProductTypeUFPorCP = DPM_VDM_Settings[PortNum].VDM_ProductTypeUFPorCP;
IDHeaderVDO[PortNum].b30.ProductTypeDFP = DPM_VDM_Settings[PortNum].VDM_ProductTypeDFP;
}
else
{
IDHeaderVDO[PortNum].b20.VID = DPM_VDM_Settings[PortNum].VDM_USB_VID_SOP;
IDHeaderVDO[PortNum].b20.ModalOperation = DPM_VDM_Settings[PortNum].VDM_ModalOperation;
IDHeaderVDO[PortNum].b20.USBHostCapability = DPM_VDM_Settings[PortNum].VDM_USBHostSupport;
IDHeaderVDO[PortNum].b20.USBDevCapability = DPM_VDM_Settings[PortNum].VDM_USBDeviceSupport;
IDHeaderVDO[PortNum].b20.ProductTypeUFPorCP = DPM_VDM_Settings[PortNum].VDM_ProductTypeUFPorCP;
}
sIdentity[PortNum].IDHeader.d32 = IDHeaderVDO[PortNum].d32;
sIdentity[PortNum].CertStatVDO.b.XID = DPM_VDM_Settings[PortNum].VDM_XID_SOP;
sIdentity[PortNum].ProductVDO.b.USBProductId = DPM_VDM_Settings[PortNum].VDM_PID_SOP;
sIdentity[PortNum].ProductVDO.b.bcdDevice = DPM_VDM_Settings[PortNum].VDM_bcdDevice_SOP;
sIdentity[PortNum].CableVDO_Presence = 0;
sIdentity[PortNum].AMA_VDO_Presence = 0;
/* Fill the AMA VDO if needed (for UFP or DFP depending on the role) */
if (USBPD_PORTDATAROLE_UFP == DPM_Params[PortNum].PE_DataRole)
{
if (PRODUCT_TYPE_AMA == DPM_VDM_Settings[PortNum].VDM_ProductTypeUFPorCP)
{
USBPD_AMAVdo_TypeDef ama_vdo =
{
.b.AMA_USB_SS_Support = AMA_USB2P0_ONLY,
.b.VBUSRequirement = VBUS_REQUIRED,
.b.VCONNRequirement = VCONN_NOT_REQUIRED,
.b.VCONNPower = VCONN_1W,
.b.Reserved = 0x0000,
.b.AMAFWVersion = 0x1,
.b.AMAHWVersion = 0x1,
};
sIdentity[PortNum].AMA_VDO_Presence = 1;
sIdentity[PortNum].AMA_VDO.d32 = ama_vdo.d32;
}
}
else
{
if (((DPM_Params[PortNum].PE_SpecRevision) > USBPD_SPECIFICATION_REV2)
&& (PRODUCT_TYPE_AMC == IDHeaderVDO[PortNum].b30.ProductTypeDFP))
{
USBPD_AMAVdo_TypeDef ama_vdo =
{
.b.AMA_USB_SS_Support = AMA_USB2P0_ONLY,
.b.VBUSRequirement = VBUS_REQUIRED,
.b.VCONNRequirement = VCONN_NOT_REQUIRED,
.b.VCONNPower = VCONN_1W,
.b.Reserved = 0x0000,
.b.AMAFWVersion = 0x1,
.b.AMAHWVersion = 0x1,
};
sIdentity[PortNum].AMA_VDO_Presence = 1;
sIdentity[PortNum].AMA_VDO.d32 = ama_vdo.d32;
}
}
*pIdentity = sIdentity[PortNum];
return USBPD_ACK;
}
/**
* @brief VDM Discover SVID callback (retrieve SVID supported by device for answer to Discovery mode)
* @param PortNum current port number
* @param p_SVID_Info Pointer on USBPD_SVIDInfo_TypeDef structure
* @retval USBPD status USBPD_ACK, USBPD_NAK, USBPD_BUSY
*/
static USBPD_StatusTypeDef USBPD_VDM_DiscoverSVIDs(uint8_t PortNum, uint16_t **p_SVID_Info, uint8_t *nb)
{
USBPD_StatusTypeDef _status = USBPD_NAK;
if (MODAL_OPERATION_SUPPORTED == DPM_VDM_Settings[PortNum].VDM_ModalOperation )
{
*nb = SVIDInfo[PortNum].NumSVIDs;
*p_SVID_Info = SVIDInfo[PortNum].SVIDs;
_status = USBPD_ACK;
}
return _status;
}
/**
* @brief VDM Discover Mode callback (report all the modes supported by SVID)
* @param PortNum current port number
* @param SVID SVID ID
* @param p_ModeInfo Pointer on USBPD_ModeInfo_TypeDef structure
* @retval USBPD status
*/
static USBPD_StatusTypeDef USBPD_VDM_DiscoverModes(uint8_t PortNum, uint16_t SVID, uint32_t **p_ModeInfo, uint8_t *nbMode)
{
USBPD_StatusTypeDef _status = USBPD_NAK;
if (MODAL_OPERATION_SUPPORTED == DPM_VDM_Settings[PortNum].VDM_ModalOperation )
{
switch(SVID)
{
case DISPLAY_PORT_SVID :
*nbMode = MODE_DP_NUMBER;
*p_ModeInfo = (uint32_t *)&vdo_dp_modes[PortNum];
_status = USBPD_ACK;
break;
default :
*nbMode = 0;
*p_ModeInfo = NULL;
break;
}
}
return _status;
}
/**
* @brief VDM Mode enter callback
* @param PortNum current port number
* @param SVID SVID ID
* @param ModeIndex Index of the mode to be entered
* @retval USBPD status
*/
static USBPD_StatusTypeDef USBPD_VDM_ModeEnter(uint8_t PortNum, uint16_t SVID, uint32_t ModeIndex)
{
USBPD_StatusTypeDef status = USBPD_NAK;
if(VDM_Mode_On[PortNum] != 0) return status;
if ((DISPLAY_PORT_SVID == SVID) && (ModeIndex == 1))
{
status = USBPD_ACK;
VDM_Mode_On[PortNum] = 1;
}
if ((DISPLAY_PORT_SVID == SVID) && (ModeIndex == 2))
{
status = USBPD_ACK;
VDM_Mode_On[PortNum] = 2;
}
return status;
}
/**
* @brief VDM Mode exit callback
* @param PortNum current port number
* @param SVID SVID ID
* @param ModeIndex Index of the mode to be exited
* @retval USBPD status
*/
static USBPD_StatusTypeDef USBPD_VDM_ModeExit(uint8_t PortNum, uint16_t SVID, uint32_t ModeIndex)
{
USBPD_StatusTypeDef status = USBPD_NAK;
if(VDM_Mode_On[PortNum] == 0) return status;
if ((DISPLAY_PORT_SVID == SVID) && (ModeIndex == 1) && (VDM_Mode_On[PortNum] == 1))
{
status = USBPD_ACK;
VDM_Mode_On[PortNum] = 0;
}
if ((DISPLAY_PORT_SVID == SVID) && (ModeIndex == 2) && (VDM_Mode_On[PortNum] == 2))
{
status = USBPD_ACK;
VDM_Mode_On[PortNum] = 0;
}
return status;
}
/**
* @brief VDM Send Specific message callback
* @param PortNum current port number
* @param NbData Pointer of number of VDO to send
* @param VDO Pointer of VDO to send
* @retval None
*/
static void USBPD_VDM_SendAttention(uint8_t PortNum, uint8_t *NbData, uint32_t *VDO)
{
if (USBPD_PORTDATAROLE_DFP == DPM_Params[PortNum].PE_DataRole)
{
USBPD_DPStatus_TypeDef dp_status = {0};
dp_status.d.ConnectStatus = MODE_DP_STATUS_CONNECT_DFP_D;
*VDO = dp_status.d32;
*NbData = 1;
}
else
{
sDP_Status[PortNum].d.ConnectStatus = MODE_DP_STATUS_CONNECT_UFP_D;
*VDO = sDP_Status[PortNum].d32;
*NbData = 1;
}
}
/**
* @brief VDM Attention callback to forward information from PE stack
* @param PortNum current port number
* @param NbData Number of received VDO
* @param VDO Received VDO
* @retval None
*/
static void USBPD_VDM_ReceiveAttention(uint8_t PortNum, uint8_t NbData, uint32_t VDO)
{
if (USBPD_PORTDATAROLE_DFP == DPM_Params[PortNum].PE_DataRole)
{
if (NbData == 1)
{
USBPD_DPStatus_TypeDef vdo;
vdo.d32 = VDO;
/* Check state of HPD pin in attention message */
if (0 == vdo.d.HPDState)
{
}
else
{
/* Screen has been connected... Sent a config message to screen for connection*/
USBPD_PE_SVDM_RequestSpecific(PortNum, USBPD_SOPTYPE_SOP, SVDM_DP_CONFIG, DISPLAY_PORT_SVID);
}
}
}
else
{
if (NbData == 1)
{
/* Check if DP Status has been received in the attention message*/
USBPD_DPStatus_TypeDef dp_status;
dp_status.d32 = VDO;
if (dp_status.d.ConnectStatus == MODE_DP_STATUS_CONNECT_UFP_D)
{
USBPD_PE_SVDM_RequestSpecific(PortNum, USBPD_SOPTYPE_SOP, SVDM_DP_CONFIG, DISPLAY_PORT_SVID);
}
}
}
}
/**
* @brief VDM Discovery identity callback (answer after sending a Discover Identity req message)
* @param PortNum current port number
* @param SOPType SOP type
* @param CommandStatus Command status based on @ref USBPD_VDM_CommandType_Typedef
* @param pIdentity Pointer on the discovery identity information based on @ref USBPD_DiscoveryIdentity_TypeDef
* @retval None
*/
static void USBPD_VDM_InformIdentity(uint8_t PortNum, USBPD_SOPType_TypeDef SOPType, USBPD_VDM_CommandType_Typedef CommandStatus, USBPD_DiscoveryIdentity_TypeDef *pIdentity)
{
switch(CommandStatus)
{
case SVDM_RESPONDER_ACK :
if (USBPD_SOPTYPE_SOP1 == SOPType)
{
uint8_t* disco_ident;
disco_ident = (uint8_t*)&DPM_Ports[PortNum].VDM_DiscoCableIdentify;
memcpy(disco_ident, (uint8_t*)pIdentity, sizeof(USBPD_DiscoveryIdentity_TypeDef));
}
else
{
uint8_t* disco_ident;
disco_ident = (uint8_t*)&DPM_Ports[PortNum].VDM_DiscoIdentify;
memcpy(disco_ident, (uint8_t*)pIdentity, sizeof(USBPD_DiscoveryIdentity_TypeDef));
#if defined(_GUI_INTERFACE)
if (USBPD_ENABLE != GUI_IsRunning())
#endif /* _GUI_INTERFACE */
{
/* Alternate mode presence */
if (pIdentity->AMA_VDO_Presence == 1)
{
/* Request to get SVID */
USBPD_PE_SVDM_RequestSVID(PortNum, USBPD_SOPTYPE_SOP);
}
}
memset(&DPM_Ports[PortNum].VDM_SVIDPortPartner, 0, sizeof(USBPD_SVIDPortPartnerInfo_TypeDef));
Remote_CurrentSVID[PortNum] = 0;
}
break;
case SVDM_RESPONDER_NAK :
/* Nothing to do */
break;
case SVDM_RESPONDER_BUSY :
/* retry in 50ms */
break;
default :
break;
}
}
/**
* @brief Inform SVID callback
* @param PortNum current port number
* @param SOPType SOP type
* @param CommandStatus Command status based on @ref USBPD_VDM_CommandType_Typedef
* @param pListSVID Pointer of list of SVID based on @ref USBPD_SVIDInfo_TypeDef
* @retval None
*/
static void USBPD_VDM_InformSVID(uint8_t PortNum, USBPD_SOPType_TypeDef SOPType, USBPD_VDM_CommandType_Typedef CommandStatus, USBPD_SVIDInfo_TypeDef *pListSVID)
{
uint32_t index = 0;
switch(CommandStatus)
{
case SVDM_RESPONDER_ACK :
if (1 == DPM_Ports[PortNum].VDM_SVIDPortPartner.FlagAllSVIDReceived)
{
/* New list of SVIDs is being received. */
memset(&DPM_Ports[PortNum].VDM_SVIDPortPartner, 0, sizeof(USBPD_SVIDPortPartnerInfo_TypeDef));
}
/* Save the received SVIDs */
for (index = 0; index < pListSVID->NumSVIDs; index++)
{
DPM_Ports[PortNum].VDM_SVIDPortPartner.SVIDs[DPM_Ports[PortNum].VDM_SVIDPortPartner.NumSVIDs++] = pListSVID->SVIDs[index];
}
/* Check if all the SVIDs have been received */
if ((pListSVID->AllSVID_Received == 0) && (0 == (DPM_Ports[PortNum].VDM_SVIDPortPartner.NumSVIDs %12)))
{
/* Request a new SVID message */
USBPD_PE_SVDM_RequestSVID(PortNum, USBPD_SOPTYPE_SOP);
}
else
{
/* All the SVIDs have been received, request discovery mode on 1st SVID available
in the list */
DPM_Ports[PortNum].VDM_SVIDPortPartner.FlagAllSVIDReceived = 1;
/* Request a discovery mode */
Remote_SVID_Mode[PortNum] = 0;
#if defined(_GUI_INTERFACE)
if (USBPD_ENABLE != GUI_IsRunning())
#endif /* _GUI_INTERFACE */
{
USBPD_PE_SVDM_RequestMode(PortNum, USBPD_SOPTYPE_SOP, DPM_Ports[PortNum].VDM_SVIDPortPartner.SVIDs[0]);
}
}
break;
case SVDM_RESPONDER_NAK :
/* Nothing to do */
break;
case SVDM_RESPONDER_BUSY :
// retry in 50ms
break;
default :
break;
}
}
/**
* @brief Inform Mode callback
* @param PortNum current port number
* @param SOPType SOP type
* @param CommandStatus Command status based on @ref USBPD_VDM_CommandType_Typedef
* @param pModesInfo Pointer of Modes info based on @ref USBPD_ModeInfo_TypeDef
* @retval None
*/
static void USBPD_VDM_InformMode(uint8_t PortNum, USBPD_SOPType_TypeDef SOPType, USBPD_VDM_CommandType_Typedef CommandStatus, USBPD_ModeInfo_TypeDef *pModesInfo)
{
switch(CommandStatus)
{
case SVDM_RESPONDER_ACK :
{
USBPD_DPModeTypeDef dp_mode;
DPM_Ports[PortNum].VDM_ModesPortPartner.NumModes = pModesInfo->NumModes;
for (uint32_t index = 0; index < DPM_Ports[PortNum].VDM_ModesPortPartner.NumModes; index++)
{
DPM_Ports[PortNum].VDM_ModesPortPartner.Modes[index] = pModesInfo->Modes[index];
}
DPM_Ports[PortNum].VDM_ModesPortPartner.SVID = pModesInfo->SVID;
dp_mode.d32 = (DPM_Ports[PortNum].VDM_ModesPortPartner.Modes[0]);
#if defined(_GUI_INTERFACE)
if (USBPD_ENABLE != GUI_IsRunning())
#endif /* _GUI_INTERFACE */
{
/* Enter in the mode only if DFP_D and UFP_D are supported */
if ((dp_mode.d.SignalDirection == MODE_DP_MODE_BOTH) || (MODE_DP_MODE_SNK == dp_mode.d.SignalDirection))
{
/* Request to enter in the 1st mode */
USBPD_PE_SVDM_RequestModeEnter(PortNum, SOPType, pModesInfo->SVID, 1);
}
}
}
break;
case SVDM_RESPONDER_NAK :
#if defined(_GUI_INTERFACE)
if (USBPD_ENABLE != GUI_IsRunning())
#endif /* _GUI_INTERFACE */
{
/* All the SVIDs have been received, request discovery mode on next SVID available
in the list */
Remote_SVID_Mode[PortNum]++;
/* Request a discovery mode */
USBPD_PE_SVDM_RequestMode(PortNum, USBPD_SOPTYPE_SOP, DPM_Ports[PortNum].VDM_SVIDPortPartner.SVIDs[Remote_SVID_Mode[PortNum]]);
}
break;
case SVDM_RESPONDER_BUSY :
// retry in 50ms
break;
default :
break;
}
}
/**
* @brief Inform Mode enter callback
* @param PortNum current port number
* @param SVID SVID ID
* @param ModeIndex Index of the mode to be entered
* @retval None
*/
static void USBPD_VDM_InformModeEnter(uint8_t PortNum, USBPD_SOPType_TypeDef SOPType, USBPD_VDM_CommandType_Typedef CommandStatus, uint16_t SVID, uint32_t ModeIndex)
{
switch(CommandStatus)
{
case SVDM_RESPONDER_ACK :
#if defined(_GUI_INTERFACE)
if (USBPD_ENABLE != GUI_IsRunning())
#endif /* _GUI_INTERFACE */
{
if (DPM_Ports[PortNum].VDM_SVIDPortPartner.SVIDs[(ModeIndex - 1)] == SVID)
{
VDM_Mode_On[PortNum] = 1;
USBPD_PE_SVDM_RequestSpecific(PortNum, USBPD_SOPTYPE_SOP, SVDM_DP_STATUS, DISPLAY_PORT_SVID);
}
}
break;
case SVDM_RESPONDER_NAK :
/* Nothing to do */
break;
case SVDM_RESPONDER_BUSY :
/* retry in 50ms */
break;
default :
break;
}
}
/**
* @brief VDM Fill DP Status
* @param PortNum current port number
* @param pDP_Status Pointer on @ref USBPD_DPStatus_TypeDef
* @retval None
*/
void USBPD_VDM_FillDPStatus(uint8_t PortNum, USBPD_DPStatus_TypeDef *pDP_Status)
{
#if defined(_GUI_INTERFACE)
memcpy(&sDP_Status[PortNum], pDP_Status, sizeof(USBPD_DPStatus_TypeDef));
#endif /* _GUI_INTERFACE */
}
/**
* @brief VDM Fill DP Config
* @param PortNum current port number
* @param pDP_Status Pointer on @ref USBPD_DPConfig_TypeDef
* @retval None
*/
void USBPD_VDM_FillDPConfig(uint8_t PortNum, USBPD_DPConfig_TypeDef *pDP_Config)
{
#if defined(_GUI_INTERFACE)
memcpy(&sDP_Config[PortNum], pDP_Config, sizeof(USBPD_DPConfig_TypeDef));
#endif /* _GUI_INTERFACE */
}
/**
* @brief VDM Send Specific message callback
* @param PortNum current port number
* @param VDMCommand VDM command based on @ref USBPD_VDM_Command_Typedef
* @param NbData Pointer of number of VDO to send
* @param VDO Pointer of VDO to send
* @retval None
*/
static void USBPD_VDM_SendSpecific(uint8_t PortNum, USBPD_VDM_Command_Typedef VDMCommand, uint8_t *NbData, uint32_t *VDO)
{
if (USBPD_PORTDATAROLE_DFP == DPM_Params[PortNum].PE_DataRole)
{
switch(VDMCommand)
{
case SVDM_DP_STATUS :
{
#if defined(_GUI_INTERFACE)
*VDO = sDP_Status[PortNum].d32;
#else
USBPD_DPStatus_TypeDef dp_status = {0};
dp_status.d.ConnectStatus = MODE_DP_STATUS_CONNECT_DFP_D;
*VDO = dp_status.d32;
#endif /* _GUI_INTERFACE */
*NbData = 1;
}
break;
case SVDM_DP_CONFIG :
{
USBPD_DPModeTypeDef dp_mode;
dp_mode.d32 = (DPM_Ports[PortNum].VDM_ModesPortPartner.Modes[0]);
if (DP_PIN_ASSIGNMENT_C == (dp_mode.d.DFP_D_Pin & DP_PIN_ASSIGNMENT_C))
{
#if defined(_GUI_INTERFACE)
*VDO = sDP_Config[PortNum].d32;
#else
USBPD_DPConfig_TypeDef vdo_config = {0};
vdo_config.d.SelectConfiguration = MODE_DP_CONFIG_SELECT_UFP_U_AS_DFP_D;
/* Support of DPv1.3 */
vdo_config.d.Signaling = 0x1;
vdo_config.d.UFP_U_Pin = DP_PIN_ASSIGNMENT_C;
*VDO = vdo_config.d32;
#endif /* _GUI_INTERFACE */
*NbData = 1;
}
}
break;
default :
break;
}
}
else
{
switch(VDMCommand)
{
case SVDM_DP_STATUS :
{
sDP_Status[PortNum].d.ConnectStatus = MODE_DP_STATUS_CONNECT_UFP_D;
*VDO = sDP_Status[PortNum].d32;
*NbData = 1;
}
break;
case SVDM_DP_CONFIG :
*VDO = 0;
*NbData = 0;
break;
default :
break;
}
}
}
/**
* @brief VDM Receive Specific message callback
* @param PortNum Current port number
* @param VDMCommand VDM command based on @ref USBPD_VDM_Command_Typedef
* @param pNbData Pointer of number of received VDO and used for the answer
* @param pVDO Pointer of received VDO and use for the answer
* @retval USBPD status
*/
static USBPD_StatusTypeDef USBPD_VDM_ReceiveSpecific(uint8_t PortNum, USBPD_VDM_Command_Typedef VDMCommand, uint8_t *pNbData, uint32_t *pVDO)
{
USBPD_StatusTypeDef status = USBPD_ACK;
if (USBPD_PORTDATAROLE_DFP == DPM_Params[PortNum].PE_DataRole)
{
/* Data role is DFP */
switch(VDMCommand)
{
case SVDM_DP_STATUS :
{
/* Port0 is configured as SRC */
sDP_Status[PortNum].d.ConnectStatus = MODE_DP_STATUS_CONNECT_DFP_D;
*pVDO = sDP_Status[PortNum].d32;
*pNbData = 1;
}
break;
case SVDM_DP_CONFIG :
break;
default :
status = USBPD_NAK;
break;
}
}
else
{
/* Data role is UFP */
switch(VDMCommand)
{
case SVDM_DP_STATUS :
{
USBPD_DPStatus_TypeDef vdo;
if (*pNbData == 1)
{
vdo.d32 = pVDO[0];
if ((MODE_DP_STATUS_CONNECT_DFP_D == vdo.d.ConnectStatus)
|| (MODE_DP_STATUS_CONNECT_BOTH == vdo.d.ConnectStatus)
|| (MODE_DP_STATUS_CONNECT_NO == vdo.d.ConnectStatus)) /* Connect none set by Chromebook only */
{
sDP_Status[PortNum].d.ConnectStatus = MODE_DP_STATUS_CONNECT_UFP_D;
*pVDO = sDP_Status[PortNum].d32;
*pNbData = 1;
}
else
{
status = USBPD_NAK;
}
}
else
{
status = USBPD_NAK;
}
}
break;
case SVDM_DP_CONFIG :
{
//USBPD_DPConfig_TypeDef vdo;
//vdo.d32 = pVDO[0];
//*pVDO = 0;
//*pNbData = 0;
}
break;
default :
status = USBPD_NAK;
break;
}
}
return status;
}
/**
* @brief VDM Inform Specific callback
* @param PortNum current port number
* @param VDMCommand VDM command based on @ref USBPD_VDM_Command_Typedef
* @param NbData Pointer of number of received VDO
* @param VDO Pointer of received VDO
* @retval status
*/
static void USBPD_VDM_InformSpecific(uint8_t PortNum, USBPD_VDM_Command_Typedef VDMCommand, uint8_t *NbData, uint32_t *VDO)
{
if (USBPD_PORTDATAROLE_DFP == DPM_Params[PortNum].PE_DataRole)
{
switch(VDMCommand)
{
case SVDM_DP_STATUS :
{
USBPD_DPStatus_TypeDef vdo_received;
vdo_received.d32 = VDO[0];
/* SEND SVDM_DP_CONFIG only if Port is connected */
if (MODE_DP_STATUS_CONNECT_NO != vdo_received.d.ConnectStatus)
{
USBPD_PE_SVDM_RequestSpecific(PortNum, USBPD_SOPTYPE_SOP, SVDM_DP_CONFIG, DISPLAY_PORT_SVID);
}
}
break;
case SVDM_DP_CONFIG :
default :
return;
}
}
else
{
switch(VDMCommand)
{
case SVDM_DP_STATUS :
{
USBPD_DPStatus_TypeDef vdo_received;
vdo_received.d32 = VDO[0];
if (vdo_received.d.ConnectStatus != MODE_DP_STATUS_CONNECT_NO)
{
sDP_Status[PortNum].d.ConnectStatus = MODE_DP_STATUS_CONNECT_UFP_D;
}
else
{
/* DP not connected */
sDP_Status[PortNum].d.ConnectStatus = MODE_DP_STATUS_CONNECT_NO;
}
}
break;
case SVDM_DP_CONFIG :
break;
default :
break;
}
}
}
/**
* @brief Initialize HPD Alert pin
* @param PortNum current port number
* @retval USBPD status
*/
//static USBPD_StatusTypeDef HPD_Init(uint8_t PortNum)
//{
// return USBPD_OK;
//}
/* Exported functions ---------------------------------------------------------*/
/**
* @brief VDM Initialization function
* @param PortNum Index of current used port
* @param pSettings Pointer on @ref USBPD_VDM_SettingsTypeDef structure
* @param pParams Pointer on @ref USBPD_ParamsTypeDef structure
* @retval status
*/
USBPD_StatusTypeDef USBPD_VDM_UserInit(uint8_t PortNum)
{
uint32_t index = 0;
/* Initialize SVID supported by consumer */
SVIDInfo[PortNum].NumSVIDs = MAX_SVID_USER;
for (index = 0; index < MAX_SVID_USER; index++)
{
SVIDInfo[PortNum].SVIDs[index] = DISPLAY_PORT_SVID + index;
}
USBPD_PE_InitVDM_Callback(PortNum, (USBPD_VDM_Callbacks *)&vdmCallbacks);
#if USBPD_PORT_COUNT == 2
if (USBPD_PORT_1 == PortNum)
return HPD_Init(PortNum);
else
#endif
return USBPD_OK;
}
/**
* @brief VDM Reset function
* @retval status
*/
void USBPD_VDM_UserReset(uint8_t PortNum)
{
/* Reset Port Partner variables*/
Remote_CurrentSVID[PortNum] = 0;
#if USBPD_PORT_COUNT == 2
if (USBPD_PORT_1 == PortNum)
{
}
#endif
/* Disconnect received on Type-C */
VDM_Mode_On[PortNum] = 0;
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/