1# Copyright 2014 The Chromium Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5 6"""Utility functions for constructing HID report descriptors. 7""" 8 9import struct 10 11import hid_constants 12 13 14def ReportDescriptor(*items): 15 return ''.join(items) 16 17 18def _PackItem(tag, typ, value=0, force_length=0): 19 """Pack a multibyte value. 20 21 See Device Class Definition for Human Interface Devices (HID) Version 1.11 22 section 5.8. 23 24 Args: 25 tag: Item tag. 26 typ: Item type. 27 value: Item value. 28 force_length: Force packing to a specific width. 29 30 Returns: 31 Packed string. 32 """ 33 if value == 0 and force_length <= 0: 34 return struct.pack('<B', tag << 4 | typ << 2 | 0) 35 elif value <= 0xff and force_length <= 1: 36 return struct.pack('<BB', tag << 4 | typ << 2 | 1, value) 37 elif value <= 0xffff and force_length <= 2: 38 return struct.pack('<BH', tag << 4 | typ << 2 | 2, value) 39 elif value <= 0xffffffff and force_length <= 4: 40 return struct.pack('<BI', tag << 4 | typ << 2 | 3, value) 41 else: 42 raise NotImplementedError('Long items are not implemented.') 43 44 45def _DefineItem(name, tag, typ): 46 """Create a function which encodes a HID item. 47 48 Args: 49 name: Function name. 50 tag: Item tag. 51 typ: Item type. 52 53 Returns: 54 A function which encodes a HID item of the given type. 55 """ 56 assert tag >= 0 and tag <= 0xF 57 assert typ >= 0 and typ <= 3 58 59 def EncodeItem(value=0, force_length=0): 60 return _PackItem(tag, typ, value, force_length) 61 62 EncodeItem.__name__ = name 63 return EncodeItem 64 65 66def _DefineMainItem(name, tag): 67 """Create a function which encodes a HID Main item. 68 69 See Device Class Definition for Human Interface Devices (HID) Version 1.11 70 section 6.2.2.4. 71 72 Args: 73 name: Function name. 74 tag: Item tag. 75 76 Returns: 77 A function which encodes a HID item of the given type. 78 79 Raises: 80 ValueError: If the tag value is out of range. 81 """ 82 assert tag >= 0 and tag <= 0xF 83 84 def EncodeMainItem(*properties): 85 value = 0 86 for bit, is_set in properties: 87 if is_set: 88 value |= 1 << bit 89 return _PackItem(tag, hid_constants.Scope.MAIN, value, force_length=1) 90 91 EncodeMainItem.__name__ = name 92 return EncodeMainItem 93 94Input = _DefineMainItem('Input', 8) 95Output = _DefineMainItem('Output', 9) 96Feature = _DefineMainItem('Feature', 11) 97 98# Input, Output and Feature Item Properties 99# 100# See Device Class Definition for Human Interface Devices (HID) Version 1.11 101# section 6.2.2.5. 102Data = (0, False) 103Constant = (0, True) 104Array = (1, False) 105Variable = (1, True) 106Absolute = (2, False) 107Relative = (2, True) 108NoWrap = (3, False) 109Wrap = (3, True) 110Linear = (4, False) 111NonLinear = (4, True) 112PreferredState = (5, False) 113NoPreferred = (5, True) 114NoNullPosition = (6, False) 115NullState = (6, True) 116NonVolatile = (7, False) 117Volatile = (7, True) 118BitField = (8, False) 119BufferedBytes = (8, True) 120 121 122def Collection(typ, *items): 123 start = struct.pack('<BB', 0xA1, typ) 124 end = struct.pack('<B', 0xC0) 125 return start + ''.join(items) + end 126 127# Global Items 128# 129# See Device Class Definition for Human Interface Devices (HID) Version 1.11 130# section 6.2.2.7. 131UsagePage = _DefineItem('UsagePage', 0, hid_constants.Scope.GLOBAL) 132LogicalMinimum = _DefineItem('LogicalMinimum', 1, hid_constants.Scope.GLOBAL) 133LogicalMaximum = _DefineItem('LogicalMaximum', 2, hid_constants.Scope.GLOBAL) 134PhysicalMinimum = _DefineItem('PhysicalMinimum', 3, hid_constants.Scope.GLOBAL) 135PhysicalMaximum = _DefineItem('PhysicalMaximum', 4, hid_constants.Scope.GLOBAL) 136UnitExponent = _DefineItem('UnitExponent', 5, hid_constants.Scope.GLOBAL) 137Unit = _DefineItem('Unit', 6, hid_constants.Scope.GLOBAL) 138ReportSize = _DefineItem('ReportSize', 7, hid_constants.Scope.GLOBAL) 139ReportID = _DefineItem('ReportID', 8, hid_constants.Scope.GLOBAL) 140ReportCount = _DefineItem('ReportCount', 9, hid_constants.Scope.GLOBAL) 141Push = _DefineItem('Push', 10, hid_constants.Scope.GLOBAL) 142Pop = _DefineItem('Pop', 11, hid_constants.Scope.GLOBAL) 143 144# Local Items 145# 146# See Device Class Definition for Human Interface Devices (HID) Version 1.11 147# section 6.2.2.8. 148Usage = _DefineItem('Usage', 0, hid_constants.Scope.LOCAL) 149UsageMinimum = _DefineItem('UsageMinimum', 1, hid_constants.Scope.LOCAL) 150UsageMaximum = _DefineItem('UsageMaximum', 2, hid_constants.Scope.LOCAL) 151DesignatorIndex = _DefineItem('DesignatorIndex', 3, hid_constants.Scope.LOCAL) 152DesignatorMinimum = _DefineItem('DesignatorMinimum', 4, 153 hid_constants.Scope.LOCAL) 154DesignatorMaximum = _DefineItem('DesignatorMaximum', 5, 155 hid_constants.Scope.LOCAL) 156StringIndex = _DefineItem('StringIndex', 7, hid_constants.Scope.LOCAL) 157StringMinimum = _DefineItem('StringMinimum', 8, hid_constants.Scope.LOCAL) 158StringMaximum = _DefineItem('StringMaximum', 9, hid_constants.Scope.LOCAL) 159Delimiter = _DefineItem('Delimiter', 10, hid_constants.Scope.LOCAL) 160