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 #include "HidItem.h"
     17 #include "HidDefs.h"
     18 #include "StreamIoUtil.h"
     19 #include <iostream>
     20 
     21 namespace HidUtil {
     22 
     23 bool HidItem::dataAsUnsigned(unsigned int *out) const  {
     24     if (data.size() > 4 || data.size() == 0) {
     25         return false;
     26     }
     27 
     28     *out = 0;
     29     int shift = 0;
     30 
     31     for (auto i : data) {
     32         *out |= (i << shift);
     33         shift += 8;
     34     }
     35     return true;
     36 }
     37 
     38 bool HidItem::dataAsSigned(int *out) const {
     39     unsigned int u;
     40     if (!dataAsUnsigned(&u)) {
     41         return false;
     42     }
     43     size_t bitSize_1 = data.size() * 8 - 1;
     44     unsigned int sign = u & (1 << bitSize_1);
     45     *out = u | ((sign == 0) ? 0 : ( ~0 << bitSize_1));
     46     return true;
     47 }
     48 
     49 std::vector<HidItem> HidItem::tokenize(const uint8_t *begin, size_t size) {
     50     // construct a stream
     51     charvectorbuf<unsigned char> buf(begin, size);
     52     std::istream is(&buf);
     53     return tokenize(is);
     54 }
     55 
     56 std::vector<HidItem> HidItem::tokenize(const std::vector<uint8_t> &descriptor) {
     57     // construct a stream
     58     charvectorbuf<unsigned char> buf(descriptor);
     59     std::istream is(&buf);
     60     return tokenize(is);
     61 }
     62 
     63 std::vector<HidItem> HidItem::tokenize(std::istream &is) {
     64     std::vector<HidItem> hidToken;
     65 
     66     // this is important to avoid skipping characters
     67     is.unsetf(std::ios_base::skipws);
     68     while (!is.eof()) {
     69         HidItem i;
     70         is >> i;
     71         if (i.valid) {
     72             hidToken.push_back(i);
     73         } else {
     74             break;
     75         }
     76     }
     77     return hidToken;
     78 }
     79 
     80 std::istream& operator>>(std::istream &is, HidUtil::HidItem &h) {
     81     using namespace HidUtil::HidDef::MainTag;
     82     using namespace HidUtil::HidDef::TagType;
     83 
     84     h.valid = false;
     85     h.offset = is.tellg();
     86     h.byteSize = 0;
     87     unsigned char first;
     88     is >> first;
     89     if (!is.eof()) {
     90         static const size_t lenTable[] = { 0, 1, 2, 4 };
     91         size_t len = lenTable[first & 0x3]; // low 2 bits are length descriptor
     92         h.tag = (first >> 4);
     93         h.type = (first & 0xC) >> 2;
     94 
     95         if (h.tag == LONG_ITEM && h.type == RESERVED) { // long item
     96             //long item
     97             unsigned char b = 0;
     98             is >> b;
     99             len = b;
    100             is >> b;
    101             h.tag = b;
    102         }
    103 
    104         h.data.resize(len);
    105         for (auto &i : h.data) {
    106             if (is.eof()) {
    107                 break;
    108             }
    109             is >> i;
    110         }
    111         h.byteSize = (ssize_t) is.tellg() - h.offset;
    112         h.valid = !is.eof();
    113     }
    114 
    115     return is;
    116 }
    117 
    118 std::ostream& operator<<(std::ostream &os, const HidUtil::HidItem &h) {
    119     os << "offset: " << h.offset << ", size: " << h.byteSize
    120        << ", tag: " << h.tag << ", type: " << h.type << ", data: ";
    121     if (h.data.empty()) {
    122         os << "[empty]";
    123     } else {
    124         os << h.data.size() << " byte(s) {";
    125         for (auto i : h.data) {
    126             os << (int) i << ", ";
    127         }
    128         os << "}";
    129     }
    130     return os;
    131 }
    132 } // namespace HidUtil
    133