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