/** ****************************************************************************** * @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****/