• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
18 #define LOG_TAG "drmhwc"
19 
20 #include "DrmProperty.h"
21 
22 #include <xf86drmMode.h>
23 
24 #include <cerrno>
25 #include <cinttypes>
26 #include <cstdint>
27 #include <string>
28 
29 #include "DrmDevice.h"
30 #include "utils/log.h"
31 
32 namespace android {
33 
DrmPropertyEnum(drm_mode_property_enum * e)34 DrmProperty::DrmPropertyEnum::DrmPropertyEnum(drm_mode_property_enum *e)
35     : value(e->value), name(e->name) {
36 }
37 
DrmProperty(const SharedFd & fd,uint32_t obj_id,drmModePropertyPtr p,uint64_t value)38 DrmProperty::DrmProperty(const SharedFd &fd, uint32_t obj_id,
39                          drmModePropertyPtr p, uint64_t value) {
40   Init(fd, obj_id, p, value);
41 }
42 
Init(const SharedFd & fd,uint32_t obj_id,drmModePropertyPtr p,uint64_t value)43 void DrmProperty::Init(const SharedFd &fd, uint32_t obj_id,
44                        drmModePropertyPtr p, uint64_t value) {
45   fd_ = fd;
46   obj_id_ = obj_id;
47   id_ = p->prop_id;
48   flags_ = p->flags;
49   name_ = p->name;
50   value_ = value;
51 
52   for (int i = 0; i < p->count_values; ++i)
53     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic):
54     values_.emplace_back(p->values[i]);
55 
56   for (int i = 0; i < p->count_enums; ++i)
57     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic):
58     enums_.emplace_back(&p->enums[i]);
59 
60   for (int i = 0; i < p->count_blobs; ++i)
61     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic):
62     blob_ids_.emplace_back(p->blob_ids[i]);
63 }
64 
GetValue() const65 std::optional<uint64_t> DrmProperty::GetValue() const {
66   if ((flags_ & DRM_MODE_PROP_BLOB) != 0)
67     return value_;
68 
69   if (values_.empty())
70     return {};
71 
72   if ((flags_ & DRM_MODE_PROP_RANGE) != 0)
73     return value_;
74 
75   if ((flags_ & DRM_MODE_PROP_ENUM) != 0) {
76     if (value_ >= enums_.size())
77       return {};
78 
79     return enums_[value_].value;
80   }
81 
82   if ((flags_ & DRM_MODE_PROP_OBJECT) != 0)
83     return value_;
84 
85   return {};
86 }
87 
RangeMin() const88 std::tuple<int, uint64_t> DrmProperty::RangeMin() const {
89   if (!IsRange())
90     return std::make_tuple(-EINVAL, 0);
91   if (values_.empty())
92     return std::make_tuple(-ENOENT, 0);
93 
94   return std::make_tuple(0, values_[0]);
95 }
96 
RangeMax() const97 std::tuple<int, uint64_t> DrmProperty::RangeMax() const {
98   if (!IsRange())
99     return std::make_tuple(-EINVAL, 0);
100   if (values_.size() < 2)
101     return std::make_tuple(-ENOENT, 0);
102 
103   return std::make_tuple(0, values_[1]);
104 }
105 
GetEnumValueWithName(const std::string & name) const106 std::tuple<uint64_t, int> DrmProperty::GetEnumValueWithName(
107     const std::string &name) const {
108   for (const auto &it : enums_) {
109     if (it.name == name) {
110       return std::make_tuple(it.value, 0);
111     }
112   }
113 
114   return std::make_tuple(UINT64_MAX, -EINVAL);
115 }
116 
AtomicSet(drmModeAtomicReq & pset,uint64_t value) const117 auto DrmProperty::AtomicSet(drmModeAtomicReq &pset, uint64_t value) const
118     -> bool {
119   if (id_ == 0) {
120     ALOGE("AtomicSet() is called on non-initialized property!");
121     return false;
122   }
123   if (drmModeAtomicAddProperty(&pset, obj_id_, id_, value) < 0) {
124     ALOGE("Failed to add obj_id: %u, prop_id: %u (%s) to pset", obj_id_, id_,
125           name_.c_str());
126     return false;
127   }
128   return true;
129 }
130 
GetEnumNameFromValue(uint64_t value) const131 std::optional<std::string> DrmProperty::GetEnumNameFromValue(
132     uint64_t value) const {
133   if (enums_.empty()) {
134     ALOGE("No enum values for property: %s", name_.c_str());
135     return {};
136   }
137 
138   for (const auto &it : enums_) {
139     if (it.value == value) {
140       return it.name;
141     }
142   }
143 
144   ALOGE("Property '%s' has no matching enum for value: %" PRIu64, name_.c_str(),
145         value);
146   return {};
147 }
148 
GetEnumMask(uint64_t & mask)149 auto DrmProperty::GetEnumMask(uint64_t &mask) -> bool {
150   if (enums_.empty()) {
151     ALOGE("No enum values for property: %s", name_.c_str());
152     return false;
153   }
154 
155   if (!IsBitmask()) {
156     ALOGE("Property %s is not a bitmask property.", name_.c_str());
157     return false;
158   }
159 
160   mask = 0;
161 
162   for (const auto &it : enums_) {
163     mask |= (1 << it.value);
164   }
165 
166   return true;
167 }
168 
169 }  // namespace android
170