/**
******************************************************************************
* @file gui_api.c
* @author MCD Application Team
* @brief GUI_API provides functions associated with answers the MCU can send
to the computer via UART.
******************************************************************************
* @attention
*
*
© Copyright (c) 2018 STMicroelectronics.
* All rights reserved.
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
#if defined(_GUI_INTERFACE)
#define GUI_API_C
#include
#include "usbpd_core.h"
#include "gui_api.h"
#include "bsp_gui.h"
#include "data_struct_tlv.h"
#include "usbpd_dpm_core.h"
#include "usbpd_trace.h"
#include "usbpd_dpm_user.h"
#include "usbpd_dpm_conf.h"
#include "tracer_emb.h"
#ifdef _VDM
#include "usbpd_vdm_user.h"
#endif /* _VDM */
#include "usbpd_pdo_defs.h"
#ifndef USBPD_TCPM_MODULE_ENABLED
//#include "usbpd_hw_if.h"
#else
#include "usbpd_tcpci.h"
#endif
#if defined(_RTOS)
#include "cmsis_os.h"
#else
#if defined(USE_STM32_UTILITY_OS)
#include "utilities_conf.h"
#endif /*USE_STM32_UTILITY_OS */
#endif /*_RTOS*/
#include "string.h"
/* generic hal function valid for all stm32 */
extern uint32_t HAL_GetTick(void);
extern void HAL_NVIC_SystemReset(void);
/** @addtogroup STM32_USBPD_LIBRARY
* @{
*/
/** @addtogroup USBPD_GUI_API
* @{
*/
/* Private enums -------------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/** @defgroup USBPD_GUI_API_Private_Defines USBPD GUI API Private Defines
* @{
*/
#if !defined(USBPD_FW_VERSION)
#define USBPD_FW_VERSION 0xFFFFFFFFU
#endif /* !USBPD_FW_VERSION */
#if !defined(USBPD_START_PORT_NUMBER)
#define USBPD_START_PORT_NUMBER 0U
#endif /* !USBPD_START_PORT_NUMBER */
#define GUI_PORT_BIT_POSITION 5u /* Bit position of port number in TAG id */
#define GUI_BOX_MESSAGES_MAX 30u
#define GUI_TIMER_ENABLE_MSK ((uint16_t)0x8000U) /*!< Enable Timer Mask */
#define GUI_TIMER_READ_MSK ((uint16_t)0x7FFFU) /*!< Read Timer Mask */
#if defined(USBPDCORE_SNK_CAPA_EXT)
#define GUI_VDM_CABLE_INFO USBPD_CORE_SNK_EXTENDED_CAPA + 1U
#else
#define GUI_VDM_CABLE_INFO USBPD_CORE_UNSTRUCTURED_VDM + 1U
#endif /* USBPDCORE_SNK_CAPA_EXT */
#if defined(_RTOS)
#if (osCMSIS < 0x20000U)
#define GUI_STACK_SIZE_ADDON_FOR_CMSIS 1
#else
#define GUI_STACK_SIZE_ADDON_FOR_CMSIS 5
#endif /* osCMSIS < 0x20000U */
#define FREERTOS_GUI_PRIORITY osPriorityLow
#define FREERTOS_GUI_STACK_SIZE (240 * GUI_STACK_SIZE_ADDON_FOR_CMSIS)
#endif /*_RTOS*/
/**
* @brief USB PD GUI REJECT REASON
*/
typedef enum
{
GUI_REJ_DPM_REJECT = 0x00, /* 0)
#define IS_GUI_TIMER_EXPIRED(_PORT_, _TIMER_) (GUI_TIMER_ENABLE_MSK == _TIMER_[_PORT_])
#if defined(_SNK) || defined(_DRP)
#define GUI_UPDATE_VOLTAGE_MIN(_PDO_VOLT_, _SNK_VOLT_) \
if ((_PDO_VOLT_) < (_SNK_VOLT_)) \
{ \
/* Update min voltage */ \
(_SNK_VOLT_) = (_PDO_VOLT_); \
}
#define GUI_UPDATE_VOLTAGE_MAX(_PDO_VOLT_, _SNK_VOLT_) \
if ((_PDO_VOLT_) > (_SNK_VOLT_)) \
{ \
/* Update min voltage */ \
(_SNK_VOLT_) = (_PDO_VOLT_); \
}
#define GUI_UPDATE_CURRENT_MAX(_PDO_CURRENT_, _SNK_CURRENT_) \
if ((_PDO_CURRENT_) > (_SNK_CURRENT_)) \
{ \
/* Update min current */ \
(_SNK_CURRENT_) = (_PDO_CURRENT_); \
}
#define GUI_UPDATE_POWER_MAX(_PDO_POWER_, _SNK_POWER_) \
if ((_PDO_POWER_) > (_SNK_POWER_)) \
{ \
/* Update min POWER */ \
(_SNK_POWER_) = (_PDO_POWER_); \
}
#define GUI_CHECK_VOLTAGE_MIN(_PDO_VOLT_, _SNK_VOLT_) \
/* Update min voltage */ \
(_SNK_VOLT_) = (_PDO_VOLT_);
#define GUI_CHECK_VOLTAGE_MAX(_PDO_VOLT_, _SNK_VOLT_) \
/* Update min voltage */ \
(_SNK_VOLT_) = (_PDO_VOLT_);
#define GUI_CHECK_CURRENT_MAX(_PDO_CURRENT_, _SNK_CURRENT_) \
/* Update min current */ \
(_SNK_CURRENT_) = (_PDO_CURRENT_);
#define GUI_CHECK_POWER_MAX(_PDO_POWER_, _SNK_POWER_) \
/* Update min POWER */ \
(_SNK_POWER_) = (_PDO_POWER_);
#define GUI_DECODE_50MV(_Value_) ((uint16_t)(((_Value_) * 50))) /* From 50mV multiples to mV */
#define GUI_DECODE_100MV(_Value_) ((uint16_t)(((_Value_) * 100))) /* From 100mV multiples to mV */
#define GUI_DECODE_10MA(_Value_) ((uint16_t)(((_Value_) * 10))) /* From 10mA multiples to mA */
#define GUI_DECODE_50MA(_Value_) ((uint16_t)(((_Value_) * 50))) /* From 50mA multiples to mA */
#define GUI_DECODE_MW(_Value_) ((uint16_t)(((_Value_) * 250))) /* From 250mW multiples to mW */
#endif /* _SNK) || _DRP */
/**
* @}
*/
/* Private function prototypes -----------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/** @defgroup USBPD_GUI_API_Private_Variables USBPD GUI API Private Variables
* @{
*/
volatile uint16_t GUI_TimerMeasReport[USBPD_PORT_COUNT]; /*!< Timer used to send measurement report */
extern USBPD_SettingsTypeDef DPM_Settings[USBPD_PORT_COUNT];
#ifdef _VDM
extern USBPD_VDM_SettingsTypeDef DPM_VDM_Settings[USBPD_PORT_COUNT];
#endif /* _VDM */
GUI_USER_ParamsTypeDef GUI_USER_Params[USBPD_PORT_COUNT];
uint8_t PtrDataRx[TLV_SIZE_MAX];
uint8_t Processed[TLV_SIZE_MAX];
USBPD_GUI_State GUI_State = GUI_STATE_INIT;
/*!< Flag to indicate that user settings is from original FW (not saved into the FLASH) */
uint8_t GUI_OriginalSettings;
#if defined(_RTOS)
osMessageQId GUIMsgBox;
#if (osCMSIS >= 0x20000U)
osThreadAttr_t GUI_Thread_Atrr = {
.name = "GUI",
.priority = FREERTOS_GUI_PRIORITY, /*osPriorityLow,*/
.stack_size = FREERTOS_GUI_STACK_SIZE
};
#endif /* osCMSIS >= 0x20000U */
#else
volatile uint32_t GUI_Flag = GUI_USER_EVENT_NONE;
#endif /* _RTOS */
const uint8_t* (*pCB_HWBoardVersion)(void) = NULL;
const uint8_t* (*pCB_HWPDType)(void) = NULL;
uint16_t (*pCB_GetVoltage)(uint8_t) = NULL;
int16_t (*pCB_GetCurrent)(uint8_t) = NULL;
USBPD_StatusTypeDef (*pCB_FreeText)(uint8_t, uint8_t*, uint16_t) = NULL;
GUI_HandleTypeDef GUI_SaveInformation[USBPD_PORT_COUNT];
/**
* @}
*/
/* Private functions ---------------------------------------------------------*/
/** @defgroup USBPD_GUI_API_Private_Functions GUI API Private Functions
* @{
*/
#ifdef _RTOS
#if (osCMSIS < 0x20000U)
static void TaskGUI(void const *argument);
#else
static void TaskGUI(void *argument);
#endif /* osCMSIS < 0x20000U */
static uint32_t CheckGUITimers(void);
#endif /* _RTOS */
static void GUI_CALLBACK_RX(uint8_t Character, uint8_t Error);
static void Send_DpmInitCnf(uint8_t PortNum, uint8_t *string);
static void Request_MessageReq(uint8_t PortNum, uint8_t* instruction, uint8_t *pEncodedMsg);
static void Send_DpmConfigSetCnf(uint8_t PortNum, uint8_t* instruction, uint8_t *pEncodedMsg);
static void Send_DpmConfigGetCnf(uint8_t PortNum, uint8_t* instruction, uint8_t *pEncodedMsg);
static void Send_DpmConfigGetRej(uint8_t PortNum, uint8_t *pEncodedMsg, USBPD_GUI_Reject_Reason RejecReason);
static void Send_DpmMessageRej(uint8_t PortNum, uint8_t *pEncodedMsg, USBPD_GUI_Reject_Reason RejecReason);
static void Send_DpmRegisterReadCnf(uint8_t PortNum, uint8_t *string, uint8_t param);
static void Send_DpmRegisterWriteCnf(uint8_t PortNum, uint8_t *string, uint8_t *toProcess);
static USBPD_StatusTypeDef Manage_FreeText(uint8_t PortNum, uint8_t *pPayload, uint16_t Size);
#if defined(_SNK) || defined(_DRP)
static void UpdateSNKPowerPort0(void);
#if USBPD_PORT_COUNT==2
static void UpdateSNKPowerPort1(void);
#endif /* USBPD_PORT_COUNT==2 */
#endif /* _SNK) || _DRP */
#if defined(USE_STM32_UTILITY_OS)
void GUI_Execute(void);
#endif /* USE_STM32_UTILITY_OS */
/**
* @}
*/
/* Exported functions ------------------------------------------------------- */
/** @addtogroup USBPD_GUI_API_Exported_Functions
* @{
*/
/**
* @brief GUI initialization function
* @param CB_HWBoardVersion BSP callback to retrieve HW Board version
* @param CB_HWPDType BSP callback to retrieve HW PD Type
* @param CB_GetVoltage BSP callback to retrieve VBUS voltage
* @param CB_GetCurrent BSP callback to retrieve IBUS current
* @retval Functional state
*/
USBPD_FunctionalState GUI_Init(const uint8_t* (*CB_HWBoardVersion)(void), const uint8_t* (*CB_HWPDType)(void), uint16_t (*CB_GetVoltage)(uint8_t), int16_t (*CB_GetCurrent)(uint8_t))
{
USBPD_FunctionalState _status = USBPD_ENABLE;
/* Retrieve data from FLASH if needed */
GUI_OriginalSettings = ((GUI_OK == BSP_GUI_LoadDataFromFlash()) ? USBPD_FALSE : USBPD_TRUE);
/* Need to update CAD_tDRP & CAD_dcSRC_DRP if CAD_SNKToggleTime not initialized */
if ((0U == DPM_Settings[USBPD_PORT_0].CAD_SNKToggleTime) || (0U == DPM_Settings[USBPD_PORT_0].CAD_SRCToggleTime))
{
DPM_USER_Settings[USBPD_PORT_0].CAD_tDRP = 80U;
DPM_USER_Settings[USBPD_PORT_0].CAD_dcSRC_DRP = 50U;
}
else
{
DPM_USER_Settings[USBPD_PORT_0].CAD_dcSRC_DRP = (DPM_Settings[USBPD_PORT_0].CAD_SRCToggleTime * 100) / (DPM_Settings[USBPD_PORT_0].CAD_SRCToggleTime + DPM_Settings[USBPD_PORT_0].CAD_SNKToggleTime);
DPM_USER_Settings[USBPD_PORT_0].CAD_tDRP = (DPM_Settings[USBPD_PORT_0].CAD_SRCToggleTime * 100) / DPM_USER_Settings[USBPD_PORT_0].CAD_dcSRC_DRP;
}
#if USBPD_PORT_COUNT==2
if ((0U == DPM_Settings[USBPD_PORT_1].CAD_SNKToggleTime) || (0U == DPM_Settings[USBPD_PORT_1].CAD_SRCToggleTime))
{
DPM_USER_Settings[USBPD_PORT_1].CAD_tDRP = 80U;
DPM_USER_Settings[USBPD_PORT_1].CAD_dcSRC_DRP = 50U;
}
else
{
DPM_USER_Settings[USBPD_PORT_1].CAD_dcSRC_DRP = (DPM_Settings[USBPD_PORT_1].CAD_SRCToggleTime * 100) / (DPM_Settings[USBPD_PORT_1].CAD_SRCToggleTime + DPM_Settings[USBPD_PORT_1].CAD_SNKToggleTime);
DPM_USER_Settings[USBPD_PORT_1].CAD_tDRP = (DPM_Settings[USBPD_PORT_1].CAD_SRCToggleTime * 100) / DPM_USER_Settings[USBPD_PORT_1].CAD_dcSRC_DRP;
}
#endif /* USBPD_PORT_COUNT==2 */
pCB_HWBoardVersion = CB_HWBoardVersion;
pCB_HWPDType = CB_HWPDType;
pCB_GetVoltage = CB_GetVoltage;
pCB_GetCurrent = CB_GetCurrent;
/* Register 2 callbacks for notification in DPM */
USBPD_DPM_SetNotification_GUI(GUI_FormatAndSendNotification, GUI_PostNotificationMessage, GUI_SaveInfo);
#if defined(_RTOS)
#if (osCMSIS < 0x20000U)
osMessageQDef(MsgBox, GUI_BOX_MESSAGES_MAX, uint32_t);
osThreadDef(GUI, TaskGUI, FREERTOS_GUI_PRIORITY, 0, FREERTOS_GUI_STACK_SIZE);
GUIMsgBox = osMessageCreate(osMessageQ(MsgBox), NULL);
if(NULL == osThreadCreate(osThread(GUI), &GUIMsgBox))
#else
GUIMsgBox = osMessageQueueNew (GUI_BOX_MESSAGES_MAX, sizeof(uint32_t), NULL);
if (NULL == osThreadNew(TaskGUI, &GUIMsgBox, &GUI_Thread_Atrr))
#endif /* osCMSIS < 0x20000U */
{
_status = USBPD_DISABLE;
}
/* Enable IRQ which has been disabled by FreeRTOS services */
__enable_irq();
#else /* RTOS */
GUI_Start();
#if defined(USE_STM32_UTILITY_OS)
UTIL_SEQ_RegTask(TASK_GUI, 0, GUI_Execute);
UTIL_SEQ_SetTask(TASK_GUI, 0);
#endif /*USE_STM32_UTILITY_OS */
#endif /* _RTOS */
return _status;
}
void GUI_Start(void)
{
/* register the GUI callback to manage UART reception */
TRACER_EMB_StartRX(GUI_CALLBACK_RX);
}
/**
* @brief GUI Task
* @param pEvent GUI User event
* @retval None
*/
#ifdef _RTOS
#if (osCMSIS < 0x20000U)
static void TaskGUI(void const *pEvent)
#else
static void TaskGUI(void *pEvent)
#endif /* osCMSIS < 0x20000U */
#else
void GUI_Execute(void)
#endif /* _RTOS */
{
#ifdef _RTOS
uint32_t _timing = osWaitForever;
osMessageQId queue = *(osMessageQId *)pEvent;
GUI_Start();
do
{
#if (osCMSIS < 0x20000U)
osEvent event = osMessageGet(queue, _timing);
switch (((GUI_USER_EVENT)event.value.v & 0xF))
#else
uint32_t event;
(void)osMessageQueueGet(queue, &event, NULL, _timing);
switch (((GUI_USER_EVENT)event & 0xF))
#endif /* osCMSIS < 0x20000U */
{
case GUI_USER_EVENT_GUI:
{
#if (osCMSIS < 0x20000U)
GUI_RXProcess((uint32_t)event.value.v);
#else
GUI_RXProcess((uint32_t)event);
#endif /* osCMSIS < 0x20000U */
/* Sent an event to check if measurement report has been requested */
#if (osCMSIS < 0x20000U)
osMessagePut(GUIMsgBox, GUI_USER_EVENT_TIMER, 0);
#else
uint32_t event = GUI_USER_EVENT_TIMER;
(void)osMessageQueuePut(GUIMsgBox, &event, 0U, 0U);
#endif /* osCMSIS < 0x20000U */
break;
}
case GUI_USER_EVENT_TIMER:
{
#endif /* _RTOS */
#ifndef _RTOS
switch (GUI_Flag & 0xF)
{
case GUI_USER_EVENT_NONE:
break;
case GUI_USER_EVENT_GUI:
GUI_RXProcess(GUI_Flag);
case GUI_USER_EVENT_TIMER:
break;
default:
break;
}
GUI_Flag = GUI_USER_EVENT_NONE;
#endif /* !_RTOS */
for(uint8_t _instance = 0; _instance < USBPD_PORT_COUNT; _instance++)
{
/* ------------------------------------------------- */
/* Check if timeout related to Measurement reporting */
/* ------------------------------------------------- */
/* - Send a GUI Event only if PE is connected
and Measurement report has been enabled */
if ((USBPD_TRUE == DPM_Params[_instance].PE_IsConnected)
&& (1 == GUI_USER_Params[_instance].u.d.MeasReportActivation)
&& (0 != GUI_USER_Params[_instance].u.d.MeasReportValue))
{
/* Check if timer has expired */
if (IS_GUI_TIMER_EXPIRED(_instance, GUI_TimerMeasReport))
{
uint32_t event_mr = GUI_USER_EVENT_GUI | (_instance << GUI_PE_PORT_NUM_Pos) | (GUI_NOTIF_MEASUREMENT << GUI_PE_NOTIF_Pos);
GUI_RXProcess(event_mr);
}
/* Start or Restart Measurement report timer */
if (!(IS_GUI_TIMER_RUNNING(_instance, GUI_TimerMeasReport)))
{
GUI_START_TIMER(_instance, GUI_TimerMeasReport, (GUI_USER_Params[_instance].u.d.MeasReportValue * GUI_NOTIF_MEASUREMENT_STEP));
}
}
else
{
/* Stop measurement report timer */
GUI_TimerMeasReport[_instance] = 0;
}
}
#ifdef _RTOS
break;
}
default:
break;
}
_timing = CheckGUITimers();
}
while(1);
#endif /* !_RTOS */
}
#ifdef _RTOS
static uint32_t CheckGUITimers(void)
{
uint32_t _timing = osWaitForever;
uint32_t _current_timing;
/* Calculate the minimum timers to wake-up GUI task */
for(uint8_t instance = 0; instance < USBPD_PORT_COUNT; instance++)
{
/* Check if Measurement reporting has been enabled by the GUI */
_current_timing = GUI_TimerMeasReport[instance] & GUI_TIMER_READ_MSK;
if(_current_timing > 0)
{
if (_current_timing < _timing)
{
_timing = _current_timing;
}
}
}
return _timing;
}
#endif /* !_RTOS */
void GUI_TimerCounter(void)
{
/* Increment GUI timer only if Measurement report has been activated */
if (1 == GUI_USER_Params[USBPD_PORT_0].u.d.MeasReportActivation)
{
if((GUI_TimerMeasReport[USBPD_PORT_0] & GUI_TIMER_READ_MSK) > 0)
{
GUI_TimerMeasReport[USBPD_PORT_0]--;
}
#if !defined(_RTOS)&&defined(USE_STM32_UTILITY_OS)
else
{
UTIL_SEQ_SetTask(TASK_GUI, 0);
}
#endif /* !_RTOS && USE_STM32_UTILITY_OS */
}
#if USBPD_PORT_COUNT==2
if (1 == GUI_USER_Params[USBPD_PORT_1].u.d.MeasReportActivation)
{
if((GUI_TimerMeasReport[USBPD_PORT_1] & GUI_TIMER_READ_MSK) > 0)
{
GUI_TimerMeasReport[USBPD_PORT_1]--;
}
#if !defined(_RTOS)&&defined(USE_STM32_UTILITY_OS)
else
{
UTIL_SEQ_SetTask(TASK_GUI, 0);
}
#endif /* !_RTOS && USE_STM32_UTILITY_OS */
}
#endif /* USBPD_PORT_COUNT == 2 */
}
/**
* @brief callback called to end a transfer.
* @param Character Byte received by the device
* @param Error Error detected in the reception
* @retval 1 if message to send to DPM application
*/
void GUI_CALLBACK_RX(uint8_t Character, uint8_t Error)
{
uint32_t event;
__disable_irq();
event = GUI_GetMessage(Character, Error);
__enable_irq();
if (event == 1)
{
#if defined(_RTOS)
#if (osCMSIS < 0x20000U)
(void)osMessagePut(GUIMsgBox, GUI_USER_EVENT_GUI, 1);
#else
uint32_t event = GUI_USER_EVENT_GUI;
(void)osMessageQueuePut(GUIMsgBox, &event, 0U, 0U);
#endif /* osCMSIS < 0x20000U */
#else
GUI_Flag = GUI_USER_EVENT_GUI;
#if defined(USE_STM32_UTILITY_OS)
GUI_RXProcess(GUI_Flag);
GUI_Flag = GUI_USER_EVENT_NONE;
#endif /* USE_STM32_UTILITY_OS */
#endif /* _RTOS */
}
}
/**
* @brief Main Trace RX process to push data on the media.
* @param Event GUI trace event
* @retval Timing
*/
uint32_t GUI_RXProcess(uint32_t Event)
{
uint8_t *msg;
USBPD_GUI_State state;
uint8_t size;
if (0 == (Event & GUI_PE_NOTIF_Msk))
{
/* Message have been received by GUI */
state = GUI_SendAnswer(&msg, &size);
switch (state)
{
case GUI_STATE_RESET:
/* DPM_RESET_REQ received by the device */
/* Save parameters in FLASH */
BSP_GUI_SaveDataInFlash();
HAL_NVIC_SystemReset();
break;
case GUI_STATE_INIT:
/* DPM_INIT_REQ received by the device */
break;
default:
/* Another GUI messages received by the device */
TRACER_EMB_Add(msg, size);
break;
}
}
else
{
uint16_t type_event = (Event & GUI_PE_NOTIF_Msk) >> GUI_PE_NOTIF_Pos;
if (GUI_NOTIF_MEASUREMENT == type_event)
{
/* Notification related to timeout for measure reporting */
/* Send a notification to associated port */
GUI_FormatAndSendNotification(((Event & GUI_PE_PORT_NUM_Msk) >> GUI_PE_PORT_NUM_Pos), GUI_NOTIF_MEASUREREPORTING, HAL_GetTick());
}
else
{
/* Message have been received by PE */
/* Send a notification to associated port */
GUI_FormatAndSendNotification(((Event & GUI_PE_PORT_NUM_Msk) >> GUI_PE_PORT_NUM_Pos), GUI_NOTIF_PE_EVENT, type_event);
}
}
return 0;
}
/**
* @brief TRACE function to send a notification
* @param PortNum Index of current used port
* @param TypeNotification Type of requested notification is a combination of @ref USBPD_TRACE_TRACE_TYPE_NOTIFICATION
* @param Value Value depending of TypeNotification
* @note If TypeNotification == GUI_NOTIF_ISCONNECTED, Value should be equal to 0 (Not connected) or 1 (connected)
* @retval USBPD Status
*/
uint32_t GUI_FormatAndSendNotification(uint32_t PortNum, uint32_t TypeNotification, uint32_t Value)
{
uint8_t *msg;
uint8_t size;
/* Only send notification if GUI is connected */
if (GUI_STATE_INIT != GUI_SendNotification(PortNum, &msg, &size, TypeNotification, Value))
{
TRACER_EMB_Add(msg, size);
}
return 0;
}
/**
* @brief Function called through UART IT RX to fill the GUI RX buffer
* @param Character Received byte
* @param Error Error if issue during reception
* @retval 1 indicates that a complete GUI message have been received
*/
uint32_t GUI_GetMessage(uint8_t Character, uint8_t Error)
{
uint32_t status = 0;
static uint16_t counter = 0; /* Allows for example to count the number of SOF or EOF we received consecutively */
static uint16_t cursor = 0; /* Our position in the buffer */
static uint16_t currentSize; /* How many bytes we should expect */
static enum receptionStateMachine
{
Rstart,
RonGoing,
Rsize,
Rend,
Rerror
} Rstate = Rstart;
if(cursor < TLV_SIZE_MAX)
{
PtrDataRx[cursor] = Character;
}
else /* buffer too small, overflow */
{
cursor = 0;
counter = 0;
Rstate = Rstart;
return 0;
}
if(Error) Rstate = Rerror;
switch(Rstate)
{
case Rstart :
if(PtrDataRx[cursor] == TLV_SOF)
{
counter++;
}
else
{
counter = 0;
cursor = 0xFFFF; /* cursor is unsigned, but it will inevitably increments at the end of function, and we need a 0 at the next pass here */
}
if(counter == 4) /* The whole SOF is received */
{
counter = 0;
Rstate = Rsize;
}
break;
case Rsize :
counter++;
if(counter == 3) /* We have received the size */
{
currentSize = (PtrDataRx[cursor-1] << 8) + PtrDataRx[cursor];
if (0 == currentSize)
{
Rstate = Rend;
}
else
{
Rstate = RonGoing;
}
counter = 0;
}
break;
case RonGoing :
counter++;
if(counter == currentSize)
{
/* When there is no value, the first EOF is handled by Rongoing, before Rend takes control */
counter = 0;
Rstate = Rend;
}
break;
case Rend :
counter++;
if(PtrDataRx[cursor] == TLV_EOF
&& PtrDataRx[cursor-1] == TLV_EOF
&& PtrDataRx[cursor-2] == TLV_EOF
&& PtrDataRx[cursor-3] == TLV_EOF)
{
/* The semaphore must be given only in this case, because otherwise it means we didn't receive the correct size of bytes */
if(counter == 4)
{
status = 1;
}
counter = 0;
cursor = 0xFFFF;
Rstate = Rstart;
}
if(cursor == currentSize + 11)
{
/* No complete EOF arrived. We reset the buffer for safety even if the instruction might be complete. */
counter = 0;
cursor = 0xFFFF;
Rstate = Rstart;
}
break;
case Rerror :
counter = 0;
cursor = 0xFFFF;
Rstate = Rstart;
break;
}
cursor++;
return status;
}
/**
* @brief Answer to a message received by the GUI
* @param pMsgToSend Pointer on the message to send
* @param pSizeMsg Pointer on the size of the message to send
* @retval GUI state
*/
USBPD_GUI_State GUI_SendAnswer(uint8_t **pMsgToSend, uint8_t *pSizeMsg)
{
/* Extract the port from the tag*/
uint8_t port = PtrDataRx[TLV_TAG_POSITION] >> GUI_PORT_BIT_POSITION;
/* Do the appropriate treatment in response to what we have received */
switch(PtrDataRx[TLV_TAG_POSITION] & 0x1F)
{
case DPM_RESET_REQ:
/* Reset*/
return GUI_STATE_RESET;
case DPM_INIT_REQ:
{
Send_DpmInitCnf(port, Processed);
*pMsgToSend = Processed;
*pSizeMsg = TLV_get_string_length(Processed) + 8;
TRACER_EMB_Add(*pMsgToSend, *pSizeMsg);
GUI_State = GUI_STATE_RUNNING;
if (0 == port)
{
/* Send a notification all the port */
GUI_FormatAndSendNotification(USBPD_PORT_0, GUI_NOTIF_ISCONNECTED | GUI_NOTIF_PE_EVENT | GUI_NOTIF_TIMESTAMP, USBPD_NOTIFY_ALL);
#if USBPD_PORT_COUNT==2
GUI_FormatAndSendNotification(USBPD_PORT_1, GUI_NOTIF_ISCONNECTED | GUI_NOTIF_PE_EVENT | GUI_NOTIF_TIMESTAMP, USBPD_NOTIFY_ALL);
#endif /* USBPD_PORT_COUNT == 2 */
}
return GUI_STATE_INIT;
}
case DPM_CONFIG_GET_REQ:
if (0 != port)
{
Send_DpmConfigGetCnf((port - 1), PtrDataRx, Processed);
}
else
{
Send_DpmConfigGetRej(port, Processed, GUI_REJ_DPM_INVALID_PORT_NUMBER);
}
break;
case DPM_CONFIG_SET_REQ:
if (0 != port)
{
Send_DpmConfigSetCnf((port - 1), PtrDataRx, Processed);
}
else
{
Send_DpmConfigGetRej(port, Processed, GUI_REJ_DPM_INVALID_PORT_NUMBER);
}
break;
case DPM_MESSAGE_REQ:
if (0 != port)
{
Request_MessageReq((port - 1), PtrDataRx, Processed);
}
else
{
Send_DpmMessageRej(port, Processed, GUI_REJ_DPM_INVALID_PORT_NUMBER);
}
break;
case DPM_REGISTER_READ_REQ:
if (0 != port)
{
/* If size is 0*/
if(!PtrDataRx[TLV_LENGTH_HIGH_POSITION] && !PtrDataRx[TLV_LENGTH_LOW_POSITION])
{
Send_DpmRegisterReadCnf((port - 1), Processed, 0xFF);
}
else
{
/* PtrDataRx[TLV_VALUE_POSITION] is the tag in parameter,
when only one parameter is needed (cf USBPD GUI specification)*/
Send_DpmRegisterReadCnf((port - 1), Processed, PtrDataRx[TLV_VALUE_POSITION]);
}
}
else
{
Send_DpmConfigGetRej(port, Processed, GUI_REJ_DPM_INVALID_PORT_NUMBER);
}
break;
case DPM_REGISTER_WRITE_REQ:
if (0 != port)
{
Send_DpmRegisterWriteCnf((port - 1), Processed, PtrDataRx);
}
else
{
Send_DpmConfigGetRej(port, Processed, GUI_REJ_DPM_INVALID_PORT_NUMBER);
}
break;
default :
break;
}
*pMsgToSend = Processed;
*pSizeMsg = TLV_get_string_length(Processed) + 8;
return GUI_State;
}
/**
* @brief Answer to a message received by the GUI
* @param PortNum Port number
* @param pMsgToSend Pointer on the message to send
* @param pSizeMsg Pointer on the size of the message to send
* @param TypeNotification Type of the notification
* @param Value Value of the notification
* @retval GUI state
*/
USBPD_GUI_State GUI_SendNotification(uint8_t PortNum, uint8_t **pMsgToSend, uint8_t *pSizeMsg, uint32_t TypeNotification, uint32_t Value)
{
TLV_ToSend_Data send_tlv;
USBPD_GUI_State gui_state = GUI_STATE_INIT;
/* Send a notitification only if GUI is running */
if (GUI_State == GUI_STATE_RUNNING)
{
TLV_init_encode(&send_tlv, __GUI_SET_TAG_ID((PortNum + 1), DPM_MESSAGE_IND), TLV_SIZE_MAX, Processed);
/* Check PD connection */
if ((TypeNotification & GUI_NOTIF_ISCONNECTED) == GUI_NOTIF_ISCONNECTED)
{
/* Is Connected*/
TLV_add(&send_tlv, GUI_IND_ISCONNECTED, 1, (uint8_t[]){DPM_Params[PortNum].PE_Power});
if (USBPD_TRUE == DPM_Params[PortNum].PE_IsConnected)
{
uint8_t rp_value = 0;
/* CC line */
TLV_add(&send_tlv, GUI_IND_CC, 1, (uint8_t[]){DPM_Params[PortNum].ActiveCCIs});
/* Power Role*/
TLV_add(&send_tlv, GUI_IND_POWERROLE, 1, (uint8_t[]){DPM_Params[PortNum].PE_PowerRole});
/* CC Default Current Advertised */
rp_value = 3; /* (uint8_t)CAD_GetRPValue(PortNum); */
TLV_add(&send_tlv, GUI_IND_CCDEFAULTCURRENTADVERTISED, 1, &rp_value);
if (USBPD_POWER_EXPLICITCONTRACT == DPM_Params[PortNum].PE_Power)
{
/* Data Role*/
TLV_add(&send_tlv, GUI_IND_DATAROLE, 1, (uint8_t[]){DPM_Params[PortNum].PE_DataRole});
/* Vconn ON*/
TLV_add(&send_tlv, GUI_IND_VCONNON, 1, (uint8_t[]){DPM_Params[PortNum].VconnStatus});
/* PD_Spec Revision */
TLV_add(&send_tlv, GUI_IND_PD_SPECREVISION, 1, (uint8_t[]){DPM_Params[PortNum].PE_SpecRevision});
}
}
}
/* Check PD message event */
if ((TypeNotification & GUI_NOTIF_PE_EVENT) == GUI_NOTIF_PE_EVENT)
{
if (USBPD_NOTIFY_ALL != Value)
{
/* PD_MessageNotif */
TLV_add(&send_tlv, GUI_IND_PD_MESSAGENOTIF, 1, (uint8_t*)&Value);
switch (Value)
{
case USBPD_NOTIFY_POWER_STATE_CHANGE :
/* Is Connected*/
TLV_add(&send_tlv, GUI_IND_ISCONNECTED, 1, (uint8_t[]){DPM_Params[PortNum].PE_Power});
if (USBPD_POWER_NO == DPM_Params[PortNum].PE_Power)
{
/* CC line */
TLV_add(&send_tlv, GUI_IND_CC, 1, (uint8_t[]){DPM_Params[PortNum].ActiveCCIs});
/* PowerRole*/
TLV_add(&send_tlv, GUI_IND_POWERROLE, 1, (uint8_t[]){DPM_Params[PortNum].PE_PowerRole});
}
break;
case USBPD_NOTIFY_GETSNKCAP_ACCEPTED :
/* NumberOfRcvSNKPDO */
TLV_add(&send_tlv, GUI_IND_NUMBEROFRCVSNKPDO, 1, (uint8_t[]){GUI_SaveInformation[PortNum].NumberOfRcvSNKPDO});
/* ListOfRcvSNKPDO*/
TLV_add(&send_tlv, GUI_IND_LISTOFRCVSNKPDO, GUI_SaveInformation[PortNum].NumberOfRcvSNKPDO * 4, (uint8_t *) GUI_SaveInformation[PortNum].ListOfRcvSNKPDO);
break;
case USBPD_NOTIFY_GETSRCCAP_ACCEPTED :
/* NumberOfRcvSRCPDO*/
TLV_add(&send_tlv, GUI_IND_NUMBEROFRCVSRCPDO, 1, (uint8_t[]){GUI_SaveInformation[PortNum].NumberOfRcvSRCPDO});
/* ListOfRcvSRCPDO*/
TLV_add(&send_tlv, GUI_IND_LISTOFRCVSRCPDO, GUI_SaveInformation[PortNum].NumberOfRcvSRCPDO * 4, (uint8_t *) GUI_SaveInformation[PortNum].ListOfRcvSRCPDO);
break;
case USBPD_NOTIFY_POWER_EXPLICIT_CONTRACT :
if (USBPD_PORTPOWERROLE_SNK == DPM_Params[PortNum].PE_PowerRole)
{
/* NumberOfRcvSRCPDO*/
TLV_add(&send_tlv, GUI_IND_NUMBEROFRCVSRCPDO, 1, (uint8_t[]){GUI_SaveInformation[PortNum].NumberOfRcvSRCPDO});
/* ListOfRcvSRCPDO*/
TLV_add(&send_tlv, GUI_IND_LISTOFRCVSRCPDO, GUI_SaveInformation[PortNum].NumberOfRcvSRCPDO * 4, (uint8_t *) GUI_SaveInformation[PortNum].ListOfRcvSRCPDO);
}
/* RDOPosition */
TLV_add(&send_tlv, GUI_IND_RDOPOSITION, 1, (uint8_t[]){GUI_SaveInformation[PortNum].RDOPosition});
/* DataRole*/
TLV_add(&send_tlv, GUI_IND_DATAROLE, 1, (uint8_t[]){DPM_Params[PortNum].PE_DataRole});
/* PowerRole*/
TLV_add(&send_tlv, GUI_IND_POWERROLE, 1, (uint8_t[]){DPM_Params[PortNum].PE_PowerRole});
/* VconnON*/
TLV_add(&send_tlv, GUI_IND_VCONNON, 1, (uint8_t[]){DPM_Params[PortNum].VconnStatus});
/* PD_SpecRevision */
TLV_add(&send_tlv, GUI_IND_PD_SPECREVISION, 1, (uint8_t[]){DPM_Params[PortNum].PE_SpecRevision});
break;
case USBPD_NOTIFY_POWER_SWAP_TO_SNK_DONE :
case USBPD_NOTIFY_POWER_SWAP_TO_SRC_DONE :
/* PowerRole*/
TLV_add(&send_tlv, GUI_IND_POWERROLE, 1, (uint8_t[]){DPM_Params[PortNum].PE_PowerRole});
break;
case USBPD_NOTIFY_DATAROLESWAP_UFP :
case USBPD_NOTIFY_DATAROLESWAP_DFP :
/* DataRole*/
TLV_add(&send_tlv, GUI_IND_DATAROLE, 1, (uint8_t[]){DPM_Params[PortNum].PE_DataRole});
break;
case USBPD_NOTIFY_PD_SPECIFICATION_CHANGE :
/* PD_SpecRevision */
TLV_add(&send_tlv, GUI_IND_PD_SPECREVISION, 1, (uint8_t[]){DPM_Params[PortNum].PE_SpecRevision});
break;
case USBPD_NOTIFY_VCONN_SWAP_COMPLETE :
/* VconnON */
TLV_add(&send_tlv, GUI_IND_VCONNON, 1, (uint8_t[]){DPM_Params[PortNum].VconnStatus});
break;
#if _PPS
case USBPD_NOTIFY_PPS_STATUS_RECEIVED :
/* PPS value */
TLV_add(&send_tlv, GUI_IND_PPS, 4, (uint8_t*)&GUI_SaveInformation[PortNum].RcvPPSStatus.d32);
break;
#endif /* _PPS */
#if _STATUS
case USBPD_NOTIFY_STATUS_RECEIVED :
{
uint8_t tab[5] = {
GUI_SaveInformation[PortNum].RcvStatus.InternalTemp,
GUI_SaveInformation[PortNum].RcvStatus.PresentInput,
GUI_SaveInformation[PortNum].RcvStatus.PresentBatteryInput,
GUI_SaveInformation[PortNum].RcvStatus.EventFlags,
GUI_SaveInformation[PortNum].RcvStatus.TemperatureStatus
};
/* Status value */
TLV_add(&send_tlv, GUI_IND_STATUS, 5, tab);
}
break;
#endif /* _STATUS */
#ifdef _VDM
case USBPD_NOTIFY_VDM_IDENTIFY_RECEIVED :
TLV_add(&send_tlv, GUI_IND_VDM_IDENTITY, 4, (uint8_t*)&GUI_SaveInformation[PortNum].VDM_DiscoIdentify.IDHeader.d32);
break;
case USBPD_NOTIFY_VDM_SVID_RECEIVED :
{
uint32_t index;
uint16_t size;
/* List of received SVDM SVID */
if (0 != GUI_SaveInformation[PortNum].VDM_SVIDPortPartner.NumSVIDs)
{
TLV_add(&send_tlv, GUI_IND_SVDM_SVIDS, 2, (uint8_t*)&GUI_SaveInformation[PortNum].VDM_SVIDPortPartner.SVIDs[0]);
size = 2;
for (index = 1; index < GUI_SaveInformation[PortNum].VDM_SVIDPortPartner.NumSVIDs; index++)
{
TLV_addValue(&send_tlv, (uint8_t*)&GUI_SaveInformation[PortNum].VDM_SVIDPortPartner.SVIDs[index], 2);
size += 2;
}
TLV_UpdateSizeTag(&send_tlv, size);
}
}
break;
case USBPD_NOTIFY_VDM_MODE_RECEIVED :
{
uint32_t index;
uint16_t size;
/* List of received SVDM MODES */
if (0 != GUI_SaveInformation[PortNum].VDM_ModesPortPartner.NumModes)
{
TLV_add(&send_tlv, GUI_IND_SVDM_MODES, 4, (uint8_t*)&GUI_SaveInformation[PortNum].VDM_ModesPortPartner.Modes[0]);
size = 4;
for (index = 1; index < GUI_SaveInformation[PortNum].VDM_ModesPortPartner.NumModes; index++)
{
TLV_addValue(&send_tlv, (uint8_t*)&GUI_SaveInformation[PortNum].VDM_ModesPortPartner.Modes[index], 4);
size += 4;
}
TLV_UpdateSizeTag(&send_tlv, size);
}
}
break;
#endif /* _VDM */
#if defined(_VCONN_SUPPORT)
case USBPD_NOTIFY_VDM_CABLE_IDENT_RECEIVED :
TLV_add(&send_tlv, GUI_IND_CABLE_VDO, 4, (uint8_t*)&GUI_SaveInformation[PortNum].VDM_DiscoCableIdentify.CableVDO.d32);
break;
#endif /* _VCONN_SUPPORT */
}
}
else
{
/* Send all the indication parameters if connected */
if (USBPD_TRUE == DPM_Params[PortNum].PE_IsConnected)
{
#if defined(_VDM)
uint32_t index;
#endif /* _VDM */
if (0 != GUI_SaveInformation[PortNum].NumberOfRcvSNKPDO)
{
/* NumberOfRcvSNKPDO */
TLV_add(&send_tlv, GUI_IND_NUMBEROFRCVSNKPDO, 1, (uint8_t[]){GUI_SaveInformation[PortNum].NumberOfRcvSNKPDO});
/* ListOfRcvSNKPDO*/
TLV_add(&send_tlv, GUI_IND_LISTOFRCVSNKPDO, GUI_SaveInformation[PortNum].NumberOfRcvSNKPDO * 4, (uint8_t *) GUI_SaveInformation[PortNum].ListOfRcvSNKPDO);
}
/* RDOPosition */
TLV_add(&send_tlv, GUI_IND_RDOPOSITION, 1, (uint8_t[]){GUI_SaveInformation[PortNum].RDOPosition});
if (USBPD_PORTPOWERROLE_SNK == DPM_Params[PortNum].PE_PowerRole)
{
/* NumberOfRcvSRCPDO*/
TLV_add(&send_tlv, GUI_IND_NUMBEROFRCVSRCPDO, 1, (uint8_t[]){GUI_SaveInformation[PortNum].NumberOfRcvSRCPDO});
/* ListOfRcvSRCPDO*/
TLV_add(&send_tlv, GUI_IND_LISTOFRCVSRCPDO, GUI_SaveInformation[PortNum].NumberOfRcvSRCPDO * 4, (uint8_t *) GUI_SaveInformation[PortNum].ListOfRcvSRCPDO);
}
/* PD_SpecRevision */
TLV_add(&send_tlv, GUI_IND_PD_SPECREVISION, 1, (uint8_t[]){DPM_Params[PortNum].PE_SpecRevision});
#if defined(USBPD_REV30_SUPPORT)
#if _SRC_CAPA_EXT
/* Number of batteries supported by the port partner */
TLV_add(&send_tlv, GUI_IND_NBBATTERIES, 1, (uint8_t[]){GUI_SaveInformation[PortNum].RcvSRCExtendedCapa.NbBatteries});
#endif /* _SRC_CAPA_EXT */
#endif /* USBPD_REV30_SUPPORT */
#if defined(_VDM)
if (0 != GUI_SaveInformation[PortNum].VDM_DiscoIdentify.IDHeader.d32)
{
TLV_add(&send_tlv, GUI_IND_VDM_IDENTITY, 4, (uint8_t*)&GUI_SaveInformation[PortNum].VDM_DiscoIdentify.IDHeader.d32);
}
#if defined(_VCONN_SUPPORT)
if (1 == GUI_SaveInformation[PortNum].VDM_DiscoCableIdentify.CableVDO_Presence)
{
TLV_add(&send_tlv, GUI_IND_CABLE_VDO, 4, (uint8_t*)&GUI_SaveInformation[PortNum].VDM_DiscoCableIdentify.CableVDO.d32);
}
#endif /* _VCONN_SUPPORT */
/* List of received SVDM SVID */
if (0 != GUI_SaveInformation[PortNum].VDM_SVIDPortPartner.NumSVIDs)
{
uint16_t size;
TLV_add(&send_tlv, GUI_IND_SVDM_SVIDS, 2, (uint8_t*)&GUI_SaveInformation[PortNum].VDM_SVIDPortPartner.SVIDs[0]);
size = 2;
for (index = 1; index < GUI_SaveInformation[PortNum].VDM_SVIDPortPartner.NumSVIDs; index++)
{
TLV_addValue(&send_tlv, (uint8_t*)&GUI_SaveInformation[PortNum].VDM_SVIDPortPartner.SVIDs[index], 2);
size += 2;
}
TLV_UpdateSizeTag(&send_tlv, size);
}
/* List of received SVDM MODES */
if (0 != GUI_SaveInformation[PortNum].VDM_ModesPortPartner.NumModes)
{
uint16_t size;
TLV_add(&send_tlv, GUI_IND_SVDM_MODES, 4, (uint8_t*)&GUI_SaveInformation[PortNum].VDM_ModesPortPartner.Modes[0]);
size = 4;
for (index = 1; index < GUI_SaveInformation[PortNum].VDM_ModesPortPartner.NumModes; index++)
{
TLV_addValue(&send_tlv, (uint8_t*)&GUI_SaveInformation[PortNum].VDM_ModesPortPartner.Modes[index], 4);
size += 4;
}
TLV_UpdateSizeTag(&send_tlv, size);
}
#endif /* _VDM */
}
}
}
/* Check if notification linked to a measure report */
if ((TypeNotification & GUI_NOTIF_MEASUREREPORTING) == GUI_NOTIF_MEASUREREPORTING)
{
uint32_t vsense = 0;
int32_t isense = 0;
TLV_add(&send_tlv, GUI_IND_TIMESTAMP, 4, (uint8_t*)&Value);
if (NULL != pCB_GetVoltage)
{
vsense = pCB_GetVoltage(PortNum);
}
if (NULL != pCB_GetVoltage)
{
isense = pCB_GetCurrent(PortNum);
if(isense < 0)
{
isense = -isense;
}
}
/* VBUS & IBUS level */
vsense = (isense << 16) | vsense;
TLV_add(&send_tlv, GUI_IND_VBUS_LEVEL, 4, (uint8_t*)&vsense);
}
/* Check if timestamp */
if ((TypeNotification & GUI_NOTIF_TIMESTAMP) == GUI_NOTIF_TIMESTAMP)
{
TLV_add(&send_tlv, GUI_IND_TIMESTAMP, 4, (uint8_t*)&Value);
}
/* Check if power change */
if ((TypeNotification & GUI_NOTIF_POWER_EVENT) == GUI_NOTIF_POWER_EVENT)
{
/* Is Connected*/
TLV_add(&send_tlv, GUI_IND_ISCONNECTED, 1, (uint8_t[]){DPM_Params[PortNum].PE_Power});
if (USBPD_POWER_NO == DPM_Params[PortNum].PE_Power)
{
/* CC line */
TLV_add(&send_tlv, GUI_IND_CC, 1, (uint8_t[]){DPM_Params[PortNum].ActiveCCIs});
/* PowerRole*/
TLV_add(&send_tlv, GUI_IND_POWERROLE, 1, (uint8_t[]){DPM_Params[PortNum].PE_PowerRole});
}
}
TLV_deinit_encode(&send_tlv);
if (0 != TLV_get_string_length(Processed))
{
*pMsgToSend = Processed;
*pSizeMsg = TLV_get_string_length(Processed) + 8;
gui_state = GUI_STATE_RUNNING;
}
}
return gui_state;
}
/**
* @brief Callback function called by PE to inform GUI about PE event.
* @param PortNum Port number
* @param EventVal Event vale @ref USBPD_NotifyEventValue_TypeDef
* @retval None
*/
void GUI_PostNotificationMessage(uint8_t PortNum, uint16_t EventVal)
{
#if defined(_SNK) || defined(_DRP)
if (USBPD_NOTIFY_REQUEST_ACCEPTED == EventVal)
{
DPM_USER_Settings[PortNum].DPM_SNKRequestedPower.OperatingVoltageInmVunits = GUI_SaveInformation[PortNum].RequestedVoltage;
DPM_USER_Settings[PortNum].DPM_SNKRequestedPower.OperatingPowerInmWunits = (GUI_SaveInformation[PortNum].RequestedVoltage * GUI_SaveInformation[PortNum].RequestedCurrent) / 1000;
}
#endif /* _SNK || _DRP */
/* Send a notitification only if GUI is running */
if (GUI_State == GUI_STATE_RUNNING)
{
uint32_t event = GUI_USER_EVENT_GUI | (PortNum << GUI_PE_PORT_NUM_Pos) | (EventVal << GUI_PE_NOTIF_Pos);
#if defined(_RTOS)
#if (osCMSIS < 0x20000U)
(void)osMessagePut(GUIMsgBox, event, 0);
#else
(void)osMessageQueuePut(GUIMsgBox, &event, 0U, 0U);
#endif /* osCMSIS < 0x20000U */
#else
GUI_Flag = event;
#if defined(USE_STM32_UTILITY_OS)
GUI_RXProcess(GUI_Flag);
GUI_Flag = GUI_USER_EVENT_NONE;
#endif /* USE_STM32_UTILITY_OS */
#endif /* _RTOS */
}
}
/**
* @brief Check is GUI is connected to the board or not
* @retval USBPD state
*/
USBPD_FunctionalState GUI_IsRunning(void)
{
return ((GUI_State == GUI_STATE_RUNNING) ? USBPD_ENABLE : USBPD_DISABLE);
}
/**
* @brief GUI callback to save information coming from PortPartner
* @param PortNum Port number
* @param DataId Type of data to be updated in DPM based on @ref USBPD_CORE_DataInfoType_TypeDef
* @param Ptr Pointer on the data
* @param Size Nb of bytes to be updated in GUI
* @retval None
*/
void GUI_SaveInfo(uint8_t PortNum, uint8_t DataId, uint8_t *Ptr, uint32_t Size)
{
uint32_t index;
/* Check type of information targeted by request */
switch (DataId)
{
/* Case requested DO position Data information :
*/
case USBPD_CORE_DATATYPE_RDO_POSITION :
if (Size == 4)
{
uint8_t* temp;
temp = (uint8_t*)&GUI_SaveInformation[PortNum].RDOPosition;
(void)memcpy(temp, Ptr, Size);
GUI_SaveInformation[PortNum].RDOPositionPrevious = *Ptr;
temp = (uint8_t*)&GUI_SaveInformation[PortNum].RDOPositionPrevious;
(void)memcpy(temp, Ptr, Size);
}
break;
/* Case Received Source PDO values Data information :
*/
case USBPD_CORE_DATATYPE_RCV_SRC_PDO :
if (Size <= (USBPD_MAX_NB_PDO * 4))
{
uint8_t* rdo;
GUI_SaveInformation[PortNum].NumberOfRcvSRCPDO = (Size / 4);
/* Copy PDO data in DPM Handle field */
for (index = 0; index < (Size / 4); index++)
{
rdo = (uint8_t*)&GUI_SaveInformation[PortNum].ListOfRcvSRCPDO[index];
(void)memcpy(rdo, (Ptr + (index * 4u)), (4u * sizeof(uint8_t)));
}
}
break;
/* Case Received Sink PDO values Data information :
*/
case USBPD_CORE_DATATYPE_RCV_SNK_PDO :
if (Size <= (USBPD_MAX_NB_PDO * 4))
{
uint8_t* rdo;
GUI_SaveInformation[PortNum].NumberOfRcvSNKPDO = (Size / 4);
/* Copy PDO data in DPM Handle field */
for (index = 0; index < (Size / 4); index++)
{
rdo = (uint8_t*)&GUI_SaveInformation[PortNum].ListOfRcvSNKPDO[index];
(void)memcpy(rdo, (Ptr + (index * 4u)), (4u * sizeof(uint8_t)));
}
}
break;
/* Case Received Request PDO Data information :
*/
case USBPD_CORE_DATATYPE_RCV_REQ_PDO :
if (Size == 4)
{
uint8_t* rdo;
rdo = (uint8_t*)&GUI_SaveInformation[PortNum].RcvRequestDOMsg;
(void)memcpy(rdo, Ptr, Size);
}
break;
#if defined(USBPD_REV30_SUPPORT)
#if _STATUS
case USBPD_CORE_INFO_STATUS :
{
uint8_t* info_status;
info_status = (uint8_t*)&GUI_SaveInformation[PortNum].RcvStatus;
memcpy(info_status, Ptr, Size);
}
break;
#endif /* _STATUS */
#if _PPS
case USBPD_CORE_PPS_STATUS :
{
uint8_t* ext_capa;
ext_capa = (uint8_t*)&GUI_SaveInformation[PortNum].RcvPPSStatus;
memcpy(ext_capa, Ptr, Size);
}
break;
#endif /* _PPS */
#if _SRC_CAPA_EXT
case USBPD_CORE_EXTENDED_CAPA :
{
uint8_t* ext_capa;
ext_capa = (uint8_t*)&GUI_SaveInformation[PortNum].RcvSRCExtendedCapa;
memcpy(ext_capa, Ptr, Size);
}
break;
#endif /* _SRC_CAPA_EXT */
#if defined(USBPDCORE_SNK_CAPA_EXT)
case USBPD_CORE_SNK_EXTENDED_CAPA :
{
uint8_t* _snk_ext_capa;
_snk_ext_capa = (uint8_t*)&GUI_SaveInformation[PortNum].RcvSNKExtendedCapa;
memcpy(_snk_ext_capa, Ptr, Size);
}
break;
#endif /* USBPDCORE_SNK_CAPA_EXT */
#if _MANU_INFO
case USBPD_CORE_GET_MANUFACTURER_INFO:
{
uint8_t* temp = (uint8_t*)Ptr;
GUI_SaveInformation[PortNum].GetManufacturerInfo.ManufacturerInfoTarget = *temp;
GUI_SaveInformation[PortNum].GetManufacturerInfo.ManufacturerInfoRef = *(temp + 1);
}
break;
#endif /* _MANU_INFO */
#if _BATTERY
case USBPD_CORE_BATTERY_STATUS:
GUI_SaveInformation[PortNum].BatteryStatus.d32 = *Ptr;
break;
case USBPD_CORE_GET_BATTERY_STATUS:
{
GUI_SaveInformation[PortNum].GetBatteryStatus.BatteryStatusRef = *(uint8_t*)Ptr;
}
break;
case USBPD_CORE_GET_BATTERY_CAPABILITY:
{
uint8_t* temp = (uint8_t*)Ptr;
GUI_SaveInformation[PortNum].GetBatteryCapability.BatteryCapRef= *temp;
}
break;
#endif /* _BATTERY */
#if _ALERT
case USBPD_CORE_ALERT:
{
uint8_t* alert;
alert = (uint8_t*)&GUI_SaveInformation[PortNum].RcvAlert.d32;
memcpy(alert, Ptr, Size);
}
break;
#endif /* _ALERT */
#endif /* USBPD_REV30_SUPPORT */
#if defined(_VCONN_SUPPORT)
case GUI_VDM_CABLE_INFO:
{
uint8_t* disco_ident;
disco_ident = (uint8_t*)&GUI_SaveInformation[PortNum].VDM_DiscoCableIdentify;
memcpy(disco_ident, Ptr, Size);
}
break;
#endif /* _VCONN_SUPPORT */
/* In case of unexpected data type (Set request could not be fulfilled) :
*/
default :
break;
}
}
/**
* @brief Register callback function to be used with Free Text feature
* @param CB_FreeText Callback function to register (port number, payload and size)
* @retval None
*/
void GUI_RegisterCallback_FreeText(USBPD_StatusTypeDef (*CB_FreeText)(uint8_t, uint8_t*, uint16_t))
{
pCB_FreeText = CB_FreeText;
}
/**
* @}
*/
/** @defgroup USBPD_GUI_API_Private_Functions GUI API Private Functions
* @{
*/
/**
* @brief Send DPM_INIT_CNF message to GUI
* @param PortNum Port number
* @param pEncodedMsg Pointer on the message to be encoded
* @retval None
*/
static void Send_DpmInitCnf(uint8_t PortNum, uint8_t *pEncodedMsg)
{
TLV_ToSend_Data ToSendTLV;
TLV_init_encode(&ToSendTLV, __GUI_SET_TAG_ID(PortNum, DPM_INIT_CNF), TLV_SIZE_MAX, pEncodedMsg);
/* Information by board */
if (0 == PortNum)
{
/* HWBoardVersion */
const uint8_t* hwversion;
if (NULL != pCB_HWBoardVersion)
{
hwversion = pCB_HWBoardVersion();
}
else
{
hwversion = (uint8_t*) "UNKNOWN";
}
TLV_add(&ToSendTLV, GUI_INIT_HWBOARDVERSION, strlen((const char*)hwversion), hwversion);
/* HWPDType */
const uint8_t* hwpdtype;
if (NULL != pCB_HWBoardVersion)
{
hwpdtype = pCB_HWPDType();
}
else
{
hwpdtype = (uint8_t*) "UNKNOWN";
}
TLV_add(&ToSendTLV, GUI_INIT_HWPDTYPE, strlen((const char*)hwpdtype), hwpdtype);
/* NbPortMax */
TLV_add(&ToSendTLV, GUI_INIT_NBPORTMAX, 1, (uint8_t[]){USBPD_PORT_COUNT});
/* FW Version */
TLV_add(&ToSendTLV, GUI_INIT_FWVERSION, 8, (uint8_t[]){
(USBPD_FW_VERSION & 0x000000FF),
(USBPD_FW_VERSION & 0x0000FF00) >> 8,
(USBPD_FW_VERSION & 0x00FF0000) >> 16,
(USBPD_FW_VERSION & 0xFF000000) >> 24,
(_LIB_ID & 0x000000FF),
(_LIB_ID & 0x0000FF00) >> 8,
(_LIB_ID & 0x00FF0000) >> 16,
(_LIB_ID & 0xFF000000) >> 24}
);
/* Start Port number */
TLV_add(&ToSendTLV, GUI_INIT_NB_PORT_START, 1, (uint8_t[]){USBPD_START_PORT_NUMBER});
/* Start Port number */
TLV_add(&ToSendTLV, GUI_INIT_NB_PORT_START, 1, (uint8_t[]){USBPD_START_PORT_NUMBER});
/* Original settings */
TLV_add(&ToSendTLV, GUI_INIT_ORIGINAL_SETTINGS, 1, (uint8_t*)&GUI_OriginalSettings);
TLV_deinit_encode(&ToSendTLV);
}
else
{
uint16_t settings;
uint8_t port = PortNum - 1;
#if defined(MB1303)
uint16_t fake = 0xADDE;
#endif /*MB1303*/
/* TypeCSpecVersion & PDSpecRevision */
settings = DPM_Settings[port].PE_SpecRevision;
TLV_add(&ToSendTLV, GUI_INIT_TYPECSPECREVISION, 2, (uint8_t[]){0x12, settings});
#if defined(USBPD_REV30_SUPPORT)
/* Extended Messages UnCkunked */
settings = DPM_Settings[port].PE_PD3_Support.d.PE_UnchunkSupport;
TLV_add(&ToSendTLV, GUI_INIT_EXTENDEDMESSAGESUNCKUNKED, 1, (uint8_t*)&settings);
#endif /* USBPD_REV30_SUPPORT */
/* AccessorySupp */
settings = DPM_Settings[port].CAD_AccesorySupport;
TLV_add(&ToSendTLV, GUI_INIT_ACCESSORYSUPP, 1, (uint8_t*)&settings);
/*PowerAccessoryDetection*/
settings = DPM_USER_Settings[port].PWR_AccessoryDetection;
TLV_add(&ToSendTLV, GUI_INIT_POWERACCESSORYDETECTION, 1, (uint8_t*)&settings);
/*PowerAccessoryTransition*/
settings = DPM_USER_Settings[port].PWR_AccessoryTransition;
TLV_add(&ToSendTLV, GUI_INIT_POWERACCESSORYTRANSITION, 1, (uint8_t*)&settings);
/*IsCable*/
TLV_add(&ToSendTLV, GUI_INIT_ISCABLE, 1, (uint8_t[]){0x00});
/*TryFeature*/
settings = DPM_Settings[port].CAD_TryFeature;
TLV_add(&ToSendTLV, GUI_INIT_TRYFEATURE, 1, (uint8_t*)&settings);
/*RpResistorValue*/
settings = DPM_USER_Settings[port].PWR_RpResistorValue;
TLV_add(&ToSendTLV, GUI_INIT_RPRESISTORVALUE, 1, (uint8_t*)&settings);
/*USBSupport*/
settings = DPM_USER_Settings[port].USB_Support;
TLV_add(&ToSendTLV, GUI_INIT_USBSUPPORT, 1, (uint8_t*)&settings);
/*USBDevice*/
settings = DPM_USER_Settings[port].USB_Device;
TLV_add(&ToSendTLV, GUI_INIT_USBDEVICE, 1, (uint8_t*)&settings);
/*USBHost*/
settings = DPM_USER_Settings[port].USB_Host;
TLV_add(&ToSendTLV, GUI_INIT_USBHOST, 1, (uint8_t*)&settings);
/*Externally_Powered*/
settings = DPM_USER_Settings[port].PWR_UnconstrainedPower;
TLV_add(&ToSendTLV, GUI_INIT_UNCONSTRAINED_POWERED, 1, (uint8_t*)&settings);
/*USBSuspendSupport*/
settings = DPM_USER_Settings[port].USB_SuspendSupport;
TLV_add(&ToSendTLV, GUI_INIT_USBSUSPENDSUPPORT, 1, (uint8_t*)&settings);
#if defined(MB1303)
/*VConnDischarge*/
TLV_add(&ToSendTLV, GUI_INIT_VCONNDISCHARGE, 2, (uint8_t*)&fake);
/*VConnLim*/
TLV_add(&ToSendTLV, GUI_INIT_VCONNILIM, 2, (uint8_t*)&fake);
/*VConnLimValue*/
TLV_add(&ToSendTLV, GUI_INIT_VCONNILIMVALUE, 2, (uint8_t*)&fake);
/*VConnMonitoring*/
TLV_add(&ToSendTLV, GUI_INIT_VCONNMONITORING, 2, (uint8_t*)&fake);
/*VConnThresholdUVLO*/
TLV_add(&ToSendTLV, GUI_INIT_VCONNTHRESHOLDUVLO, 2, (uint8_t*)&fake);
/*VConnSupply*/
TLV_add(&ToSendTLV, GUI_INIT_VCONNSUPPLY, 2, (uint8_t*)&fake);
#endif /*MB1303*/
TLV_deinit_encode(&ToSendTLV);
}
}
/**
* @brief Execution of the message received
* @note Generation of a TLV instruction to send in the context of DPM_MESSAGE
*/
static void Request_MessageReq(uint8_t PortNum, uint8_t* instruction, uint8_t *pEncodedMsg)
{
USBPD_StatusTypeDef status = USBPD_ERROR;
TLV_Received_Data process_tlv;
TLV_ToSend_Data send_tlv;
TLV_init_decode(&process_tlv, instruction);
TLV_init_encode(&send_tlv, __GUI_SET_TAG_ID((PortNum + 1), DPM_MESSAGE_CNF), TLV_SIZE_MAX, pEncodedMsg);
/*
In case there is an error, we use this variable to know when to send a DPM_MESSAGE_REJ
instead of a DPM_MESSAGE_CNF. This variable contains the cause if there is one.
*/
USBPD_GUI_Reject_Reason error = GUI_REJ_DPM_REJECT;
uint8_t tag;
uint16_t length;
uint8_t *value;
TLV_get(&process_tlv, &tag, &length, &value);
switch(tag)
/*
Each case should:
- Apply his specific request in the stack. If parameters are needed, they can be found in the value pointer
- If there is an error, set the error variable according to it (cf USBPD_GUI_Specification)
- Otherwise in case of success, do nothing else
*/
{
case GUI_MSG_GOTOMIN :
status = USBPD_DPM_RequestGotoMin(PortNum);
break;
case GUI_MSG_PING :
status = USBPD_DPM_RequestPing(PortNum);
break;
case GUI_MSG_GET_SRC_CAPA :
status = USBPD_DPM_RequestGetSourceCapability(PortNum);
break;
case GUI_MSG_GET_SNK_CAPA :
status = USBPD_DPM_RequestGetSinkCapability(PortNum);
break;
case GUI_MSG_DR_SWAP :
status = USBPD_DPM_RequestDataRoleSwap(PortNum);
break;
case GUI_MSG_PR_SWAP :
status = USBPD_DPM_RequestPowerRoleSwap(PortNum);
break;
case GUI_MSG_VCONN_SWAP :
status = USBPD_DPM_RequestVconnSwap(PortNum);
break;
case GUI_MSG_SOURCE_CAPA :
status = USBPD_DPM_RequestSourceCapability(PortNum);
break;
case GUI_MSG_REQUEST :
{
uint16_t voltage = 0;
uint8_t nb_expected_tag = 0;
uint8_t index_pdo = 0;
if (length > TLV_SIZE_MAX) break;
TLV_get(&process_tlv, &tag, &length, &value);
while((0 != length) && (TLV_SIZE_MAX > length) && (nb_expected_tag < 2))
{
nb_expected_tag++;
if (GUI_PARAM_MSG_RDOPOSITION == (USBPD_GUI_Tag_ParamMsg)tag)
{
index_pdo = value[0];
}
else if (GUI_PARAM_MSG_REQUESTEDVOLTAGE == (USBPD_GUI_Tag_ParamMsg)tag)
{
voltage = LE16(&value[0]);
}
TLV_get(&process_tlv, &tag, &length, &value);
}
if (2 == nb_expected_tag)
{
status = USBPD_DPM_RequestMessageRequest(PortNum, index_pdo, voltage);
}
}
break;
case GUI_MSG_SOFT_RESET :
TLV_get(&process_tlv, &tag, &length, &value);
if (GUI_PARAM_MSG_SOPTYPE == (USBPD_GUI_Tag_ParamMsg)tag)
{
status = USBPD_DPM_RequestSoftReset(PortNum, (USBPD_SOPType_TypeDef)value[0]);
}
break;
case GUI_MSG_HARD_RESET :
status = USBPD_DPM_RequestHardReset(PortNum);
break;
case GUI_MSG_CABLE_RESET :
status = USBPD_DPM_RequestCableReset(PortNum);
break;
#if defined(_VDM) || defined(_VCONN_SUPPORT)
case GUI_MSG_VDM_DISCO_IDENT :
if (length > TLV_SIZE_MAX) break;
TLV_get(&process_tlv, &tag, &length, &value);
if (GUI_PARAM_MSG_SOPTYPE == (USBPD_GUI_Tag_ParamMsg)tag)
{
status = USBPD_DPM_RequestVDM_DiscoveryIdentify(PortNum, (USBPD_SOPType_TypeDef)value[0]);
}
break;
case GUI_MSG_VDM_DISCO_SVID :
if (length > TLV_SIZE_MAX) break;
TLV_get(&process_tlv, &tag, &length, &value);
if (GUI_PARAM_MSG_SOPTYPE == (USBPD_GUI_Tag_ParamMsg)tag)
{
status = USBPD_DPM_RequestVDM_DiscoverySVID(PortNum, (USBPD_SOPType_TypeDef)value[0]);
}
break;
case GUI_MSG_VDM_DISCO_MODE :
{
uint16_t svid = 0;
uint8_t nb_expected_tag = 0;
uint8_t sop = USBPD_SOPTYPE_SOP;
if (length > TLV_SIZE_MAX) break;
TLV_get(&process_tlv, &tag, &length, &value);
while((0 != length) && (TLV_SIZE_MAX > length) && (nb_expected_tag < 2))
{
nb_expected_tag++;
if (GUI_PARAM_MSG_SOPTYPE == (USBPD_GUI_Tag_ParamMsg)tag)
{
sop = value[0];
}
else if (GUI_PARAM_MSG_SVDM_SVID == (USBPD_GUI_Tag_ParamMsg)tag)
{
svid = LE16(&value[0]);
}
TLV_get(&process_tlv, &tag, &length, &value);
}
if (2 == nb_expected_tag)
{
status = USBPD_DPM_RequestVDM_DiscoveryMode(PortNum, (USBPD_SOPType_TypeDef)sop, svid);
}
}
break;
case GUI_MSG_VDM_ENTER_MODE :
{
uint16_t mode = 0, svid = 0;
uint8_t nb_expected_tag = 0;
uint8_t sop = USBPD_SOPTYPE_SOP;
if (length > TLV_SIZE_MAX) break;
TLV_get(&process_tlv, &tag, &length, &value);
while((0 != length) && (TLV_SIZE_MAX > length) && (nb_expected_tag < 3))
{
nb_expected_tag++;
if (GUI_PARAM_MSG_SOPTYPE == (USBPD_GUI_Tag_ParamMsg)tag)
{
sop = value[0];
}
else if (GUI_PARAM_MSG_SVDM_SVID == (USBPD_GUI_Tag_ParamMsg)tag)
{
svid = LE16(&value[0]);
}
else if (GUI_PARAM_MSG_SVDM_MODEINDEX == (USBPD_GUI_Tag_ParamMsg)tag)
{
mode = LE16(&value[0]);
}
TLV_get(&process_tlv, &tag, &length, &value);
}
if (3 == nb_expected_tag)
{
status = USBPD_DPM_RequestVDM_EnterMode(PortNum, (USBPD_SOPType_TypeDef)sop, svid, mode);
}
}
break;
case GUI_MSG_VDM_EXIT_MODE :
{
uint16_t svid = 0, mode = 0;
uint8_t nb_expected_tag = 0;
uint8_t sop = USBPD_SOPTYPE_SOP;
if (length > TLV_SIZE_MAX) break;
TLV_get(&process_tlv, &tag, &length, &value);
while((0 != length) && (TLV_SIZE_MAX > length) && (nb_expected_tag < 3))
{
nb_expected_tag++;
if (GUI_PARAM_MSG_SOPTYPE == (USBPD_GUI_Tag_ParamMsg)tag)
{
sop = value[0];
}
else if (GUI_PARAM_MSG_SVDM_SVID == (USBPD_GUI_Tag_ParamMsg)tag)
{
svid = LE16(&value[0]);
}
else if (GUI_PARAM_MSG_SVDM_MODEINDEX == (USBPD_GUI_Tag_ParamMsg)tag)
{
mode = value[0];
}
TLV_get(&process_tlv, &tag, &length, &value);
}
if (3 == nb_expected_tag)
{
status = USBPD_DPM_RequestVDM_ExitMode(PortNum, (USBPD_SOPType_TypeDef)sop, svid, mode);
}
}
break;
case GUI_MSG_VDM_UNSTRUCTURED :
break;
#endif /* _VDM || _VCONN_SUPPORT */
#if defined(_VDM)
case GUI_MSG_DISPLAY_PORT_STATUS :
{
uint32_t dp_status;
uint16_t svid = 0;
uint8_t nb_expected_tag = 0;
uint8_t sop = USBPD_SOPTYPE_SOP;
if (length > TLV_SIZE_MAX) break;
TLV_get(&process_tlv, &tag, &length, &value);
while((0 != length) && (TLV_SIZE_MAX > length) && (nb_expected_tag < 3))
{
nb_expected_tag++;
if (GUI_PARAM_MSG_SOPTYPE == (USBPD_GUI_Tag_ParamMsg)tag)
{
sop = value[0];
}
else if (GUI_PARAM_MSG_SVDM_SVID == (USBPD_GUI_Tag_ParamMsg)tag)
{
svid = LE16(&value[0]);
}
else if (GUI_PARAM_MSG_DP_STATUS == (USBPD_GUI_Tag_ParamMsg)tag)
{
dp_status = LE32(&value[0]);
}
TLV_get(&process_tlv, &tag, &length, &value);
}
if (3 == nb_expected_tag)
{
status = USBPD_DPM_RequestDisplayPortStatus(PortNum, (USBPD_SOPType_TypeDef)sop, svid, &dp_status);
}
}
break;
case GUI_MSG_DISPLAY_PORT_CONFIG :
{
uint32_t dp_config;
uint16_t svid = 0;
uint8_t nb_expected_tag = 0;
uint8_t sop = USBPD_SOPTYPE_SOP;
if (length > TLV_SIZE_MAX) break;
TLV_get(&process_tlv, &tag, &length, &value);
while((0 != length) && (TLV_SIZE_MAX > length) && (nb_expected_tag < 3))
{
nb_expected_tag++;
if (GUI_PARAM_MSG_SOPTYPE == (USBPD_GUI_Tag_ParamMsg)tag)
{
sop = value[0];
}
else if (GUI_PARAM_MSG_SVDM_SVID == (USBPD_GUI_Tag_ParamMsg)tag)
{
svid = LE16(&value[0]);
}
else if (GUI_PARAM_MSG_DP_CONFIGURE== (USBPD_GUI_Tag_ParamMsg)tag)
{
dp_config = LE32(&value[0]);
}
TLV_get(&process_tlv, &tag, &length, &value);
}
if (3 == nb_expected_tag)
{
status = USBPD_DPM_RequestDisplayPortConfig(PortNum, (USBPD_SOPType_TypeDef)sop, svid, &dp_config);
}
}
break;
case GUI_MSG_DISPLAY_PORT_ATTENTION :
break;
case GUI_MSG_VDM_ATTENTION :
{
uint16_t svid = 0;
uint8_t nb_expected_tag = 0;
uint8_t sop = USBPD_SOPTYPE_SOP;
if (length > TLV_SIZE_MAX) break;
TLV_get(&process_tlv, &tag, &length, &value);
while((0 != length) && (TLV_SIZE_MAX > length) && (nb_expected_tag < 2))
{
nb_expected_tag++;
if (GUI_PARAM_MSG_SOPTYPE == (USBPD_GUI_Tag_ParamMsg)tag)
{
sop = value[0];
}
else if (GUI_PARAM_MSG_SVDM_SVID == (USBPD_GUI_Tag_ParamMsg)tag)
{
svid = LE16(&value[0]);
}
TLV_get(&process_tlv, &tag, &length, &value);
}
if (2 == nb_expected_tag)
{
status = USBPD_DPM_RequestAttention(PortNum, (USBPD_SOPType_TypeDef)sop, svid);
}
}
break;
#endif /* _VDM */
case GUI_MSG_FREE_TEXT :
{
uint8_t nb_expected_tag = 0;
if (length > TLV_SIZE_MAX) break;
TLV_get(&process_tlv, &tag, &length, &value);
while((0 != length) && (TLV_SIZE_MAX > length) && (nb_expected_tag < 1))
{
nb_expected_tag++;
}
if (1 == nb_expected_tag)
{
status = Manage_FreeText(PortNum, value, length);
}
}
break;
#ifdef USBPD_REV30_SUPPORT
case GUI_MSG_FR_SWAP :
status = USBPD_DPM_RequestFastRoleSwap(PortNum);
break;
case GUI_MSG_GET_PPS_STATUS :
status = USBPD_DPM_RequestGetPPS_Status(PortNum);
break;
case GUI_MSG_GET_COUNTRY_CODES :
status = USBPD_DPM_RequestGetCountryCodes(PortNum);
break;
case GUI_MSG_GET_STATUS :
status = USBPD_DPM_RequestGetStatus(PortNum);
break;
case GUI_MSG_GET_SOURCE_CAPA_EXTENDED :
status = USBPD_DPM_RequestGetSourceCapabilityExt(PortNum);
break;
case GUI_MSG_GET_SINK_CAPA_EXTENDED :
status = USBPD_DPM_RequestGetSinkCapabilityExt(PortNum);
break;
case GUI_MSG_ALERT :
if (length > TLV_SIZE_MAX) break;
TLV_get(&process_tlv, &tag, &length, &value);
if (GUI_PARAM_MSG_ALERTMSG == (USBPD_GUI_Tag_ParamMsg)tag)
{
USBPD_ADO_TypeDef alert;
alert.d32 = LE32(&value[0]);
status = USBPD_DPM_RequestAlert(PortNum, alert);
}
break;
case GUI_MSG_GET_COUNTRY_INFO :
if (length > TLV_SIZE_MAX) break;
TLV_get(&process_tlv, &tag, &length, &value);
if (GUI_PARAM_MSG_COUNTRYCODE == (USBPD_GUI_Tag_ParamMsg)tag)
{
uint16_t country_code;
country_code = LE16(&value[0]);
status = USBPD_DPM_RequestGetCountryInfo(PortNum, country_code);
}
break;
case GUI_MSG_GET_BAT_CAPA :
if (length > TLV_SIZE_MAX) break;
TLV_get(&process_tlv, &tag, &length, &value);
if (GUI_PARAM_MSG_BATTERYREF == (USBPD_GUI_Tag_ParamMsg)tag)
{
status = USBPD_DPM_RequestGetBatteryCapability(PortNum, (uint8_t*)&value[0]);
}
break;
case GUI_MSG_GET_BAT_STATUS :
if (length > TLV_SIZE_MAX) break;
TLV_get(&process_tlv, &tag, &length, &value);
if (GUI_PARAM_MSG_BATTERYREF == (USBPD_GUI_Tag_ParamMsg)tag)
{
status = USBPD_DPM_RequestGetBatteryStatus(PortNum, (uint8_t*)&value[0]);
}
break;
case GUI_MSG_GET_MANU_INFO :
{
uint16_t manu_info;
uint8_t nb_expected_tag = 0;
uint8_t sop = USBPD_SOPTYPE_SOP;
if (length > TLV_SIZE_MAX) break;
TLV_get(&process_tlv, &tag, &length, &value);
while((0 != length) && (TLV_SIZE_MAX > length) && (nb_expected_tag < 2))
{
nb_expected_tag++;
if (GUI_PARAM_MSG_SOPTYPE == (USBPD_GUI_Tag_ParamMsg)tag)
{
sop = value[0];
}
else if (GUI_PARAM_MSG_MANUINFODATA == (USBPD_GUI_Tag_ParamMsg)tag)
{
manu_info = LE16(&value[0]);
}
TLV_get(&process_tlv, &tag, &length, &value);
}
if (2 == nb_expected_tag)
{
status = USBPD_DPM_RequestGetManufacturerInfo(PortNum, (USBPD_SOPType_TypeDef)sop, (uint8_t*)&manu_info);
}
}
break;
case GUI_MSG_SECU_REQUEST :
status = USBPD_DPM_RequestSecurityRequest(PortNum);
break;
case GUI_MSG_FIRM_UPDATE_REQUEST :
break;
#endif /* USBPD_REV30_SUPPORT */
default :
break;
}
/* Only applies if an error was specified (= if the case couldn't success)*/
if (USBPD_OK != status)
{
switch (status)
{
case USBPD_BUSY:
error = GUI_REJ_DPM_NOT_READY;
break;
case USBPD_TIMEOUT:
error = GUI_REJ_DPM_TIMEOUT;
break;
default:
case USBPD_NOTSUPPORTED:
case USBPD_ERROR:
error = GUI_REJ_DPM_REJECT;
break;
}
TLV_deinit_encode(&send_tlv);
TLV_init_encode(&send_tlv, __GUI_SET_TAG_ID((PortNum + 1), DPM_MESSAGE_REJ), TLV_SIZE_MAX, pEncodedMsg); /* Turn the tag 0x0A into 0x0B to signal an error*/
TLV_addValue(&send_tlv, (uint8_t*)&error, 1);
}
TLV_deinit_encode(&send_tlv);
TLV_deinit_decode(&process_tlv);
}
/**
* @brief Application of the received configuration
* @note Generation of a TLV instruction to send in the context of DPM_CONFIG_SET
*/
static void Send_DpmConfigSetCnf(uint8_t PortNum, uint8_t* instruction, uint8_t *pEncodedMsg)
{
TLV_ToSend_Data send_tlv;
TLV_Received_Data process_tlv;
/*
In case there is an error, we use this variable to know when to send a DPM_CONFIG_SET instead
of a DPM_MESSAGE_CNF. This variable contains the cause if there is one.
*/
uint8_t *value;
uint16_t size;
uint16_t dcdrp = 0;
uint8_t error = 0xFF;
uint8_t param_not_applicated[GUI_PARAM_ALL]; /* List of parameters who could not be applied. */
uint8_t counter_param_not_applicated = 0; /* Counter of not applicated parameters */
uint8_t tag, flag_drp = 0, tdrp = 0;
TLV_init_decode(&process_tlv, instruction);
/* This is the pEncodedMsg can be sent as it is at this point, if there isn't any error during application of settings*/
TLV_init_encode(&send_tlv, __GUI_SET_TAG_ID((PortNum + 1), DPM_CONFIG_SET_CNF), TLV_SIZE_MAX, pEncodedMsg);
/* Do while loop, used to parse and apply each parameter */
while(0xFF != TLV_get(&process_tlv, &tag, &size, &value))
/*
As long as we haven't read all the parameters. If error is set, we continue to loop
to apply the other parameters if it's because of a DPM_REJECT
While loop, used to parse and apply each parameter
*/
{
switch((USBPD_GUI_Tag_Param)tag)
/*
Each case should:
- Apply his specific parameter. If data is needed, it can be found in the value pointer
- In case of success, do nothing else
- Otherwise if there is an error, set the error variable according to it (cf USBPD_GUI_Specification)
- If the error is DPM_REJECT (0x00), add the parameter tag to param_not_applicated, using the
counter counter_param_not_applicated. It allows to list the rejected parameters in the DPM_CONFIG_REJ
*/
{
case GUI_PARAM_SOP :
#if !defined(USBPDCORE_LIB_NO_PD)
/* SOP & SOP1 & SOP2 */
/* SOP1_Debug & SOP2_Debug not implemented */
DPM_Settings[PortNum].PE_SupportedSOP = value[0];
#endif /* !USBPDCORE_LIB_NO_PD */
break;
#if defined(USBPD_REV30_SUPPORT)
case GUI_PARAM_FASTROLESWAP :
/*FastRoleSwap*/
DPM_Settings[PortNum].PE_PD3_Support.d.PE_FastRoleSwapSupport = value[0];
break;
#endif /*USBPD_REV30_SUPPORT*/
case GUI_PARAM_DATAROLESWAP_TO_UFP :
/*DataRoleSwap to UFP */
DPM_USER_Settings[PortNum].PE_DR_Swap_To_UFP = value[0];
break;
case GUI_PARAM_DATAROLESWAP_TO_DFP :
/*DataRoleSwap to DFP */
DPM_USER_Settings[PortNum].PE_DR_Swap_To_DFP = value[0];
break;
case GUI_PARAM_DEFAULTPOWERROLE :
/*DefaultPowerRole*/
DPM_Settings[PortNum].PE_DefaultRole = (USBPD_PortPowerRole_TypeDef)value[0];
break;
#if !defined(USBPDCORE_LIB_NO_PD)
case GUI_PARAM_DRP_SUPPORT :
/*DRP_Support*/
DPM_Settings[PortNum].PE_RoleSwap = value[0];
break;
case GUI_PARAM_CADROLETOGGLE :
/*CADRoleToggle*/
DPM_Settings[PortNum].CAD_RoleToggle = value[0];
break;
case GUI_PARAM_PE_SCAP_HR :
/*PE_SCAP_HR*/
DPM_Settings[PortNum].PE_CapscounterSupport = value[0];
break;
case GUI_PARAM_VCONNSWAP :
/*VConnSwap*/
DPM_USER_Settings[PortNum].PE_VconnSwap = value[0];
break;
#if defined(_VDM)
case GUI_PARAM_VDM_SUPPORT :
/* DRP Support */
DPM_Settings[PortNum].PE_VDMSupport = value[0];
break;
#endif /*_VDM*/
case GUI_PARAM_PING_SUPPORT :
/* Ping Support */
DPM_Settings[PortNum].PE_PingSupport = value[0];
break;
#if defined(USBPD_REV30_SUPPORT)
case GUI_PARAM_PPS_SUPPORT :
DPM_Settings[PortNum].PE_PD3_Support.PD3_Support = LE16(&value[0]);
break;
#endif /*USBPD_REV30_SUPPORT*/
#endif /* !USBPDCORE_LIB_NO_PD */
#if defined(_SNK) || defined(_DRP)
case GUI_PARAM_SNK_PDO :
{
uint32_t index_pdo, index_gui;
uint32_t pdo;
#if USBPD_PORT_COUNT==2
if (USBPD_PORT_0 == PortNum)
#endif /* USBPD_PORT_COUNT==2 */
{
memset(PORT0_PDO_ListSNK, 0, sizeof(PORT0_PDO_ListSNK));
for (index_pdo = 0, index_gui = 0; index_gui < size; index_pdo++)
{
pdo = LE32(&value[index_gui]);
PORT0_PDO_ListSNK[index_pdo] = pdo;
index_gui = index_gui + 4;
}
USBPD_NbPDO[0] = (size / 4);
UpdateSNKPowerPort0();
}
#if USBPD_PORT_COUNT==2
else
{
memset(PORT1_PDO_ListSNK, 0, sizeof(PORT1_PDO_ListSNK));
for (index_pdo = 0, index_gui = 0; index_gui < size; index_pdo++)
{
pdo = LE32(&value[index_gui]);
PORT1_PDO_ListSNK[index_pdo] = pdo;
index_gui = index_gui + 4;
}
USBPD_NbPDO[2] = (size / 4);
UpdateSNKPowerPort1();
}
#endif /* USBPD_PORT_COUNT==2 */
}
break;
#endif /* (_SNK) || (_DRP) */
#if defined(_SRC) || defined(_DRP)
case GUI_PARAM_SRC_PDO :
{
uint32_t index_pdo, index_gui;
uint32_t pdo;
#if USBPD_PORT_COUNT==2
if (USBPD_PORT_0 == PortNum)
#endif /* USBPD_PORT_COUNT==2 */
{
memset(PORT0_PDO_ListSRC, 0, sizeof(PORT0_PDO_ListSRC));
for (index_pdo = 0, index_gui = 0; index_gui < size; index_pdo++)
{
pdo = LE32(&value[index_gui]);
PORT0_PDO_ListSRC[index_pdo] = pdo;
index_gui = index_gui + 4;
}
USBPD_NbPDO[1] = (size / 4);
}
#if USBPD_PORT_COUNT==2
else
{
memset(PORT1_PDO_ListSRC, 0, sizeof(PORT1_PDO_ListSRC));
for (index_pdo = 0, index_gui = 0; index_gui < size; index_pdo++)
{
pdo = LE32(&value[index_gui]);
PORT1_PDO_ListSRC[index_pdo] = pdo;
index_gui = index_gui + 4;
}
USBPD_NbPDO[3] = (size / 4);
}
#endif /* USBPD_PORT_COUNT==2 */
}
break;
#endif /* (_SRC) || (_DRP) */
case GUI_PARAM_TDRP :
tdrp = value[0];
DPM_USER_Settings[PortNum].CAD_tDRP = tdrp;
flag_drp = 1;
break;
case GUI_PARAM_DCSRC_DRP :
dcdrp = value[0];
DPM_USER_Settings[PortNum].CAD_dcSRC_DRP = dcdrp;
flag_drp = 1;
break;
case GUI_PARAM_RESPONDS_TO_DISCOV_SOP :
DPM_Settings[PortNum].PE_RespondsToDiscovSOP = value[0];
break;
case GUI_PARAM_ATTEMPTS_DISCOV_SOP :
DPM_Settings[PortNum].PE_AttemptsDiscovSOP = value[0];
break;
case GUI_PARAM_XID_SOP :
DPM_ID_Settings[PortNum].XID = LE32(&value[0]);
break;
case GUI_PARAM_USB_VID_SOP :
DPM_ID_Settings[PortNum].VID = LE16(&value[0]);
break;
case GUI_PARAM_PID_SOP :
DPM_ID_Settings[PortNum].PID = LE16(&value[0]);
break;
#if defined(_VDM)
case GUI_PARAM_DATA_CAPABLE_AS_USB_HOST_SOP :
DPM_VDM_Settings[PortNum].VDM_USBHostSupport = (USBPD_USBCapa_TypeDef)value[0];
break;
case GUI_PARAM_DATA_CAPABLE_AS_USB_DEVICE_SOP :
DPM_VDM_Settings[PortNum].VDM_USBDeviceSupport = (USBPD_USBCapa_TypeDef)value[0];
break;
case GUI_PARAM_PRODUCT_TYPE_SOP :
DPM_VDM_Settings[PortNum].VDM_ProductTypeUFPorCP= (USBPD_ProductType_TypeDef)value[0];
break;
case GUI_PARAM_MODAL_OPERATION_SUPPORTED_SOP :
DPM_VDM_Settings[PortNum].VDM_ModalOperation = (USBPD_ModalOp_TypeDef)value[0];
break;
case GUI_PARAM_BCDDEVICE_SOP :
DPM_VDM_Settings[PortNum].VDM_bcdDevice_SOP = LE16(&value[0]);
break;
#endif /* _VDM */
case GUI_PARAM_MEASUREREPORTING :
/* MeasurementReporting */
GUI_USER_Params[PortNum].u.MeasurementReporting = value[0];
break;
#if defined(USBPD_REV30_SUPPORT)
#if _MANU_INFO
case GUI_PARAM_MANUINFOPORT_VID :
DPM_USER_Settings[PortNum].DPM_ManuInfoPort.VID = LE16(&value[0]);
DPM_USER_Settings[PortNum].DPM_ManuInfoPort.PID = LE16(&value[2]);
size -= 4;
memcpy(DPM_USER_Settings[PortNum].DPM_ManuInfoPort.ManuString, &value[4], size);
break;
#endif /* _MANU_INFO */
#endif /*USBPD_REV30_SUPPORT*/
default :
error = GUI_REJ_DPM_REJECT;
param_not_applicated[counter_param_not_applicated] = tag;
counter_param_not_applicated++;
break;
}
}
#if !defined(USBPDCORE_LIB_NO_PD)
/* Updtate CAD_SNKToggleTime & CAD_SRCToggleTime only if TDRP and/or DC_SRC_DRP have been received */
if (1 == flag_drp)
{
uint16_t calcul;
if (0 == tdrp)
{
tdrp = DPM_Settings[PortNum].CAD_SNKToggleTime + DPM_Settings[PortNum].CAD_SRCToggleTime;
}
if (0 == dcdrp)
{
dcdrp = (DPM_Settings[PortNum].CAD_SRCToggleTime * 100) / (DPM_Settings[PortNum].CAD_SNKToggleTime + DPM_Settings[PortNum].CAD_SRCToggleTime);
}
calcul = (tdrp * dcdrp) / 100;
DPM_Settings[PortNum].CAD_SRCToggleTime = (uint8_t)calcul;
calcul = tdrp * (100 - dcdrp) / 100;
DPM_Settings[PortNum].CAD_SNKToggleTime = (uint8_t)calcul;
}
#endif /* !USBPDCORE_LIB_NO_PD */
/* Only applies if an error was specified. Will send a DPM_CONFIG_REJ instead of DPM_CONFIG_SET_CNF*/
if(error != 0xFF)
{
TLV_deinit_encode(&send_tlv);
TLV_init_encode(&send_tlv, __GUI_SET_TAG_ID((PortNum + 1), DPM_CONFIG_REJ), TLV_SIZE_MAX, pEncodedMsg);
TLV_addValue(&send_tlv, &error, 1);
/* If the cause of error is DPM_REJECT, we have to list the tag of parameters which didn't pass */
if(!error)
{
uint32_t index;
for(index = 0; index < counter_param_not_applicated; index++)
{
TLV_addValue(&send_tlv, ¶m_not_applicated[index], 1);
}
}
TLV_deinit_encode(&send_tlv);
}
}
static void Send_DpmConfigGetCnf(uint8_t PortNum, uint8_t* instruction, uint8_t *pEncodedMsg)
{
TLV_ToSend_Data send_tlv;
TLV_init_encode(&send_tlv, __GUI_SET_TAG_ID((PortNum + 1), DPM_CONFIG_GET_CNF), TLV_SIZE_MAX, pEncodedMsg);
uint16_t length = TLV_get_string_length(instruction) - TLV_HEADER_SIZE;
uint8_t index = 0;
uint8_t param;
/* This is a state machine. */
do
{
/* If there is no parameters, we go through each case of the state machine in one pass. (conditionnal breaks) */
if(0 == length)
{
param = GUI_PARAM_ALL;
}
else
{
/* If there are, we loop the state machine and go through one case each time. */
param = instruction[TLV_VALUE_POSITION + index];
}
/*
Each case should simply use the TLV_add function to insert his corresponding data,
as suggested in comment. Manual cast to (uint8_t *) may be required.
*/
switch((USBPD_GUI_Tag_Param)param)
{
case GUI_PARAM_ALL :
#if !defined(USBPDCORE_LIB_NO_PD)
case GUI_PARAM_SOP :
{
/* SOP & SOP1 & SOP2 */
/* SOP1_Debug & SOP2_Debug not implemented */
uint8_t settings = DPM_Settings[PortNum].PE_SupportedSOP;
TLV_add(&send_tlv, GUI_PARAM_SOP, 1, &settings);
if(0 != length)
{
break;
}
}
#if defined(USBPD_REV30_SUPPORT)
case GUI_PARAM_FASTROLESWAP :
{
/*FastRoleSwap*/
uint8_t settings = DPM_Settings[PortNum].PE_PD3_Support.d.PE_FastRoleSwapSupport;
TLV_add(&send_tlv, GUI_PARAM_FASTROLESWAP, 1, &settings);
if(0 != length)
{
break;
}
}
#endif /*USBPD_REV30_SUPPORT*/
#endif /* !USBPDCORE_LIB_NO_PD */
case GUI_PARAM_DATAROLESWAP_TO_UFP :
{
/* DataRoleSwap to UFP */
uint8_t settings = DPM_USER_Settings[PortNum].PE_DR_Swap_To_UFP;
TLV_add(&send_tlv, GUI_PARAM_DATAROLESWAP_TO_UFP, 1, &settings);
if(0 != length)
{
break;
}
}
case GUI_PARAM_DATAROLESWAP_TO_DFP :
{
/* DataRoleSwap to DFP */
uint8_t settings = DPM_USER_Settings[PortNum].PE_DR_Swap_To_DFP;
TLV_add(&send_tlv, GUI_PARAM_DATAROLESWAP_TO_DFP, 1, &settings);
if(0 != length)
{
break;
}
}
case GUI_PARAM_DEFAULTPOWERROLE :
{
/*DefaultPowerRole*/
uint8_t settings = DPM_Settings[PortNum].PE_DefaultRole;
TLV_add(&send_tlv, GUI_PARAM_DEFAULTPOWERROLE, 1, &settings);
if(0 != length)
{
break;
}
}
#if !defined(USBPDCORE_LIB_NO_PD)
case GUI_PARAM_DRP_SUPPORT :
{
/*DRP_Support*/
uint8_t settings = DPM_Settings[PortNum].PE_RoleSwap;
TLV_add(&send_tlv, GUI_PARAM_DRP_SUPPORT, 1, &settings);
if(0 != length)
{
break;
}
}
case GUI_PARAM_CADROLETOGGLE :
{
/*CADRoleToggle*/
uint8_t settings = DPM_Settings[PortNum].CAD_RoleToggle;
TLV_add(&send_tlv, GUI_PARAM_CADROLETOGGLE, 1, &settings);
if(0 != length)
{
break;
}
}
case GUI_PARAM_PE_SCAP_HR :
{
/*PE_SCAP_HR*/
uint8_t settings = DPM_Settings[PortNum].PE_CapscounterSupport;
TLV_add(&send_tlv, GUI_PARAM_PE_SCAP_HR, 1, &settings);
if(0 != length)
{
break;
}
}
#if defined(_VDM)
case GUI_PARAM_VDM_SUPPORT :
{
/* DRP Support */
uint8_t settings = DPM_Settings[PortNum].PE_VDMSupport;
TLV_add(&send_tlv, GUI_PARAM_VDM_SUPPORT, 1, &settings);
if(0 != length)
{
break;
}
}
#endif /*_VDM*/
case GUI_PARAM_PING_SUPPORT :
{
/* Ping Support */
uint8_t settings = DPM_Settings[PortNum].PE_PingSupport;
TLV_add(&send_tlv, GUI_PARAM_PING_SUPPORT, 1, &settings);
if(0 != length)
{
break;
}
}
#if defined(USBPD_REV30_SUPPORT)
case GUI_PARAM_PPS_SUPPORT :
{
/* PD3 Support */
uint16_t settings = DPM_Settings[PortNum].PE_PD3_Support.PD3_Support;
TLV_add(&send_tlv, GUI_PARAM_PPS_SUPPORT, 2, (uint8_t*)&settings);
if(0 != length)
{
break;
}
}
#endif /*USBPD_REV30_SUPPORT*/
#endif /* !USBPDCORE_LIB_NO_PD */
case GUI_PARAM_VCONNSWAP :
{
/*VConnSwap*/
uint8_t settings = DPM_USER_Settings[PortNum].PE_VconnSwap;
TLV_add(&send_tlv, GUI_PARAM_VCONNSWAP, 1, &settings);
if(0 != length)
{
break;
}
}
#if defined(_SNK) || defined(_DRP)
case GUI_PARAM_SNK_PDO :
{
uint8_t* list_pdo;
uint8_t nb_pdo;
#if USBPD_PORT_COUNT==2
if (USBPD_PORT_0 == PortNum)
#endif /* USBPD_PORT_COUNT==2 */
{
nb_pdo = USBPD_NbPDO[0];
list_pdo = (uint8_t*)PORT0_PDO_ListSNK;
}
#if USBPD_PORT_COUNT==2
else
{
nb_pdo = USBPD_NbPDO[2];
list_pdo = (uint8_t*)PORT1_PDO_ListSNK;
}
#endif /* USBPD_PORT_COUNT==2 */
TLV_add(&send_tlv, GUI_PARAM_SNK_PDO, nb_pdo * 4, list_pdo);
}
if(0 != length)
{
break;
}
#endif /* _SNK || _DRP */
#if defined(_SRC) || defined(_DRP)
case GUI_PARAM_SRC_PDO :
{
uint8_t* list_pdo;
uint8_t nb_pdo;
#if USBPD_PORT_COUNT==2
if (USBPD_PORT_0 == PortNum)
#endif /* USBPD_PORT_COUNT==2 */
{
nb_pdo = USBPD_NbPDO[1];
list_pdo = (uint8_t*)PORT0_PDO_ListSRC;
}
#if USBPD_PORT_COUNT==2
else
{
nb_pdo = USBPD_NbPDO[3];
list_pdo = (uint8_t*)PORT1_PDO_ListSRC;
}
#endif /* USBPD_PORT_COUNT==2 */
TLV_add(&send_tlv, GUI_PARAM_SRC_PDO, nb_pdo * 4, list_pdo);
}
if(0 != length)
{
break;
}
#endif /* _SRC || _DRP */
case GUI_PARAM_TDRP :
{
/* Calculate the current value of tDRP (value between 50ms and 100ms) */
uint8_t value = DPM_USER_Settings[PortNum].CAD_tDRP;
TLV_add(&send_tlv, GUI_PARAM_TDRP, 1, &value);
}
if(0 != length)
{
break;
}
case GUI_PARAM_DCSRC_DRP :
{
/* Calculate the current value of tDRP (value between 50ms and 100ms) */
uint8_t value = DPM_USER_Settings[PortNum].CAD_dcSRC_DRP;
TLV_add(&send_tlv, GUI_PARAM_DCSRC_DRP, 1, &value);
}
if(0 != length)
{
break;
}
#if !defined(USBPDCORE_LIB_NO_PD)
case GUI_PARAM_RESPONDS_TO_DISCOV_SOP :
{
uint8_t settings = DPM_Settings[PortNum].PE_RespondsToDiscovSOP;
TLV_add(&send_tlv, GUI_PARAM_RESPONDS_TO_DISCOV_SOP, 1, &settings);
}
if(0 != length)
{
break;
}
case GUI_PARAM_ATTEMPTS_DISCOV_SOP :
{
uint8_t settings = DPM_Settings[PortNum].PE_AttemptsDiscovSOP;
TLV_add(&send_tlv, GUI_PARAM_ATTEMPTS_DISCOV_SOP, 1, &settings);
}
if(0 != length)
{
break;
}
#endif /* !USBPDCORE_LIB_NO_PD */
case GUI_PARAM_XID_SOP :
{
uint32_t value = DPM_ID_Settings[PortNum].XID;
TLV_add(&send_tlv, GUI_PARAM_XID_SOP, 4, (uint8_t*)&value);
}
if(0 != length)
{
break;
}
case GUI_PARAM_USB_VID_SOP :
{
uint16_t value = DPM_ID_Settings[PortNum].VID;
TLV_add(&send_tlv, GUI_PARAM_USB_VID_SOP, 2, (uint8_t*)&value);
}
if(0 != length)
{
break;
}
case GUI_PARAM_PID_SOP :
{
uint16_t value = DPM_ID_Settings[PortNum].PID;
TLV_add(&send_tlv, GUI_PARAM_PID_SOP, 2, (uint8_t*)&value);
}
if(0 != length)
{
break;
}
#if defined(_VDM)
case GUI_PARAM_DATA_CAPABLE_AS_USB_HOST_SOP :
{
uint8_t settings = DPM_VDM_Settings[PortNum].VDM_USBHostSupport;
TLV_add(&send_tlv, GUI_PARAM_DATA_CAPABLE_AS_USB_HOST_SOP, 1, &settings);
}
if(0 != length)
{
break;
}
case GUI_PARAM_DATA_CAPABLE_AS_USB_DEVICE_SOP :
{
uint8_t settings = DPM_VDM_Settings[PortNum].VDM_USBDeviceSupport;
TLV_add(&send_tlv, GUI_PARAM_DATA_CAPABLE_AS_USB_DEVICE_SOP, 1, &settings);
}
if(0 != length)
{
break;
}
case GUI_PARAM_PRODUCT_TYPE_SOP :
{
uint8_t settings = DPM_VDM_Settings[PortNum].VDM_ProductTypeUFPorCP;
TLV_add(&send_tlv, GUI_PARAM_PRODUCT_TYPE_SOP, 1, &settings);
}
if(0 != length)
{
break;
}
case GUI_PARAM_MODAL_OPERATION_SUPPORTED_SOP :
{
uint8_t settings = DPM_VDM_Settings[PortNum].VDM_ModalOperation;
TLV_add(&send_tlv, GUI_PARAM_MODAL_OPERATION_SUPPORTED_SOP, 1, &settings);
}
if(0 != length)
{
break;
}
case GUI_PARAM_BCDDEVICE_SOP :
{
uint16_t value = DPM_VDM_Settings[PortNum].VDM_bcdDevice_SOP;
TLV_add(&send_tlv, GUI_PARAM_BCDDEVICE_SOP, 2, (uint8_t*)&value);
}
if(0 != length)
{
break;
}
#endif /* _VDM */
case GUI_PARAM_MEASUREREPORTING :
{
uint8_t settings = GUI_USER_Params[PortNum].u.MeasurementReporting;
TLV_add(&send_tlv, GUI_PARAM_MEASUREREPORTING, 1, &settings);
}
if(0 != length)
{
break;
}
#if defined(USBPD_REV30_SUPPORT)
#if _MANU_INFO
case GUI_PARAM_MANUINFOPORT_VID :
{
uint8_t size = sizeof(DPM_USER_Settings[PortNum].DPM_ManuInfoPort.ManuString) + 4;
TLV_add(&send_tlv, GUI_PARAM_MANUINFOPORT_VID, size, (uint8_t*)&DPM_USER_Settings[PortNum].DPM_ManuInfoPort);
}
if(0 != length)
{
break;
}
#endif /* _MANU_INFO */
#endif /*USBPD_REV30_SUPPORT*/
default:
if(0 != length)
{
/* At least 1 parameter does not exist */
TLV_deinit_encode(&send_tlv);
Send_DpmConfigGetRej(PortNum, pEncodedMsg, GUI_REJ_DPM_INVALID_MESSAGE);
goto __end;
}
break;
}
index++;
/*
Loop until we haven't processed each specified parameter.
If there weren't any (length = 0), we exit the loop after one execution.
*/
} while(index < length);
__end:
TLV_deinit_encode(&send_tlv);
}
static void Send_DpmConfigGetRej(uint8_t PortNum, uint8_t *pEncodedMsg, USBPD_GUI_Reject_Reason RejectReason)
{
TLV_ToSend_Data send_tlv;
TLV_init_encode(&send_tlv, DPM_CONFIG_REJ, TLV_SIZE_MAX, pEncodedMsg);
TLV_add(&send_tlv, RejectReason, 0, NULL);
TLV_deinit_encode(&send_tlv);
}
static void Send_DpmMessageRej(uint8_t PortNum, uint8_t *pEncodedMsg, USBPD_GUI_Reject_Reason RejectReason)
{
TLV_ToSend_Data send_tlv;
TLV_init_encode(&send_tlv, DPM_MESSAGE_REJ, TLV_SIZE_MAX, pEncodedMsg);
TLV_add(&send_tlv, RejectReason, 0, NULL);
TLV_deinit_encode(&send_tlv);
}
static void Send_DpmRegisterReadCnf(uint8_t PortNum, uint8_t *pEncodedMsg, uint8_t param)
{
TLV_ToSend_Data ToSendTLV;
TLV_init_encode(&ToSendTLV, __GUI_SET_TAG_ID((PortNum +1), DPM_REGISTER_READ_CNF), TLV_SIZE_MAX, pEncodedMsg);
uint8_t stateMachineArray[GUI_REG_NUMBER_OF_REGISTERS] = {
GUI_REG_VENDOR_ID, GUI_REG_PRODUCT_ID, GUI_REG_DEVICE_ID, GUI_REG_USBTYPEC_REV,
GUI_REG_USBPD_REV_VER, GUI_REG_USBPD_INTERFACE_REV, GUI_REG_ALERT, GUI_REG_ALERT_MASK,
GUI_REG_POWER_STATUS_MASK, GUI_REG_FAULT_STATUS_MASK, GUI_REG_CONFIG_STANDARD_OUTPUT,
GUI_REG_TCPC_CONTROL, GUI_REG_ROLE_CONTROL, GUI_REG_FAULT_CONTROL, GUI_REG_POWER_CONTROL,
GUI_REG_CC_STATUS, GUI_REG_POWER_STATUS, GUI_REG_FAULT_STATUS, GUI_REG_COMMAND, GUI_REG_DECIVE_CAP1,
GUI_REG_DECIVE_CAP2, GUI_REG_STD_INPUT_CAP, GUI_REG_STD_OUTPUT_CAP, GUI_REG_MSG_HEADER_INFO,
GUI_REG_RX_DETECT, GUI_REG_RX_BYTE_COUNT, GUI_REG_RX_BUFFER_FRAME_TYPE, GUI_REG_RX_HEADER,
GUI_REG_RX_DATA, GUI_REG_TRANSMIT, GUI_REG_TX_BYTE_COUNT, GUI_REG_TX_HEADER, GUI_REG_TX_DATA,
GUI_REG_VBUS_VOLTAGE, GUI_REG_VBUS_SINK_DISCONNECT_THRESHOLD, GUI_REG_VBUS_STOP_DISCHARGE_THRESHOLD,
GUI_REG_VBUS_VOLTAGE_ALARM_HI_CFG, GUI_REG_VBUS_VOLTAGE_ALARM_LO_CFG, GUI_REG_VENDOR_DATA
};
uint8_t counter = 0;
/* If param is not at 0xFF, then it means we only want one parameter.
We then have to get out of the state machine after the first state */
if(param != 0xFF)
{
*stateMachineArray = param;
}
do
{
switch(stateMachineArray[counter])
/*
In each case, the register needs to be read. Inclusion in the TLV which
is going to be sent has to be done with TLV_add().
*/
{
case GUI_REG_VENDOR_ID :
break;
case GUI_REG_PRODUCT_ID :
break;
case GUI_REG_DEVICE_ID :
break;
case GUI_REG_USBTYPEC_REV :
break;
case GUI_REG_USBPD_REV_VER :
break;
case GUI_REG_USBPD_INTERFACE_REV :
break;
case GUI_REG_ALERT :
break;
case GUI_REG_ALERT_MASK :
break;
case GUI_REG_POWER_STATUS_MASK :
break;
case GUI_REG_FAULT_STATUS_MASK :
break;
case GUI_REG_CONFIG_STANDARD_OUTPUT :
break;
case GUI_REG_TCPC_CONTROL :
break;
case GUI_REG_ROLE_CONTROL :
break;
case GUI_REG_FAULT_CONTROL :
break;
case GUI_REG_POWER_CONTROL :
break;
case GUI_REG_CC_STATUS :
break;
case GUI_REG_POWER_STATUS :
break;
case GUI_REG_FAULT_STATUS :
break;
case GUI_REG_COMMAND :
break;
case GUI_REG_DECIVE_CAP1 :
break;
case GUI_REG_DECIVE_CAP2 :
break;
case GUI_REG_STD_INPUT_CAP :
break;
case GUI_REG_STD_OUTPUT_CAP :
break;
case GUI_REG_MSG_HEADER_INFO :
break;
case GUI_REG_RX_DETECT :
break;
case GUI_REG_RX_BYTE_COUNT :
break;
case GUI_REG_RX_BUFFER_FRAME_TYPE :
break;
case GUI_REG_RX_HEADER :
break;
case GUI_REG_RX_DATA :
break;
case GUI_REG_TRANSMIT :
break;
case GUI_REG_TX_BYTE_COUNT :
break;
case GUI_REG_TX_HEADER :
break;
case GUI_REG_TX_DATA :
break;
case GUI_REG_VBUS_VOLTAGE :
break;
case GUI_REG_VBUS_SINK_DISCONNECT_THRESHOLD :
break;
case GUI_REG_VBUS_STOP_DISCHARGE_THRESHOLD :
break;
case GUI_REG_VBUS_VOLTAGE_ALARM_HI_CFG :
break;
case GUI_REG_VBUS_VOLTAGE_ALARM_LO_CFG :
break;
case GUI_REG_VENDOR_DATA :
break;
default :
break;
}
counter++;
} while(counter < GUI_REG_NUMBER_OF_REGISTERS && param != 0xFF);
TLV_deinit_encode(&ToSendTLV);
}
static void Send_DpmRegisterWriteCnf(uint8_t PortNum, uint8_t *pEncodedMsg, uint8_t *toProcess)
{
TLV_Received_Data ToProcessTLV;
TLV_init_decode(&ToProcessTLV, toProcess);
uint8_t registerName;
uint16_t registerSize;
uint8_t *registerValue;
TLV_get(&ToProcessTLV, ®isterName, ®isterSize, ®isterValue);
switch(registerName)
/*
Each case should write the data pointed by registerValue in the appropriate register,
while taking into account the size of the data with registerSize.
*/
{
case GUI_REG_VENDOR_ID :
break;
case GUI_REG_PRODUCT_ID :
break;
case GUI_REG_DEVICE_ID :
break;
case GUI_REG_USBTYPEC_REV :
break;
case GUI_REG_USBPD_REV_VER :
break;
case GUI_REG_USBPD_INTERFACE_REV :
break;
case GUI_REG_ALERT :
break;
case GUI_REG_ALERT_MASK :
break;
case GUI_REG_POWER_STATUS_MASK :
break;
case GUI_REG_FAULT_STATUS_MASK :
break;
case GUI_REG_CONFIG_STANDARD_OUTPUT :
break;
case GUI_REG_TCPC_CONTROL :
break;
case GUI_REG_ROLE_CONTROL :
break;
case GUI_REG_FAULT_CONTROL :
break;
case GUI_REG_POWER_CONTROL :
break;
case GUI_REG_CC_STATUS :
break;
case GUI_REG_POWER_STATUS :
break;
case GUI_REG_FAULT_STATUS :
break;
case GUI_REG_COMMAND :
break;
case GUI_REG_DECIVE_CAP1 :
break;
case GUI_REG_DECIVE_CAP2 :
break;
case GUI_REG_STD_INPUT_CAP :
break;
case GUI_REG_STD_OUTPUT_CAP :
break;
case GUI_REG_MSG_HEADER_INFO :
break;
case GUI_REG_RX_DETECT :
break;
case GUI_REG_RX_BYTE_COUNT :
break;
case GUI_REG_RX_BUFFER_FRAME_TYPE :
break;
case GUI_REG_RX_HEADER :
break;
case GUI_REG_RX_DATA :
break;
case GUI_REG_TRANSMIT :
break;
case GUI_REG_TX_BYTE_COUNT :
break;
case GUI_REG_TX_HEADER :
break;
case GUI_REG_TX_DATA :
break;
case GUI_REG_VBUS_VOLTAGE :
break;
case GUI_REG_VBUS_SINK_DISCONNECT_THRESHOLD :
break;
case GUI_REG_VBUS_STOP_DISCHARGE_THRESHOLD :
break;
case GUI_REG_VBUS_VOLTAGE_ALARM_HI_CFG :
break;
case GUI_REG_VBUS_VOLTAGE_ALARM_LO_CFG :
break;
case GUI_REG_VENDOR_DATA :
break;
default :
break;
}
TLV_deinit_decode(&ToProcessTLV);
TLV_ToSend_Data ToSendTLV;
/* Generation of the empty response, as it should be done*/
TLV_init_encode(&ToSendTLV, __GUI_SET_TAG_ID((PortNum + 1), DPM_REGISTER_WRITE_CNF), 12, pEncodedMsg);
TLV_deinit_encode(&ToSendTLV);
}
/**
* @brief Manage Free text sent by the GUI
* @param PortNum The current port number
* @param pPayload Pointer of the text to manage
* @param Size Size of the text
* @retval USBPD Status
*/
static USBPD_StatusTypeDef Manage_FreeText(uint8_t PortNum, uint8_t *pPayload, uint16_t Size)
{
USBPD_StatusTypeDef _status = USBPD_FAIL;
if (NULL != pCB_FreeText)
{
pCB_FreeText(PortNum, pPayload, Size);
_status = USBPD_OK;
}
return _status;
}
#if defined(_SNK) || defined(_DRP)
/**
* @brief Function to update SNK PDO and power user settings on Port0
* @retval None
*/
static void UpdateSNKPowerPort0(void)
{
USBPD_PDO_TypeDef pdo;
uint32_t _max_power = 0;
uint16_t _voltage = 0, _current = 0, _power = 0;
uint16_t _min_voltage = 0xFFFF, _max_voltage = 0, _max_current = 0;
for (uint32_t _index = 0; _index < USBPD_NbPDO[0]; _index++)
{
pdo.d32 = PORT0_PDO_ListSNK[_index];
switch (pdo.GenericPDO.PowerObject)
{
case USBPD_CORE_PDO_TYPE_FIXED: /*!< Fixed Supply PDO */
_voltage = GUI_DECODE_50MV(pdo.SNKFixedPDO.VoltageIn50mVunits);
GUI_UPDATE_VOLTAGE_MIN(_voltage, _min_voltage);
GUI_UPDATE_VOLTAGE_MAX(_voltage, _max_voltage);
_current = GUI_DECODE_10MA(pdo.SNKFixedPDO.OperationalCurrentIn10mAunits);
GUI_UPDATE_CURRENT_MAX(_current, _max_current);
break;
case USBPD_CORE_PDO_TYPE_BATTERY: /*!< Battery Supply PDO */
_voltage = GUI_DECODE_50MV(pdo.SNKBatteryPDO.MinVoltageIn50mVunits);
GUI_UPDATE_VOLTAGE_MIN(_voltage, _min_voltage);
_voltage = GUI_DECODE_50MV(pdo.SNKBatteryPDO.MaxVoltageIn50mVunits);
GUI_UPDATE_VOLTAGE_MAX(_voltage, _max_voltage);
_power = GUI_DECODE_MW(pdo.SNKBatteryPDO.OperationalPowerIn250mWunits);
GUI_UPDATE_POWER_MAX(_power, _max_power);
break;
case USBPD_CORE_PDO_TYPE_VARIABLE: /*!< Variable Supply (non-battery) PDO */
_voltage = GUI_DECODE_50MV(pdo.SNKVariablePDO.MinVoltageIn50mVunits);
GUI_UPDATE_VOLTAGE_MIN(_voltage, _min_voltage);
_voltage = GUI_DECODE_50MV(pdo.SNKVariablePDO.MaxVoltageIn50mVunits);
GUI_UPDATE_VOLTAGE_MAX(_voltage, _max_voltage);
_current = GUI_DECODE_10MA(pdo.SNKVariablePDO.OperationalCurrentIn10mAunits);
GUI_UPDATE_CURRENT_MAX(_current, _max_current);
break;
#if _PPS
case USBPD_CORE_PDO_TYPE_APDO: /*!< Augmented Power Data Object (APDO) */
_voltage = GUI_DECODE_100MV(pdo.SRCSNKAPDO.MinVoltageIn100mV);
GUI_UPDATE_VOLTAGE_MIN(_voltage, _min_voltage);
_voltage = GUI_DECODE_100MV(pdo.SRCSNKAPDO.MaxVoltageIn100mV);
GUI_UPDATE_VOLTAGE_MAX(_voltage, _max_voltage);
_current = GUI_DECODE_50MA(pdo.SRCSNKAPDO.MaxCurrentIn50mAunits);
GUI_UPDATE_CURRENT_MAX(_current, _max_current);
break;
#endif /*_USBPD_REV30_SUPPORT && PPS*/
default:
break;
}
}
GUI_CHECK_VOLTAGE_MIN(_min_voltage, DPM_USER_Settings[USBPD_PORT_0].DPM_SNKRequestedPower.MinOperatingVoltageInmVunits);
GUI_CHECK_VOLTAGE_MAX(_max_voltage, DPM_USER_Settings[USBPD_PORT_0].DPM_SNKRequestedPower.MaxOperatingVoltageInmVunits);
GUI_CHECK_CURRENT_MAX(_max_current, DPM_USER_Settings[USBPD_PORT_0].DPM_SNKRequestedPower.MaxOperatingCurrentInmAunits);
_max_power = (_max_voltage * _max_current) / 1000;
GUI_CHECK_POWER_MAX(_max_power, DPM_USER_Settings[USBPD_PORT_0].DPM_SNKRequestedPower.MaxOperatingPowerInmWunits);
}
#if USBPD_PORT_COUNT==2
/**
* @brief Function to update SNK PDO and power user settings on Port1
* @retval None
*/
static void UpdateSNKPowerPort1(void)
{
USBPD_PDO_TypeDef pdo;
uint32_t _max_power = 0;
uint16_t _voltage = 0, _current = 0, _power = 0;
uint16_t _min_voltage = 0xFFFF, _max_voltage = 0, _max_current = 0;
for (uint32_t _index = 0; _index < USBPD_NbPDO[2]; _index++)
{
pdo.d32 = PORT1_PDO_ListSNK[_index];
switch (pdo.GenericPDO.PowerObject)
{
case USBPD_CORE_PDO_TYPE_FIXED: /*!< Fixed Supply PDO */
_voltage = GUI_DECODE_50MV(pdo.SNKFixedPDO.VoltageIn50mVunits);
GUI_UPDATE_VOLTAGE_MIN(_voltage, _min_voltage);
GUI_UPDATE_VOLTAGE_MAX(_voltage, _max_voltage);
_current = GUI_DECODE_10MA(pdo.SNKFixedPDO.OperationalCurrentIn10mAunits);
GUI_UPDATE_CURRENT_MAX(_current, _max_current);
break;
case USBPD_CORE_PDO_TYPE_BATTERY: /*!< Battery Supply PDO */
_voltage = GUI_DECODE_50MV(pdo.SNKBatteryPDO.MinVoltageIn50mVunits);
GUI_UPDATE_VOLTAGE_MIN(_voltage, _min_voltage);
_voltage = GUI_DECODE_50MV(pdo.SNKBatteryPDO.MaxVoltageIn50mVunits);
GUI_UPDATE_VOLTAGE_MAX(_voltage, _max_voltage);
_power = GUI_DECODE_MW(pdo.SNKBatteryPDO.OperationalPowerIn250mWunits);
GUI_UPDATE_POWER_MAX(_power, _max_power);
break;
case USBPD_CORE_PDO_TYPE_VARIABLE: /*!< Variable Supply (non-battery) PDO */
_voltage = GUI_DECODE_50MV(pdo.SNKVariablePDO.MinVoltageIn50mVunits);
GUI_UPDATE_VOLTAGE_MIN(_voltage, _min_voltage);
_voltage = GUI_DECODE_50MV(pdo.SNKVariablePDO.MaxVoltageIn50mVunits);
GUI_UPDATE_VOLTAGE_MAX(_voltage, _max_voltage);
_current = GUI_DECODE_10MA(pdo.SNKVariablePDO.OperationalCurrentIn10mAunits);
GUI_UPDATE_CURRENT_MAX(_current, _max_current);
break;
#if _PPS
case USBPD_CORE_PDO_TYPE_APDO: /*!< Augmented Power Data Object (APDO) */
_voltage = GUI_DECODE_100MV(pdo.SRCSNKAPDO.MinVoltageIn100mV);
GUI_UPDATE_VOLTAGE_MIN(_voltage, _min_voltage);
_voltage = GUI_DECODE_100MV(pdo.SRCSNKAPDO.MaxVoltageIn100mV);
GUI_UPDATE_VOLTAGE_MAX(_voltage, _max_voltage);
_current = GUI_DECODE_50MA(pdo.SRCSNKAPDO.MaxCurrentIn50mAunits);
GUI_UPDATE_CURRENT_MAX(_current, _max_current);
break;
#endif /*_USBPD_REV30_SUPPORT && PPS*/
default:
break;
}
}
GUI_CHECK_VOLTAGE_MIN(_min_voltage, DPM_USER_Settings[USBPD_PORT_1].DPM_SNKRequestedPower.MinOperatingVoltageInmVunits);
GUI_CHECK_VOLTAGE_MAX(_max_voltage, DPM_USER_Settings[USBPD_PORT_1].DPM_SNKRequestedPower.MaxOperatingVoltageInmVunits);
GUI_CHECK_CURRENT_MAX(_max_current, DPM_USER_Settings[USBPD_PORT_1].DPM_SNKRequestedPower.MaxOperatingCurrentInmAunits);
_max_power = (_max_voltage * _max_current) / 1000;
GUI_CHECK_POWER_MAX(_max_power, DPM_USER_Settings[USBPD_PORT_1].DPM_SNKRequestedPower.MaxOperatingPowerInmWunits);
}
#endif /* USBPD_PORT_COUNT==2 */
#endif /* _SNK) || _DRP */
/**
* @}
*/
/**
* @}
*/
#endif /* _GUI_INTERFACE */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/