Home | History | Annotate | Download | only in HidUtils
      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)
     62     const std::shared_ptr<HidTreeNode> getTree() const { return mTree; }
     63 
     64     // get all parsed report in a parsed form.
     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 
     93     int64_t minRaw;
     94     int64_t maxRaw;
     95 
     96     // conversion for float point values
     97     // real value = (signExtendIfNeeded(raw) + b) * a
     98     // raw value = mask(real/a - b);
     99     //
    100     // conversion for integer values
    101     // real value = signExtendedIfNeeded(raw) + b;
    102     // raw value = mask(real - b);
    103     double a; // scaling
    104     int64_t b; // offset
    105     unsigned int unit;
    106 
    107     size_t bitOffset;
    108     size_t bitSize; // bit length per unit
    109     size_t count;
    110 
    111     // helper function
    112     bool isSigned() const {
    113         return minRaw < 0;
    114     }
    115 
    116     bool isByteAligned() const {
    117         return (bitOffset & 7) == 0 && (bitSize & 7) == 0;
    118     }
    119 
    120     // convert raw values to unsigned format
    121     uint32_t mask(int64_t input) const {
    122         return static_cast<uint32_t>(input & rawMask());
    123     }
    124 
    125     bool decode(uint32_t input, double *output) const {
    126         if (output == nullptr) {
    127             return false;
    128         }
    129         int64_t s = signExtendIfNeeded(input);
    130         if (s < minRaw || s > maxRaw) {
    131             return false;
    132         }
    133         *output = (s + b) * a;
    134         return true;
    135     }
    136 
    137     bool encode(double input, uint32_t *output) const {
    138         if (output == nullptr) {
    139             return false;
    140         }
    141         input = input / a - b;
    142         if (input < minRaw || input > maxRaw) {
    143             return false;
    144         }
    145         *output = static_cast<uint32_t>(static_cast<int64_t>(input) & rawMask());
    146         return true;
    147     }
    148 
    149     int64_t rawMask() const {
    150         constexpr int64_t one = 1;
    151         return (one << bitSize) - 1;
    152     }
    153 
    154     int64_t signExtendIfNeeded(int64_t value) const {
    155         return value | ((isSigned() && isNegative(value)) ? ~rawMask() : 0);
    156     }
    157 
    158     bool isNegative(int64_t value) const {
    159         constexpr int64_t one = 1;
    160         return ((one << (bitSize - 1)) & value) != 0;
    161     }
    162 };
    163 
    164 // a collection of report item that forms a packet
    165 // this is the input output unit with HID hardware
    166 struct HidParser::ReportPacket {
    167     std::vector<ReportItem> reports;
    168     size_t bitSize;
    169     int type; // REPORT_TYPE_FEATURE/INPUT/OUTPUT
    170     unsigned int id;
    171 
    172     size_t getByteSize() const { return (bitSize + 7) / 8; };
    173 };
    174 
    175 std::ostream& operator<<(std::ostream &os, const HidParser::DigestVector &digest2);
    176 } // namespace HidUtil
    177 
    178 #endif // HIDUTIL_HIDPARSER_H_
    179