Files
2026-08-24 10:03:24 +08:00

214 lines
6.9 KiB
C++

/*
* Copyright (c) 2020 Amlogic, Inc. All rights reserved.
*
* This source code is subject to the terms and conditions defined in the
* file 'LICENSE' which is part of this source code package.
*
* Description:
*/
#include <string.h>
#include <errno.h>
#include <MesonLog.h>
#include "DrmProperty.h"
#include <inttypes.h>
//#include <format>
#include "BasicTypes.h"
#ifdef __ANDROID__
#include <android-base/stringprintf.h>
using android::base::StringAppendF;
#endif
DrmProperty::DrmProperty(drmModePropertyPtr p, uint32_t objectId, uint64_t value, int32_t fd)
: mValue(value), mComponentId(objectId), mDrvFd(fd) {
memcpy(&mPropRes, p, sizeof(mPropRes));
if (p->count_values > 0) {
size_t contentLen = p->count_values * sizeof(uint64_t);
mPropRes.values = (uint64_t*)malloc(contentLen);
memcpy(mPropRes.values, p->values, contentLen);
} else {
mPropRes.values = NULL;
}
if (p->count_enums > 0) {
size_t contentLen = p->count_enums * sizeof(struct drm_mode_property_enum);
mPropRes.enums = (struct drm_mode_property_enum *)malloc(contentLen);
memcpy(mPropRes.enums, p->enums, contentLen);
} else {
mPropRes.enums = NULL;
}
if (p->count_blobs > 0) {
size_t contentLen = p->count_blobs * sizeof(uint32_t);
mPropRes.blob_ids = (uint32_t*)malloc(contentLen);
memcpy(mPropRes.blob_ids, p->blob_ids, contentLen);
} else {
mPropRes.blob_ids = NULL;
}
mType = 0;
if (drm_property_type_is(p, DRM_MODE_PROP_RANGE)) {
mType = DRM_MODE_PROP_RANGE;
MESON_ASSERT(p->count_values > 0, " NO RANGE SPECIFIED (%s)", mPropRes.name);
} else if (drm_property_type_is(p, DRM_MODE_PROP_SIGNED_RANGE)) {
mType = DRM_MODE_PROP_SIGNED_RANGE;
MESON_ASSERT(p->count_values > 0, " NO RANGE SPECIFIED (%s)", mPropRes.name);
} else if (drm_property_type_is(p, DRM_MODE_PROP_ENUM)) {
mType = DRM_MODE_PROP_ENUM;
MESON_ASSERT(p->count_enums > 0, " NO ENUM SPECIFIED (%s)", mPropRes.name);
} else if (drm_property_type_is(p, DRM_MODE_PROP_OBJECT)) {
mType = DRM_MODE_PROP_OBJECT;
} else if (drm_property_type_is(p, DRM_MODE_PROP_BLOB)) {
mType = DRM_MODE_PROP_BLOB;
} else if (drm_property_type_is(p, DRM_MODE_PROP_BITMASK)) {
mType = DRM_MODE_PROP_BITMASK;
}
MESON_ASSERT(mType !=0, "UNKNOWN type for prop (%s)", mPropRes.name);
MESON_LOGD("DrmProperty: %s (%d), value [%" PRId64 "]",
mPropRes.name, mPropRes.prop_id, mValue);
}
DrmProperty::~DrmProperty() {
if (mPropRes.values)
free(mPropRes.values);
if (mPropRes.enums)
free(mPropRes.enums);
if (mPropRes.blob_ids)
free(mPropRes.blob_ids);
}
int DrmProperty::setValue(uint64_t val) {
if (isImmutable())
return -EIO;
if (mType == DRM_MODE_PROP_RANGE) {
if (val < mPropRes.values[0] || val > mPropRes.values[1]) {
MESON_LOGE("[%s] RANGE ERROR (%" PRId64 ") -> (%" PRId64 ",%" PRId64 ")",
mPropRes.name, val, mPropRes.values[0], mPropRes.values[1]);
return -EINVAL;
}
} else if (mType == DRM_MODE_PROP_SIGNED_RANGE) {
int64_t signedVal = (int64_t)val;
int64_t minVal = (int64_t) mPropRes.values[0];
int64_t maxVal = (int64_t) mPropRes.values[1];
if (signedVal < minVal || signedVal > maxVal) {
return -EINVAL;
}
}
if (mValue != val) {
mValue = val;
}
return 0;
}
uint64_t DrmProperty::getValue() {
switch (mType) {
case DRM_MODE_PROP_OBJECT:
case DRM_MODE_PROP_RANGE:
case DRM_MODE_PROP_SIGNED_RANGE:
case DRM_MODE_PROP_BLOB:
case DRM_MODE_PROP_ENUM:
case DRM_MODE_PROP_BITMASK:
return mValue;
default:
MESON_LOGE("unknown property type");
return 0;
}
}
int DrmProperty::getBlobData(std::vector<uint8_t> & blob) {
if (mType != DRM_MODE_PROP_BLOB)
return -EINVAL;
return getBlobData(blob, mValue);
}
int DrmProperty::getBlobData(std::vector<uint8_t> & blob, uint32_t blobId) {
MESON_ASSERT(mType == DRM_MODE_PROP_BLOB, "Only For blob.");
drmModePropertyBlobPtr blobProp =
drmModeGetPropertyBlob(mDrvFd, blobId);
if (!blobProp) {
return -EIO;
}
uint8_t * blobData = (uint8_t * )blobProp->data;
for (int i = 0; i < blobProp->length; i++) {
blob.push_back(blobData[i]);
}
drmModeFreePropertyBlob(blobProp);
return 0;
}
int DrmProperty::getEnumValueWithName(const char *name, uint64_t & val) {
MESON_ASSERT(mType == DRM_MODE_PROP_ENUM, "Only For RANG ENUM.");
for (int i = 0; i < mPropRes.count_enums; i++) {
if (strcmp(mPropRes.enums[i].name, name) == 0) {
val = mPropRes.enums[i].value;
return 0;
}
}
//MESON_LOGE("GetEnum value failed with %s", name);
return -EINVAL;
}
int DrmProperty::getRangeValue(uint64_t &min, uint64_t &max) {
MESON_ASSERT(mType == DRM_MODE_PROP_RANGE || mType == DRM_MODE_PROP_SIGNED_RANGE, "Only For RANG PROP.");
min = mPropRes.values[0];
max = mPropRes.values[1];
return 0;
}
int DrmProperty::apply(drmModeAtomicReqPtr req) {
return drmModeAtomicAddProperty(req, mComponentId, mPropRes.prop_id, getValue());
}
void DrmProperty::dump(std::string &dumpstr) {
StringAppendF(&dumpstr,
"DrmProperty: [%s]-[%d], value [%" PRIu64 "], immutable[%d]:",
mPropRes.name, mPropRes.prop_id, mValue, isImmutable());
if (mType == DRM_MODE_PROP_RANGE) {
dumpstr.append("values:");
for (int i = 0; i < mPropRes.count_values; i++) {
StringAppendF(&dumpstr, " %" PRIu64 " ", mPropRes.values[i]);
}
dumpstr.append("\n");
} else if (mType == DRM_MODE_PROP_ENUM) {
dumpstr.append("enums:");
for (int i = 0; i < mPropRes.count_enums; i++) {
StringAppendF(&dumpstr, " %s=%llu",
mPropRes.enums[i].name,
(unsigned long long)mPropRes.enums[i].value);
}
dumpstr.append("\n");
} else if (mType == DRM_MODE_PROP_BLOB) {
dumpstr.append("blobs:");
std::vector<unsigned char> blob;
for (int i = 0; i < mPropRes.count_blobs; i++) {
if (0 == getBlobData(blob, mPropRes.blob_ids[i])) {
StringAppendF(&dumpstr, "-id[%d-%" PRIuFAST16 "]:",
mPropRes.blob_ids[i],
(uint_fast16_t)blob.size());
for (uint8_t val : blob)
StringAppendF(&dumpstr, "%.2hhx", val);
dumpstr.append("\n");
}
}
if (0 == getBlobData(blob)) {
StringAppendF(&dumpstr, "-val[%" PRIu64 "-%" PRIuFAST16 "]:",
mValue,
(uint_fast16_t)blob.size());
for (uint8_t val : blob)
StringAppendF(&dumpstr, "%.2hhx", val);
dumpstr.append("\n");
}
}
}