• 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 #pragma once
18 
19 #include <xf86drmMode.h>
20 
21 #include <cinttypes>
22 #include <cstdint>
23 #include <map>
24 #include <optional>
25 #include <string>
26 #include <vector>
27 
28 #include "drm/DrmUnique.h"
29 #include "utils/fd.h"
30 #include "utils/log.h"
31 
32 namespace android {
33 
34 class DrmProperty {
35  public:
36   DrmProperty() = default;
37   DrmProperty(const SharedFd &fd, uint32_t obj_id, drmModePropertyPtr p,
38               uint64_t value);
39   DrmProperty(const DrmProperty &) = delete;
40   DrmProperty &operator=(const DrmProperty &) = delete;
41 
42   auto Init(const SharedFd &fd, uint32_t obj_id, drmModePropertyPtr p,
43             uint64_t value) -> void;
44   std::tuple<uint64_t, int> GetEnumValueWithName(const std::string &name) const;
45 
GetId()46   auto GetId() const {
47     return id_;
48   }
49 
GetName()50   auto GetName() const {
51     return name_;
52   }
53 
54   auto GetValue() const -> std::optional<uint64_t>;
55 
IsImmutable()56   bool IsImmutable() const {
57     return id_ != 0 && (flags_ & DRM_MODE_PROP_IMMUTABLE) != 0;
58   }
59 
IsRange()60   bool IsRange() const {
61     return id_ != 0 && (flags_ & DRM_MODE_PROP_RANGE) != 0;
62   }
63 
IsBitmask()64   bool IsBitmask() const {
65     return id_ != 0 && (flags_ & DRM_MODE_PROP_BITMASK) != 0;
66   }
67 
68   auto RangeMin() const -> std::tuple<int, uint64_t>;
69   auto RangeMax() const -> std::tuple<int, uint64_t>;
70 
71   [[nodiscard]] auto AtomicSet(drmModeAtomicReq &pset, uint64_t value) const
72       -> bool;
73 
74   template <class E>
75   auto AddEnumToMap(const std::string &name, E key, std::map<E, uint64_t> &map)
76       -> bool;
77 
78   template <class E>
79   auto AddEnumToMapReverse(const std::string &name, E value,
80                            std::map<uint64_t, E> &map) -> bool;
81 
82   auto GetEnumMask(uint64_t &mask) -> bool;
83 
84   explicit operator bool() const {
85     return id_ != 0;
86   }
87 
88   auto GetEnumNameFromValue(uint64_t value) const -> std::optional<std::string>;
89 
IsBlob()90   bool IsBlob() const {
91     return id_ != 0 && (flags_ & DRM_MODE_PROP_BLOB) != 0;
92   }
93   template <typename T>
94   bool GetBlobData(std::vector<T> &data_out) const;
95 
96  private:
97   class DrmPropertyEnum {
98    public:
99     explicit DrmPropertyEnum(drm_mode_property_enum *e);
100     ~DrmPropertyEnum() = default;
101 
102     uint64_t value;
103     std::string name;
104   };
105 
106   SharedFd fd_ = nullptr;
107   uint32_t obj_id_ = 0;
108   uint32_t id_ = 0;
109 
110   uint32_t flags_ = 0;
111   std::string name_;
112   uint64_t value_ = 0;
113 
114   std::vector<uint64_t> values_;
115   std::vector<DrmPropertyEnum> enums_;
116   std::vector<uint32_t> blob_ids_;
117 };
118 
119 template <class E>
120 auto DrmProperty::AddEnumToMap(const std::string &name, E key,
121                                std::map<E, uint64_t> &map) -> bool {
122   uint64_t enum_value = UINT64_MAX;
123   int err = 0;
124   std::tie(enum_value, err) = GetEnumValueWithName(name);
125   if (err == 0) {
126     map[key] = enum_value;
127     return true;
128   }
129 
130   return false;
131 }
132 
133 template <class E>
134 auto DrmProperty::AddEnumToMapReverse(const std::string &name, E value,
135                                       std::map<uint64_t, E> &map) -> bool {
136   uint64_t enum_value = UINT64_MAX;
137   int err = 0;
138   std::tie(enum_value, err) = GetEnumValueWithName(name);
139   if (err == 0) {
140     map[enum_value] = value;
141     return true;
142   }
143 
144   return false;
145 }
146 
147 template <typename T>
GetBlobData(std::vector<T> & data_out)148 bool DrmProperty::GetBlobData(std::vector<T> &data_out) const {
149   auto value = GetValue();
150   if (!fd_) {
151     ALOGE("Could not read blob data from property %s: No fd", name_.c_str());
152     return false;
153   }
154   if (!IsBlob()) {
155     ALOGE("Property %s is not blob type", name_.c_str());
156     return false;
157   }
158   if (!value.has_value()) {
159     ALOGE("Could not read blob data from property %s: No blob id",
160           name_.c_str());
161     return false;
162   }
163 
164   auto blob = MakeDrmModePropertyBlobUnique(*fd_, value.value());
165   if (blob == nullptr) {
166     ALOGE("Failed to read blob with id=%" PRIu64 " from property %s",
167           value.value(), name_.c_str());
168     return false;
169   }
170 
171   if (blob->length % sizeof(T) != 0) {
172     ALOGE(
173         "Property %s blob size of %u bytes is not divisible by type argument "
174         "size of %zu bytes",
175         name_.c_str(), blob->length, sizeof(T));
176     return false;
177   }
178 
179   auto cast_data = static_cast<T *>(blob->data);
180   size_t cast_data_length = blob->length / sizeof(T);
181   data_out.assign(cast_data, cast_data + cast_data_length);
182 
183   return true;
184 }
185 
186 }  // namespace android
187