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