Conversation
* RDKEMW-4848: pass the proper handle to dsEnableHDCP
There was a problem hiding this comment.
Pull request overview
This PR refactors the dynamic library loading mechanism for device settings configuration to use a shared library handle instead of opening/closing the library multiple times. The changes introduce a centralized getDLInstance() and releaseDLInstance() pattern, and update all config loading methods to accept a handle parameter.
Key Changes
- Centralized dynamic library handle management with thread-safe singleton pattern
- Updated all config load methods to accept a
void* pDLHandleparameter - Added support for FrontPanelConfig in the initialization flow
- Removed the
parse_opt_flag()function and associated delay logic
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| ds/manager.cpp | Added getDLInstance/releaseDLInstance functions, refactored searchConfigs to use provided handle, updated Initialize/load methods to pass handle to configs, removed parse_opt_flag function and delay logic |
| ds/include/manager.hpp | Updated searchConfigs declaration to include pDLHandle parameter, removed parse_opt_flag declaration |
| ds/videoOutputPortConfig.hpp | Updated load method signature to accept pDLHandle parameter |
| ds/videoOutputPortConfig.cpp | Refactored load to accept handle parameter, moved symbol search variables into conditional block, added dynamic vs old config loading logic |
| ds/videoDeviceConfig.hpp | Updated load method signature to accept pDLHandle parameter |
| ds/videoDeviceConfig.cpp | Refactored load to accept handle parameter, added dynamic vs old config loading logic |
| ds/audioOutputPortConfig.hpp | Updated load method signature to accept pDLHandle parameter |
| ds/audioOutputPortConfig.cpp | Refactored load to accept handle parameter, added dynamic vs old config loading logic |
| ds/include/frontPanelConfig.hpp | Moved load method from private to public, added m_isFPConfigLoaded member, updated load signature to accept pDLHandle |
| ds/frontPanelConfig.cpp | Removed load call from getInstance, added load validation checks with m_isFPConfigLoaded, refactored load to accept handle parameter and support dynamic/old config loading |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
ds/frontPanelConfig.cpp
Outdated
| configuration.pKIndicators[i].colorMode)); | ||
| } | ||
| } | ||
| if (pDLHandle) |
There was a problem hiding this comment.
In the FrontPanelConfig::load method, the check for pDLHandle uses a different null comparison pattern (pDLHandle without nullptr comparison) compared to other config files which consistently use "nullptr != pDLHandle". Consider using "nullptr != pDLHandle" for consistency with the rest of the codebase.
| if (pDLHandle) | |
| if (nullptr != pDLHandle) |
| } | ||
| m_isFPConfigLoaded = true; | ||
| INT_INFO("Exit function\n"); | ||
| return; |
There was a problem hiding this comment.
The explicit return statement at the end of a void function is unnecessary. Since this function returns void, the return statement at line 554 can be removed as the function will automatically return at its end.
| return; |
ds/videoDeviceConfig.cpp
Outdated
|
|
||
| if ( false == isDynamicConfigLoad) | ||
| { | ||
| INT_INFO("Read Old Configs\n"); |
There was a problem hiding this comment.
The log message format for old config loading is inconsistent. In videoDeviceConfig.cpp line 164 it says "Read Old Configs" while other files (videoOutputPortConfig.cpp line 435, audioOutputPortConfig.cpp line 235, frontPanelConfig.cpp line 482) consistently use "Using OLD config loading". Consider updating this message to match the consistent pattern used elsewhere.
| INT_INFO("Read Old Configs\n"); | |
| INT_INFO("Using OLD config loading\n"); |
ds/manager.cpp
Outdated
| void* getDLInstance() | ||
| { | ||
| std::lock_guard<std::mutex> lock(gDLMutex); | ||
| dlerror(); // clear old error | ||
| if (nullptr == gDLHandle){ | ||
| gDLHandle = dlopen(RDK_DSHAL_NAME, RTLD_LAZY); | ||
| } | ||
| INT_INFO("%d:%s: DL Instance '%s'\n", __LINE__, __func__, (nullptr == gDLHandle ? "NULL" : "Valid")); | ||
| return gDLHandle; | ||
| } |
There was a problem hiding this comment.
The getDLInstance function does not log or handle the error when dlopen fails. The old implementation would log the error message from dlerror(), but this new implementation only logs whether the handle is NULL or Valid. Consider logging the actual error message from dlerror() when dlopen fails to aid in debugging issues with loading the dynamic library.
ds/manager.cpp
Outdated
| void* pDLHandle = getDLInstance(); | ||
| device::AudioOutputPortConfig::getInstance().load(pDLHandle); | ||
| device::VideoOutputPortConfig::getInstance().load(pDLHandle); | ||
| device::VideoDeviceConfig::getInstance().load(pDLHandle); |
There was a problem hiding this comment.
The Manager::load() method calls load for AudioOutputPortConfig, VideoOutputPortConfig, and VideoDeviceConfig, but does not call FrontPanelConfig::getInstance().load(pDLHandle). This is inconsistent with Manager::Initialize() which calls load on all four config classes including FrontPanelConfig. This inconsistency could lead to FrontPanelConfig not being properly loaded when Manager::load() is called.
| device::VideoDeviceConfig::getInstance().load(pDLHandle); | |
| device::VideoDeviceConfig::getInstance().load(pDLHandle); | |
| device::FrontPanelConfig::getInstance().load(pDLHandle); |
Reason for change: consume the config variables using dlsym() in MW. Test Procedure: refer RDKEMW-8587 Risks: High Signed-off-by:gsanto722 <grandhi_santoshkumar@comcast.com>
Signed-off-by: grandhi_santoshkumar <grandhi_santoshkumar@comcast.com>
Reason for change: consume the config variables using dlsym() in MW. Test Procedure: refer RDKEMW-8587 Risks: High Signed-off-by:gsanto722 <grandhi_santoshkumar@comcast.com>
Reason for change: consume the config variables using dlsym() in MW. Test Procedure: refer RDKEMW-8587 Risks: High Signed-off-by:gsanto722 <grandhi_santoshkumar@comcast.com>
Reason for change: consume the config variables using dlsym() in MW. Test Procedure: refer RDKEMW-8587 Risks: High Signed-off-by:gsanto722 <grandhi_santoshkumar@comcast.com>
Reason for change: consume the config variables using dlsym() in MW. Test Procedure: refer RDKEMW-8587 Risks: High Signed-off-by:gsanto722 <grandhi_santoshkumar@comcast.com>
Reason for change: consume the config variables using dlsym() in MW. Test Procedure: refer RDKEMW-8587 Risks: High Signed-off-by: grandhi_santoshkumar <grandhi_santoshkumar@comcast.com>
Reason for change: consume the config variables using dlsym() in MW. Test Procedure: refer RDKEMW-8587 Risks: High Signed-off-by:gsanto722 <grandhi_santoshkumar@comcast.com>
…logging format Signed-off-by: yuvaramachandran_gurusamy <yuvaramachandran_gurusamy@comcast.com>
Signed-off-by: yuvaramachandran_gurusamy <yuvaramachandran_gurusamy@comcast.com>
Reason for change: Address review comments. Test Procedure: refer RDKEMW-8587 Risks: High Signed-off-by:gsanto722 <grandhi_santoshkumar@comcast.com>
Reason for change: Addressed review comments. Test Procedure: refer RDKEMW-8587 Risks: High Signed-off-by:gsanto722 <grandhi_santoshkumar@comcast.com>
ef2294f to
b8cdf99
Compare
Reason for change: Address the other static config read places. Test Procedure: refer RDKEMW-8587 Risks: High Signed-off-by:gsanto722 <grandhi_santoshkumar@comcast.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 22 out of 22 changed files in this pull request and generated 33 comments.
Comments suppressed due to low confidence (1)
rpc/srv/dsVideoPort.c:1963
getPixelResolution()returnsResn->pixelResolutioneven wheniCount == 0or whenresolutionisn't found; in both casesResnwill point at the first (zero-initialized) element, causing an incorrect pixelResolution to be returned. Add an explicit fallback (e.g., default resolution) wheniCount==0or no match is found.
dsVideoPortResolution_t kVidoeResolutionsSettings[16] = {};
int iCount = 0;
dsGetVideoPortResolutions(&iCount, kVidoeResolutionsSettings);
// Print kVidoeResolutionsSettings array
INT_INFO("[DsMgr] ========== Dumping kVidoeResolutionsSettings Array in getPixelResolution ==========\r\n");
INT_INFO("[DsMgr] Total resolutions retrieved: %d\r\n", iCount);
for (int k = 0; k < iCount; k++) {
dsVideoPortResolution_t *res = &kVidoeResolutionsSettings[k];
INT_INFO("[DsMgr] [%d] name=%s, pixelRes=%d, aspectRatio=%d, stereoMode=%d, frameRate=%d, interlaced=%d\r\n",
k, res->name, res->pixelResolution, res->aspectRatio,
res->stereoScopicMode, res->frameRate, res->interlaced);
}
INT_INFO("[DsMgr] ========== End of kVidoeResolutionsSettings Dump ==========\r\n");
dsVideoPortResolution_t *Resn = &kVidoeResolutionsSettings[0];
for (int i = 0; i < iCount; i++)
{
Resn = &kVidoeResolutionsSettings[i];
if (resolution.compare(Resn->name) == 0 )
{
break;
}
}
return Resn->pixelResolution;
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Print kVidoeResolutionsSettings array | ||
| INT_INFO("[DsMgr] ========== Dumping kVidoeResolutionsSettings Array in getPixelResolution ==========\r\n"); | ||
| INT_INFO("[DsMgr] Total resolutions retrieved: %d\r\n", iCount); | ||
| for (int k = 0; k < iCount; k++) { | ||
| dsVideoPortResolution_t *res = &kVidoeResolutionsSettings[k]; | ||
| INT_INFO("[DsMgr] [%d] name=%s, pixelRes=%d, aspectRatio=%d, stereoMode=%d, frameRate=%d, interlaced=%d\r\n", | ||
| k, res->name, res->pixelResolution, res->aspectRatio, | ||
| res->stereoScopicMode, res->frameRate, res->interlaced); | ||
| } | ||
| INT_INFO("[DsMgr] ========== End of kVidoeResolutionsSettings Dump ==========\r\n"); |
There was a problem hiding this comment.
The unconditional INT_INFO dumps for every port/resolution will be very noisy in production and can impact performance. Consider gating these dumps behind INT_DEBUG, a runtime flag, or the existing /opt/dsMgrDumpDeviceConfigs switch used elsewhere.
rpc/srv/dsDisplay.c
Outdated
| dsVideoPortPortConfig_t kVideoPortPorts[16] = {}; | ||
|
|
||
| //numPorts = dsUTL_DIM(kSupportedPortTypes); | ||
| getVideoPortVPorts(&numPorts, kVideoPortPorts); | ||
|
|
||
| // Print kVideoPortPorts array | ||
| INT_INFO("[DsMgr] ========== Dumping kVideoPortPorts Array ==========\r\n"); | ||
| INT_INFO("[DsMgr] Total ports retrieved: %d\r\n", numPorts); | ||
| for (int k = 0; k < numPorts; k++) { | ||
| dsVideoPortPortConfig_t *port = &kVideoPortPorts[k]; | ||
| INT_INFO("[DsMgr] [%d] type=%d, index=%d, connectedAOP_type=%d, connectedAOP_index=%d, defaultResolution=%s\r\n", | ||
| k, port->id.type, port->id.index, | ||
| port->connectedAOP.type, port->connectedAOP.index, | ||
| port->defaultResolution); | ||
| } | ||
| INT_INFO("[DsMgr] ========== End of kVideoPortPorts Dump ==========\r\n"); | ||
|
|
||
| numPorts = dsUTL_DIM(kSupportedPortTypes); | ||
| for(i=0; i< numPorts; i++) | ||
| { | ||
| dsGetDisplay(kPorts[i].id.type, kPorts[i].id.index, &halhandle); | ||
| dsGetDisplay(kVideoPortPorts[i].id.type, kVideoPortPorts[i].id.index, &halhandle); |
There was a problem hiding this comment.
kVideoPortPorts is a fixed-size array of 16, but getVideoPortVPorts(&numPorts, ...) can return more than 16 ports. Both the dump loop and the lookup loop will read past the stack buffer. Clamp numPorts to the array capacity (or switch to a sized allocation).
| #include <pthread.h> | ||
| #include <unistd.h> | ||
| #include <dlfcn.h> | ||
| #include <fstream> |
There was a problem hiding this comment.
#include <fstream> appears unused in this file (no std::ifstream/ofstream usage). If it's not needed, remove it to avoid extra compile time and warnings.
| #include <fstream> |
| INT_INFO("[DsMgr] [%d] type=%d, index=%d, connectedAOP_type=%d, connectedAOP_index=%d, defaultResolution=%s\r\n", | ||
| k, port->id.type, port->id.index, | ||
| port->connectedAOP.type, port->connectedAOP.index, | ||
| port->defaultResolution); |
There was a problem hiding this comment.
In the port dump, port->defaultResolution is logged with %s without a NULL check. If any port has a NULL defaultResolution this will crash. Use a ternary fallback (as done elsewhere) or skip printing when NULL.
| port->defaultResolution); | |
| port->defaultResolution ? port->defaultResolution : "NULL"); |
| using namespace std; | ||
|
|
There was a problem hiding this comment.
using namespace std; in a public header (manager.hpp) pollutes the global namespace for every translation unit that includes it and can cause name collisions. Remove it and qualify symbols with std:: instead (or keep using directives inside .cpp files only).
| using namespace std; |
| #include "dsUtl.h" | ||
| #include "stdlib.h" | ||
| #include "dslogger.h" | ||
| #include <dlfcn.h> |
There was a problem hiding this comment.
<dlfcn.h> is included here but there are no dlopen/dlsym usages in this file. If it's not needed, remove it to avoid unnecessary dependencies and warnings.
| #include <dlfcn.h> |
rpc/srv/dsVideoPort.c
Outdated
| dsVideoPortResolution_t kVidoeResolutionsSettings[16] = {}; | ||
| int iCount = 0; | ||
| dsGetVideoPortResolutions(&iCount, kVidoeResolutionsSettings); | ||
|
|
||
| // Print kVidoeResolutionsSettings array | ||
| INT_INFO("[DsMgr] ========== Dumping kVidoeResolutionsSettings Array in getPixelResolution ==========\r\n"); | ||
| INT_INFO("[DsMgr] Total resolutions retrieved: %d\r\n", iCount); | ||
| for (int k = 0; k < iCount; k++) { | ||
| dsVideoPortResolution_t *res = &kVidoeResolutionsSettings[k]; | ||
| INT_INFO("[DsMgr] [%d] name=%s, pixelRes=%d, aspectRatio=%d, stereoMode=%d, frameRate=%d, interlaced=%d\r\n", | ||
| k, res->name, res->pixelResolution, res->aspectRatio, | ||
| res->stereoScopicMode, res->frameRate, res->interlaced); | ||
| } | ||
| INT_INFO("[DsMgr] ========== End of kVidoeResolutionsSettings Dump ==========\r\n"); | ||
|
|
||
| for (unsigned int i = 0; i < dsUTL_DIM(kResolutions); i++) | ||
| dsVideoPortResolution_t *Resn = &kVidoeResolutionsSettings[0]; | ||
|
|
||
| for (int i = 0; i < iCount; i++) | ||
| { | ||
| Resn = &kResolutions[i]; | ||
| Resn = &kVidoeResolutionsSettings[i]; |
There was a problem hiding this comment.
kVidoeResolutionsSettings is a fixed-size array of 16, but dsGetVideoPortResolutions(&iCount, ...) can return more than 16. The dump loop and search loop iterate to iCount, which will read past the end of the buffer. Clamp iCount to the array capacity or switch to a sized allocation/two-pass query.
| return eRet; | ||
| } | ||
|
|
||
| //This funcation does not have any caller. |
There was a problem hiding this comment.
Typo in comment: "funcation" -> "function".
| //This funcation does not have any caller. | |
| //This function does not have any caller. |
ds/videoOutputPortConfig.cpp
Outdated
| void VideoOutputPortConfig::getVideoPortVPorts(int *pPortCount, dsVideoPortPortConfig_t *pPorts) | ||
| { | ||
| if (nullptr == pPortCount) { | ||
| INT_ERROR("pPortCount is NULL"); | ||
| return; | ||
| } | ||
|
|
||
| *pPortCount = _vPorts.size(); | ||
|
|
||
| if (nullptr != pPorts) { | ||
| // Reverse logic: Create pPorts from _vPorts | ||
| for (size_t i = 0; i < _vPorts.size(); i++) { | ||
| VideoOutputPort& port = _vPorts.at(i); | ||
|
|
||
| // Populate port ID | ||
| pPorts[i].id.type = (dsVideoPortType_t)port.getType().getId(); | ||
| pPorts[i].id.index = port.getIndex(); | ||
|
|
||
| // Populate connected audio output port | ||
| AudioOutputPort& audioPort = port.getAudioOutputPort(); | ||
| pPorts[i].connectedAOP.type = (dsAudioPortType_t)audioPort.getType().getId(); | ||
| pPorts[i].connectedAOP.index = audioPort.getIndex(); | ||
|
|
||
| // Get default resolution name - pointer to persistent string in VideoResolution object | ||
| const VideoResolution& defaultRes = port.getDefaultResolution(); | ||
| pPorts[i].defaultResolution = defaultRes.getName().c_str(); | ||
| } | ||
| INT_INFO("Populated %zu video ports to pPorts", _vPorts.size()); |
There was a problem hiding this comment.
getVideoPortVPorts() fills pPorts[i] for _vPorts.size() entries with no way for callers to specify their buffer capacity; RPC callers currently allocate 16 entries. This can overflow the caller buffer. Add a capacity parameter (or two-pass sizing) and clamp writes to the provided capacity.
rpc/srv/dsVideoPort.c
Outdated
| dsVideoPortPortConfig_t kVideoPortPorts[16] = {}; | ||
|
|
||
| getVideoPortVPorts(&numPorts, kVideoPortPorts); | ||
|
|
||
| // Print kVideoPortPorts array | ||
| INT_INFO("[DsMgr] ========== Dumping kVideoPortPorts Array in _GetVideoPortType ==========\r\n"); | ||
| INT_INFO("[DsMgr] Total ports retrieved: %d\r\n", numPorts); | ||
| for (int k = 0; k < numPorts; k++) { | ||
| dsVideoPortPortConfig_t *port = &kVideoPortPorts[k]; | ||
| INT_INFO("[DsMgr] [%d] type=%d, index=%d, connectedAOP_type=%d, connectedAOP_index=%d, defaultResolution=%s\r\n", | ||
| k, port->id.type, port->id.index, | ||
| port->connectedAOP.type, port->connectedAOP.index, | ||
| port->defaultResolution ? port->defaultResolution : "NULL"); | ||
| } |
There was a problem hiding this comment.
kVideoPortPorts is a fixed-size array of 16, but getVideoPortVPorts(&numPorts, ...) can return more than 16 ports, after which the log loop and the lookup loop will read past the end of the stack buffer. Clamp numPorts to the array capacity (or call once with NULL to get the required size and allocate accordingly).
…) in MW. Reason for change: Implemented logic to load both dynamic and static configurations on the server side and removed unnecessary code. Test Procedure: refer RDKEMW-8587, RDKEMW-12193 Risks: High Signed-off-by:gsanto722 <grandhi_santoshkumar@comcast.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 31 out of 31 changed files in this pull request and generated 14 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| dsVideoPortResolution_t *kVidoeResolutionsSettings = NULL; | ||
| int iCount = 0; | ||
| dsGetVideoPortResolutions(&iCount, &kVidoeResolutionsSettings); | ||
|
|
||
| // Print kVidoeResolutionsSettings array | ||
| INT_INFO("[DsMgr] ========== Dumping kVidoeResolutionsSettings Array in getPixelResolution ==========\r\n"); | ||
| INT_INFO("[DsMgr] Total resolutions retrieved: %d\r\n", iCount); | ||
| for (int k = 0; k < iCount; k++) { | ||
| dsVideoPortResolution_t *res = &kVidoeResolutionsSettings[k]; | ||
| INT_INFO("[DsMgr] [%d] name=%s, pixelRes=%d, aspectRatio=%d, stereoMode=%d, frameRate=%d, interlaced=%d\r\n", | ||
| k, res->name, res->pixelResolution, res->aspectRatio, | ||
| res->stereoScopicMode, res->frameRate, res->interlaced); | ||
| } | ||
| INT_INFO("[DsMgr] ========== End of kVidoeResolutionsSettings Dump ==========\r\n"); | ||
|
|
||
| for (unsigned int i = 0; i < dsUTL_DIM(kResolutions); i++) | ||
| dsVideoPortResolution_t *Resn = &kVidoeResolutionsSettings[0]; | ||
|
|
||
| for (int i = 0; i < iCount; i++) |
There was a problem hiding this comment.
kVidoeResolutionsSettings[0] is dereferenced even if dsGetVideoPortResolutions returns iCount <= 0 or a NULL pointer. If iCount is 0/-1, this is an out-of-bounds/null dereference. Add a guard (e.g., if (!kVidoeResolutionsSettings || iCount <= 0) return <fallback>;) before accessing index 0 and before iterating/logging.
| k, port->id.type, port->id.index, | ||
| port->connectedAOP.type, port->connectedAOP.index, | ||
| port->defaultResolution); |
There was a problem hiding this comment.
INT_INFO(... defaultResolution=%s ...) passes port->defaultResolution directly, but this field can be NULL (other code paths already treat it as optional). Passing NULL to %s is undefined and can crash. Use a ternary (port->defaultResolution ? port->defaultResolution : "NULL").
| k, port->id.type, port->id.index, | |
| port->connectedAOP.type, port->connectedAOP.index, | |
| port->defaultResolution); | |
| k, port->id.type, port->id.index, | |
| port->connectedAOP.type, port->connectedAOP.index, | |
| port->defaultResolution ? port->defaultResolution : "NULL"); |
| #include <stdio.h> | ||
| #include <stdlib.h> | ||
| #include <string.h> | ||
| #include "dsserverlogger.h" | ||
| #include "dsTypes.h" | ||
| #include "dsVideoPortSettings.h" | ||
|
|
There was a problem hiding this comment.
This file uses access(..., F_OK) but doesn’t include <unistd.h>. Please include it directly here to avoid implicit-declaration / missing-symbol issues when headers change or compilers are stricter.
| #include <stdio.h> | ||
| #include <stdlib.h> | ||
| #include <string.h> | ||
| #include "dsserverlogger.h" | ||
| #include "dsTypes.h" | ||
| #include "dsVideoDeviceSettings.h" | ||
|
|
There was a problem hiding this comment.
This file calls access(..., F_OK) but does not include <unistd.h> (where access/F_OK are declared). Add the include to make the dependency explicit.
| INT_INFO("[DsMgr] ========== Dumping kVideoPortPorts Array in _GetVideoPortType ==========\r\n"); | ||
| INT_INFO("[DsMgr] Total ports retrieved: %d\r\n", numPorts); | ||
| for (int k = 0; k < numPorts; k++) { | ||
| const dsVideoPortPortConfig_t *port = &kVideoPortPorts[k]; | ||
| INT_INFO("[DsMgr] [%d] type=%d, index=%d, connectedAOP_type=%d, connectedAOP_index=%d, defaultResolution=%s\r\n", | ||
| k, port->id.type, port->id.index, | ||
| port->connectedAOP.type, port->connectedAOP.index, | ||
| port->defaultResolution ? port->defaultResolution : "NULL"); | ||
| } | ||
| INT_INFO("[DsMgr] ========== End of kVideoPortPorts Dump ==========\r\n"); |
There was a problem hiding this comment.
This function logs the entire port-config array at INFO level every time _GetVideoPortType() runs. This is likely a hot path and will spam logs / add overhead in production. Consider gating this behind INT_DEBUG, the existing /opt/dsMgrDumpDeviceConfigs flag, or a build-time debug switch.
| INT_INFO("[DsMgr] ========== Dumping kVideoPortPorts Array in _GetVideoPortType ==========\r\n"); | |
| INT_INFO("[DsMgr] Total ports retrieved: %d\r\n", numPorts); | |
| for (int k = 0; k < numPorts; k++) { | |
| const dsVideoPortPortConfig_t *port = &kVideoPortPorts[k]; | |
| INT_INFO("[DsMgr] [%d] type=%d, index=%d, connectedAOP_type=%d, connectedAOP_index=%d, defaultResolution=%s\r\n", | |
| k, port->id.type, port->id.index, | |
| port->connectedAOP.type, port->connectedAOP.index, | |
| port->defaultResolution ? port->defaultResolution : "NULL"); | |
| } | |
| INT_INFO("[DsMgr] ========== End of kVideoPortPorts Dump ==========\r\n"); | |
| INT_DEBUG("[DsMgr] ========== Dumping kVideoPortPorts Array in _GetVideoPortType ==========\r\n"); | |
| INT_DEBUG("[DsMgr] Total ports retrieved: %d\r\n", numPorts); | |
| for (int k = 0; k < numPorts; k++) { | |
| const dsVideoPortPortConfig_t *port = &kVideoPortPorts[k]; | |
| INT_DEBUG("[DsMgr] [%d] type=%d, index=%d, connectedAOP_type=%d, connectedAOP_index=%d, defaultResolution=%s\r\n", | |
| k, port->id.type, port->id.index, | |
| port->connectedAOP.type, port->connectedAOP.index, | |
| port->defaultResolution ? port->defaultResolution : "NULL"); | |
| } | |
| INT_DEBUG("[DsMgr] ========== End of kVideoPortPorts Dump ==========\r\n"); |
| @@ -604,14 +620,14 @@ static void filterEDIDResolution(intptr_t handle, dsDisplayEDID_t *edid) | |||
| edid->numOfSupportedResolution = 0; | |||
| for (size_t i = 0; i < iCount; i++) | |||
| { | |||
| presolution = &kResolutions[i]; | |||
| presolution = &kVidoeResolutionsSettings[i]; | |||
There was a problem hiding this comment.
iCount is an int populated by dsGetVideoPortResolutions, but the subsequent loop uses size_t i < iCount. If iCount is negative (e.g., -1 when configs aren’t loaded), it will be converted to a huge size_t and the loop will walk off into memory; additionally kVidoeResolutionsSettings isn’t checked for NULL before dereference. Use an int loop variable and guard if (!kVidoeResolutionsSettings || iCount <= 0) { ... } before iterating.
| INT_INFO("[DsMgr] ========== Dumping kVidoeResolutionsSettings Array ==========\r\n"); | ||
| INT_INFO("[DsMgr] Total resolutions retrieved: %d\r\n", iCount); | ||
| for (int k = 0; k < iCount; k++) { | ||
| dsVideoPortResolution_t *res = &kVidoeResolutionsSettings[k]; | ||
| INT_INFO("[DsMgr] [%d] name=%s, pixelRes=%d, aspectRatio=%d, stereoMode=%d, frameRate=%d, interlaced=%d\r\n", | ||
| k, res->name, res->pixelResolution, res->aspectRatio, | ||
| res->stereoScopicMode, res->frameRate, res->interlaced); | ||
| } | ||
| INT_INFO("[DsMgr] ========== End of kVidoeResolutionsSettings Dump ==========\r\n"); |
There was a problem hiding this comment.
This unconditional INFO-level dump of every resolution retrieved from config can be very noisy (and filterEDIDResolution() is invoked on display/EDID flows). Consider moving these to INT_DEBUG and/or gating behind the existing /opt/dsMgrDumpDeviceConfigs flag to avoid log spam in normal operation.
| INT_INFO("[DsMgr] ========== Dumping kVidoeResolutionsSettings Array ==========\r\n"); | |
| INT_INFO("[DsMgr] Total resolutions retrieved: %d\r\n", iCount); | |
| for (int k = 0; k < iCount; k++) { | |
| dsVideoPortResolution_t *res = &kVidoeResolutionsSettings[k]; | |
| INT_INFO("[DsMgr] [%d] name=%s, pixelRes=%d, aspectRatio=%d, stereoMode=%d, frameRate=%d, interlaced=%d\r\n", | |
| k, res->name, res->pixelResolution, res->aspectRatio, | |
| res->stereoScopicMode, res->frameRate, res->interlaced); | |
| } | |
| INT_INFO("[DsMgr] ========== End of kVidoeResolutionsSettings Dump ==========\r\n"); | |
| INT_DEBUG("[DsMgr] ========== Dumping kVidoeResolutionsSettings Array ==========\r\n"); | |
| INT_DEBUG("[DsMgr] Total resolutions retrieved: %d\r\n", iCount); | |
| for (int k = 0; k < iCount; k++) { | |
| dsVideoPortResolution_t *res = &kVidoeResolutionsSettings[k]; | |
| INT_DEBUG("[DsMgr] [%d] name=%s, pixelRes=%d, aspectRatio=%d, stereoMode=%d, frameRate=%d, interlaced=%d\r\n", | |
| k, res->name, res->pixelResolution, res->aspectRatio, | |
| res->stereoScopicMode, res->frameRate, res->interlaced); | |
| } | |
| INT_DEBUG("[DsMgr] ========== End of kVidoeResolutionsSettings Dump ==========\r\n"); |
rpc/srv/dsVideoPortConfig.c
Outdated
| allocatedVideoPortConfigs = (dsVideoPortTypeConfig_t*)malloc(size * sizeof(dsVideoPortTypeConfig_t)); | ||
| if (allocatedVideoPortConfigs == NULL) { | ||
| INT_ERROR("Failed to allocate memory for %s video port configs\n", configType); | ||
| return -1; | ||
| } | ||
|
|
||
| memcpy(allocatedVideoPortConfigs, source, size * sizeof(dsVideoPortTypeConfig_t)); | ||
| videoPortConfiguration.pKVideoPortConfigs = allocatedVideoPortConfigs; | ||
| INT_INFO("Allocated and copied %d video port configs (%s)", size, configType); |
There was a problem hiding this comment.
allocateAndCopyVideoPortConfigs() overwrites allocatedVideoPortConfigs on each call without freeing any previous allocation. If configs can be reloaded (e.g., dsLoadConfigs() called more than once), this leaks memory and leaves stale pointers in videoPortConfiguration. Consider freeing any existing allocation (and resetting globals) before allocating new memory, or use realloc with careful error handling.
rpc/srv/dsVideoPortConfig.c
Outdated
| int dsGetDefaultResolutionIndex(void) | ||
| { | ||
| return g_defaultResIndex; | ||
| } |
There was a problem hiding this comment.
dsGetDefaultResolutionIndex is implemented as int dsGetDefaultResolutionIndex(void) (returns a value), but the public header declares void dsGetDefaultResolutionIndex(int* outDefaultIndex) and call sites pass an output pointer. This is undefined behavior and will also leave callers’ defaultIndex uninitialized/incorrect. Make the implementation match the header (set the out param), or change the header + all callers to the return-value form consistently.
| int defaultIndex = 0; | ||
| dsGetVideoPortResolutions(&numResolutions, &resolutions); | ||
| dsGetDefaultResolutionIndex(&defaultIndex); |
There was a problem hiding this comment.
This code calls dsGetDefaultResolutionIndex(&defaultIndex), but the current implementation in dsVideoPortConfig.c is a no-arg function returning int. With the current mismatch, defaultIndex may stay at its initialized value and the selected resolution can be wrong. Align the API so the default index is reliably returned here.
| int defaultIndex = 0; | |
| dsGetVideoPortResolutions(&numResolutions, &resolutions); | |
| dsGetDefaultResolutionIndex(&defaultIndex); | |
| int defaultIndex = dsGetDefaultResolutionIndex(); | |
| dsGetVideoPortResolutions(&numResolutions, &resolutions); |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 31 out of 31 changed files in this pull request and generated 30 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| * @param[out] outConfigSize Pointer to store the number of video device configs, or NULL | ||
| * @param[out] outConfigs Pointer to store the video device configs array, or NULL | ||
| */ | ||
| void dsGetVideoDeviceConfigs(int* outConfigSize, dsVideoConfig_t** outConfigs); |
There was a problem hiding this comment.
API design inconsistency. The function dsGetVideoDeviceConfigs returns a non-const pointer (dsVideoConfig_t**) at line 56, which allows callers to modify the internal configuration. For consistency with other getter functions and to prevent unintended modifications, consider changing the signature to return const dsVideoConfig_t** instead.
| void dsGetVideoDeviceConfigs(int* outConfigSize, dsVideoConfig_t** outConfigs); | |
| void dsGetVideoDeviceConfigs(int* outConfigSize, const dsVideoConfig_t** outConfigs); |
| typedef struct videoDeviceConfig | ||
| { | ||
| dsVideoConfig_t *pKVideoDeviceConfigs; | ||
| int *pKVideoDeviceConfigs_size; | ||
| }videoDeviceConfig_t; |
There was a problem hiding this comment.
Duplicate type definition. The videoDeviceConfig_t struct is defined in both dsConfigs.h (lines 58-62) and dsVideoDeviceConfig.h (lines 37-41) with identical structure. This duplication can lead to maintenance issues. Consider defining it in only one header file (preferably dsVideoDeviceConfig.h) and having dsConfigs.h include that header instead.
rpc/srv/dsVideoPortConfig.c
Outdated
| *(videoPortConfiguration.pKVideoPortConfigs_size) = configSize; | ||
| *(videoPortConfiguration.pKVideoPortPorts_size) = portSize; | ||
| *(videoPortConfiguration.pKResolutionsSettings_size) = resolutionSize; |
There was a problem hiding this comment.
Critical bug: Dereferencing uninitialized pointers. The pointers pKVideoPortConfigs_size, pKVideoPortPorts_size, and pKResolutionsSettings_size in videoPortConfiguration are never allocated or initialized before being dereferenced at these lines. This will cause crashes or undefined behavior. These pointers need to be allocated before use.
rpc/srv/dsAudioConfig.c
Outdated
| } | ||
| } | ||
|
|
||
| // Store sizes for getter functions |
There was a problem hiding this comment.
Critical bug: Dereferencing uninitialized pointers. The pointers pKConfigSize and pKPortSize in audioConfiguration are never allocated or initialized before being dereferenced at lines 179-180 and later at lines 182-185, 194, 204. This will cause crashes or undefined behavior. These pointers need to be allocated before use.
| // Store sizes for getter functions | |
| // Store sizes for getter functions | |
| if (audioConfiguration.pKConfigSize == NULL) { | |
| audioConfiguration.pKConfigSize = (int *)malloc(sizeof(int)); | |
| if (audioConfiguration.pKConfigSize == NULL) { | |
| INT_ERROR("Failed to allocate memory for audio configuration size\n"); | |
| return; | |
| } | |
| } | |
| if (audioConfiguration.pKPortSize == NULL) { | |
| audioConfiguration.pKPortSize = (int *)malloc(sizeof(int)); | |
| if (audioConfiguration.pKPortSize == NULL) { | |
| INT_ERROR("Failed to allocate memory for audio port size\n"); | |
| return; | |
| } | |
| } |
| } | ||
| } | ||
| catch (...) { | ||
| cout << "VIdeo Outport Exception Thrown. ..."<<endl; |
There was a problem hiding this comment.
Spelling error in comment. "VIdeo" should be "Video" (capital I should be lowercase).
| cout << "VIdeo Outport Exception Thrown. ..."<<endl; | |
| cout << "Video Outport Exception Thrown. ..."<<endl; |
| typedef struct videoPortConfigs | ||
| { | ||
| const dsVideoPortTypeConfig_t *pKVideoPortConfigs; | ||
| int *pKVideoPortConfigs_size; | ||
| const dsVideoPortPortConfig_t *pKVideoPortPorts; | ||
| int *pKVideoPortPorts_size; | ||
| dsVideoPortResolution_t *pKVideoPortResolutionsSettings; | ||
| int *pKResolutionsSettings_size; | ||
| int *pKDefaultResIndex; | ||
| }videoPortConfigs_t; |
There was a problem hiding this comment.
Duplicate type definition. The videoPortConfigs_t struct is defined in both dsConfigs.h (lines 47-56) and dsVideoPortConfig.h (lines 37-46) with identical structure. This duplication can lead to maintenance issues. Consider defining it in only one header file (preferably dsVideoPortConfig.h) and having dsConfigs.h include that header instead.
|
|
||
| void audioDumpconfig(audioConfigs_t *config) | ||
| { | ||
| if (nullptr == config) { |
There was a problem hiding this comment.
Inconsistent NULL checking syntax. This file uses both NULL (C-style, line 48) and nullptr (C++-style, line 50). This is a C file, so use NULL consistently throughout.
| if (nullptr == config) { | |
| if (NULL == config) { |
rpc/srv/dsAudioConfig.c
Outdated
| if(ret == -1) | ||
| { | ||
| INT_ERROR("failed to create dynamic memory\n"); | ||
| } | ||
|
|
||
| // Reading Audio port configs | ||
| portSize = (dynamicAudioConfigs->pKPortSize) ? *(dynamicAudioConfigs->pKPortSize) : -1; | ||
| ret = allocateAndCopyAudioPorts(dynamicAudioConfigs->pKAudioPorts, portSize, true); | ||
| if(ret == -1) | ||
| { | ||
| INT_ERROR("failed to create dynamic memory\n"); | ||
| } | ||
| } | ||
| else { | ||
| // Using static configuration | ||
| configSize = dsUTL_DIM(kConfigs); | ||
| ret = allocateAndCopyAudioConfigs(kConfigs, configSize, false); | ||
| if(ret == -1) | ||
| { | ||
| INT_ERROR("failed to create dynamic memory\n"); | ||
| } | ||
|
|
||
| portSize = dsUTL_DIM(kPorts); | ||
| ret = allocateAndCopyAudioPorts(kPorts, portSize, false); | ||
| if(ret == -1) | ||
| { | ||
| INT_ERROR("failed to create dynamic memory\n"); |
There was a problem hiding this comment.
Potential memory leak. If the second allocation for audio ports (line 155) fails after the first allocation for audio configs (line 147) succeeded, or vice versa in the static configuration path, the previously allocated memory is not freed. Add proper cleanup on failure.
| if(ret == -1) | |
| { | |
| INT_ERROR("failed to create dynamic memory\n"); | |
| } | |
| // Reading Audio port configs | |
| portSize = (dynamicAudioConfigs->pKPortSize) ? *(dynamicAudioConfigs->pKPortSize) : -1; | |
| ret = allocateAndCopyAudioPorts(dynamicAudioConfigs->pKAudioPorts, portSize, true); | |
| if(ret == -1) | |
| { | |
| INT_ERROR("failed to create dynamic memory\n"); | |
| } | |
| } | |
| else { | |
| // Using static configuration | |
| configSize = dsUTL_DIM(kConfigs); | |
| ret = allocateAndCopyAudioConfigs(kConfigs, configSize, false); | |
| if(ret == -1) | |
| { | |
| INT_ERROR("failed to create dynamic memory\n"); | |
| } | |
| portSize = dsUTL_DIM(kPorts); | |
| ret = allocateAndCopyAudioPorts(kPorts, portSize, false); | |
| if(ret == -1) | |
| { | |
| INT_ERROR("failed to create dynamic memory\n"); | |
| if (ret == -1) | |
| { | |
| INT_ERROR("failed to create dynamic memory for audio type configs\n"); | |
| // Nothing to clean up yet in this path | |
| return; | |
| } | |
| // Reading Audio port configs | |
| portSize = (dynamicAudioConfigs->pKPortSize) ? *(dynamicAudioConfigs->pKPortSize) : -1; | |
| ret = allocateAndCopyAudioPorts(dynamicAudioConfigs->pKAudioPorts, portSize, true); | |
| if (ret == -1) | |
| { | |
| INT_ERROR("failed to create dynamic memory for audio port configs\n"); | |
| // Clean up previously allocated audio type configs in dynamic path | |
| if (audioConfiguration.pKAudioConfigs != NULL) { | |
| free(audioConfiguration.pKAudioConfigs); | |
| audioConfiguration.pKAudioConfigs = NULL; | |
| } | |
| if (audioConfiguration.pKConfigSize != NULL) { | |
| *(audioConfiguration.pKConfigSize) = 0; | |
| } | |
| return; | |
| } | |
| } | |
| else { | |
| // Using static configuration | |
| configSize = dsUTL_DIM(kConfigs); | |
| ret = allocateAndCopyAudioConfigs(kConfigs, configSize, false); | |
| if (ret == -1) | |
| { | |
| INT_ERROR("failed to create dynamic memory for audio type configs\n"); | |
| // No dynamic memory to free in static configuration path | |
| return; | |
| } | |
| portSize = dsUTL_DIM(kPorts); | |
| ret = allocateAndCopyAudioPorts(kPorts, portSize, false); | |
| if (ret == -1) | |
| { | |
| INT_ERROR("failed to create dynamic memory for audio port configs\n"); | |
| // Leave audio type configs as-is; reset ports to safe state | |
| audioConfiguration.pKAudioPorts = NULL; | |
| if (audioConfiguration.pKPortSize != NULL) { | |
| *(audioConfiguration.pKPortSize) = 0; | |
| } | |
| return; |
| fprintf(stderr, "[DS][%d] %s [%s:%d] %s: %s \n", | ||
| (int)syscall(SYS_gettid), | ||
| levelMap[static_cast<int>(priority)], |
There was a problem hiding this comment.
Potential buffer overflow risk. The code uses static_cast<int>(priority) as an array index into levelMap without bounds checking. If an invalid priority value is passed (e.g., greater than TRACE_LEVEL), this will result in an out-of-bounds array access. Add bounds checking before indexing the array.
| fprintf(stderr, "[DS][%d] %s [%s:%d] %s: %s \n", | |
| (int)syscall(SYS_gettid), | |
| levelMap[static_cast<int>(priority)], | |
| int levelIndex = static_cast<int>(priority); | |
| const char *levelStr = "UNKNOWN"; | |
| if (levelIndex >= INFO_LEVEL && levelIndex <= TRACE_LEVEL) | |
| { | |
| levelStr = levelMap[levelIndex]; | |
| } | |
| fprintf(stderr, "[DS][%d] %s [%s:%d] %s: %s \n", | |
| (int)syscall(SYS_gettid), | |
| levelStr, |
| if (( false == m_isFPInitialized) || (true == m_isFPConfigLoaded)) { | ||
| INT_ERROR("'%s'", (!m_isFPInitialized) ? "Front Panel not initialized" : "Front Panel Config already loaded"); | ||
| return; | ||
| } |
There was a problem hiding this comment.
Possible unintended behavior when m_isFPConfigLoaded is true. The function returns early if config is already loaded (line 418-420), but there's no indication whether this is intentional (idempotent loading) or an error condition. If loading twice is an error, the error message should be more explicit. If it's intentional, consider using INT_INFO instead of INT_ERROR, or add a comment explaining the behavior.
| if (( false == m_isFPInitialized) || (true == m_isFPConfigLoaded)) { | |
| INT_ERROR("'%s'", (!m_isFPInitialized) ? "Front Panel not initialized" : "Front Panel Config already loaded"); | |
| return; | |
| } | |
| if (false == m_isFPInitialized) { | |
| INT_ERROR("'%s'", "Front Panel not initialized"); | |
| return; | |
| } | |
| // It is intentional that load() is idempotent: if config is already loaded, | |
| // treat this as a no-op and log at info level rather than as an error. | |
| if (true == m_isFPConfigLoaded) { | |
| INT_INFO("'%s'", "Front Panel Config already loaded, skipping reload"); | |
| return; | |
| } |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 31 out of 31 changed files in this pull request and generated 17 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| #include <vector> | ||
|
|
||
| typedef struct videoDeviceConfig | ||
| { | ||
| dsVideoConfig_t *pKVideoDeviceConfigs; | ||
| int *pKVideoDeviceConfigs_size; | ||
| }videoDeviceConfig_t; | ||
|
|
There was a problem hiding this comment.
Duplicate type definition. The videoDeviceConfig_t structure is defined in both videoDeviceConfig.hpp (lines 38-42) and dsVideoDeviceConfig.h (lines 37-41). This could lead to confusion and type mismatches. Consolidate to a single definition or ensure they're truly different types with different purposes.
| #include <vector> | |
| typedef struct videoDeviceConfig | |
| { | |
| dsVideoConfig_t *pKVideoDeviceConfigs; | |
| int *pKVideoDeviceConfigs_size; | |
| }videoDeviceConfig_t; | |
| #include "dsVideoDeviceConfig.h" | |
| #include <vector> |
| dsError_t ret = dsERR_NONE; | ||
| intptr_t handle = -1; | ||
|
|
||
| // Assuming isHDMIOutPortPresent() will only be 'true' for Source devices | ||
| dsVideoPortType_t portType = device::Host::getInstance().isHDMIOutPortPresent() | ||
| ? dsVIDEOPORT_TYPE_HDMI | ||
| : dsVIDEOPORT_TYPE_INTERNAL; | ||
| ret = dsGetVideoPort(portType, 0, &handle); | ||
| if ((ret == dsERR_NONE) && (handle != -1)) { | ||
| ret = dsEnableHDCP(handle, contentProtect, hdcpKey, keySize); | ||
| } else { | ||
| INT_ERROR("VideoOutputPortType::enabledHDCP: Error type %d, handle=%p, error code=%d", portType, (void *)handle, ret); | ||
| // Set ret to an error code on dsGetVideoPort failure or invalid handle to ensure exception is thrown | ||
| ret = dsERR_GENERAL; | ||
| } |
There was a problem hiding this comment.
API signature change may break existing code. The dsEnableHDCP function signature changed from taking a port type (dsVideoPortType_t) to taking a handle (intptr_t). This is a breaking API change. Ensure that all callers of this function throughout the codebase have been updated to pass a handle instead of a port type, or that this is the only usage of this API.
| } dlSymbolLookup_t; | ||
|
|
||
|
|
||
| static int LoadDLSymbols(void* pDLHandle, const dlSymbolLookup_t* symbols, int numberOfSymbols) |
There was a problem hiding this comment.
Duplicate type definition and naming inconsistency. The dlSymbolLookup type is defined in both ds/include/manager.hpp (lines 173-176) and rpc/srv/dsConfigs.c (lines 49-52), with slightly different naming (struct vs typedef struct). The function LoadDLSymbols is also duplicated in both files with different signatures (bool vs int return type). Consolidate these to a common header to avoid inconsistencies.
| } dlSymbolLookup_t; | |
| static int LoadDLSymbols(void* pDLHandle, const dlSymbolLookup_t* symbols, int numberOfSymbols) | |
| } dsConfigs_dlSymbolLookup_t; | |
| static int LoadDLSymbols(void* pDLHandle, const dsConfigs_dlSymbolLookup_t* symbols, int numberOfSymbols) |
rpc/srv/dsAudioConfig.c
Outdated
| // Allocate and copy audio type configs | ||
| if (allocateAndCopyAudioConfigs(audioConfigs, configSize, isDynamic) == -1) { | ||
| INT_ERROR("Failed to allocate audio type configs\n"); | ||
| return; |
There was a problem hiding this comment.
Inconsistent return type. Function is declared with void return type (line 50) but returns a value here. Should be return statement without a value, or the function should be declared to return int to match the error checking pattern in the caller (dsConfigs.c line 111).
rpc/srv/dsAudioConfig.c
Outdated
| free(audioConfiguration.pKAudioConfigs); | ||
| audioConfiguration.pKAudioConfigs = NULL; | ||
| } | ||
| return; |
There was a problem hiding this comment.
Inconsistent return type. Function is declared with void return type (line 50) but returns a value here. Should be return statement without a value, or the function should be declared to return int to match the error checking pattern in the caller (dsConfigs.c line 111).
| void dsGetAudioPortConfigs(int* outPortSize, const dsAudioPortConfig_t** outPorts); | ||
|
|
||
| #ifdef __cplusplus | ||
| } | ||
| #endif | ||
|
|
||
| #endif /* _DS_AUDIO_CONFIG_H_ */ | ||
|
|
||
| /** @} */ | ||
| /** @} */ |
There was a problem hiding this comment.
Missing function declaration. The function dsAudioConfigFree is called in dsMgr.c line 149, but it's not declared in the dsAudioConfig.h header file. Add the function declaration to the header file to ensure proper API visibility.
| typedef struct videoPortConfigs | ||
| { | ||
| const dsVideoPortTypeConfig_t *pKConfigs; | ||
| int *pKVideoPortConfigs_size; | ||
| const dsVideoPortPortConfig_t *pKPorts; | ||
| int *pKVideoPortPorts_size; | ||
| dsVideoPortResolution_t *pKResolutionsSettings; | ||
| int *pKResolutionsSettings_size; | ||
| }videoPortConfigs_t; |
There was a problem hiding this comment.
Duplicate type definition. The videoPortConfigs_t structure is defined both in videoOutputPortConfig.hpp (lines 39-47) and in dsVideoPortConfig.h (lines 37-46), with slightly different field names (pKConfigs vs pKVideoPortConfigs). This could lead to confusion and type mismatches. Consolidate to a single definition or ensure they're truly different types with different purposes.
| typedef struct audioConfigs | ||
| { | ||
| const dsAudioTypeConfig_t *pKConfigs; | ||
| const dsAudioPortConfig_t *pKPorts; | ||
| int *pKConfigSize; | ||
| int *pKPortSize; | ||
| }audioConfigs_t; |
There was a problem hiding this comment.
Duplicate type definition. The audioConfigs_t structure is defined in both audioOutputPortConfig.hpp (lines 41-47) and dsAudioConfig.h (lines 37-43). This could lead to confusion and type mismatches. Consolidate to a single definition or ensure they're truly different types with different purposes.
| typedef struct audioConfigs | |
| { | |
| const dsAudioTypeConfig_t *pKConfigs; | |
| const dsAudioPortConfig_t *pKPorts; | |
| int *pKConfigSize; | |
| int *pKPortSize; | |
| }audioConfigs_t; | |
| typedef struct audioConfigs audioConfigs_t; |
| #define DEBUG 1 // Using for dumpconfig | ||
|
|
There was a problem hiding this comment.
Debug macro definition left in production code. Line 38 defines DEBUG macro but it's not used conditionally in the dumpconfig function that follows. If this is meant for conditional compilation, wrap the dumpconfig function calls with #ifdef DEBUG guards. Otherwise, remove this definition to avoid confusion.
| #define DEBUG 1 // Using for dumpconfig |
| INT_INFO("\n=============== Starting to Dump VideoPort Configs ===============\n"); | ||
|
|
||
| int configSize = -1, portSize = -1, resolutionSize = -1; | ||
| if (( NULL != config->pKVideoPortConfigs ) && ( NULL != config->pKVideoPortPorts ) && ( nullptr != config->pKVideoPortResolutionsSettings )) |
There was a problem hiding this comment.
Inconsistent NULL checking style. This line uses nullptr (C++ keyword) in C code, while other NULL checks in the same function use NULL (lines 55, 66 use NULL elsewhere). In C code, use NULL consistently instead of nullptr.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 31 out of 31 changed files in this pull request and generated 22 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| INT_INFO("Entering capabilityType = 0x%08X\n", capabilityType); | ||
| dlerror(); /* clear old error */ | ||
| pDLHandle = dlopen(RDK_DSHAL_NAME, RTLD_LAZY); |
There was a problem hiding this comment.
Missing error handling: The function doesn't check for dlopen failures. If pDLHandle is NULL (dlopen failed), the code will pass NULL to LoadDLSymbols, which will fail silently and fall back to static configurations. Consider logging dlerror() message when dlopen fails to help diagnose library loading issues.
| pDLHandle = dlopen(RDK_DSHAL_NAME, RTLD_LAZY); | |
| pDLHandle = dlopen(RDK_DSHAL_NAME, RTLD_LAZY); | |
| if (NULL == pDLHandle) { | |
| const char* dlErrMsg = dlerror(); | |
| if (dlErrMsg != NULL) { | |
| INT_ERROR("Failed to load '%s': %s\n", RDK_DSHAL_NAME, dlErrMsg); | |
| } else { | |
| INT_ERROR("Failed to load '%s': unknown dlopen error\n", RDK_DSHAL_NAME); | |
| } | |
| } |
| #define DEBUG 1 // Using for dumpconfig | ||
|
|
There was a problem hiding this comment.
Undefined preprocessor macro: The code references DEBUG macro at line 38, but this macro is defined locally in this file. However, DEBUG is commonly a predefined macro in many build systems. Consider using a more specific name like DS_VIDEO_DEVICE_DEBUG to avoid conflicts.
| #define DEBUG 1 // Using for dumpconfig | |
| // Local debug flag for VideoDeviceConfig; avoid clobbering global DEBUG. | |
| #ifndef DS_VIDEO_DEVICE_DEBUG | |
| #define DS_VIDEO_DEVICE_DEBUG 1 // Using for dumpconfig | |
| #endif | |
| // Preserve existing behavior: only define DEBUG here if not provided by build system. | |
| #ifndef DEBUG | |
| #define DEBUG DS_VIDEO_DEVICE_DEBUG | |
| #endif |
| : dsVIDEOPORT_TYPE_INTERNAL; | ||
| ret = dsGetVideoPort(portType, 0, &handle); | ||
| if ((ret == dsERR_NONE) && (handle != -1)) { | ||
| ret = dsEnableHDCP(handle, contentProtect, hdcpKey, keySize); |
There was a problem hiding this comment.
Changed API signature: The dsEnableHDCP function call changed from passing a port type (dsVideoPortType_t) to passing a handle (intptr_t). This is a breaking API change that needs to be verified against the HAL library implementation. Ensure that the HAL library's dsEnableHDCP function signature matches this new usage.
| errno_t rc = -1; | ||
| dsVideoPortResolution_t *edidResn = NULL; | ||
| dsVideoPortResolution_t *presolution = NULL; | ||
| dsVideoPortResolution_t *presolution = NULL, *kVidoeResolutionsSettings = NULL; |
There was a problem hiding this comment.
Spelling error in variable name: kVidoeResolutionsSettings should be kVideoResolutionsSettings (misspelled "Video" as "Vidoe"). This variable appears multiple times in this function.
| componentPortPresent = true;; | ||
| if (typeConfigs[i].typeId == dsVIDEOPORT_TYPE_COMPONENT) | ||
| { | ||
| componentPortPresent = true; |
There was a problem hiding this comment.
Unnecessary double semicolon at the end of the statement. Remove one semicolon.
| @@ -259,88 +257,207 @@ List<VideoResolution> VideoOutputPortConfig::getSupportedResolutions(bool isIgn | |||
| for (VideoResolution resolution : tmpsupportedResolutions){ | |||
| _supportedResolutions.push_back(resolution); | |||
| } | |||
| cout << "[DsMgr] _supportedResolutions cache after update, size: " << _supportedResolutions.size() << endl; | |||
| for (size_t idx = 0; idx < _supportedResolutions.size(); idx++) { | |||
| const VideoResolution& res = _supportedResolutions[idx]; | |||
| cout << "[DsMgr] [" << idx << "] " << res.getName() | |||
| << " pixelRes=" << res.getPixelResolution().getId() | |||
| << " aspectRatio=" << res.getAspectRatio().getId() | |||
| << " frameRate=" << res.getFrameRate().getId() << endl; | |||
| } | |||
There was a problem hiding this comment.
Debugging code left in production: The cout statements (lines 220-230, 260-267) appear to be debug code that should be removed or replaced with proper logging macros (INT_INFO/INT_DEBUG) for consistency with the rest of the codebase.
| return numElements; | ||
| } | ||
|
|
||
| int dsLoadVideoOutputPortConfig(const videoPortConfigs_t* dynamicVideoPortConfigs) |
There was a problem hiding this comment.
API signature mismatch: The header file declares dsLoadVideoOutputPortConfig as returning void (line 53 of dsVideoPortConfig.h), but the implementation returns int. This inconsistency will cause compilation errors or undefined behavior.
| return numElements; | ||
| } | ||
|
|
||
| int dsLoadVideoDeviceConfig(const videoDeviceConfig_t* dynamicVideoDeviceConfigs) |
There was a problem hiding this comment.
API signature mismatch: The header file declares dsLoadVideoDeviceConfig as returning void (line 48 of dsVideoDeviceConfig.h), but the implementation returns int. This inconsistency will cause compilation errors or undefined behavior.
| int kPortSize; | ||
| }audioConfigsLocal_t; | ||
|
|
||
| static audioConfigsLocal_t audioConfiguration = {0}; |
There was a problem hiding this comment.
Potential race condition: The global static variable audioConfiguration is accessed and modified without any mutex protection. Multiple threads could potentially call dsLoadAudioOutputPortConfig or the getter functions concurrently, leading to data races. Consider adding mutex protection around accesses to this shared state.
| int dsLoadVideoOutputPortConfig(const videoPortConfigs_t* dynamicVideoPortConfigs) | ||
| { | ||
| int configSize, portSize, resolutionSize, defaultResIndex; | ||
| const dsVideoPortTypeConfig_t* videoPortConfigs; | ||
| const dsVideoPortPortConfig_t* videoPortPorts; | ||
| const dsVideoPortResolution_t* videoPortResolutions; | ||
| bool isDynamic; | ||
|
|
||
| INT_INFO("Using '%s' config\n", dynamicVideoPortConfigs ? "dynamic" : "static"); | ||
|
|
||
| // Set up parameters based on config source | ||
| if (NULL != dynamicVideoPortConfigs) { | ||
| configSize = *(dynamicVideoPortConfigs->pKVideoPortConfigs_size); | ||
| portSize = *(dynamicVideoPortConfigs->pKVideoPortPorts_size); | ||
| resolutionSize = *(dynamicVideoPortConfigs->pKResolutionsSettings_size); | ||
| defaultResIndex = *(dynamicVideoPortConfigs->pKDefaultResIndex); | ||
| videoPortConfigs = dynamicVideoPortConfigs->pKVideoPortConfigs; | ||
| videoPortPorts = dynamicVideoPortConfigs->pKVideoPortPorts; | ||
| videoPortResolutions = dynamicVideoPortConfigs->pKVideoPortResolutionsSettings; | ||
| isDynamic = true; | ||
| } else { | ||
| configSize = dsUTL_DIM(kConfigs); | ||
| portSize = dsUTL_DIM(kPorts); | ||
| resolutionSize = dsUTL_DIM(kResolutions); | ||
| defaultResIndex = kDefaultResIndex; | ||
| videoPortConfigs = kConfigs; | ||
| videoPortPorts = kPorts; | ||
| videoPortResolutions = kResolutions; | ||
| isDynamic = false; | ||
| } | ||
|
|
||
| // Allocate and copy video port type configs | ||
| if (allocateAndCopyVideoPortConfigs(videoPortConfigs, configSize, isDynamic) == -1) { | ||
| INT_ERROR("Failed to allocate video port configs\n"); | ||
| return -1; | ||
| } | ||
|
|
||
| // Allocate and copy video port ports | ||
| if (allocateAndCopyVideoPortPorts(videoPortPorts, portSize, isDynamic) == -1) { | ||
| INT_ERROR("Failed to allocate video port ports\n"); | ||
| // Clean up previously allocated memory | ||
| if (videoPortConfiguration.pKVideoPortConfigs != NULL) { | ||
| free(videoPortConfiguration.pKVideoPortConfigs); | ||
| videoPortConfiguration.pKVideoPortConfigs = NULL; | ||
| } | ||
| return -1; | ||
| } | ||
|
|
||
| // Allocate and copy video port resolutions | ||
| if (allocateAndCopyVideoPortResolutions(videoPortResolutions, resolutionSize, isDynamic) == -1) { | ||
| INT_ERROR("Failed to allocate video port resolutions\n"); | ||
| // Clean up previously allocated memory | ||
| if (videoPortConfiguration.pKVideoPortConfigs != NULL) { | ||
| free(videoPortConfiguration.pKVideoPortConfigs); | ||
| videoPortConfiguration.pKVideoPortConfigs = NULL; | ||
| } | ||
| if (videoPortConfiguration.pKVideoPortPorts != NULL) { | ||
| free(videoPortConfiguration.pKVideoPortPorts); | ||
| videoPortConfiguration.pKVideoPortPorts = NULL; | ||
| } | ||
| return -1; | ||
| } | ||
|
|
||
| INT_INFO("Store sizes configSize =%d, portSize =%d, resolutionSize = %d\n", configSize, portSize, resolutionSize); | ||
| videoPortConfiguration.kDefaultResIndex = defaultResIndex; | ||
| INT_INFO("Store sizes videoPortConfiguration.kDefaultResIndex = %d\n", videoPortConfiguration.kDefaultResIndex); | ||
|
|
||
| INT_INFO("Store sizes configSize =%d, portSize =%d, resolutionSize = %d\n", configSize, portSize, resolutionSize); | ||
| videoPortConfiguration.kVideoPortConfigs_size = configSize; | ||
| videoPortConfiguration.kVideoPortPorts_size = portSize; | ||
| videoPortConfiguration.kResolutionsSettings_size = resolutionSize; | ||
| INT_INFO("Store sizes kVideoPortConfigs_size = %d\n", videoPortConfiguration.kVideoPortConfigs_size); | ||
| INT_INFO("Store sizes kVideoPortPorts_size = %d\n", videoPortConfiguration.kVideoPortPorts_size); | ||
| INT_INFO("Store sizes kResolutionsSettings_size = %d\n", videoPortConfiguration.kResolutionsSettings_size); | ||
|
|
||
| INT_INFO("VideoPort Config[%p] ConfigSize[%d] Ports[%p] PortSize[%d] Resolutions[%p] ResolutionSize[%d] DefaultResIndex[%d]\n", | ||
| videoPortConfiguration.pKVideoPortConfigs, | ||
| videoPortConfiguration.kVideoPortConfigs_size, | ||
| videoPortConfiguration.pKVideoPortPorts, | ||
| videoPortConfiguration.kVideoPortPorts_size, | ||
| videoPortConfiguration.pKVideoPortResolutionsSettings, | ||
| videoPortConfiguration.kResolutionsSettings_size, | ||
| videoPortConfiguration.kDefaultResIndex); | ||
| videoPortDumpconfig(&videoPortConfiguration); | ||
| return 0; | ||
| } |
There was a problem hiding this comment.
Potential double-free vulnerability: If dsLoadVideoOutputPortConfig is called multiple times, the previously allocated memory will be leaked before being replaced with new allocations. Additionally, there's no check to prevent double-initialization. Consider adding a flag to track initialization state and free existing memory before reallocating.
No description provided.