• 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 #include "drmproperty.h"
18 #include "drmdevice.h"
19 
20 #include <errno.h>
21 #include <stdint.h>
22 #include <string>
23 
24 #include <xf86drmMode.h>
25 #include <log/log.h>
26 #include <inttypes.h>
27 #include <utils/Errors.h>
28 
U642I64(uint64_t val)29 static inline int64_t U642I64(uint64_t val) {
30   return *(reinterpret_cast<int64_t *>(&val));
31 }
32 
33 namespace android {
34 
DrmPropertyEnum(drm_mode_property_enum * e)35 DrmProperty::DrmPropertyEnum::DrmPropertyEnum(drm_mode_property_enum *e)
36     : value_(e->value), name_(e->name) {
37 }
38 
~DrmPropertyEnum()39 DrmProperty::DrmPropertyEnum::~DrmPropertyEnum() {
40 }
41 
DrmProperty(drmModePropertyPtr p,uint64_t value)42 DrmProperty::DrmProperty(drmModePropertyPtr p, uint64_t value)
43     : id_(0), type_(DRM_PROPERTY_TYPE_INVALID), flags_(0), name_("") {
44   init(p, value);
45 }
46 
init(drmModePropertyPtr p,uint64_t value)47 void DrmProperty::init(drmModePropertyPtr p, uint64_t value) {
48   id_ = p->prop_id;
49   flags_ = p->flags;
50   name_ = p->name;
51   value_ = value;
52 
53   for (int i = 0; i < p->count_values; ++i) values_.push_back(p->values[i]);
54 
55   for (int i = 0; i < p->count_enums; ++i) enums_.push_back(DrmPropertyEnum(&p->enums[i]));
56 
57   for (int i = 0; i < p->count_blobs; ++i) blob_ids_.push_back(p->blob_ids[i]);
58 
59   if ((flags_ & DRM_MODE_PROP_RANGE) || (flags_ & DRM_MODE_PROP_SIGNED_RANGE))
60     type_ = DRM_PROPERTY_TYPE_INT;
61   else if (flags_ & DRM_MODE_PROP_ENUM)
62     type_ = DRM_PROPERTY_TYPE_ENUM;
63   else if (flags_ & DRM_MODE_PROP_OBJECT)
64     type_ = DRM_PROPERTY_TYPE_OBJECT;
65   else if (flags_ & DRM_MODE_PROP_BLOB)
66     type_ = DRM_PROPERTY_TYPE_BLOB;
67   else if (flags_ & DRM_MODE_PROP_BITMASK)
68     type_ = DRM_PROPERTY_TYPE_BITMASK;
69 }
70 
id() const71 uint32_t DrmProperty::id() const {
72   return id_;
73 }
74 
name() const75 std::string DrmProperty::name() const {
76   return name_;
77 }
78 
value() const79 std::tuple<int, uint64_t> DrmProperty::value() const {
80   if (type_ == DRM_PROPERTY_TYPE_BLOB)
81     return std::make_tuple(0, value_);
82 
83   if (values_.size() == 0)
84     return std::make_tuple(-ENOENT, 0);
85 
86   switch (type_) {
87     case DRM_PROPERTY_TYPE_INT:
88       return std::make_tuple(0, value_);
89 
90     case DRM_PROPERTY_TYPE_BITMASK:
91       return std::make_tuple(0, value_);
92 
93     case DRM_PROPERTY_TYPE_ENUM:
94       if (value_ >= enums_.size())
95         return std::make_tuple(-ENOENT, 0);
96 
97       return std::make_tuple(0, enums_[value_].value_);
98 
99     case DRM_PROPERTY_TYPE_OBJECT:
100       return std::make_tuple(0, value_);
101 
102     default:
103       return std::make_tuple(-EINVAL, 0);
104   }
105 }
106 
printProperty() const107 void DrmProperty::printProperty() const
108 {
109   ALOGD("=====================================================");
110   ALOGD("name: %s, type(%d), value_(%" PRId64 ")", name_.c_str(), type_, value_);
111   ALOGD("values.size(%zu)", values_.size());
112   for (uint32_t i = 0; i < values_.size(); i++) {
113     ALOGD("[%d] %" PRId64 "", i, values_[i]);
114   }
115   ALOGD("enums.size(%zu)", enums_.size());
116   uint32_t i = 0;
117   for (auto const &it : enums_) {
118     ALOGD("[%d] %s %" PRId64 "", i++, it.name_.c_str(), it.value_);
119   }
120 }
121 
isImmutable() const122 bool DrmProperty::isImmutable() const {
123   return id_ && (flags_ & DRM_MODE_PROP_IMMUTABLE);
124 }
125 
isRange() const126 bool DrmProperty::isRange() const {
127   return id_ && (flags_ & DRM_MODE_PROP_RANGE);
128 }
129 
isSignedRange() const130 bool DrmProperty::isSignedRange() const {
131   return (flags_ & DRM_MODE_PROP_EXTENDED_TYPE) == DRM_MODE_PROP_SIGNED_RANGE;
132 }
133 
isBitmask() const134 bool DrmProperty::isBitmask() const {
135   return id_ && (flags_ & DRM_MODE_PROP_BITMASK);
136 }
137 
rangeMin() const138 std::tuple<int, uint64_t> DrmProperty::rangeMin() const {
139   if (!isRange())
140     return std::make_tuple(-EINVAL, 0);
141   if (values_.size() < 1)
142     return std::make_tuple(-ENOENT, 0);
143 
144   return std::make_tuple(0, values_[0]);
145 }
146 
rangeMax() const147 std::tuple<int, uint64_t> DrmProperty::rangeMax() const {
148   if (!isRange())
149     return std::make_tuple(-EINVAL, 0);
150   if (values_.size() < 2)
151     return std::make_tuple(-ENOENT, 0);
152 
153   return std::make_tuple(0, values_[1]);
154 }
155 
getEnumValueWithName(std::string name) const156 std::tuple<uint64_t, int> DrmProperty::getEnumValueWithName(std::string name) const {
157   for (auto it : enums_) {
158     if (it.name_.compare(name) == 0) {
159       return std::make_tuple(it.value_, 0);
160     }
161   }
162 
163   return std::make_tuple(UINT64_MAX, -EINVAL);
164 }
165 
validateChange(uint64_t value) const166 bool DrmProperty::validateChange(uint64_t value) const {
167   if (isImmutable()) {
168     ALOGE("%s: %s is immutable drm property (%zu)", __func__, name().c_str());
169     return false;
170   } else if (isRange()) {
171     if (value < values_[0] || value > values_[1]) {
172       ALOGE("%s: range property %s set to %" PRIu64 " is invalid [%" PRIu64 "-%" PRIu64 "]",
173             __func__, name().c_str(), value, values_[0], values_[1]);
174       return false;
175     }
176   } else if (isSignedRange()) {
177     int64_t svalue = U642I64(value);
178 
179     if (svalue < U642I64(values_[0]) || svalue > U642I64(values_[1])) {
180       ALOGE("%s: signed property %s set to %" PRIi64 " is invalid [%" PRIi64 "-%" PRIi64 "]",
181             __func__, name().c_str(), svalue, U642I64(values_[0]), U642I64(values_[1]));
182       return false;
183     }
184   } else if (isBitmask()) {
185     uint64_t valid_mask = 0;
186 
187     for (auto i = 0; i < values_.size(); i++) {
188       valid_mask |= (1ULL << values_[i]);
189     }
190     if (value & ~valid_mask) {
191       ALOGE("%s: bitmask property %s set to 0x%" PRIx64 " is invalid [0x%" PRIx64 "]", __func__,
192             name().c_str(), value, valid_mask);
193       return false;
194     }
195   }
196 
197   return true;
198 }
199 
updateValue(uint64_t value)200 void DrmProperty::updateValue(uint64_t value) {
201   value_ = value;
202 }
203 
halToDrmEnum(const uint32_t halData,const MapHal2DrmEnum & drmEnums)204 std::tuple<uint64_t, int> DrmEnumParser::halToDrmEnum(const uint32_t halData,
205                                                       const MapHal2DrmEnum& drmEnums) {
206   auto it = drmEnums.find(halData);
207   if (it != drmEnums.end()) {
208     return std::make_tuple(it->second, NO_ERROR);
209   } else {
210     ALOGE("%s: Failed to find standard enum(%d)", __func__, halData);
211     return std::make_tuple(0, -EINVAL);
212   }
213 }
214 
parseEnums(const DrmProperty & property,const std::vector<std::pair<uint32_t,const char * >> & enums,MapHal2DrmEnum & out_enums)215 void DrmEnumParser::parseEnums(const DrmProperty &property,
216                                const std::vector<std::pair<uint32_t, const char *>> &enums,
217                                MapHal2DrmEnum& out_enums) {
218   uint64_t value;
219   int err;
220   for (auto &e : enums) {
221     std::tie(value, err) = property.getEnumValueWithName(e.second);
222     if (err) {
223       ALOGE("%s: Fail to find enum value with name %s", __func__, e.second);
224     } else {
225       out_enums[e.first] = value;
226     }
227   }
228 }
229 
230 }  // namespace android
231