Skip to content

Commit

Permalink
Add basic Unit and Unit Exponent support (#1)
Browse files Browse the repository at this point in the history
Unit systems and it's esponent values are supported. but It has yet to
expliot the different systems and provide meaningful information to the
API
  • Loading branch information
NZSmartie committed May 5, 2016
1 parent 7de184c commit ef8e69a
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 6 deletions.
9 changes: 5 additions & 4 deletions Readme.md
Expand Up @@ -10,12 +10,13 @@ At this stage, this library is still in early development and adoption is not re

#### Progress

- [x] Parse HID descriptor from byte array
- [ ] Support for HID spec 1.11 items *(See Issue [#1](https://github.com/NZSmartie/PyHIDParser/issues/1))*
- [x] Parse HID Report descriptor from byte array
- [ ] Support for HID spec 1.11 items *(See Issue [#1](https://github.com/NZSmartie/PyHIDParser/issues/1))*
- [x] Main items (Collections, Inputs, Outputs and Features)
- [ ] Global items *(missing `unit` and `unit exponent`)*
- [ ] Local items *(missing `string index/maximum/minimum` and delimiter`)*
- [x] Global items
- [ ] Local items *(missing `delimiter`)*
- [ ] ~~Support vender defined long items~~ *(not going to happen any time soon)*
- [x] Parse HID Physical Descriptor
- [x] Create an application API for handing HID items - *Don't want the application developer to deal with states, nesting or closing collections, etc*
- [x] Access reports based on usages
- [x] Serialize/Deserialize reports to/from the HID device
Expand Down
43 changes: 42 additions & 1 deletion hidparser/Device.py
@@ -1,4 +1,4 @@
from hidparser.enums import CollectionType, ReportType, ReportFlags
from hidparser.enums import CollectionType, ReportType, ReportFlags, UnitSystem
from hidparser.UsagePage import UsagePage, Usage, UsageType
from hidparser.helper import ValueRange

Expand All @@ -7,6 +7,42 @@
from bitstring import BitArray as _BitArray, Bits as _Bits


class Unit:
"""
Unit for Report values.
Attributes:
system (UnitSystem): The system used when interpreting the
"""
_map_nibble_exponent = {
0x0: 0, 0x1:1, 0x2: 2, 0x3: 3, 0x4: 4, 0x5: 5, 0x6: 6, 0x7: 7,
0x8: -8, 0x9: -7, 0xA: -6, 0xB: -5, 0xC: -4, 0xD: -3, 0xE: -2, 0xF: -1
}

def __init__(self):
self.system = UnitSystem.NONE
self.length = 0
self.mass = 0
self.time = 0
self.temperature = 0
self.current = 0
self.luminosity = 0

@classmethod
def from_bytes(cls, data: bytes):
unit = Unit()
unit.system = UnitSystem(data[0]&0x0F)
unit.length = cls._map_nibble_exponent[(data[0] & 0xF0) >> 4]
if len(data) > 1:
unit.mass = cls._map_nibble_exponent[data[1] & 0x0F]
unit.time = cls._map_nibble_exponent[(data[1] & 0xF0) >> 4]
if len(data) > 2:
unit.temperature = cls._map_nibble_exponent[data[2] & 0x0F]
unit.current = cls._map_nibble_exponent[(data[2] & 0xF0) >> 4]
if len(data) > 3:
unit.luminosity = cls._map_nibble_exponent[data[3] & 0x0F]


class Report:
def __init__(
self,
Expand All @@ -19,6 +55,8 @@ def __init__(
count: int=0,
logical_range=None,
physical_range=None,
unit=None,
exponent=1,
flags=None,
parent=None
):
Expand All @@ -35,6 +73,9 @@ def __init__(
self.logical_range = logical_range if logical_range is not None else ValueRange() # type: ValueRange
self.physical_range = physical_range if physical_range is not None else _copy(self.logical_range) # type: ValueRange

self.unit = unit if unit is not None else Unit()
self.unit_exponent = exponent

if type(usages) not in (list, tuple):
usages = (usages,)
self.usages = usages
Expand Down
5 changes: 5 additions & 0 deletions hidparser/DeviceBuilder.py
Expand Up @@ -14,6 +14,9 @@ def __init__(self):
self.designators = range(0)
self.strings = range(0)

self.unit = None
self.unit_exponent = 1

self.report_size = 0
self.report_count = 0
self.logical_range = ValueRange()
Expand Down Expand Up @@ -56,6 +59,8 @@ def add_report(self, report_type: ReportType, flags):
count=self.report_count,
logical_range=_copy.copy(self.logical_range),
physical_range=_copy.copy(self.physical_range),
unit=self.unit,
exponent=self.unit_exponent,
flags=flags
))

Expand Down
6 changes: 5 additions & 1 deletion hidparser/ItemGlobal.py
@@ -1,6 +1,6 @@
from hidparser import DeviceBuilder
from hidparser.Item import ItemType, Item, ValueItem

from hidparser.Unit import Unit as _Unit
from hidparser.UsagePage import UsagePage


Expand Down Expand Up @@ -84,6 +84,8 @@ def _get_type(cls):


class UnitExponentItem(ValueItem):
def visit(self, descriptor: DeviceBuilder):
descriptor.unit_exponent = self.value

@classmethod
def _get_tag(cls):
Expand All @@ -95,6 +97,8 @@ def _get_type(cls):


class UnitItem(Item):
def visit(self, descriptor: DeviceBuilder):
descriptor.unit = _Unit.from_bytes(self.data)

@classmethod
def _get_tag(cls):
Expand Down
34 changes: 34 additions & 0 deletions hidparser/enums.py
Expand Up @@ -54,3 +54,37 @@ class CollectionType(Enum):
NAMED_ARRAY = 4
USAGE_SWITCH = 5
USAGE_MODIFIER = 6


class UnitSystem(Enum):
NONE = 0x0
SI_LINEAR = 0x01
SI_ROTATION = 0x02
ENGLISH_LINEAR = 0x03
ENGLISH_ROTATION = 0x04
VENDOR_DEFINED = 0x0F

def __repr__(self):
return "<{}: {}>".format(self.__class__.name, self._name_.replace("_", " ").title())


# TODO Support printing out SI units ("cm", "mm", "km" etc...)
# TODO Support SI Linear, SI Rotation, English Linear and English Rotation
class UnitLength(Enum):
NONE = 0
CENTIMETERS = 1
METERS = 3
KILOMETERS = 6
MILLIMETERS = -1
MICROMETERS = -4
NANOMETERS = -7


class UnitMass(Enum):
NONE = 0
GRAMS = 1
KILOGRAMS = 4
TON = 7
MILLIGRAMS = -2
MICROGRAMS = -5
NANOGRAMS = -8

0 comments on commit ef8e69a

Please sign in to comment.