15c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Copyright 2014 The Chromium Authors. All rights reserved. 25c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Use of this source code is governed by a BSD-style license that can be 35c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// found in the LICENSE file. 45c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 55c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "device/hid/hid_report_descriptor_item.h" 65c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 75c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include <stdlib.h> 85c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 95c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/logging.h" 105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "device/hid/hid_usage_and_page.h" 115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liunamespace device { 135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liunamespace { 155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liustruct Header { 175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu uint8_t size : 2; 185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu uint8_t type : 2; 195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu uint8_t tag : 4; 205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}; 215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} // namespace 235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuHidReportDescriptorItem::HidReportDescriptorItem( 255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const uint8_t* bytes, 265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu HidReportDescriptorItem* previous) 275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu : previous_(previous), next_(NULL), parent_(NULL), shortData_(0) { 285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu Header* header = (Header*)&bytes[0]; 295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu tag_ = (Tag)(header->tag << 2 | header->type); 305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (IsLong()) { 325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // In a long item, payload size is the second byte. 335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu payload_size_ = bytes[1]; 345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } else { 355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu payload_size_ = header->size; 365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu DCHECK(payload_size_ <= sizeof(shortData_)); 375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu memcpy(&shortData_, &bytes[GetHeaderSize()], payload_size()); 385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (previous) { 415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu DCHECK(!previous->next_); 425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu previous->next_ = this; 435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu switch (previous->tag()) { 445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu case kTagCollection: 455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu parent_ = previous; 465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu break; 475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu default: 485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu break; 495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (!parent_) { 515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu switch (tag()) { 525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu case kTagEndCollection: 535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (previous->parent()) { 545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu parent_ = previous->parent()->parent(); 555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu break; 575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu default: 585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu parent_ = previous->parent(); 595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu break; 605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liusize_t HidReportDescriptorItem::GetDepth() const { 665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu HidReportDescriptorItem* parent_item = parent(); 675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (parent_item) 685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return parent_item->GetDepth() + 1; 695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return 0; 705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool HidReportDescriptorItem::IsLong() const { return tag() == kTagLong; } 735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liusize_t HidReportDescriptorItem::GetHeaderSize() const { 755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return IsLong() ? 3 : 1; 765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liusize_t HidReportDescriptorItem::GetSize() const { 795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return GetHeaderSize() + payload_size(); 805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuuint32_t HidReportDescriptorItem::GetShortData() const { 835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu DCHECK(!IsLong()); 845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return shortData_; 855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuHidReportDescriptorItem::CollectionType 885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuHidReportDescriptorItem::GetCollectionTypeFromValue(uint32_t value) { 895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu switch (value) { 905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu case 0x00: 915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return kCollectionTypePhysical; 925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu case 0x01: 93116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return kCollectionTypeApplication; 945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu case 0x02: 95116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return kCollectionTypeLogical; 965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu case 0x03: 97116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return kCollectionTypeReport; 985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu case 0x04: 99116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return kCollectionTypeNamedArray; 1005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu case 0x05: 101116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return kCollectionTypeUsageSwitch; 1025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu case 0x06: 103116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return kCollectionTypeUsageModifier; 1045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu default: 1055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu break; 1065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 1075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (0x80 < value && value < 0xFF) 1085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return kCollectionTypeVendor; 1095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return kCollectionTypeReserved; 1105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 1115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 1125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} // namespace device 113