• 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 #ifndef HIDUTIL_HIDPARSER_H_
17 #define HIDUTIL_HIDPARSER_H_
18 
19 #include "HidItem.h"
20 #include "HidTree.h"
21 #include "HidGlobal.h"
22 #include "HidLocal.h"
23 #include <unordered_map>
24 #include <unordered_set>
25 #include <vector>
26 #include <array>
27 #include <ostream>
28 
29 namespace HidUtil {
30 class HidParser {
31 public:
32     enum {
33         REPORT_TYPE_FEATURE = 0,
34         REPORT_TYPE_INPUT = 1,
35         REPORT_TYPE_OUTPUT = 2
36     };
37 
38     struct ReportItem;
39     struct ReportPacket;
40 
41     // report (including input output and feature) grouped by full usage
42     struct ReportDigest {
43         unsigned int fullUsage;
44         std::vector<ReportPacket> packets;
45     };
46 
47     typedef std::vector<ReportDigest> DigestVector;
48 
49     // parse HID descriptor
50     bool parse(const std::vector<HidItem> &token);
51     bool parse(const unsigned char *begin, size_t size);
52 
53     // filter the tree to eliminate single child report leaf node causes by usage array type
54     // reports
55     void filterTree();
56 
57     // generate a list of report digest for all interested usage. It will automatically
58     // call filterTree().
59     DigestVector generateDigest(const std::unordered_set<unsigned int> &interestedUsage);
60 
61     // get parsed tree (filtered or not filtered)
getTree()62     const std::shared_ptr<HidTreeNode> getTree() const { return mTree; }
63 
64     // get all parsed report in a parsed form.
getReport()65     const std::vector<HidReport>& getReport() const { return mReport; }
66 
67 private:
68     typedef std::array<std::vector<HidReport>, 3> ReportSet;
69     typedef std::unordered_map<unsigned int /* reportId */, ReportSet> ReportSetGroup;
70 
71     // helper subroutines
72     void reset();
73     bool processMainTag(const HidItem &i);
74     static void filterTree(std::shared_ptr<HidTreeNode> &node);
75     static void digest(
76             DigestVector *digestVector,
77             const std::shared_ptr<HidTreeNode> &node,
78             const std::unordered_set<unsigned int> &interestedUsage);
79     static std::vector<ReportPacket> convertGroupToPacket(const ReportSetGroup &group);
80 
81     HidGlobalStack mGlobalStack;
82     HidLocal mLocal;
83     std::shared_ptr<HidTreeNode> mTree;
84     std::shared_ptr<HidTreeNode> mCurrent;
85     std::vector<HidReport> mReport;
86 };
87 
88 struct HidParser::ReportItem {
89     unsigned int usage;
90     unsigned int id;
91     int type; // feature, input or output
92     std::vector<unsigned int> usageVector;
93 
94     int64_t minRaw;
95     int64_t maxRaw;
96 
97     // conversion for float point values
98     // real value = (signExtendIfNeeded(raw) + b) * a
99     // raw value = mask(real/a - b);
100     //
101     // conversion for integer values
102     // real value = signExtendedIfNeeded(raw) + b;
103     // raw value = mask(real - b);
104     double a; // scaling
105     int64_t b; // offset
106     unsigned int unit;
107 
108     size_t bitOffset;
109     size_t bitSize; // bit length per unit
110     size_t count;
111 
112     // helper function
isSignedReportItem113     bool isSigned() const {
114         return minRaw < 0;
115     }
116 
isByteAlignedReportItem117     bool isByteAligned() const {
118         return (bitOffset & 7) == 0 && (bitSize & 7) == 0;
119     }
120 
121     // convert raw values to unsigned format
maskReportItem122     uint32_t mask(int64_t input) const {
123         return static_cast<uint32_t>(input & rawMask());
124     }
125 
decodeReportItem126     bool decode(uint32_t input, double *output) const {
127         if (output == nullptr) {
128             return false;
129         }
130         int64_t s = signExtendIfNeeded(input);
131         if (s < minRaw || s > maxRaw) {
132             return false;
133         }
134         *output = (s + b) * a;
135         return true;
136     }
137 
encodeReportItem138     bool encode(double input, uint32_t *output) const {
139         if (output == nullptr) {
140             return false;
141         }
142         input = input / a - b;
143         if (input < minRaw || input > maxRaw) {
144             return false;
145         }
146         *output = static_cast<uint32_t>(static_cast<int64_t>(input) & rawMask());
147         return true;
148     }
149 
rawMaskReportItem150     int64_t rawMask() const {
151         constexpr int64_t one = 1;
152         return (one << bitSize) - 1;
153     }
154 
signExtendIfNeededReportItem155     int64_t signExtendIfNeeded(int64_t value) const {
156         return value | ((isSigned() && isNegative(value)) ? ~rawMask() : 0);
157     }
158 
isNegativeReportItem159     bool isNegative(int64_t value) const {
160         constexpr int64_t one = 1;
161         return ((one << (bitSize - 1)) & value) != 0;
162     }
163 };
164 
165 // a collection of report item that forms a packet
166 // this is the input output unit with HID hardware
167 struct HidParser::ReportPacket {
168     std::vector<ReportItem> reports;
169     size_t bitSize;
170     int type; // REPORT_TYPE_FEATURE/INPUT/OUTPUT
171     unsigned int id;
172 
getByteSizeReportPacket173     size_t getByteSize() const { return (bitSize + 7) / 8; };
174 };
175 
176 std::ostream& operator<<(std::ostream &os, const HidParser::DigestVector &digest2);
177 
178 } // namespace HidUtil
179 
180 #endif // HIDUTIL_HIDPARSER_H_
181