#!/usr/bin/env python
"""This module is mostly a playground for descriptor-parsing code.
Copyright (c) 2005 Charles Lepple
You may distribute this file under the terms of either the GNU General Public
License or the Artistic License."""
__author__ = "Charles Lepple <clepple+libhid@ghz.cc>"
__date__ = "20 February 2005"
import os, sys, re
def extract_bytes_libhid(f):
"""Extract an array of bytes from a hex dump generated by libhid.
The returned list contains unsigned integers corresponding to the
bytes."""
descriptor_seen = 0
descriptor_text = []
for line in f:
if descriptor_seen:
if 'parsing the HID tree' in line:
descriptor_seen = 0
else:
# Chop off "TRACE: hid_prepare_parser(): 0xZZZ":
descriptor_text += line.split()[3:]
else:
if 'raw report descriptor' in line:
descriptor_seen = 1
# Map each string element into an integer:
return [int(var, 16) for var in descriptor_text]
def extract_bytes(f):
"""Extract an array of descriptor bytes from an assembly file, or just a
list of hex bytes. ('ret' statements, colons, comments and labels are
removed.) The returned list contains unsigned integers corresponding to the
bytes."""
descriptor_text = []
re_ret = re.compile(r'ret[a-z]+', re.IGNORECASE)
# Labels begin in the first column, and optionally have a colon afterwards:
re_label = re.compile(r'^[a-z0-9_]+:?', re.IGNORECASE)
re_comment = re.compile(r';.*$')
for line in f:
line = re_comment.sub('', line)
line = re_label.sub('', line)
line = re_ret.sub('', line)
# print "Line: " + line
descriptor_text += line.split()
# Map each string element into an integer:
return [int(var, 16) for var in descriptor_text]
# string.join([ "%02x" % var for var in descriptor_bytes])
def parse_tag(desc, index = 0):
"""Examine and print information about the item at desc[index].
Returns the length of the item (including the tag), which can be used to
advance index to the next item in the descriptor.
Currently, only short tags are handled.
bSize:
0 = 0 bytes
1 = 1 byte
2 = 2 bytes
3 = 4 bytes"""
bSize = (1 << (desc[index] & 0x3)) / 2
bType = (desc[index] >> 2) & 0x3
bTag = (desc[index] >> 4) & 0xF
print "[0x%04x]" % index,
data = 0
for byte in range(bSize+1):
print "0x%02x" % desc[index+byte],
if byte > 0:
data = desc[index+byte] << (8*(byte-1)) | data
# FIXME: sign-extend data if necessary
if bSize > 0:
print "(value: 0x%x / %d)" % (data, data),
print
print " bSize = %d byte(s)" % bSize
print " bType = 0x%02x (%s)" \
% (bType, ('Main', 'Global', 'Local', 'Reserved')[bType])
print " bTag = 0x%02x" % bTag,
if bType == 0: # Main
print "(%s)" % ('Input', 'Output', 'Collection', 'Feature', \
'End Collection')[bTag-8],
if bTag == 0x0a: # Collection type
if data <= 6:
print "(%s)" % ('Physical', 'Application', 'Logical', 'Report', \
'Named Array', 'Usage Switch', 'Usage Modifier')[data],
else:
print "(Vendor defined: 0x%x)" % data,
elif bType == 1: # Global
print "(%s)" % ('Usage page', 'Logical Minimum', 'Logical Maximum', \
'Physical Minimum', 'Physical Maximum', 'Unit Exponent', 'Unit', \
'Report Size', 'Report ID', 'Report Count', 'Push', 'Pop')[bTag],
elif bType == 2: # Local
print "(%s)" % ('Usage', 'Usage Minimum', 'Usage Maximum', \
'Designator Index', 'Designator Minimum', 'Designator Maximum', \
'String Index', 'String Minimum', 'String Maximum', \
'Delimiter')[bTag],
print
print
return bSize + 1
def tokenize_descriptor(desc):
byte_index = 0;
while byte_index < len(desc):
byte_index += parse_tag(desc, byte_index)
def main():
if(len(sys.argv) > 1):
fname = sys.argv[1]
else:
fname = '../ref/test_libhid_output/MGE_Pulsar_Evolution_500'
f = open(fname, 'r')
# desc_bytes = extract_bytes(f)
# - or -
desc_bytes = extract_bytes_libhid(f)
f.close()
tokenize_descriptor(desc_bytes)
print "done"
if __name__ == '__main__':
main()
syntax highlighted by Code2HTML, v. 0.9.1