15f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# Copyright 2014 The Chromium Authors. All rights reserved. 25f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be 35f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# found in the LICENSE file. 45f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 55f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 65f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)"""Utility functions for constructing HID report descriptors. 75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)""" 85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)import struct 105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)import hid_constants 125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)def ReportDescriptor(*items): 155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ''.join(items) 165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)def _PackItem(tag, typ, value=0, force_length=0): 195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Pack a multibyte value. 205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) See Device Class Definition for Human Interface Devices (HID) Version 1.11 225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) section 5.8. 235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Args: 255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) tag: Item tag. 265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) typ: Item type. 275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) value: Item value. 285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) force_length: Force packing to a specific width. 295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Returns: 315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Packed string. 325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if value == 0 and force_length <= 0: 345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return struct.pack('<B', tag << 4 | typ << 2 | 0) 355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif value <= 0xff and force_length <= 1: 365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return struct.pack('<BB', tag << 4 | typ << 2 | 1, value) 375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif value <= 0xffff and force_length <= 2: 385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return struct.pack('<BH', tag << 4 | typ << 2 | 2, value) 395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif value <= 0xffffffff and force_length <= 4: 405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return struct.pack('<BI', tag << 4 | typ << 2 | 3, value) 415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) raise NotImplementedError('Long items are not implemented.') 435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)def _DefineItem(name, tag, typ): 465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Create a function which encodes a HID item. 475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Args: 495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) name: Function name. 505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) tag: Item tag. 515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) typ: Item type. 525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Returns: 545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) A function which encodes a HID item of the given type. 555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) assert tag >= 0 and tag <= 0xF 575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) assert typ >= 0 and typ <= 3 585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def EncodeItem(value=0, force_length=0): 605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return _PackItem(tag, typ, value, force_length) 615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EncodeItem.__name__ = name 635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return EncodeItem 645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)def _DefineMainItem(name, tag): 675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Create a function which encodes a HID Main item. 685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) See Device Class Definition for Human Interface Devices (HID) Version 1.11 705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) section 6.2.2.4. 715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Args: 735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) name: Function name. 745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) tag: Item tag. 755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Returns: 775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) A function which encodes a HID item of the given type. 785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Raises: 805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ValueError: If the tag value is out of range. 815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) assert tag >= 0 and tag <= 0xF 835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def EncodeMainItem(*properties): 855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) value = 0 865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for bit, is_set in properties: 875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if is_set: 885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) value |= 1 << bit 895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return _PackItem(tag, hid_constants.Scope.MAIN, value, force_length=1) 905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EncodeMainItem.__name__ = name 925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return EncodeMainItem 935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)Input = _DefineMainItem('Input', 8) 955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)Output = _DefineMainItem('Output', 9) 965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)Feature = _DefineMainItem('Feature', 11) 975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# Input, Output and Feature Item Properties 995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# 1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# See Device Class Definition for Human Interface Devices (HID) Version 1.11 1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# section 6.2.2.5. 1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)Data = (0, False) 1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)Constant = (0, True) 1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)Array = (1, False) 1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)Variable = (1, True) 1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)Absolute = (2, False) 1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)Relative = (2, True) 1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)NoWrap = (3, False) 1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)Wrap = (3, True) 1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)Linear = (4, False) 1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)NonLinear = (4, True) 1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)PreferredState = (5, False) 1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)NoPreferred = (5, True) 1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)NoNullPosition = (6, False) 1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)NullState = (6, True) 1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)NonVolatile = (7, False) 1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)Volatile = (7, True) 1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)BitField = (8, False) 1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)BufferedBytes = (8, True) 1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)def Collection(typ, *items): 1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) start = struct.pack('<BB', 0xA1, typ) 1245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) end = struct.pack('<B', 0xC0) 1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return start + ''.join(items) + end 1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# Global Items 1285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# 1295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# See Device Class Definition for Human Interface Devices (HID) Version 1.11 1305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# section 6.2.2.7. 1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)UsagePage = _DefineItem('UsagePage', 0, hid_constants.Scope.GLOBAL) 1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)LogicalMinimum = _DefineItem('LogicalMinimum', 1, hid_constants.Scope.GLOBAL) 1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)LogicalMaximum = _DefineItem('LogicalMaximum', 2, hid_constants.Scope.GLOBAL) 1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)PhysicalMinimum = _DefineItem('PhysicalMinimum', 3, hid_constants.Scope.GLOBAL) 1355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)PhysicalMaximum = _DefineItem('PhysicalMaximum', 4, hid_constants.Scope.GLOBAL) 1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)UnitExponent = _DefineItem('UnitExponent', 5, hid_constants.Scope.GLOBAL) 1375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)Unit = _DefineItem('Unit', 6, hid_constants.Scope.GLOBAL) 1385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)ReportSize = _DefineItem('ReportSize', 7, hid_constants.Scope.GLOBAL) 1395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)ReportID = _DefineItem('ReportID', 8, hid_constants.Scope.GLOBAL) 1405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)ReportCount = _DefineItem('ReportCount', 9, hid_constants.Scope.GLOBAL) 1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)Push = _DefineItem('Push', 10, hid_constants.Scope.GLOBAL) 1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)Pop = _DefineItem('Pop', 11, hid_constants.Scope.GLOBAL) 1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# Local Items 1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# 1465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# See Device Class Definition for Human Interface Devices (HID) Version 1.11 1475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# section 6.2.2.8. 1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)Usage = _DefineItem('Usage', 0, hid_constants.Scope.LOCAL) 1495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)UsageMinimum = _DefineItem('UsageMinimum', 1, hid_constants.Scope.LOCAL) 1505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)UsageMaximum = _DefineItem('UsageMaximum', 2, hid_constants.Scope.LOCAL) 1515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)DesignatorIndex = _DefineItem('DesignatorIndex', 3, hid_constants.Scope.LOCAL) 1525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)DesignatorMinimum = _DefineItem('DesignatorMinimum', 4, 1535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) hid_constants.Scope.LOCAL) 1545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)DesignatorMaximum = _DefineItem('DesignatorMaximum', 5, 1555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) hid_constants.Scope.LOCAL) 1565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)StringIndex = _DefineItem('StringIndex', 7, hid_constants.Scope.LOCAL) 1575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)StringMinimum = _DefineItem('StringMinimum', 8, hid_constants.Scope.LOCAL) 1585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)StringMaximum = _DefineItem('StringMaximum', 9, hid_constants.Scope.LOCAL) 1595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)Delimiter = _DefineItem('Delimiter', 10, hid_constants.Scope.LOCAL) 160