/* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "HidItem.h" #include "HidDefs.h" #include "StreamIoUtil.h" #include <iostream> namespace HidUtil { bool HidItem::dataAsUnsigned(unsigned int *out) const { if (data.size() > 4 || data.size() == 0) { return false; } *out = 0; int shift = 0; for (auto i : data) { *out |= (i << shift); shift += 8; } return true; } bool HidItem::dataAsSigned(int *out) const { unsigned int u; if (!dataAsUnsigned(&u)) { return false; } size_t bitSize_1 = data.size() * 8 - 1; unsigned int sign = u & (1 << bitSize_1); *out = u | ((sign == 0) ? 0 : ( ~0 << bitSize_1)); return true; } std::vector<HidItem> HidItem::tokenize(const uint8_t *begin, size_t size) { // construct a stream charvectorbuf<unsigned char> buf(begin, size); std::istream is(&buf); return tokenize(is); } std::vector<HidItem> HidItem::tokenize(const std::vector<uint8_t> &descriptor) { // construct a stream charvectorbuf<unsigned char> buf(descriptor); std::istream is(&buf); return tokenize(is); } std::vector<HidItem> HidItem::tokenize(std::istream &is) { std::vector<HidItem> hidToken; // this is important to avoid skipping characters is.unsetf(std::ios_base::skipws); while (!is.eof()) { HidItem i; is >> i; if (i.valid) { hidToken.push_back(i); } else { break; } } return hidToken; } std::istream& operator>>(std::istream &is, HidUtil::HidItem &h) { using namespace HidUtil::HidDef::MainTag; using namespace HidUtil::HidDef::TagType; h.valid = false; h.offset = is.tellg(); h.byteSize = 0; unsigned char first; is >> first; if (!is.eof()) { static const size_t lenTable[] = { 0, 1, 2, 4 }; size_t len = lenTable[first & 0x3]; // low 2 bits are length descriptor h.tag = (first >> 4); h.type = (first & 0xC) >> 2; if (h.tag == LONG_ITEM && h.type == RESERVED) { // long item //long item unsigned char b = 0; is >> b; len = b; is >> b; h.tag = b; } h.data.resize(len); for (auto &i : h.data) { if (is.eof()) { break; } is >> i; } h.byteSize = (ssize_t) is.tellg() - h.offset; h.valid = !is.eof(); } return is; } std::ostream& operator<<(std::ostream &os, const HidUtil::HidItem &h) { os << "offset: " << h.offset << ", size: " << h.byteSize << ", tag: " << h.tag << ", type: " << h.type << ", data: "; if (h.data.empty()) { os << "[empty]"; } else { os << h.data.size() << " byte(s) {"; for (auto i : h.data) { os << (int) i << ", "; } os << "}"; } return os; } } // namespace HidUtil