• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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 #include "HidReport.h"
17 #include "HidDefs.h"
18 #include <cmath>
19 #include <sstream>
20 #include <iomanip>
21 
22 namespace HidUtil {
HidReport(uint32_t type,uint32_t data,const HidGlobal & global,const HidLocal & local)23 HidReport::HidReport(uint32_t type, uint32_t data,
24                      const HidGlobal &global, const HidLocal &local)
25         : mIsCollapsed(false),
26           mReportType(type),
27           mFlag(data),
28           mUsagePage(global.usagePage.get(0)),   // default value 0
29           mUsage(local.getUsage(0)),
30           mUsageVector(local.usage),
31           mLogicalMin(global.logicalMin.get(0)), // default value 0
32           mLogicalMax(global.logicalMax.get(0)),
33           mReportSize(global.reportSize),
34           mReportCount(global.reportCount),
35           mPhysicalMin(global.physicalMin),
36           mPhysicalMax(global.physicalMax),
37           mExponent(global.exponent),
38           mUnit(global.unit),
39           mReportId(global.reportId) { }
40 
getStringType() const41 std::string HidReport::getStringType() const {
42     return reportTypeToString(mReportType);
43 }
44 
reportTypeToString(int type)45 std::string HidReport::reportTypeToString(int type) {
46     using namespace HidDef::MainTag;
47     switch(type) {
48         case INPUT:
49             return "INPUT";
50         case OUTPUT:
51             return "OUTPUT";
52         case FEATURE:
53             return "FEATURE";
54         default:
55             return "<<UNKNOWN>>";
56     }
57 }
58 
getExponentValue() const59 double HidReport::getExponentValue() const {
60     if (!mExponent.isSet()) {
61         return 1;
62     }
63     // default exponent is 0
64     int exponentInt = mExponent.get(0);
65     if (exponentInt > 15 || exponentInt < 0) {
66         return NAN;
67     }
68     return pow(10.0, static_cast<double>((exponentInt <= 7) ? exponentInt : exponentInt - 16));
69 }
70 
getExponentString() const71 std::string HidReport::getExponentString() const {
72     int exponentInt = mExponent.get(0);
73     if (exponentInt > 15 || exponentInt < 0) {
74         return "[error]";
75     }
76     return std::string("x10^")
77             + std::to_string((exponentInt <= 7) ? exponentInt : exponentInt - 16);
78 }
79 
getUnitString() const80 std::string HidReport::getUnitString() const {
81     if (!mUnit.isSet()) {
82         return "default";
83     }
84     return "[not implemented]";
85 
86     std::ostringstream ret;
87     ret << std::hex << std::setfill('0') << std::setw(2) << mUnit.get(0);
88     return ret.str();
89 }
90 
getFlagString() const91 std::string HidReport::getFlagString() const {
92     using namespace HidDef::ReportFlag;
93     std::string ret;
94     ret += (mFlag & DATA_CONST) ? "Const " : "Data ";
95     ret += (mFlag & ARRAY_VARIABLE) ? "Variable " : "Array ";
96     ret += (mFlag & WRAP) ? "Wrap " : "";
97     ret += (mFlag & NONLINEAR) ? "Nonlinear " : "";
98     ret += (mFlag & NO_PREFERRED) ? "NoPreferred " : "";
99     ret += (mFlag & NULL_STATE) ? "NullState " : "";
100     ret += (mFlag & VOLATILE) ? "Volatile " : "";
101     ret += (mFlag & BUFFERED_BYTES) ? "BufferedBytes " : "";
102     return ret;
103 }
104 
105 // isArray() will return true for reports that may contains multiple values, e.g. keyboard scan
106 // code, which can have multiple value, each denoting a key pressed down at the same time. It will
107 // return false if repor represent a vector or matrix.
108 //
109 // This slightly deviates from HID's definition, it is more convenient this way as matrix/vector
110 // input is treated similarly as variables.
isArray() const111 bool HidReport::isArray() const {
112     using namespace HidDef::ReportFlag;
113     return (mFlag & ARRAY_VARIABLE) == 0 && mIsCollapsed;
114 }
115 
isVariable() const116 bool HidReport::isVariable() const {
117     return !isArray();
118 }
119 
isData() const120 bool HidReport::isData() const {
121     using namespace HidDef::ReportFlag;
122     return (mFlag & DATA_CONST) == 0;
123 }
124 
operator <<(std::ostream & os,const HidReport & h)125 std::ostream& operator<<(std::ostream& os, const HidReport& h) {
126     os << h.getStringType() << ", "
127        << "usage: " << std::hex << h.getFullUsage() << std::dec << ", ";
128 
129     if (h.isData()) {
130         auto range = h.getLogicalRange();
131         os << "logMin: " << range.first << ", "
132            << "logMax: " << range.second << ", ";
133 
134         if (range == h.getPhysicalRange()) {
135             os << "phy===log, ";
136         } else {
137             range = h.getPhysicalRange();
138             os << "phyMin: " << range.first << ", "
139                << "phyMax: " << range.second << ", ";
140         }
141 
142         if (h.isArray()) {
143             os << "map: (" << std::hex;
144             for (auto i : h.getUsageVector()) {
145                 os << i << ",";
146             }
147             os << "), " << std::dec;
148         }
149 
150         os << "exponent: " << h.getExponentString() << ", "
151            << "unit: " << h.getUnitString() << ", ";
152     } else {
153         os << "constant: ";
154     }
155     os << "size: " << h.getSize() << "bit x " << h.getCount() << ", "
156        << "id: " << h.mReportId;
157 
158     return os;
159 }
160 
getLogicalRange() const161 std::pair<int64_t, int64_t> HidReport::getLogicalRange() const {
162     int64_t a = mLogicalMin;
163     int64_t b = mLogicalMax;
164 
165     if (a > b) {
166         // might be unsigned
167         a = a & ((static_cast<int64_t>(1) << getSize()) - 1);
168         b = b & ((static_cast<int64_t>(1) << getSize()) - 1);
169         if (a > b) {
170             // bad hid descriptor
171             return {0, 0};
172         }
173     }
174     return {a, b};
175 }
176 
getPhysicalRange() const177 std::pair<int64_t, int64_t> HidReport::getPhysicalRange() const {
178     if (!(mPhysicalMin.isSet() && mPhysicalMax.isSet())) {
179         // physical range undefined, use logical range
180         return getLogicalRange();
181     }
182 
183     int64_t a = mPhysicalMin.get(0);
184     int64_t b = mPhysicalMax.get(0);
185 
186     if (a > b) {
187         a = a & ((static_cast<int64_t>(1) << getSize()) - 1);
188         b = b & ((static_cast<int64_t>(1) << getSize()) - 1);
189         if (a > b) {
190             return {0, 0};
191         }
192     }
193     return {a, b};
194 }
195 
getFullUsage() const196 unsigned int HidReport::getFullUsage() const {
197     return mUsage | (mUsagePage << 16);
198 }
199 
getSize() const200 size_t HidReport::getSize() const {
201     return mReportSize;
202 }
203 
getCount() const204 size_t HidReport::getCount() const {
205     return mReportCount;
206 }
207 
getUnit() const208 unsigned int HidReport::getUnit() const {
209     return mUnit.get(0); // default unit is 0 means default unit
210 }
211 
getReportId() const212 unsigned HidReport::getReportId() const {
213     // if report id is not specified, it defaults to zero
214     return mReportId.get(0);
215 }
216 
getType() const217 unsigned HidReport::getType() const {
218     return mReportType;
219 }
220 
setCollapsed(uint32_t fullUsage)221 void HidReport::setCollapsed(uint32_t fullUsage) {
222     mUsage = fullUsage & 0xFFFF;
223     mUsagePage = fullUsage >> 16;
224     mIsCollapsed = true;
225 }
226 
getUsageVector() const227 const std::vector<unsigned int>& HidReport::getUsageVector() const {
228     return mUsageVector;
229 }
230 } // namespace HidUtil
231