Merge pull request #24 from VorpalBlade/feature/code-cleanup

Major code cleanup:
This commit is contained in:
uunicorn 2020-08-06 22:41:07 +12:00 committed by GitHub
commit 6a7ae704e7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
29 changed files with 2205 additions and 1007 deletions

394
.style.yapf Normal file
View file

@ -0,0 +1,394 @@
[style]
# Align closing bracket with visual indentation.
align_closing_bracket_with_visual_indent=True
# Allow dictionary keys to exist on multiple lines. For example:
#
# x = {
# ('this is the first element of a tuple',
# 'this is the second element of a tuple'):
# value,
# }
allow_multiline_dictionary_keys=False
# Allow lambdas to be formatted on more than one line.
allow_multiline_lambdas=False
# Allow splitting before a default / named assignment in an argument list.
allow_split_before_default_or_named_assigns=True
# Allow splits before the dictionary value.
allow_split_before_dict_value=True
# Let spacing indicate operator precedence. For example:
#
# a = 1 * 2 + 3 / 4
# b = 1 / 2 - 3 * 4
# c = (1 + 2) * (3 - 4)
# d = (1 - 2) / (3 + 4)
# e = 1 * 2 - 3
# f = 1 + 2 + 3 + 4
#
# will be formatted as follows to indicate precedence:
#
# a = 1*2 + 3/4
# b = 1/2 - 3*4
# c = (1+2) * (3-4)
# d = (1-2) / (3+4)
# e = 1*2 - 3
# f = 1 + 2 + 3 + 4
#
arithmetic_precedence_indication=False
# Number of blank lines surrounding top-level function and class
# definitions.
blank_lines_around_top_level_definition=2
# Insert a blank line before a class-level docstring.
blank_line_before_class_docstring=False
# Insert a blank line before a module docstring.
blank_line_before_module_docstring=False
# Insert a blank line before a 'def' or 'class' immediately nested
# within another 'def' or 'class'. For example:
#
# class Foo:
# # <------ this blank line
# def method():
# ...
blank_line_before_nested_class_or_def=False
# Do not split consecutive brackets. Only relevant when
# dedent_closing_brackets is set. For example:
#
# call_func_that_takes_a_dict(
# {
# 'key1': 'value1',
# 'key2': 'value2',
# }
# )
#
# would reformat to:
#
# call_func_that_takes_a_dict({
# 'key1': 'value1',
# 'key2': 'value2',
# })
coalesce_brackets=False
# The column limit.
column_limit=100
# The style for continuation alignment. Possible values are:
#
# - SPACE: Use spaces for continuation alignment. This is default behavior.
# - FIXED: Use fixed number (CONTINUATION_INDENT_WIDTH) of columns
# (ie: CONTINUATION_INDENT_WIDTH/INDENT_WIDTH tabs or
# CONTINUATION_INDENT_WIDTH spaces) for continuation alignment.
# - VALIGN-RIGHT: Vertically align continuation lines to multiple of
# INDENT_WIDTH columns. Slightly right (one tab or a few spaces) if
# cannot vertically align continuation lines with indent characters.
continuation_align_style=SPACE
# Indent width used for line continuations.
continuation_indent_width=4
# Put closing brackets on a separate line, dedented, if the bracketed
# expression can't fit in a single line. Applies to all kinds of brackets,
# including function definitions and calls. For example:
#
# config = {
# 'key1': 'value1',
# 'key2': 'value2',
# } # <--- this bracket is dedented and on a separate line
#
# time_series = self.remote_client.query_entity_counters(
# entity='dev3246.region1',
# key='dns.query_latency_tcp',
# transform=Transformation.AVERAGE(window=timedelta(seconds=60)),
# start_ts=now()-timedelta(days=3),
# end_ts=now(),
# ) # <--- this bracket is dedented and on a separate line
dedent_closing_brackets=False
# Disable the heuristic which places each list element on a separate line
# if the list is comma-terminated.
disable_ending_comma_heuristic=False
# Place each dictionary entry onto its own line.
each_dict_entry_on_separate_line=True
# Require multiline dictionary even if it would normally fit on one line.
# For example:
#
# config = {
# 'key1': 'value1'
# }
force_multiline_dict=False
# The regex for an i18n comment. The presence of this comment stops
# reformatting of that line, because the comments are required to be
# next to the string they translate.
i18n_comment=
# The i18n function call names. The presence of this function stops
# reformattting on that line, because the string it has cannot be moved
# away from the i18n comment.
i18n_function_call=
# Indent blank lines.
indent_blank_lines=False
# Put closing brackets on a separate line, indented, if the bracketed
# expression can't fit in a single line. Applies to all kinds of brackets,
# including function definitions and calls. For example:
#
# config = {
# 'key1': 'value1',
# 'key2': 'value2',
# } # <--- this bracket is indented and on a separate line
#
# time_series = self.remote_client.query_entity_counters(
# entity='dev3246.region1',
# key='dns.query_latency_tcp',
# transform=Transformation.AVERAGE(window=timedelta(seconds=60)),
# start_ts=now()-timedelta(days=3),
# end_ts=now(),
# ) # <--- this bracket is indented and on a separate line
indent_closing_brackets=False
# Indent the dictionary value if it cannot fit on the same line as the
# dictionary key. For example:
#
# config = {
# 'key1':
# 'value1',
# 'key2': value1 +
# value2,
# }
indent_dictionary_value=False
# The number of columns to use for indentation.
indent_width=4
# Join short lines into one line. E.g., single line 'if' statements.
join_multiple_lines=True
# Do not include spaces around selected binary operators. For example:
#
# 1 + 2 * 3 - 4 / 5
#
# will be formatted as follows when configured with "*,/":
#
# 1 + 2*3 - 4/5
no_spaces_around_selected_binary_operators=
# Use spaces around default or named assigns.
spaces_around_default_or_named_assign=False
# Adds a space after the opening '{' and before the ending '}' dict delimiters.
#
# {1: 2}
#
# will be formatted as:
#
# { 1: 2 }
spaces_around_dict_delimiters=False
# Adds a space after the opening '[' and before the ending ']' list delimiters.
#
# [1, 2]
#
# will be formatted as:
#
# [ 1, 2 ]
spaces_around_list_delimiters=False
# Use spaces around the power operator.
spaces_around_power_operator=False
# Use spaces around the subscript / slice operator. For example:
#
# my_list[1 : 10 : 2]
spaces_around_subscript_colon=False
# Adds a space after the opening '(' and before the ending ')' tuple delimiters.
#
# (1, 2, 3)
#
# will be formatted as:
#
# ( 1, 2, 3 )
spaces_around_tuple_delimiters=False
# The number of spaces required before a trailing comment.
# This can be a single value (representing the number of spaces
# before each trailing comment) or list of values (representing
# alignment column values; trailing comments within a block will
# be aligned to the first column value that is greater than the maximum
# line length within the block). For example:
#
# With spaces_before_comment=5:
#
# 1 + 1 # Adding values
#
# will be formatted as:
#
# 1 + 1 # Adding values <-- 5 spaces between the end of the statement and comment
#
# With spaces_before_comment=15, 20:
#
# 1 + 1 # Adding values
# two + two # More adding
#
# longer_statement # This is a longer statement
# short # This is a shorter statement
#
# a_very_long_statement_that_extends_beyond_the_final_column # Comment
# short # This is a shorter statement
#
# will be formatted as:
#
# 1 + 1 # Adding values <-- end of line comments in block aligned to col 15
# two + two # More adding
#
# longer_statement # This is a longer statement <-- end of line comments in block aligned to col 20
# short # This is a shorter statement
#
# a_very_long_statement_that_extends_beyond_the_final_column # Comment <-- the end of line comments are aligned based on the line length
# short # This is a shorter statement
#
spaces_before_comment=2
# Insert a space between the ending comma and closing bracket of a list,
# etc.
space_between_ending_comma_and_closing_bracket=True
# Use spaces inside brackets, braces, and parentheses. For example:
#
# method_call( 1 )
# my_dict[ 3 ][ 1 ][ get_index( *args, **kwargs ) ]
# my_set = { 1, 2, 3 }
space_inside_brackets=False
# Split before arguments
split_all_comma_separated_values=False
# Split before arguments, but do not split all subexpressions recursively
# (unless needed).
split_all_top_level_comma_separated_values=False
# Split before arguments if the argument list is terminated by a
# comma.
split_arguments_when_comma_terminated=False
# Set to True to prefer splitting before '+', '-', '*', '/', '//', or '@'
# rather than after.
split_before_arithmetic_operator=False
# Set to True to prefer splitting before '&', '|' or '^' rather than
# after.
split_before_bitwise_operator=True
# Split before the closing bracket if a list or dict literal doesn't fit on
# a single line.
split_before_closing_bracket=True
# Split before a dictionary or set generator (comp_for). For example, note
# the split before the 'for':
#
# foo = {
# variable: 'Hello world, have a nice day!'
# for variable in bar if variable != 42
# }
split_before_dict_set_generator=True
# Split before the '.' if we need to split a longer expression:
#
# foo = ('This is a really long string: {}, {}, {}, {}'.format(a, b, c, d))
#
# would reformat to something like:
#
# foo = ('This is a really long string: {}, {}, {}, {}'
# .format(a, b, c, d))
split_before_dot=False
# Split after the opening paren which surrounds an expression if it doesn't
# fit on a single line.
split_before_expression_after_opening_paren=False
# If an argument / parameter list is going to be split, then split before
# the first argument.
split_before_first_argument=False
# Set to True to prefer splitting before 'and' or 'or' rather than
# after.
split_before_logical_operator=True
# Split named assignments onto individual lines.
split_before_named_assigns=True
# Set to True to split list comprehensions and generators that have
# non-trivial expressions and multiple clauses before each of these
# clauses. For example:
#
# result = [
# a_long_var + 100 for a_long_var in xrange(1000)
# if a_long_var % 10]
#
# would reformat to something like:
#
# result = [
# a_long_var + 100
# for a_long_var in xrange(1000)
# if a_long_var % 10]
split_complex_comprehension=False
# The penalty for splitting right after the opening bracket.
split_penalty_after_opening_bracket=300
# The penalty for splitting the line after a unary operator.
split_penalty_after_unary_operator=10000
# The penalty of splitting the line around the '+', '-', '*', '/', '//',
# ``%``, and '@' operators.
split_penalty_arithmetic_operator=300
# The penalty for splitting right before an if expression.
split_penalty_before_if_expr=0
# The penalty of splitting the line around the '&', '|', and '^'
# operators.
split_penalty_bitwise_operator=300
# The penalty for splitting a list comprehension or generator
# expression.
split_penalty_comprehension=80
# The penalty for characters over the column limit.
split_penalty_excess_character=7000
# The penalty incurred by adding a line split to the unwrapped line. The
# more line splits added the higher the penalty.
split_penalty_for_added_line_split=30
# The penalty of splitting a list of "import as" names. For example:
#
# from a_very_long_or_indented_module_name_yada_yad import (long_argument_1,
# long_argument_2,
# long_argument_3)
#
# would reformat to something like:
#
# from a_very_long_or_indented_module_name_yada_yad import (
# long_argument_1, long_argument_2, long_argument_3)
split_penalty_import_names=0
# The penalty of splitting the line around the 'and' and 'or'
# operators.
split_penalty_logical_operator=300
# Use the Tab character for indentation.
use_tabs=False

View file

@ -1,15 +1,13 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import os import os
from binascii import unhexlify from binascii import unhexlify
from enum import Enum
from validitysensor.flash import read_flash
from validitysensor.sensor import *
from validitysensor import init
from time import sleep from time import sleep
from usb import core as usb_core
from validitysensor import init
from validitysensor.sensor import glow_start_scan, glow_end_scan
from validitysensor.tls import tls
from validitysensor.util import assert_status
if __name__ == "__main__": if __name__ == "__main__":
if os.geteuid() != 0: if os.geteuid() != 0:
@ -23,10 +21,9 @@ if __name__ == "__main__":
glow_end_scan() glow_end_scan()
sleep(0.05) sleep(0.05)
led_script = unhexlify( led_script = unhexlify('39ff100000ff03000001ff002000000000ffff0000ffff0000ff03000001ff00'
'39ff100000ff03000001ff002000000000ffff0000ffff0000ff03000001ff00' \ '200000000000000000ffff0000ff03000001ff002000000000ffff0000000000'
'200000000000000000ffff0000ff03000001ff002000000000ffff0000000000' \ '0000000000000000000000000000000000000000000000000000000000000000'
'0000000000000000000000000000000000000000000000000000000000000000' \
'0000000000000000000000000000000000000000000000000000000000') '0000000000000000000000000000000000000000000000000000000000')
assert_status(tls.app(led_script)) assert_status(tls.app(led_script))

View file

@ -20,24 +20,25 @@
import argparse import argparse
import os import os
import shutil
import subprocess import subprocess
import sys import sys
import tempfile import tempfile
import urllib.request import urllib.request
import shutil from enum import Enum
from enum import Enum, auto
from time import sleep
from usb import core as usb_core from usb import core as usb_core
python_validity_data = '/usr/share/python-validity/' python_validity_data = '/usr/share/python-validity/'
# FIXME: supported usb ids are duplicated in usb.py # FIXME: supported usb ids are duplicated in usb.py
class VFS(Enum): class VFS(Enum):
DEV_90 = (0x138a, 0x0090) DEV_90 = (0x138a, 0x0090)
DEV_97 = (0x138a, 0x0097) DEV_97 = (0x138a, 0x0097)
DEV_9a = (0x06cb, 0x009a) DEV_9a = (0x06cb, 0x009a)
DEFAULT_URIS = { DEFAULT_URIS = {
VFS.DEV_90: { VFS.DEV_90: {
'driver': 'https://download.lenovo.com/pccbbs/mobiles/n1cgn08w.exe', 'driver': 'https://download.lenovo.com/pccbbs/mobiles/n1cgn08w.exe',
@ -76,15 +77,12 @@ def download_and_extract_fw(dev_type, fwdir, fwuri=None):
with open(fwarchive, 'wb') as out_file: with open(fwarchive, 'wb') as out_file:
out_file.write(response.read()) out_file.write(response.read())
subprocess.check_call(['innoextract', subprocess.check_call([
'--output-dir', fwdir, 'innoextract', '--output-dir', fwdir, '--include', fwname, '--collisions', 'overwrite',
'--include', fwname,
'--collisions', 'overwrite',
fwarchive fwarchive
]) ])
fwpath = subprocess.check_output([ fwpath = subprocess.check_output(['find', fwdir, '-name', fwname]).decode('utf-8').strip()
'find', fwdir, '-name', fwname]).decode('utf-8').strip()
print('Found firmware at {}'.format(fwpath)) print('Found firmware at {}'.format(fwpath))
if not fwpath: if not fwpath:
@ -92,6 +90,7 @@ def download_and_extract_fw(dev_type, fwdir, fwuri=None):
return fwpath return fwpath
if __name__ == "__main__": if __name__ == "__main__":
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument('--driver-uri') parser.add_argument('--driver-uri')
@ -111,8 +110,7 @@ if __name__ == "__main__":
raise Exception('No supported validity device found') raise Exception('No supported validity device found')
try: try:
subprocess.check_call(['innoextract', '--version'], subprocess.check_call(['innoextract', '--version'], stdout=subprocess.DEVNULL)
stdout=subprocess.DEVNULL)
except Exception as e: except Exception as e:
print('Impossible to run innoextract: {}'.format(e)) print('Impossible to run innoextract: {}'.format(e))
sys.exit(1) sys.exit(1)

View file

@ -1,6 +1,8 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import argparse import argparse
import logging
import logging.handlers
import os import os
import pwd import pwd
import re import re
@ -16,21 +18,18 @@ import dbus
import dbus.mainloop.glib import dbus.mainloop.glib
import dbus.service import dbus.service
import yaml import yaml
from gi.repository import GLib
from usb import core as usb_core from usb import core as usb_core
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
from gi.repository import GLib
import logging
import logging.handlers
from validitysensor import init from validitysensor import init
from validitysensor.tls import tls
from validitysensor.usb import usb
from validitysensor.sid import sid_from_string
from validitysensor.db import subtype_to_string, db, SidIdentity, User from validitysensor.db import subtype_to_string, db, SidIdentity, User
from validitysensor.sensor import sensor, RebootException from validitysensor.sensor import sensor, RebootException
from validitysensor.sid import sid_from_string
from validitysensor.tls import tls
from validitysensor.usb import usb
from validitysensor.winbio_constants import finger_ids from validitysensor.winbio_constants import finger_ids
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
GLib.threads_init() GLib.threads_init()
INTERFACE_NAME = 'io.github.uunicorn.Fprint.Device' INTERFACE_NAME = 'io.github.uunicorn.Fprint.Device'
@ -64,9 +63,7 @@ class Device(dbus.service.Object):
"""Resolve user name to database object""" """Resolve user name to database object"""
return db.lookup_user(self.user2identity(user)) return db.lookup_user(self.user2identity(user))
@dbus.service.method(dbus_interface=INTERFACE_NAME, @dbus.service.method(dbus_interface=INTERFACE_NAME, in_signature="s", out_signature="as")
in_signature="s",
out_signature="as")
def ListEnrolledFingers(self, user): def ListEnrolledFingers(self, user):
try: try:
logging.debug('In ListEnrolledFingers %s' % user) logging.debug('In ListEnrolledFingers %s' % user)
@ -82,9 +79,7 @@ class Device(dbus.service.Object):
except Exception as e: except Exception as e:
raise e raise e
@dbus.service.method(dbus_interface=INTERFACE_NAME, @dbus.service.method(dbus_interface=INTERFACE_NAME, in_signature='s', out_signature='')
in_signature='s',
out_signature='')
def DeleteEnrolledFingers(self, user): def DeleteEnrolledFingers(self, user):
logging.debug('In DeleteEnrolledFingers %s' % user) logging.debug('In DeleteEnrolledFingers %s' % user)
usr = self.user2record(user) usr = self.user2record(user)
@ -94,9 +89,7 @@ class Device(dbus.service.Object):
db.del_record(usr.dbid) db.del_record(usr.dbid)
@dbus.service.method(dbus_interface=INTERFACE_NAME, @dbus.service.method(dbus_interface=INTERFACE_NAME, in_signature='ss', out_signature='')
in_signature='ss',
out_signature='')
def VerifyStart(self, user, finger): def VerifyStart(self, user, finger):
logging.debug('In VerifyStart for %s, %s' % (user, finger)) logging.debug('In VerifyStart for %s, %s' % (user, finger))
@ -130,15 +123,11 @@ class Device(dbus.service.Object):
thread.daemon = True thread.daemon = True
thread.start() thread.start()
@dbus.service.method(dbus_interface=INTERFACE_NAME, @dbus.service.method(dbus_interface=INTERFACE_NAME, in_signature='', out_signature='')
in_signature='',
out_signature='')
def Cancel(self): def Cancel(self):
sensor.cancel() sensor.cancel()
@dbus.service.method(dbus_interface=INTERFACE_NAME, @dbus.service.method(dbus_interface=INTERFACE_NAME, in_signature='ss', out_signature='')
in_signature='ss',
out_signature='')
def EnrollStart(self, user, finger_name): def EnrollStart(self, user, finger_name):
logging.debug('In EnrollStart %s for %s' % (finger_name, user)) logging.debug('In EnrollStart %s for %s' % (finger_name, user))
@ -169,11 +158,9 @@ class Device(dbus.service.Object):
logging.exception(e) logging.exception(e)
self.EnrollStatus('enroll-failed', True) self.EnrollStatus('enroll-failed', True)
if index == None: if index is None:
logging.exception( logging.exception('Unknown finger name passed to enroll? ' + finger_name + ' (' +
'Unknown finger name passed to enroll? ' + winbio_name + ')')
finger_name + ' (' + winbio_name + ')'
)
self.EnrollStatus('enroll-failed', True) self.EnrollStatus('enroll-failed', True)
else: else:
thread = Thread(target=run) thread = Thread(target=run)
@ -192,9 +179,7 @@ class Device(dbus.service.Object):
def EnrollStatus(self, result, done): def EnrollStatus(self, result, done):
logging.debug('EnrollStatus') logging.debug('EnrollStatus')
@dbus.service.method(dbus_interface=INTERFACE_NAME, @dbus.service.method(dbus_interface=INTERFACE_NAME, in_signature='s', out_signature='s')
in_signature='s',
out_signature='s')
def RunCmd(self, cmd): def RunCmd(self, cmd):
logging.debug('RunCmd') logging.debug('RunCmd')
return hexlify(tls.app(unhexlify(cmd))).decode() return hexlify(tls.app(unhexlify(cmd))).decode()
@ -228,7 +213,10 @@ def main():
parser = argparse.ArgumentParser('Open fprintd DBus service') parser = argparse.ArgumentParser('Open fprintd DBus service')
parser.add_argument('--debug', help='Enable tracing', action='store_true') parser.add_argument('--debug', help='Enable tracing', action='store_true')
parser.add_argument('--devpath', help='USB device path: usb-<busnum>-<address>') parser.add_argument('--devpath', help='USB device path: usb-<busnum>-<address>')
parser.add_argument('--configpath', default='/etc/python-validity', type=Path, help='Path to config files') parser.add_argument('--configpath',
default='/etc/python-validity',
type=Path,
help='Path to config files')
args = parser.parse_args() args = parser.parse_args()
if args.debug: if args.debug:

View file

@ -1,13 +1,11 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import argparse
import re
import dbus
import dbus.mainloop.glib
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
from gi.repository import GObject, GLib
import sys import sys
import dbus.mainloop.glib
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
bus = dbus.SystemBus() bus = dbus.SystemBus()
o = bus.get_object('net.reactivated.Fprint', '/net/reactivated/Fprint/Manager', introspect=False) o = bus.get_object('net.reactivated.Fprint', '/net/reactivated/Fprint/Manager', introspect=False)
o = o.GetDefaultDevice() o = o.GetDefaultDevice()

View file

@ -1,6 +1,5 @@
from validitysensor.usb import usb
from validitysensor.sensor import factory_reset, RebootException from validitysensor.sensor import factory_reset, RebootException
from validitysensor.usb import usb
try: try:
usb.open() usb.open()

View file

@ -1,13 +1,8 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import argparse
import re
import dbus
import dbus.mainloop.glib import dbus.mainloop.glib
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
from gi.repository import GObject, GLib
import pwd dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
bus = dbus.SystemBus() bus = dbus.SystemBus()
o = bus.get_object('org.freedesktop.DBus', '/org/freedesktop/DBus') o = bus.get_object('org.freedesktop.DBus', '/org/freedesktop/DBus')

View file

@ -1,3 +1,7 @@
import code
import logging
from binascii import hexlify
from validitysensor.tls import tls from validitysensor.tls import tls
from validitysensor.usb import usb from validitysensor.usb import usb
from validitysensor.db import db from validitysensor.db import db
@ -7,12 +11,11 @@ from validitysensor.sid import *
from validitysensor.init import open as open9x from validitysensor.init import open as open9x
from threading import Condition from threading import Condition
from time import sleep from time import sleep
import logging
import code
# usb.trace_enabled = True # usb.trace_enabled = True
# tls.trace_enabled = True # tls.trace_enabled = True
def identify(): def identify():
def update_cb(e): def update_cb(e):
print('Capture error: %s, try again' % repr(e)) print('Capture error: %s, try again' % repr(e))
@ -21,6 +24,7 @@ def identify():
print('Got finger %x for user recordid %d. Hash: %s' % (subtype, usrid, hexlify(hsh).decode())) print('Got finger %x for user recordid %d. Hash: %s' % (subtype, usrid, hexlify(hsh).decode()))
def enroll(sid, finger): def enroll(sid, finger):
def update_cb(x, e): def update_cb(x, e):
if e is not None: if e is not None:
@ -31,4 +35,3 @@ def enroll(sid, finger):
recid = sensor.enroll(sid, finger, update_cb) recid = sensor.enroll(sid, finger, update_cb)
print('Created a finger record with dbid %d' % recid) print('Created a finger record with dbid %d' % recid)

View file

@ -10,19 +10,12 @@ setup(name='python-validity',
'bin/validity-led-dance', 'bin/validity-led-dance',
'bin/validity-sensors-firmware', 'bin/validity-sensors-firmware',
], ],
install_requires=[ install_requires=['cryptography >= 2.1.4', 'pyusb >= 1.0.0', 'pyyaml >= 3.12'],
'cryptography >= 2.1.4',
'pyusb >= 1.0.0',
'pyyaml >= 3.12'
],
data_files=[ data_files=[
('share/dbus-1/system.d/', ['dbus_service/io.github.uunicorn.Fprint.conf']), ('share/dbus-1/system.d/', ['dbus_service/io.github.uunicorn.Fprint.conf']),
('lib/python-validity/', ['dbus_service/dbus-service']), ('lib/python-validity/', ['dbus_service/dbus-service']),
('share/python-validity/playground/', [ ('share/python-validity/playground/', [
'scripts/dbus-cmd.py', 'scripts/dbus-cmd.py', 'scripts/lsdbus.py', 'scripts/factory-reset.py',
'scripts/lsdbus.py',
'scripts/factory-reset.py',
'scripts/prototype.py' 'scripts/prototype.py'
]), ]),
] ])
)

View file

@ -1,13 +1,4 @@
from enum import Enum, auto def __load_blob(blob: str) -> bytes:
class Blobs(Enum):
init_hardcoded = auto()
init_hardcoded_clean_slate = auto()
reset_blob = auto()
db_write_enable = auto()
def __load_blob(blob):
from .usb import usb from .usb import usb
if usb.usb_dev().idVendor == 0x138a: if usb.usb_dev().idVendor == 0x138a:
@ -22,6 +13,8 @@ def __load_blob(blob):
globals()[blob] = getattr(blobs, blob) globals()[blob] = getattr(blobs, blob)
return globals()[blob] return globals()[blob]
for p in dir(Blobs):
if isinstance(getattr(Blobs, p), Blobs): init_hardcoded = lambda: __load_blob('init_hardcoded')
globals()[p] = lambda bname=p: __load_blob(bname) init_hardcoded_clean_slate = lambda: __load_blob('init_hardcoded_clean_slate')
reset_blob = lambda: __load_blob('reset_blob')
db_write_enable = lambda: __load_blob('db_write_enable')

View file

@ -1,4 +1,3 @@
from .util import unhex from .util import unhex
init_hardcoded = unhex(''' init_hardcoded = unhex('''
@ -365,4 +364,3 @@ c2d182e1e30182e1c321d341d341e321c301e1e241e201f201d1c321a301e1c211e21341f1e20202
8080808180818081808080818081808180818081808180808081808180818081808180818081808180818 8080808180818081808080818081808180818081808180808081808180818081808180818081808180818
0818081808180818081808080808080808080807f807f807f807f7f7e7e 0818081808180818081808080808080808080807f807f807f807f7f7e7e
''') ''')

View file

@ -1,4 +1,3 @@
from .util import unhex from .util import unhex
init_hardcoded = unhex(''' init_hardcoded = unhex('''

View file

@ -1,4 +1,3 @@
from .util import unhex from .util import unhex
init_hardcoded = unhex(''' init_hardcoded = unhex('''

View file

@ -1,36 +1,43 @@
import typing import typing
from .tls import tls
from .util import assert_status
from binascii import hexlify from binascii import hexlify
from struct import pack, unpack
from .blobs import db_write_enable from .blobs import db_write_enable
from .flash import call_cleanups from .flash import call_cleanups
from .sid import * from .sid import SidIdentity, sid_from_bytes
from .tls import tls
from .util import assert_status
from .winbio_constants import finger_names from .winbio_constants import finger_names
class UserStorage():
def __init__(self, dbid, name): class UserStorage:
def __init__(self, dbid: int, name: str):
self.dbid = dbid self.dbid = dbid
self.name = name self.name = name
self.users = [] self.users = []
def __repr__(self): def __repr__(self):
return '<UserStorage: dbid=%04x name=%s users=%s>' % (self.dbid, repr(self.name), repr(self.users)) return '<UserStorage: dbid=%04x name=%s users=%s>' % (self.dbid, repr(
self.name), repr(self.users))
class User():
def __init__(self, dbid, identity): class User:
def __init__(self, dbid: int, identity: str):
self.dbid = dbid self.dbid = dbid
self.identity = identity self.identity = identity
self.fingers=[] self.fingers: typing.List[typing.Mapping[str, int]] = []
def __repr__(self): def __repr__(self):
return '<User: dbid=%04x identity=%s fingers=%s>' % (self.dbid, repr(self.identity), repr(self.fingers)) return '<User: dbid=%04x identity=%s fingers=%s>' % (self.dbid, repr(
self.identity), repr(self.fingers))
def subtype_to_string(s: int): def subtype_to_string(s: int):
finger_name = finger_names.get(s, None) finger_name = finger_names.get(s, None)
return finger_name or 'Unknown' return finger_name or 'Unknown'
def parse_user_storage(rsp):
def parse_user_storage(rsp: bytes):
rc, = unpack('<H', rsp[:2]) rc, = unpack('<H', rsp[:2])
if rc == 0x04b3: if rc == 0x04b3:
@ -56,7 +63,8 @@ def parse_user_storage(rsp):
return storage return storage
def parse_identity(b):
def parse_identity(b: bytes):
t, b = b[:4], b[4:] t, b = b[:4], b[4:]
t, = unpack('<L', t) t, = unpack('<L', t)
@ -67,6 +75,7 @@ def parse_identity(b):
raise Exception('Don' 't know how to handle identity type %d' % t) raise Exception('Don' 't know how to handle identity type %d' % t)
def parse_user(rsp: bytes): def parse_user(rsp: bytes):
assert_status(rsp[:2]) assert_status(rsp[:2])
rsp = rsp[2:] rsp = rsp[2:]
@ -89,6 +98,7 @@ def parse_user(rsp: bytes):
return user return user
def identity_to_bytes(identity: str): def identity_to_bytes(identity: str):
if isinstance(identity, SidIdentity): if isinstance(identity, SidIdentity):
b = identity.to_bytes() b = identity.to_bytes()
@ -103,7 +113,8 @@ def identity_to_bytes(identity: str):
else: else:
raise Exception('Don' 't know how to handle identity %s' % repr(identity)) raise Exception('Don' 't know how to handle identity %s' % repr(identity))
class DbRecord():
class DbRecord:
def __init__(self): def __init__(self):
self.dbid = 0 self.dbid = 0
self.type = 0 self.type = 0
@ -113,17 +124,12 @@ class DbRecord():
def __repr__(self): def __repr__(self):
return '<DbRecord: dbid=%d type=%d storage=%d value=%s children=%s>' % ( return '<DbRecord: dbid=%d type=%d storage=%d value=%s children=%s>' % (
self.dbid, self.dbid, self.type, self.storage, repr(self.value), repr(self.children))
self.type,
self.storage,
repr(self.value),
repr(self.children)
)
class Db(): class Db:
class Info(): class Info:
def __init__(self, total, used, free, records, roots): def __init__(self, total: int, used: int, free: int, records: int, roots):
self.total = total # partition size self.total = total # partition size
self.used = used # used (not deleted) self.used = used # used (not deleted)
self.free = free # unallocated space self.free = free # unallocated space
@ -150,7 +156,7 @@ class Db():
rc = self.get_record_children(stg.dbid).children rc = self.get_record_children(stg.dbid).children
return [i['dbid'] for i in rc if i['type'] == 8] # 8 == "data" type return [i['dbid'] for i in rc if i['type'] == 8] # 8 == "data" type
def get_user(self, dbid): def get_user(self, dbid: int):
return parse_user(tls.cmd(pack('<BHHH', 0x4a, dbid, 0, 0))) return parse_user(tls.cmd(pack('<BHHH', 0x4a, dbid, 0, 0)))
def lookup_user(self, identity: str) -> typing.Optional[User]: def lookup_user(self, identity: str) -> typing.Optional[User]:
@ -165,7 +171,7 @@ class Db():
else: else:
return parse_user(rsp) return parse_user(rsp)
def get_record_value(self, dbid): def get_record_value(self, dbid: int):
rsp = tls.cmd(pack('<BH', 0x49, dbid)) rsp = tls.cmd(pack('<BH', 0x49, dbid))
assert_status(rsp) assert_status(rsp)
@ -175,7 +181,7 @@ class Db():
return rec return rec
def get_record_children(self, dbid): def get_record_children(self, dbid: int):
rsp = tls.cmd(pack('<BH', 0x46, dbid)) rsp = tls.cmd(pack('<BH', 0x46, dbid))
assert_status(rsp) assert_status(rsp)
@ -189,7 +195,7 @@ class Db():
return rec return rec
def del_record(self, dbid): def del_record(self, dbid: int):
assert_status(tls.cmd(pack('<BH', 0x48, dbid))) assert_status(tls.cmd(pack('<BH', 0x48, dbid)))
def db_info(self): def db_info(self):
@ -204,7 +210,7 @@ class Db():
return Db.Info(total, used, free, records, roots) return Db.Info(total, used, free, records, roots)
def new_record(self, parent, typ, storage, data): def new_record(self, parent: int, typ: int, storage: int, data: bytes):
self.db_info() # TODO check free space, compact the partition when out of storage self.db_info() # TODO check free space, compact the partition when out of storage
assert_status(tls.cmd(db_write_enable)) assert_status(tls.cmd(db_write_enable))
try: try:
@ -215,21 +221,21 @@ class Db():
call_cleanups() call_cleanups()
return recid return recid
def new_user(self, identity): def new_user(self, identity: str):
data = identity_to_bytes(identity) data = identity_to_bytes(identity)
stg = self.get_user_storage(name='StgWindsor') stg = self.get_user_storage(name='StgWindsor')
rec = self.new_record(stg.dbid, 5, stg.dbid, data) rec = self.new_record(stg.dbid, 5, stg.dbid, data)
return rec return rec
def new_finger(self, userid, template): def new_finger(self, userid: int, template: bytes):
stg = self.get_user_storage(name='StgWindsor') stg = self.get_user_storage(name='StgWindsor')
# We ask to create an object of type 0xb, # We ask to create an object of type 0xb,
# but because of the magical `db_write_enable` in the new_record() it ends up being 0x6 # but because of the magical `db_write_enable` in the new_record() it ends up being 0x6
rec = self.new_record(userid, 0xb, stg.dbid, template) rec = self.new_record(userid, 0xb, stg.dbid, template)
return rec return rec
def new_data(self, parent, data): def new_data(self, parent: int, data: bytes):
stg = self.get_user_storage(name='StgWindsor') stg = self.get_user_storage(name='StgWindsor')
data = pack('<HH', 1, len(data)) + data data = pack('<HH', 1, len(data)) + data
rec = self.new_record(parent, 0x8, stg.dbid, data) rec = self.new_record(parent, 0x8, stg.dbid, data)
@ -252,7 +258,8 @@ class Db():
for u in usrs: for u in usrs:
print('%2d: User %s with %d fingers:' % (u.dbid, repr(u.identity), len(u.fingers))) print('%2d: User %s with %d fingers:' % (u.dbid, repr(u.identity), len(u.fingers)))
for f in u.fingers: for f in u.fingers:
print(' %2d: %02x (%s)' % (f['dbid'], f['subtype'], subtype_to_string(f['subtype']))) print(' %2d: %02x (%s)' %
(f['dbid'], f['subtype'], subtype_to_string(f['subtype'])))
db = Db() db = Db()

View file

@ -1,26 +1,40 @@
from .tls import tls import typing
from struct import pack, unpack from struct import pack, unpack
from .util import assert_status, unhex
from .blobs import db_write_enable from .blobs import db_write_enable
from .hw_tables import flash_ic_table_lookup from .hw_tables import flash_ic_table_lookup, FlashIcInfo
from .tls import tls
from .util import assert_status, unhex
class FlashInfo():
def __init__(self, ic, blocks, unknown0, blocksize, unknown1, partitions):
self.ic, self.blocks, self.unknown0, self.blocksize, self.unknown1, self.partitions = ic, blocks, unknown0, blocksize, unknown1, partitions
def __repr__(self):
return 'FlashInfo(%s, 0x%x, 0x%x, 0x%x, 0x%x, %s)' % (repr(self.ic), self.blocks, self.unknown0, self.blocksize, self.unknown1, repr(self.partitions))
# type 01 is for the firmware - written blocks are decrypted on the fly using fw key # type 01 is for the firmware - written blocks are decrypted on the fly using fw key
# access lvl: # access lvl:
# 2 -- write only # 2 -- write only
# 7 -- can read/write even without TLS # 7 -- can read/write even without TLS
class PartitionInfo(): class PartitionInfo:
def __init__(self, id, type, access_lvl, offset, size): def __init__(self, id: int, type: int, access_lvl: int, offset: int, size: int):
self.id, self.type, self.access_lvl, self.offset, self.size = id, type, access_lvl, offset, size self.id, self.type, self.access_lvl, self.offset, self.size = id, type, access_lvl, offset, size
def __repr__(self): def __repr__(self):
return 'PartitionInfo(0x%02x, 0x%02x, 0x%04x, 0x%08x, 0x%08x)' % (self.id, self.type, self.access_lvl, self.offset, self.size) return 'PartitionInfo(0x%02x, 0x%02x, 0x%04x, 0x%08x, 0x%08x)' % (
self.id, self.type, self.access_lvl, self.offset, self.size)
class FlashInfo:
def __init__(self, ic: FlashIcInfo, blocks: int, unknown0: int, blocksize: int, unknown1: int,
partitions: typing.Sequence[PartitionInfo]):
self.ic = ic
self.blocks = blocks
self.unknown0 = unknown0
self.blocksize = blocksize
self.unknown1 = unknown1
self.partitions = partitions
def __repr__(self):
return 'FlashInfo(%s, 0x%x, 0x%x, 0x%x, 0x%x, %s)' % (repr(
self.ic), self.blocks, self.unknown0, self.blocksize, self.unknown1,
repr(self.partitions))
def get_flash_info(): def get_flash_info():
rsp = tls.cmd(unhex('3e')) rsp = tls.cmd(unhex('3e'))
@ -32,8 +46,9 @@ def get_flash_info():
ic = flash_ic_table_lookup(jid0, jid1, blocks * blocksize) ic = flash_ic_table_lookup(jid0, jid1, blocks * blocksize)
if ic == None: if ic is None:
raise Exception('Unknown flash IC. JEDEC id=%x:%x, size=%dx%d' % (jid0, jid1, blocks, blocksize)) raise Exception('Unknown flash IC. JEDEC id=%x:%x, size=%dx%d' %
(jid0, jid1, blocks, blocksize))
partitions = [rsp[i * 0xc:(i + 1) * 0xc] for i in range(0, pcnt)] partitions = [rsp[i * 0xc:(i + 1) * 0xc] for i in range(0, pcnt)]
partitions = [unpack('<BBHLL', i) for i in partitions] partitions = [unpack('<BBHLL', i) for i in partitions]
@ -41,6 +56,7 @@ def get_flash_info():
return FlashInfo(ic, blocks, unknown0, blocksize, unknown1, partitions) return FlashInfo(ic, blocks, unknown0, blocksize, unknown1, partitions)
# >>> 4302 -- get partition header (get fwext info) # >>> 4302 -- get partition header (get fwext info)
# b004 -- no fw detected # b004 -- no fw detected
# 0000 # 0000
@ -54,21 +70,26 @@ def get_flash_info():
# 0200 2377 0000 0100 802f0000 # 0200 2377 0000 0100 802f0000
# 0200 6637 0100 0c00 f0220200 # 0200 6637 0100 0c00 f0220200
# 0100 2556 0000 0100 60040000 # 0100 2556 0000 0100 60040000
class ModuleInfo(): class ModuleInfo:
def __init__(self, type, subtype, major, minor, size): def __init__(self, type: int, subtype: int, major: int, minor: int, size: int):
self.type, self.subtype, self.major, self.minor, self.size = type, subtype, major, minor, size self.type, self.subtype, self.major, self.minor, self.size = type, subtype, major, minor, size
def __repr__(self): def __repr__(self):
return 'ModuleInfo(0x%04x, 0x%04x, %d, %d, %d)' % (self.type, self.subtype, self.major, self.minor, self.size) return 'ModuleInfo(0x%04x, 0x%04x, %d, %d, %d)' % (self.type, self.subtype, self.major,
self.minor, self.size)
class FirmwareInfo():
def __init__(self, major, minor, buildtime, modules): class FirmwareInfo:
def __init__(self, major: int, minor: int, buildtime: int,
modules: typing.Sequence[ModuleInfo]):
self.major, self.minor, self.buildtime, self.modules = major, minor, buildtime, modules self.major, self.minor, self.buildtime, self.modules = major, minor, buildtime, modules
def __repr__(self): def __repr__(self):
return 'FirmwareInfo(%d, %d, %d, %s)' % (self.major, self.minor, self.buildtime, repr(self.modules)) return 'FirmwareInfo(%d, %d, %d, %s)' % (self.major, self.minor, self.buildtime,
repr(self.modules))
def get_fw_info(partition):
def get_fw_info(partition: int):
rsp = tls.cmd(pack('<BB', 0x43, partition)) rsp = tls.cmd(pack('<BB', 0x43, partition))
# don't want to throw exception here - it is normal not to have FW when we're about to upload it # don't want to throw exception here - it is normal not to have FW when we're about to upload it
@ -86,9 +107,11 @@ def get_fw_info(partition):
return FirmwareInfo(major, minor, buildtime, modules) return FirmwareInfo(major, minor, buildtime, modules)
def write_enable(): def write_enable():
assert_status(tls.cmd(db_write_enable)) assert_status(tls.cmd(db_write_enable))
def call_cleanups(): def call_cleanups():
rsp = tls.cmd(b'\x1a') rsp = tls.cmd(b'\x1a')
err = unpack('<H', rsp[:2])[0] err = unpack('<H', rsp[:2])[0]
@ -96,14 +119,16 @@ def call_cleanups():
return # don't throw an exception, just ignore return # don't throw an exception, just ignore
assert_status(rsp) assert_status(rsp)
def erase_flash(partition):
def erase_flash(partition: int):
assert_status(tls.cmd(db_write_enable)) assert_status(tls.cmd(db_write_enable))
try: try:
assert_status(tls.cmd(pack('<BB', 0x3f, partition))) assert_status(tls.cmd(pack('<BB', 0x3f, partition)))
finally: finally:
call_cleanups() call_cleanups()
def read_flash(partition, addr, size):
def read_flash(partition: int, addr: int, size: int) -> bytes:
cmd = pack('<BBBHLL', 0x40, partition, 1, 0, addr, size) cmd = pack('<BBBHLL', 0x40, partition, 1, 0, addr, size)
rsp = tls.cmd(cmd) rsp = tls.cmd(cmd)
assert_status(rsp) assert_status(rsp)
@ -111,7 +136,8 @@ def read_flash(partition, addr, size):
return rsp[8:8 + sz] return rsp[8:8 + sz]
def write_flash(partition, addr, buf):
def write_flash(partition: int, addr: int, buf: bytes):
tls.cmd(db_write_enable) tls.cmd(db_write_enable)
cmd = pack('<BBBHLL', 0x41, partition, 1, 0, addr, len(buf)) + buf cmd = pack('<BBBHLL', 0x41, partition, 1, 0, addr, len(buf)) + buf
try: try:
@ -120,21 +146,25 @@ def write_flash(partition, addr, buf):
finally: finally:
call_cleanups() call_cleanups()
def write_flash_all(partition, ptr, buf):
def write_flash_all(partition: int, ptr: int, buf: bytes):
bs = 0x1000 bs = 0x1000
while len(buf) > 0: while len(buf) > 0:
chunk, buf = buf[:bs], buf[bs:] chunk, buf = buf[:bs], buf[bs:]
write_flash(partition, ptr, chunk) write_flash(partition, ptr, chunk)
ptr += len(chunk) ptr += len(chunk)
def read_flash_all(partition, start, size):
def read_flash_all(partition: int, start: int, size: int):
bs = 0x1000 bs = 0x1000
blocks = [read_flash(partition, addr, bs) for addr in range(start, start + size, bs)] blocks = [read_flash(partition, addr, bs) for addr in range(start, start + size, bs)]
return b''.join(blocks)[:size] return b''.join(blocks)[:size]
def write_fw_signature(partition, signature):
def write_fw_signature(partition: int, signature: bytes):
rsp = tls.cmd(pack('<BBxH', 0x42, partition, len(signature)) + signature) rsp = tls.cmd(pack('<BBxH', 0x42, partition, len(signature)) + signature)
assert_status(rsp) assert_status(rsp)
def read_tls_flash(): def read_tls_flash():
return read_flash(1, 0, 0x1000) return read_flash(1, 0, 0x1000)

View file

@ -1,81 +1,775 @@
from .table_types import SensorTypeInfo, SensorCaptureProg from .table_types import SensorTypeInfo, SensorCaptureProg
SensorTypeInfo.table = [ SensorTypeInfo.table = [
SensorTypeInfo(sensor_type=0x00db, bytes_per_line=0x98, repeat_multiplier=1, lines_per_calibration_data=144, line_width=144, calibration_blob='101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f'), SensorTypeInfo(
SensorTypeInfo(sensor_type=0x00e4, bytes_per_line=0x78, repeat_multiplier=2, lines_per_calibration_data=100, line_width=112, calibration_blob='9392918f8e8d8b8a898786858382817f7e7d7b7a797776757372716f6e6d6b6a696766656362615f5e5d5b5a595756555251504e4d4c4a49484645444241403e3d3c3a39383635343231302e2d2c2a29282625242221201e1d1c1a19181615141211100e'), sensor_type=0x00db,
SensorTypeInfo(sensor_type=0x00ed, bytes_per_line=0x78, repeat_multiplier=2, lines_per_calibration_data=112, line_width=112, calibration_blob='9b9a999796959392918f8e8d8b8a898786858382817f7e7d7b7a797776757372716f6e6d6b6a696766656362615f5e5d5b5a595756555251504e4d4c4a49484645444241403e3d3c3a39383635343231302e2d2c2a29282625242221201e1d1c1a19181615141211100e0d0c0a090806'), bytes_per_line=0x98,
SensorTypeInfo(sensor_type=0x0199, bytes_per_line=0x78, repeat_multiplier=2, lines_per_calibration_data=112, line_width=112, calibration_blob='9b9a999796959392918f8e8d8b8a898786858382817f7e7d7b7a797776757372716f6e6d6b6a696766656362615f5e5d5b5a595756555251504e4d4c4a49484645444241403e3d3c3a39383635343231302e2d2c2a29282625242221201e1d1c1a19181615141211100e0d0c0a090806'), repeat_multiplier=1,
SensorTypeInfo(sensor_type=0x00b5, bytes_per_line=0x78, repeat_multiplier=2, lines_per_calibration_data=112, line_width=112, calibration_blob='9b9a999796959392918f8e8d8b8a898786858382817f7e7d7b7a797776757372716f6e6d6b6a696766656362615f5e5d5b5a595756555251504e4d4c4a49484645444241403e3d3c3a39383635343231302e2d2c2a29282625242221201e1d1c1a19181615141211100e0d0c0a090806'), lines_per_calibration_data=144,
SensorTypeInfo(sensor_type=0x0885, bytes_per_line=0x78, repeat_multiplier=2, lines_per_calibration_data=112, line_width=112, calibration_blob='9b9a999796959392918f8e8d8b8a898786858382817f7e7d7b7a797776757372716f6e6d6b6a696766656362615f5e5d5b5a595756555251504e4d4c4a49484645444241403e3d3c3a39383635343231302e2d2c2a29282625242221201e1d1c1a19181615141211100e0d0c0a090806'), line_width=144,
SensorTypeInfo(sensor_type=0x1055, bytes_per_line=0x78, repeat_multiplier=2, lines_per_calibration_data=112, line_width=112, calibration_blob='9b9a999796959392918f8e8d8b8a898786858382817f7e7d7b7a797776757372716f6e6d6b6a696766656362615f5e5d5b5a595756555251504e4d4c4a49484645444241403e3d3c3a39383635343231302e2d2c2a29282625242221201e1d1c1a19181615141211100e0d0c0a090806'), calibration_blob=
SensorTypeInfo(sensor_type=0x1825, bytes_per_line=0x78, repeat_multiplier=2, lines_per_calibration_data=112, line_width=112, calibration_blob='9b9a999796959392918f8e8d8b8a898786858382817f7e7d7b7a797776757372716f6e6d6b6a696766656362615f5e5d5b5a595756555251504e4d4c4a49484645444241403e3d3c3a39383635343231302e2d2c2a29282625242221201e1d1c1a19181615141211100e0d0c0a090806'), '101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f'
SensorTypeInfo(sensor_type=0x1ff5, bytes_per_line=0x78, repeat_multiplier=2, lines_per_calibration_data=112, line_width=112, calibration_blob='9b9a999796959392918f8e8d8b8a898786858382817f7e7d7b7a797776757372716f6e6d6b6a696766656362615f5e5d5b5a595756555251504e4d4c4a49484645444241403e3d3c3a39383635343231302e2d2c2a29282625242221201e1d1c1a19181615141211100e0d0c0a090806'), ),
SensorTypeInfo(sensor_type=0x00b3, bytes_per_line=0x60, repeat_multiplier=2, lines_per_calibration_data=84, line_width=85, calibration_blob='898786858382817f7e7d7b7a797776757372716f6e6d6b6a696766656362615f5e5d5b5a595756555251504e4d4c4a49484645444241403e3d3c3a39383635343231302e2d2c2a29282625242221201e1d1c1a19'), SensorTypeInfo(
SensorTypeInfo(sensor_type=0x143b, bytes_per_line=0x5c, repeat_multiplier=2, lines_per_calibration_data=84, line_width=84, calibration_blob='898786858382817f7e7d7b7a797776757372716f6e6d6b6a696766656362615f5e5d5b5a595756555251504e4d4c4a49484645444241403e3d3c3a39383635343231302e2d2c2a29282625242221201e1d1c1a19'), sensor_type=0x00e4,
SensorTypeInfo(sensor_type=0x08b1, bytes_per_line=0x58, repeat_multiplier=2, lines_per_calibration_data=78, line_width=78, calibration_blob='9b9a9996959392918f8e8d8b8a89878685837d7b7a7977767573716f6d6b6a695d5b5a595756555251504e4d4c4a41403e3d3c3a393432312c2a28261e1d1c1a19181615141211100d0c0a090806'), bytes_per_line=0x78,
SensorTypeInfo(sensor_type=0x00e1, bytes_per_line=0x58, repeat_multiplier=2, lines_per_calibration_data=78, line_width=78, calibration_blob='9b9a9996959392918f8e8d8b8a89878685837d7b7a7977767573716f6d6b6a695d5b5a595756555251504e4d4c4a41403e3d3c3a393432312c2a28261e1d1c1a19181615141211100d0c0a090806'), repeat_multiplier=2,
SensorTypeInfo(sensor_type=0x00ea, bytes_per_line=0x5c, repeat_multiplier=1, lines_per_calibration_data=84, line_width=84, calibration_blob='898786858382817f7e7d7b7a797776757372716f6e6d6b6a696766656362615f5e5d5b5a595756555251504e4d4c4a49484645444241403e3d3c3a39383635343231302e2d2c2a29282625242221201e1d1c1a19'), lines_per_calibration_data=100,
SensorTypeInfo(sensor_type=0x0194, bytes_per_line=0x7c, repeat_multiplier=3, lines_per_calibration_data=84, line_width=114, calibration_blob='000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f50515253'), line_width=112,
SensorTypeInfo(sensor_type=0x0126, bytes_per_line=0xa0, repeat_multiplier=2, lines_per_calibration_data=56, line_width=144, calibration_blob='0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40414243'), calibration_blob=
SensorTypeInfo(sensor_type=0x0117, bytes_per_line=0xa0, repeat_multiplier=4, lines_per_calibration_data=56, line_width=144, calibration_blob='0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40414243'), '9392918f8e8d8b8a898786858382817f7e7d7b7a797776757372716f6e6d6b6a696766656362615f5e5d5b5a595756555251504e4d4c4a49484645444241403e3d3c3a39383635343231302e2d2c2a29282625242221201e1d1c1a19181615141211100e'
SensorTypeInfo(sensor_type=0x08f3, bytes_per_line=0xa0, repeat_multiplier=1, lines_per_calibration_data=56, line_width=144, calibration_blob='0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40414243'), ),
SensorTypeInfo(sensor_type=0x08f6, bytes_per_line=0xa0, repeat_multiplier=1, lines_per_calibration_data=56, line_width=144, calibration_blob='0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40414243'), SensorTypeInfo(
SensorTypeInfo(sensor_type=0x0121, bytes_per_line=0xa0, repeat_multiplier=2, lines_per_calibration_data=56, line_width=144, calibration_blob='0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40414243'), sensor_type=0x00ed,
SensorTypeInfo(sensor_type=0x0b4b, bytes_per_line=0xa0, repeat_multiplier=2, lines_per_calibration_data=56, line_width=144, calibration_blob='0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40414243'), bytes_per_line=0x78,
SensorTypeInfo(sensor_type=0x0b4d, bytes_per_line=0xa0, repeat_multiplier=2, lines_per_calibration_data=56, line_width=144, calibration_blob='0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40414243'), repeat_multiplier=2,
SensorTypeInfo(sensor_type=0x0130, bytes_per_line=0xa0, repeat_multiplier=2, lines_per_calibration_data=40, line_width=144, calibration_blob='15161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3b'), lines_per_calibration_data=112,
SensorTypeInfo(sensor_type=0x0be2, bytes_per_line=0xa0, repeat_multiplier=2, lines_per_calibration_data=40, line_width=144, calibration_blob='15161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3b'), line_width=112,
SensorTypeInfo(sensor_type=0x0be1, bytes_per_line=0xa0, repeat_multiplier=2, lines_per_calibration_data=40, line_width=144, calibration_blob='15161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3b'), calibration_blob=
SensorTypeInfo(sensor_type=0x0518, bytes_per_line=0xa0, repeat_multiplier=2, lines_per_calibration_data=40, line_width=144, calibration_blob='15161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3b'), '9b9a999796959392918f8e8d8b8a898786858382817f7e7d7b7a797776757372716f6e6d6b6a696766656362615f5e5d5b5a595756555251504e4d4c4a49484645444241403e3d3c3a39383635343231302e2d2c2a29282625242221201e1d1c1a19181615141211100e0d0c0a090806'
SensorTypeInfo(sensor_type=0x0179, bytes_per_line=0x98, repeat_multiplier=3, lines_per_calibration_data=56, line_width=144, calibration_blob='3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172'), ),
SensorTypeInfo(
sensor_type=0x0199,
bytes_per_line=0x78,
repeat_multiplier=2,
lines_per_calibration_data=112,
line_width=112,
calibration_blob=
'9b9a999796959392918f8e8d8b8a898786858382817f7e7d7b7a797776757372716f6e6d6b6a696766656362615f5e5d5b5a595756555251504e4d4c4a49484645444241403e3d3c3a39383635343231302e2d2c2a29282625242221201e1d1c1a19181615141211100e0d0c0a090806'
),
SensorTypeInfo(
sensor_type=0x00b5,
bytes_per_line=0x78,
repeat_multiplier=2,
lines_per_calibration_data=112,
line_width=112,
calibration_blob=
'9b9a999796959392918f8e8d8b8a898786858382817f7e7d7b7a797776757372716f6e6d6b6a696766656362615f5e5d5b5a595756555251504e4d4c4a49484645444241403e3d3c3a39383635343231302e2d2c2a29282625242221201e1d1c1a19181615141211100e0d0c0a090806'
),
SensorTypeInfo(
sensor_type=0x0885,
bytes_per_line=0x78,
repeat_multiplier=2,
lines_per_calibration_data=112,
line_width=112,
calibration_blob=
'9b9a999796959392918f8e8d8b8a898786858382817f7e7d7b7a797776757372716f6e6d6b6a696766656362615f5e5d5b5a595756555251504e4d4c4a49484645444241403e3d3c3a39383635343231302e2d2c2a29282625242221201e1d1c1a19181615141211100e0d0c0a090806'
),
SensorTypeInfo(
sensor_type=0x1055,
bytes_per_line=0x78,
repeat_multiplier=2,
lines_per_calibration_data=112,
line_width=112,
calibration_blob=
'9b9a999796959392918f8e8d8b8a898786858382817f7e7d7b7a797776757372716f6e6d6b6a696766656362615f5e5d5b5a595756555251504e4d4c4a49484645444241403e3d3c3a39383635343231302e2d2c2a29282625242221201e1d1c1a19181615141211100e0d0c0a090806'
),
SensorTypeInfo(
sensor_type=0x1825,
bytes_per_line=0x78,
repeat_multiplier=2,
lines_per_calibration_data=112,
line_width=112,
calibration_blob=
'9b9a999796959392918f8e8d8b8a898786858382817f7e7d7b7a797776757372716f6e6d6b6a696766656362615f5e5d5b5a595756555251504e4d4c4a49484645444241403e3d3c3a39383635343231302e2d2c2a29282625242221201e1d1c1a19181615141211100e0d0c0a090806'
),
SensorTypeInfo(
sensor_type=0x1ff5,
bytes_per_line=0x78,
repeat_multiplier=2,
lines_per_calibration_data=112,
line_width=112,
calibration_blob=
'9b9a999796959392918f8e8d8b8a898786858382817f7e7d7b7a797776757372716f6e6d6b6a696766656362615f5e5d5b5a595756555251504e4d4c4a49484645444241403e3d3c3a39383635343231302e2d2c2a29282625242221201e1d1c1a19181615141211100e0d0c0a090806'
),
SensorTypeInfo(
sensor_type=0x00b3,
bytes_per_line=0x60,
repeat_multiplier=2,
lines_per_calibration_data=84,
line_width=85,
calibration_blob=
'898786858382817f7e7d7b7a797776757372716f6e6d6b6a696766656362615f5e5d5b5a595756555251504e4d4c4a49484645444241403e3d3c3a39383635343231302e2d2c2a29282625242221201e1d1c1a19'
),
SensorTypeInfo(
sensor_type=0x143b,
bytes_per_line=0x5c,
repeat_multiplier=2,
lines_per_calibration_data=84,
line_width=84,
calibration_blob=
'898786858382817f7e7d7b7a797776757372716f6e6d6b6a696766656362615f5e5d5b5a595756555251504e4d4c4a49484645444241403e3d3c3a39383635343231302e2d2c2a29282625242221201e1d1c1a19'
),
SensorTypeInfo(
sensor_type=0x08b1,
bytes_per_line=0x58,
repeat_multiplier=2,
lines_per_calibration_data=78,
line_width=78,
calibration_blob=
'9b9a9996959392918f8e8d8b8a89878685837d7b7a7977767573716f6d6b6a695d5b5a595756555251504e4d4c4a41403e3d3c3a393432312c2a28261e1d1c1a19181615141211100d0c0a090806'
),
SensorTypeInfo(
sensor_type=0x00e1,
bytes_per_line=0x58,
repeat_multiplier=2,
lines_per_calibration_data=78,
line_width=78,
calibration_blob=
'9b9a9996959392918f8e8d8b8a89878685837d7b7a7977767573716f6d6b6a695d5b5a595756555251504e4d4c4a41403e3d3c3a393432312c2a28261e1d1c1a19181615141211100d0c0a090806'
),
SensorTypeInfo(
sensor_type=0x00ea,
bytes_per_line=0x5c,
repeat_multiplier=1,
lines_per_calibration_data=84,
line_width=84,
calibration_blob=
'898786858382817f7e7d7b7a797776757372716f6e6d6b6a696766656362615f5e5d5b5a595756555251504e4d4c4a49484645444241403e3d3c3a39383635343231302e2d2c2a29282625242221201e1d1c1a19'
),
SensorTypeInfo(
sensor_type=0x0194,
bytes_per_line=0x7c,
repeat_multiplier=3,
lines_per_calibration_data=84,
line_width=114,
calibration_blob=
'000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f50515253'
),
SensorTypeInfo(
sensor_type=0x0126,
bytes_per_line=0xa0,
repeat_multiplier=2,
lines_per_calibration_data=56,
line_width=144,
calibration_blob=
'0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40414243'
),
SensorTypeInfo(
sensor_type=0x0117,
bytes_per_line=0xa0,
repeat_multiplier=4,
lines_per_calibration_data=56,
line_width=144,
calibration_blob=
'0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40414243'
),
SensorTypeInfo(
sensor_type=0x08f3,
bytes_per_line=0xa0,
repeat_multiplier=1,
lines_per_calibration_data=56,
line_width=144,
calibration_blob=
'0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40414243'
),
SensorTypeInfo(
sensor_type=0x08f6,
bytes_per_line=0xa0,
repeat_multiplier=1,
lines_per_calibration_data=56,
line_width=144,
calibration_blob=
'0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40414243'
),
SensorTypeInfo(
sensor_type=0x0121,
bytes_per_line=0xa0,
repeat_multiplier=2,
lines_per_calibration_data=56,
line_width=144,
calibration_blob=
'0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40414243'
),
SensorTypeInfo(
sensor_type=0x0b4b,
bytes_per_line=0xa0,
repeat_multiplier=2,
lines_per_calibration_data=56,
line_width=144,
calibration_blob=
'0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40414243'
),
SensorTypeInfo(
sensor_type=0x0b4d,
bytes_per_line=0xa0,
repeat_multiplier=2,
lines_per_calibration_data=56,
line_width=144,
calibration_blob=
'0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40414243'
),
SensorTypeInfo(
sensor_type=0x0130,
bytes_per_line=0xa0,
repeat_multiplier=2,
lines_per_calibration_data=40,
line_width=144,
calibration_blob=
'15161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3b'),
SensorTypeInfo(
sensor_type=0x0be2,
bytes_per_line=0xa0,
repeat_multiplier=2,
lines_per_calibration_data=40,
line_width=144,
calibration_blob=
'15161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3b'),
SensorTypeInfo(
sensor_type=0x0be1,
bytes_per_line=0xa0,
repeat_multiplier=2,
lines_per_calibration_data=40,
line_width=144,
calibration_blob=
'15161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3b'),
SensorTypeInfo(
sensor_type=0x0518,
bytes_per_line=0xa0,
repeat_multiplier=2,
lines_per_calibration_data=40,
line_width=144,
calibration_blob=
'15161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3b'),
SensorTypeInfo(
sensor_type=0x0179,
bytes_per_line=0x98,
repeat_multiplier=3,
lines_per_calibration_data=56,
line_width=144,
calibration_blob=
'3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172'
),
] ]
SensorCaptureProg.table = [ SensorCaptureProg.table = [
SensorCaptureProg(major=0x6, minor=0x0, build=0x0, u1=0x0, dev_type=0x0, a0=0x0, a1=0x0, blobs=['23000000320074000000008000200000502077322820020030200000082110000c211000482105004c2105002020000024200000582000005c20000060204300682014006c2001247020012c842020008c20900190202c01942001809c200902a0200b19b4200000b8203a00bc201400c0200200c4200200c82008003300100000000080cc200000a101d0200000a10132004c0000000080dc20e803e0206401e420d002e8200001ec201400f0200500fc200000b8203a00140800000008040008080000080802001408300008080300140831001c081a004c11240050110000', '2a00080020010100100100002c002800802080200000000000013f4000000000080f080f00000000279c1000279c10000000000000000000340040000300000007160000240a59085a0701c9500aaa07010ada08db0701c9460b2107010800800a0088c9590a5a07010aa908aa0701c91f0ac900000c040100000000', '29000400000000003500040000000000']), SensorCaptureProg(
SensorCaptureProg(major=0x6, minor=0x6, build=0x0, u1=0x0, dev_type=0x0, a0=0x0, a1=0x0, blobs=['23000000320074000000008000200000502077322820020030200000082110000c211000482105004c2105002020000024200000582000005c20000060204300682014006c2001247020012c842020008c20900190202c01942001809c200902a0200b19b4200000b8203a00bc201400c0200200c4200200c82008003300100000000080cc200000a101d0200000a10132004c0000000080dc20e803e0206401e420d002e8200001ec201400f0200500fc200000b8203a00140800000008040008080000080802001408300008080300140831001c081a004c11240050110000', '2a00080020010100100100002c002800802080200000000000013f4000000000080f080f00000000279c1000279c10000000000000000000340040000300000007160000240a59085a0701c9500aaa07010ada08db0701c9460b2107010800800a0088c9590a5a07010aa908aa0701c91f0ac900000c040100000000', '29000400000000003500040000000000']), major=0x6,
SensorCaptureProg(major=0x6, minor=0x7, build=0x0, u1=0x0, dev_type=0x0, a0=0x0, a1=0x0, blobs=['23000000320074000000008000200000502077322820020030200000082110000c211000482105004c2105002020000024200000582000005c20000060204300682014006c2001247020012c842020008c20900190202c01942001809c200902a0200b19b4200000b8203a00bc201400c0200200c4200200c82008003300100000000080cc200000a101d0200000a10132004c0000000080dc20e803e0206401e420d002e8200001ec201400f0200500fc200000b8203a00140800000008040008080000080802001408300008080300140831001c081a004c11240050110000', '2a00080020010100100100002c002800802080200000000000013f4000000000080f080f00000000279c1000279c10000000000000000000340040000300000007160000240a59085a0701c9500aaa07010ada08db0701c9460b2107010800800a0088c9590a5a07010aa908aa0701c91f0ac900000c040100000000', '29000400000000003500040000000000']), minor=0x0,
SensorCaptureProg(major=0x6, minor=0x8, build=0x0, u1=0x0, dev_type=0x0, a0=0x0, a1=0x0, blobs=['23000000320074000000008000200000502077322820020030200000082110000c211000482105004c2105002020000024200000582000005c20000060204300682014006c2001247020012c842020008c20900190202c01942001809c200902a0200b19b4200000b8203a00bc201400c0200200c4200200c82008003300100000000080cc200000a101d0200000a10132004c0000000080dc20e803e0206401e420d002e8200001ec201400f0200500fc200000b8203a00140800000008040008080000080802001408300008080300140831001c081a004c11240050110000', '2a00080020010100100100002c002800802080200000000000013f4000000000080f080f00000000279c1000279c10000000000000000000340040000300000007160000240a59085a0701c9500aaa07010ada08db0701c9460b2107010800800a0088c9590a5a07010aa908aa0701c91f0ac900000c040100000000', '29000400000000003500040000000000']), build=0x0,
SensorCaptureProg(major=0x6, minor=0xa, build=0x0, u1=0x0, dev_type=0x0, a0=0x0, a1=0x0, blobs=['230000003200680000000080002000002020000024200000382000002820df0b2c20df0b302000003420000050200a005c20000064204300602000004c2000006c20100070201000742005007820050084202000b4200000b8203b00bc201400c0200200c4200100c82002007403000233001c000000008054202a2203005820272f0300cc200000ef03d0200000ef033200480000000080dc20fa00e020fa00e420b400e820b400f0200500f8200500b8203b00002804001428000008280000082800001428300008280000142831001c281a006411240068110000', '2a00080020010100100100002c002800802080200000000000013f4000000000080f080f00000000279c1000279c10000000000000000000340040000300000007160000240a59085a0701c9500aaa07010ada08db0701c9460b2107010800800a0088c9590a5a07010aa908aa0701c91f0ac900000c040100000000', '29000400000000003500040000000000']), u1=0x0,
SensorCaptureProg(major=0x6, minor=0xb, build=0x0, u1=0x0, dev_type=0x0, a0=0x0, a1=0x0, blobs=['230000003200680000000080002000002020000024200000382000002820df0b2c20df0b302000003420000050200a005c20000064204300602000004c2000006c20100070201000742005007820050084202000b4200000b8203b00bc201400c0200200c4200100c82002007403000233001c000000008054202a2203005820272f0300cc200000ef03d0200000ef033200480000000080dc20fa00e020fa00e420b400e820b400f0200500f8200500b8203b00002804001428000008280000082800001428300008280000142831001c281a006411240068110000', '2a00080020010100100100002c002800802080200000000000013f4000000000080f080f00000000279c1000279c10000000000000000000340040000300000007160000240a59085a0701c9500aaa07010ada08db0701c9460b2107010800800a0088c9590a5a07010aa908aa0701c91f0ac900000c040100000000', '29000400000000003500040000000000']), dev_type=0x0,
SensorCaptureProg(major=0x6, minor=0x14, build=0x0, u1=0x0, dev_type=0x0, a0=0x0, a1=0x0, blobs=['230000003200680000000080002000002020000024200000382000002820df0b2c20df0b302000003420000050200a005c20000064204300602000004c2000006c20100070201000742005007820050084202000b4200000b8203b00bc201400c0200200c4200100c82002007403000233001c000000008054202a2203005820272f0300cc200000ef03d0200000ef033200480000000080dc20fa00e020fa00e420b400e820b400f0200500f8200500b8203b00002804001428000008280000082800001428300008280000142831001c281a006411240068110000', '2a00080020010100100100002c002800802080200000000000013f4000000000080f080f00000000279c1000279c10000000000000000000340040000300000007160000240a59085a0701c9500aaa07010ada08db0701c9460b2107010800800a0088c9590a5a07010aa908aa0701c91f0ac900000c040100000000', '29000400000000003500040000000000']), a0=0x0,
SensorCaptureProg(major=0x6, minor=0x6, build=0x0, u1=0x0, dev_type=0x885, a0=0x18, a1=0x19, blobs=['23000000200008000020008000000100320074000000008020200400242000005020773628200100302001003c208000082150000c210000482105004c210000582000005c2000006020000068200a006c20014970200141742001887820018084202000942001809c200902a0200b19b4200300b8203b04bc201400c0200200c4200100c82002003300100000000080cc200000f503d0200000a1013200440000000080dc20e803e0206401e420d002e8200001f0200500f8200500fc200000b8203a00000804001408000008080000080800001408300008080000140831001c081a00', '32000c0000000080501101004c111e00340070010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010221710221710221610221610221601066310250101000007c8078c06ff4f80006d0300200307030b90098db08d099186890b9108c180910ac190ba2c928f099382890b938889898908c881910ac8888a9189099a82890b9a8889898908d081910ad0888a9189080282890a02095a80890b5a888908d981890ad98891898a095e81890b5e8889898908e181890ae18891898a096481890b64888989096e8108e9810b6e880ae9889191ba096f828f0b6f8889918908f082890af08891898a097681890b7690b9928f08f882910af8908a8a91097c818a0b7c88090181890b018889892491097f818a0b7f900908818a0b0890898a910c0703030720040200002f0004007000000029000400700000003500040080000000']), a1=0x0,
SensorCaptureProg(major=0x6, minor=0x7, build=0x0, u1=0x0, dev_type=0x885, a0=0x18, a1=0x19, blobs=['23000000200008000020008000000100320074000000008020200400242000005020773628200100302001003c208000082150000c210000482105004c210000582000005c2000006020000068200a006c20014970200141742001887820018084202000942001809c200902a0200b19b4200300b8203b04bc201400c0200200c4200100c82002003300100000000080cc200000f503d0200000a1013200440000000080dc20e803e0206401e420d002e8200001f0200500f8200500fc200000b8203a00000804001408000008080000080800001408300008080000140831001c081a00', '32000c0000000080501101004c111e00340070010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010221710221710221610221610221601066310250101000007c8078c06ff4f80006d0300200307030b90098db08d099186890b9108c180910ac190ba2c928f099382890b938889898908c881910ac8888a9189099a82890b9a8889898908d081910ad0888a9189080282890a02095a80890b5a888908d981890ad98891898a095e81890b5e8889898908e181890ae18891898a096481890b64888989096e8108e9810b6e880ae9889191ba096f828f0b6f8889918908f082890af08891898a097681890b7690b9928f08f882910af8908a8a91097c818a0b7c88090181890b018889892491097f818a0b7f900908818a0b0890898a910c0703030720040200002f0004007000000029000400700000003500040080000000']), blobs=[
SensorCaptureProg(major=0x6, minor=0x0, build=0x0, u1=0x0, dev_type=0x1055, a0=0x18, a1=0x19, blobs=['23000000200008000020008000000100320074000000008020200400242000005020773628200100302001003c208000082138000c210000482103004c210000582000005c20000060200000682005006c20014970200141742001887820018084202000942001809c200902a0200b19b4200300b8203b04bc201400c0200200c4200100c82002003300100000000080cc200000f503d0200000a1013200440000000080dc20e803e0206401e420d002e8200001f0200500f8200500fc200000b8203a00000804001408000008080000080800001408300008080000140831001c081a00', '32000c0000000080501101004c111e00340070010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010221710221710221610221610221601066310250101000007c8078c06ff4f80006d0300200307030b90098db08d099186890b9108c180910ac190ba2c928f099382890b938889898908c881910ac8888a9189099a82890b9a8889898908d081910ad0888a9189080282890a02095a80890b5a888908d981890ad98891898a095e81890b5e8889898908e181890ae18891898a096481890b64888989096e8108e9810b6e880ae9889191ba096f828f0b6f8889918908f082890af08891898a097681890b7690b9928f08f882910af8908a8a91097c818a0b7c88090181890b018889892491097f818a0b7f900908818a0b0890898a910c0703030720040200002f0004007000000029000400700000003500040080000000']), '23000000320074000000008000200000502077322820020030200000082110000c211000482105004c2105002020000024200000582000005c20000060204300682014006c2001247020012c842020008c20900190202c01942001809c200902a0200b19b4200000b8203a00bc201400c0200200c4200200c82008003300100000000080cc200000a101d0200000a10132004c0000000080dc20e803e0206401e420d002e8200001ec201400f0200500fc200000b8203a00140800000008040008080000080802001408300008080300140831001c081a004c11240050110000',
SensorCaptureProg(major=0x6, minor=0x0, build=0x0, u1=0x0, dev_type=0x1825, a0=0x18, a1=0x19, blobs=['23000000200008000020008000000100320074000000008020200400242000005020773628200100302001003c208000082138000c210000482108004c210000582000005c20000060200000682005006c20014970200141742001887820018084202000942001809c200902a0200b19b4200300b8203b04bc201400c0200200c4200100c82002003300100000000080cc200000f503d0200000a1013200440000000080dc20e803e0206401e420d002e8200001f0200500f8200500fc200000b8203a00000804001408000008080000080800001408300008080000140831001c081a00', '32000c0000000080501101004c111e00340074010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010221710221710221610221610221601062810250101000007c8078c06ff4f80006d0300200307030990098db00b90880991858e08c1810b9190910ac1b828928a0993878a890b9388898908c88191890ac8889289099a818a890b9a88898908d08191890ad08892890802818a095a810a0288890b5a8808d98189890ad9908989095e8289890b5e88898908e18189890ae190898909648289890b648889096e8108e981890b6e880ae99091b9096f828a8f0b6f88918908f0818a890af090898909768289910b76b8918a08f88792910af8888a92097c81898a0b7c09018089890b01888991097f812089920b7f09088089920b088889920c07030307200402000000002f0004007000000029000400700000003500040080000000']), '2a00080020010100100100002c002800802080200000000000013f4000000000080f080f00000000279c1000279c10000000000000000000340040000300000007160000240a59085a0701c9500aaa07010ada08db0701c9460b2107010800800a0088c9590a5a07010aa908aa0701c91f0ac900000c040100000000',
SensorCaptureProg(major=0x6, minor=0x0, build=0x0, u1=0x0, dev_type=0xb5, a0=0x18, a1=0x19, blobs=['23000000200008000020008000000100320074000000008020200400242000005020773628200100302001003c208000082138000c210000482106004c210000582000005c20000060200000682005006c20014970200141742001887820018084202000942001809c200902a0200b19b4200300b8203b04bc201400c0200200c4200100c82002003300100000000080cc200000f503d0200000a1013200440000000080dc20e803e0206401e420d002e8200001f0200500f8200500fc200000b8203a00000804001408000008080000080800001408300008080000140831001c081a00', '32000c0000000080501101004c111e0034007801000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001023171023171023161023161023160106635205001025010100000007c8078c06ff00004f80006d0300280307030990098db00b90880991858e08c1810b9190910ac1b8928a0993878a890b9388898908c88191890ac8889289099a818a890b9a88898908d08191890ad08892890802818a095a810a0288890b5a8808d98189890ad9908989095e8289890b5e88898908e18189890ae190898909648289890b648889096e8108e981890b6e880ae99091b9096f828a8f0b6f88918908f0818a890af090898909768289910b76b8918a08f88792910af8888a92097c81898a0b7c09018089890b01888991097f8189920b7f09088089920b088889920c07030307200402000000002f0004007000000029000400700000003500040080000000']), '29000400000000003500040000000000'
SensorCaptureProg(major=0x6, minor=0x0, build=0x0, u1=0x0, dev_type=0x1ff5, a0=0x18, a1=0x19, blobs=['23000000200008000020008000000100320074000000008020200400242000005020773628200100302001003c208000082138000c210000482106004c210000582000005c20000060200000682005006c20014970200141742001887820018084202000942001809c200902a0200b19b4200300b8203b04bc201400c0200200c4200100c82002003300100000000080cc200000f503d0200000a1013200440000000080dc20e803e0206401e420d002e8200001f0200500f8200500fc200000b8203a00000804001408000008080000080800001408300008080000140831001c081a00', '32000c0000000080501101004c111e00340074010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010221710221710221610221610221601062810250101000007c8078c06ff4f80006d0300200307030990098db00b90880991858e08c1810b9190910ac1b828928a0993878a890b9388898908c88191890ac8889289099a818a890b9a88898908d08191890ad08892890802818a095a810a0288890b5a8808d98189890ad9908989095e8289890b5e88898908e18189890ae190898909648289890b648889096e8108e981890b6e880ae99091b9096f828a8f0b6f88918908f0818a890af090898909768289910b76b8918a08f88792910af8888a92097c81898a0b7c09018089890b01888991097f812089920b7f09088089920b088889920c07030307200402000000002f0004007000000029000400700000003500040080000000']), ]),
SensorCaptureProg(major=0x6, minor=0x7, build=0x0, u1=0x0, dev_type=0x1825, a0=0x18, a1=0x19, blobs=['23000000200008000020008000000100320074000000008020200400242000005020773628200100302001003c208000082138000c210000482108004c210000582000005c20000060200000682005006c20014970200141742001887820018084202000942001809c200902a0200b19b4200300b8203b04bc201400c0200200c4200100c82002003300100000000080cc200000f503d0200000a1013200440000000080dc20e803e0206401e420d002e8200001f0200500f8200500fc200000b8203a00000804001408000008080000080800001408300008080000140831001c081a00', '32000c0000000080501101004c111e00340074010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010221710221710221610221610221601065010240101000007c8078c06ff00004f80006d0300280307030990098db00b90880991858e08c1810b9190910ac1b8928a0993878a890b9388898908c88191890ac8889289099a818a890b9a88898908d08191890ad08892890802818a095a810a0288890b5a8808d98189890ad9908989095e8289890b5e88898908e18189890ae190898909648289890b648889096e8108e981890b6e880ae99091b9096f828a8f0b6f88918908f0818a890af090898909768289910b76b8918a08f88792910af8888a92097c81898a0b7c09018089890b01888991097f8189920b7f09088089920b088889920c07030307200402000000002f0004007000000029000400700000003500040080000000']), SensorCaptureProg(
SensorCaptureProg(major=0x6, minor=0x0, build=0x0, u1=0x0, dev_type=0xe4, a0=0x18, a1=0x19, blobs=['23000000200008000020008000000100320070000000008020200400242000005020773628200100302001003c208000082138000c210000482108004c210000582000005c20000060200000682005006c20014970200141742001887820018084202000942001809c200902a0200b19b4200300bc201400c0200200c4200100c82002003300100000000080cc200000f503d0200000a1013200440000000080dc20e803e0206401e420d002e8200001f0200500f8200500fc200000b8203a00000804001408000008080000080800001408300008080000140831001c081a00', '32000c0000000080501101004c111e00340070010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010221410221410221410221410221401066510250101000007c8078c06ff4f80006d0300280307030990098db00b90880991858e08c1810b9190910ac1b8928a0993878a890b9388898908c88191890ac8889289099a818a890b9a88898908d08191890ad08892890802818a095a810a0288890b5a8808d98189890ad9908989095e8289890b5e88898908e18189890ae190898909648289890b648889096e8108e981890b6e880ae99091b9096f828a8f0b6f88918908f0818a890af090898909768289910b76b8918a08f88792910af8888a92097c81898a0b7c09018089890b01888991097f8189920b7f09088089920b088889920c0703030720040200002f0004006400000029000400700000003500040080000000']), major=0x6,
SensorCaptureProg(major=0x6, minor=0x0, build=0x0, u1=0x0, dev_type=0xed, a0=0x18, a1=0x19, blobs=['23000000200008000020008000000100320074000000008020200400242000005020773628200100302001003c208000082138000c210000482104004c210000582000005c20000060200000682005006c20014970200141742001887820018084202000942001809c200902a0200b19b4200300b8203b04bc201400c0200200c4200100c82002003300100000000080cc200000f503d0200000a1013200440000000080dc20e803e0206401e420d002e8200001f0200500f8200500fc200000b8203a00000804001408000008080000080800001408300008080000140831001c081a00', '32000c0000000080501101004c111e00340074010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010221710221710221610221610221601065010240101000007c8078c06ff00004f80006d0300280307030990098db00b90880991858e08c1810b9190910ac1b8928a0993878a890b9388898908c88191890ac8889289099a818a890b9a88898908d08191890ad08892890802818a095a810a0288890b5a8808d98189890ad9908989095e8289890b5e88898908e18189890ae190898909648289890b648889096e8108e981890b6e880ae99091b9096f828a8f0b6f88918908f0818a890af090898909768289910b76b8918a08f88792910af8888a92097c81898a0b7c09018089890b01888991097f8189920b7f09088089920b088889920c07030307200402000000002f0004007000000029000400700000003500040080000000']), minor=0x6,
SensorCaptureProg(major=0x6, minor=0x7, build=0x0, u1=0x0, dev_type=0x143b, a0=0x18, a1=0x19, blobs=['23000000200008000020008000000100320070000000008020200400242000005020773628200100302001003c208000082138000c210000482108004c210000582000005c2000006020000068200a006c20014970200141742001887820018084202000942001809c200902a0200b19b4200300bc201400c0200200c4200100c82002003300100000000080cc200000d600d0200000a1013200440000000080dc20e803e0206401e420d002e8200001f0200500f8200500fc200000b8203a00000804001408000008080000080800001408300008080000140831001c081a00', '32000c0000000080501101004c1117003400340200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101c11101c11101c11101c11101c10010657101e0101000007c8078c06ff00004f80006d03002c03070308c608c709930703800ac60994800ac70995800b930996800b940997800b950998800b9608c8800b9708ca800b9808cb800ac808cc800aca08ce800acb08cf800acc099a800ace099b800acf099c800b9a099d800b9b099e800b9c099f800b9d08d0800b9e08d2800b9f08d3800ad008d4800ad208d6800ad308d7800ad40802800ad60803800ad7095a800a02095b800a03095c800b5a095d800b5b08d9800b5c08da800b5d08db800ad908dd800ada08de800adb08df800add095e800ade095f800adf0960800b5e0961800b5f0962800b600963800b6108e1800b6208e2800b6308e3800ae108e5800ae208e6800ae308e7800ae50964800ae60965800ae70966800b640967800b650968800b66096e800b6708e9800b6808ea800b6e08eb800ae908ed800aea08ef800aeb08ee800aed096f800aef0970800aee0971800b6f0972800b700974800b710975800b7208f0800b7408f1800b7508f2800af008f4800af108f5800af208f6800af40976800af50977800af60979800b760978800b77097a800b79097b800b7808f8800b7a08fa800b7b08fc800af808fd800afa08fe800afc0900800c2007030307200402002f0004005400000029000400580000003500040068000000']), build=0x0,
SensorCaptureProg(major=0x6, minor=0x7, build=0x0, u1=0x0, dev_type=0xb3, a0=0x18, a1=0x19, blobs=['23000000200008000020008000000100320070000000008020200400242000005020773628200100302001003c208000082140000c210000482106004c210000582000005c2000006020000068200a006c20012970200121742001887820018084202000942001809c200902a0200b19b4200300bc201400c0200100c4200100c82002003300100000000080cc2000002c01d0200000a1013200440000000080dc205302e0206401e420a901e8200001f0200500f8200500fc200000b8203a00000804001408000008080000080800001408300008080000140831001c081a00', '32000c0000000080501101004c11180034003c0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101c11101c11101c11101c11101c10010657101e0101000007c8078c06ff00004f80006d03002c0308c608c70703800ac60993800ac70994800b930995800b940996800b950997800b960998800b9708c8800b9808ca800ac808cb800aca08cc800acb08ce800acc08cf800ace099a800acf099b800b9a099c800b9b099d800b9c099e800b9d099f800b9e08d0800b9f08d2800ad008d3800ad208d4800ad308d6800ad408d7800ad60802800ad70803800a02095a800a03095b800b5a095c800b5b095d800b5c08d9800b5d08da800ad908db800ada08dd800adb08de800add08df800ade095e800adf095f800b5e0960800b5f0961800b600962800b610963800b6208e1800b6308e2800ae108e3800ae208e5800ae308e6800ae508e7800ae60964800ae70965800b640966800b650967800b660968800b67096e800b6808e9800b6e08ea800ae908eb800aea08ed800aeb08ef800aed08ee800aef096f800aee0970800b6f0971800b700972800b710974800b720975800b7408f0800b7508f1800af008f2800af108f4800af208f5800af408f6800af50976800af60977800b760979800b770978800b79097a800b78097b800b7a08f8800b7b08fa800af808fc800afa08fd800afc08fe800afd090080808080240c0703030720040200000000002f0004005400000029000400580000003500040068000000']), u1=0x0,
SensorCaptureProg(major=0x6, minor=0x0, build=0x0, u1=0x0, dev_type=0xe1, a0=0x18, a1=0x19, blobs=['2300000020000800002000800000010032006c000000008020200400242000005020773628200100302001003c208000082138000c210000482105004c210000582000005c2000006020000068200a006c20014970200141742001887820018084203000942001809c200902a0200b19bc201400c0200200c4200100c82002003300100000000080cc2000006401d0200000a1013200440000000080dc20e803e0206401e420d002e8200001f0200500f8200500fc200000b8203b00000804001408000008080000080800001408300008080000140831001c081a00', '32000c0000000080501101004c11160034001402000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101b10101b10101b10101b0f101b0f010656101e0101000007c8078c06ff4f80006d03002c03070308c108bf098f0703800ac10990800abf098d800b8f0991800b900992800b8d08c5800b9108c3800b9208c6800ac508c4800ac308cb800ac608c7800ac40993800acb0994800ac70995800b930997800b940996800b950998800b9708ce800b9608cc800b9808cf800ace08d0800acc08d2800acf08dd800ad0099a800ad2099b800add099c800b9a0803800b9b095a800b9c095b800a0308de800b5a08df800b5b08e1800ade08eb800adf08ed800ae108f1800aeb095c800aed0962800af10963800b5c096f800b620970800b630971800b6f08f2800b7008f5800b7108f6800af208fa800af508f8800af608fc800afa0974800af80976800afc097b800b74097a800b76097f800b7b097e800b7a08fd800b7f08fe800b7e090b800afd090c800afe090d800b0b090f800b0c0980800b0d0982800b0f0983800b80097d800b820978800b83097c800b7d0914800b780908800b7c0909800b140907800b080905800b090904800b070979800b050977800b040975800b790972800b77096c800b750936800b7209348080800c20070303072004020000002f0004004e00000029000400540000003500040064000000']), dev_type=0x0,
SensorCaptureProg(major=0x6, minor=0x0, build=0x0, u1=0x0, dev_type=0x8b1, a0=0x18, a1=0x19, blobs=['2300000020000800002000800000010032006c000000008020200400242000005020773628200100302001003c208000082138000c210000482107004c210000582000005c2000006020000068200a006c20014970200141742001887820018084203000942001809c200902a0200b19bc201400c0200200c4200100c82002003300100000000080cc2000002c00d0200000a1013200440000000080dc20e803e0206401e420d002e8200001f0200500f8200500fc200000b8203a00000804001408000008080000080800001408300008080000140831001c081a00', '32000c0000000080501101004c11160034001402000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101b10101b10101b10101b0f101b0f010656101e0101000007c8078c06ff4f80006d03002c03070308c108bf098f0703800ac10990800abf098d800b8f0991800b900992800b8d08c5800b9108c3800b9208c6800ac508c4800ac308cb800ac608c7800ac40993800acb0994800ac70995800b930997800b940996800b950998800b9708ce800b9608cc800b9808cf800ace08d0800acc08d2800acf08dd800ad0099a800ad2099b800add099c800b9a0803800b9b095a800b9c095b800a0308de800b5a08df800b5b08e1800ade08eb800adf08ed800ae108f1800aeb095c800aed0962800af10963800b5c096f800b620970800b630971800b6f08f2800b7008f5800b7108f6800af208fa800af508f8800af608fc800afa0974800af80976800afc097b800b74097a800b76097f800b7b097e800b7a08fd800b7f08fe800b7e090b800afd090c800afe090d800b0b090f800b0c0980800b0d0982800b0f0983800b80097d800b820978800b83097c800b7d0914800b780908800b7c0909800b140907800b080905800b090904800b070979800b050977800b040975800b790972800b77096c800b750936800b7209348080800c20070303072004020000002f0004004e00000029000400540000003500040064000000']), a0=0x0,
SensorCaptureProg(major=0x6, minor=0x0, build=0x0, u1=0x0, dev_type=0xea, a0=0x18, a1=0x19, blobs=['23000000200008000020008000000100320070000000008020200400242000005020773628200100302001003c208000082138000c210000482106004c210000582000005c2000006020000068200a006c20014970200141742001887820018084202000942001809c200902a0200b19b4200300bc201400c0200200c4200100c82002003300100000000080cc200000d600d0200000a1013200440000000080dc20e803e0206401e420d002e8200001f0200500f8200500fc200000b8203b00000804001408000008080000080800001408300008080000140831001c081a00', '32000c0000000080501101004c11170034003002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101b11101b11101b11101b11101b1001064d101d0101000007c8078c06ff00004f80006d03002c03070308c608c709930703800ac60994800ac70995800b930996800b940997800b950998800b9608c8800b9708ca800b9808cb800ac808cc800aca08ce800acb08cf800acc099a800ace099b800acf099c800b9a099d800b9b099e800b9c099f800b9d08d0800b9e08d2800b9f08d3800ad008d4800ad208d6800ad308d7800ad40802800ad60803800ad7095a800a02095b800a03095c800b5a095d800b5b08d9800b5c08da800b5d08db800ad908dd800ada08de800adb08df800add095e800ade095f800adf0960800b5e0961800b5f0962800b600963800b6108e1800b6208e2800b6308e3800ae108e5800ae208e6800ae308e7800ae50964800ae60965800ae70966800b640967800b650968800b66096e800b6708e9800b6808ea800b6e08eb800ae908ed800aea08ef800aeb08ee800aed096f800aef0970800aee0971800b6f0972800b700974800b710975800b7208f0800b7408f1800b7508f2800af008f4800af108f5800af208f6800af40976800af50977800af60979800b760978800b77097a800b79097b800b7808f8800b7a08fa800b7b08fc800af808fd800afa08fe800afc0900800c2007030307200402002f0004005400000029000400540000003500040064000000']), a1=0x0,
SensorCaptureProg(major=0x6, minor=0x0, build=0x0, u1=0x0, dev_type=0x199, a0=0x18, a1=0x19, blobs=['23000000200008000020008000000100320074000000008020200400242000005020773628200100302001003c208000082138000c210000482107004c210000582000005c20000060200000682005006c20014970200141742001887820018084202000942001809c200902a0200b19b4200300b8203b04bc201400c0200200c4200100c82002003300100000000080cc200000f503d0200000a1013200440000000080dc20e803e0206401e420d002e8200001f0200500f8200500fc200000b8203a00000804001408000008080000080800001408300008080000140831001c081a00', '32000c0000000080501101004c111e00340078010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010221710221710221610221610221601065010250101000007c8078c06ff0000000000004f80006d0300280307030990098db00b90880991858e08c1810b9190910ac1b8928a0993878a890b9388898908c88191890ac8889289099a818a890b9a88898908d08191890ad08892890802818a095a810a0288890b5a8808d98189890ad9908989095e8289890b5e88898908e18189890ae190898909648289890b648889096e8108e981890b6e880ae99091b9096f828a8f0b6f88918908f0818a890af090898909768289910b76b8918a08f88792910af8888a92097c81898a0b7c09018089890b01888991097f8189920b7f09088089920b088889920c07030307200402000000002f0004007000000029000400700000003500040080000000']), blobs=[
SensorCaptureProg(major=0x6, minor=0x14, build=0x0, u1=0x0, dev_type=0x8f3, a0=0x18, a1=0x19, blobs=['2300000020000800002000800000010032006000000000802020040024200000382000002820df0b2c20df0b302000003420000050200a015c200000602000004c2003006c20700070207000742001007820010084202000b4200000bc201400c0200200c4200100c820020074030002a0030000330028000000008054202a2203005820272f03004420898103004820868e0300cc200000ef03d0200000ef033200400000000080dc20fa00e020fa00e420b400e820b400f0200500f8200500b8203a00002804001428000008280000082800001428300008280000142831001c281a00', '330064030000008064200000a10c642000109f0c64200020a20c642000309e0c64200040a30c642000509d0c64200060a40c642000709c0c64200080a60c642000909b0c642000a0a70c642000b09a0c642000c0a80c642000d0990c642000e0a90c642000f0980c64200000af0c64200010950c64200020b00c64200030940c64200040b10c64200050930c64200060b20c64200070920c64200080b30c642000908b0c642000a0b70c642000b08a0c642000c0b80c642000d0890c642000e0b90c642000f0880c64200000ba0c64200010870c64200020bb0c64200030810c64200040bf0c64200050800c64200060c00c642000707f0c64200080c10c642000907e0c642000a0c20c642000b07d0c642000c0c50c642000d0720c642000e0c60c642000f0710c64200000c70c64200010700c64200020c80c642000306f0c64200040c90c64200050630c642000606c0c64200070620c642000806b0c64200090610c642000a06a0c642000b0600c642000c0690c642000d05f0c642000e05e0c642000f04f0c642000005d0c642000104e0c642000205c0c642000304d0c642000405b0c642000504c0c642000605a0c642000704b0c64200080310c642000904a0c642000a0300c642000b0490c642000c02f0c642000d0480c642000e02e0c642000f0470c642000002d0c64200010460c64200020ca0c642000303b0c64200040cb0c642000503a0c64200060cc0c64200070390c64200080cd0c64200090380c642000a0ce0c642000b02c0c642000c0d10c642000d02b0c642000e0d20c642000f02a0c64200000d30c64200010290c64200020d60c64200030280c64200040d70c642000501d0c64200060d80c642000701c0c64200080d90c642000901b0c642000a0da0c642000b01a0c642000c0de0c642000d0190c642000e0df0c642000f0150c64200000e00c64200010140c64200020e10c64200030130c64200040e20c64200050120c64200060e40c64200070110c64200080e50c642000900d0c642000a0e60c642000b00c0c642000c0e70c642000d00b0c642000e0e80c642000f00a0c64200000ea0c64200010070c64200020eb0c64200030060c64200040ec0c64200050050c64200060ed0c64200070040c64200080ee0c64200090030c642000a0ef0c642000b0020c642000c0f00c642000d0010c642000e0f10c642000f0000c', '32000c000000008068110100641126003400180200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007e007e0102a13102a13102a12010000061e102d0101000007c8078c060b5d00005e00004f80005080006d030059940b070100002403089808a9089908a8089a08a7089b08a6089c08a4089d08a3089e08a2089f08a1c0102c03088808b9088908b8088a08b7088b08b3089208b2089308b1089408b0089508afc01003087108c6087208c5087d08c2087e08c1087f08c0088008bf088108bb088708bac0100628070103084f085e085f08690860086a0861086b0862086c086308c9086f08c8087008c7c010030847082e0848082f08490830084a0831084b085a084c085b084d085c084e085dc01003082a08d2082b08d1082c08ce083808cd083908cc083a08cb083b08ca0846082dc0100632070103081508df081908de081a08da081b08d9081c08d8081d08d7082808d6082908d3c01059940b03080a08e8080b08e7080c08e6080d08e5081108e4081208e2081308e1081408e0c0102403080008f1080108f0080208ef080308ee080408ed080508ec080608eb080708eac0100c0720070c2003040200004200080002089000000000002f00040038000000290004009000000035000400a0000000']), '23000000320074000000008000200000502077322820020030200000082110000c211000482105004c2105002020000024200000582000005c20000060204300682014006c2001247020012c842020008c20900190202c01942001809c200902a0200b19b4200000b8203a00bc201400c0200200c4200200c82008003300100000000080cc200000a101d0200000a10132004c0000000080dc20e803e0206401e420d002e8200001ec201400f0200500fc200000b8203a00140800000008040008080000080802001408300008080300140831001c081a004c11240050110000',
SensorCaptureProg(major=0x6, minor=0x14, build=0x0, u1=0x0, dev_type=0x8f6, a0=0x18, a1=0x19, blobs=['2300000020000800002000800000010032005c00000000802020040024200000382000002820df0b2c20df0b302000003420000050200a015c200000602000004c2003006c20500070205000742000007820000084202000b4200000bc201400c0200200c4200100c820020074030002330028000000008054202a2203005820272f03004420898103004820868e0300cc200000ef03d0200000ef033200400000000080dc20fa00e020fa00e420b400e820b400f0200500f8200500b8203a00002804001428000008280000082800001428300008280000142831001c281a00330064030000008064200000a10c642000109f0c64200020a20c642000309e0c64200040a30c642000509d0c64200060a40c642000709c0c64200080a60c642000909b0c642000a0a70c642000b09a0c642000c0a80c642000d0990c642000e0a90c642000f0980c64200000af0c64200010950c64200020b00c64200030940c64200040b10c64200050930c64200060b20c64200070920c64200080b30c642000908b0c642000a0b70c642000b08a0c642000c0b80c642000d0890c642000e0b90c642000f0880c64200000ba0c64200010870c64200020bb0c64200030810c64200040bf0c64200050800c64200060c00c642000707f0c64200080c10c642000907e0c642000a0c20c642000b07d0c642000c0c50c642000d0720c642000e0c60c642000f0710c64200000c70c64200010700c64200020c80c642000306f0c64200040c90c64200050630c642000606c0c64200070620c642000806b0c64200090610c642000a06a0c642000b0600c642000c0690c642000d05f0c642000e05e0c642000f04f0c642000005d0c642000104e0c642000205c0c642000304d0c642000405b0c642000504c0c642000605a0c642000704b0c64200080310c642000904a0c642000a0300c642000b0490c642000c02f0c642000d0480c642000e02e0c642000f0470c642000002d0c64200010460c64200020ca0c642000303b0c64200040cb0c642000503a0c64200060cc0c64200070390c64200080cd0c64200090380c642000a0ce0c642000b02c0c642000c0d00c642000d02b0c642000e0d10c642000f02a0c64200000d20c64200010290c64200020d30c64200030280c64200040d60c642000501c0c64200060d70c642000701b0c64200080d80c642000901a0c642000a0d90c642000b0190c642000c0da0c642000d0150c642000e0df0c642000f0140c64200000e00c64200010130c64200020e10c64200030120c64200040e20c64200050110c64200060e40c642000700e0c64200080e50c642000900d0c642000a0e60c642000b00c0c642000c0e70c642000d00b0c642000e0e80c642000f00a0c64200000ea0c64200010070c64200020eb0c64200030060c64200040ec0c64200050050c64200060ed0c64200070040c64200080ee0c64200090030c642000a0ef0c642000b0020c642000c0f00c642000d0010c642000e0f10c642000f0000c', '32000c0000000080681101006411260034001c0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007e007e0102a13102a13102a12010000061e102d0101000007c8078c060b5d00005e00004f80005080006d030059940b070100000720240308a1089f08a2089e08a3089d08a4089c08a6089b08a7089a08a8089908a90898c0102c0308af089508b0089408b1089308b2089208b3088b08b7088a08b8088908b90888c0100308ba088708bb088108bf088008c0087f08c1087e08c2087d08c5087208c60871c010062807010308c7087008c8086f08c90863086c0862086b0861086a08600869085f085e084fc01003085d084e085c084d085b084c085a084b0831084a08300849082f0848082e0847c01003082d084608ca083b08cb083a08cc083908cd083808ce082c08d0082b08d1082ac010063207010308d2082908d3082808d6081c08d7081b08d8081a08d9081908da081508df0814c0100308e0081308e1081208e2081108e4080e08e5080d08e6080c08e7080b08e8080ac010240308ea080708eb080608ec080508ed080408ee080308ef080208f0080108f10800c010070320030c07030703072004020000004200080002089000000000002f00040038000000', '2f00040038000000290004009000000035000400a0000000']), '2a00080020010100100100002c002800802080200000000000013f4000000000080f080f00000000279c1000279c10000000000000000000340040000300000007160000240a59085a0701c9500aaa07010ada08db0701c9460b2107010800800a0088c9590a5a07010aa908aa0701c91f0ac900000c040100000000',
SensorCaptureProg(major=0x6, minor=0x14, build=0x0, u1=0x0, dev_type=0x121, a0=0x18, a1=0x19, blobs=['2300000020000800002000800000010032005c00000000802020040024200000382000002820df0b2c20df0b302000003420000050200a015c200000602000004c2003006c20720070207200742001007820010084202000b4200000bc201400c0200200c4200100c820020074030002330028000000008054202a2203005820272f03004420898103004820868e0300cc200000ef03d0200000ef033200400000000080dc20fa00e020fa00e420b400e820b400f0200500f8200500b8203a00002804001428000008280000082800001428300008280000142831001c281a00', '330064030000008064200000a10c642000109f0c64200020a20c642000309e0c64200040a30c642000509d0c64200060a40c642000709c0c64200080a60c642000909b0c642000a0a70c642000b09a0c642000c0a80c642000d0990c642000e0a90c642000f0980c64200000af0c64200010950c64200020b00c64200030940c64200040b10c64200050930c64200060b20c64200070920c64200080b30c642000908b0c642000a0b70c642000b08a0c642000c0b80c642000d0890c642000e0b90c642000f0880c64200000ba0c64200010870c64200020bb0c64200030810c64200040bf0c64200050800c64200060c00c642000707f0c64200080c10c642000907e0c642000a0c20c642000b07d0c642000c0c50c642000d0720c642000e0c60c642000f0710c64200000c70c64200010700c64200020c80c642000306f0c64200040c90c642000506d0c642000607a0c642000706c0c64200080790c642000906b0c642000a0780c642000b06a0c642000c06e0c642000d0690c642000e0630c642000f05e0c64200000620c642000105d0c64200020610c642000305c0c64200040600c642000505b0c642000605f0c642000705a0c64200080310c642000904a0c642000a0300c642000b0490c642000c02f0c642000d0480c642000e02e0c642000f0470c642000002d0c64200010460c64200020ca0c642000303b0c64200040cb0c642000503a0c64200060cc0c64200070390c64200080cd0c64200090380c642000a0ce0c642000b02c0c642000c0d00c642000d02b0c642000e0d10c642000f02a0c64200000d20c64200010290c64200020d30c64200030280c64200040d60c642000501c0c64200060d70c642000701b0c64200080d80c642000901a0c642000a0d90c642000b0190c642000c0da0c642000d0150c642000e0df0c642000f0140c64200000e00c64200010130c64200020e10c64200030120c64200040e20c64200050110c64200060e40c642000700e0c64200080e50c642000900d0c642000a0e60c642000b00c0c642000c0e70c642000d00b0c642000e0e80c642000f00a0c64200000ea0c64200010070c64200020eb0c64200030060c64200040ec0c64200050050c64200060ed0c64200070040c64200080ee0c64200090030c642000a0ef0c642000b0020c642000c0f00c642000d0010c642000e0f10c642000f0000c', '32000c000000008068110100641126003400180200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007e007e0102a13102a13102a120100000620102d0101000007c8078c060b5d00005e00004f80005080006d030059940b07010000240308a1089f08a2089e08a3089d08a4089c08a6089b08a7089a08a8089908a90898c0102c0308af089508b0089408b1089308b2089208b3088b08b7088a08b8088908b90888c0100308ba088708bb088108bf088008c0087f08c1087e08c2087d08c5087208c60871c010062807010308c7087008c8086f08c9086d087a086c0879086b0878086a086e08690863085ec010030862085d0861085c0860085b085f085a0831084a08300849082f0848082e0847c01003082d084608ca083b08cb083a08cc083908cd083808ce082c08d0082b08d1082ac010063007010308d2082908d3082808d6081c08d7081b08d8081a08d9081908da081508df0814c01059940b0308e0081308e1081208e2081108e4080e08e5080d08e6080c08e7080b08e8080ac010240308ea080708eb080608ec080508ed080408ee080308ef080208f0080108f10800c0100c0720070c2003040200004200080002089000000000002f00040038000000290004009000000035000400a0000000']), '29000400000000003500040000000000'
SensorCaptureProg(major=0x6, minor=0x15, build=0x0, u1=0x0, dev_type=0x121, a0=0x18, a1=0x19, blobs=['2300000020000800002000800000010032005c00000000802020040024200000382000002820df0b2c20df0b302000003420000050200a015c200000602000004c2003006c20720070207200742001007820010084202000b4200000bc201400c0200200c4200100c820020074030002330028000000008054202a2203005820272f03004420898103004820868e0300cc200000ef03d0200000ef033200400000000080dc20fa00e020fa00e420b400e820b400f0200500f8200500b8203a00002804001428000008280000082800001428300008280000142831001c281a00', '330064030000008064200000a10c642000109f0c64200020a20c642000309e0c64200040a30c642000509d0c64200060a40c642000709c0c64200080a60c642000909b0c642000a0a70c642000b09a0c642000c0a80c642000d0990c642000e0a90c642000f0980c64200000af0c64200010950c64200020b00c64200030940c64200040b10c64200050930c64200060b20c64200070920c64200080b30c642000908b0c642000a0b70c642000b08a0c642000c0b80c642000d0890c642000e0b90c642000f0880c64200000ba0c64200010870c64200020bb0c64200030810c64200040bf0c64200050800c64200060c00c642000707f0c64200080c10c642000907e0c642000a0c20c642000b07d0c642000c0c50c642000d0720c642000e0c60c642000f0710c64200000c70c64200010700c64200020c80c642000306f0c64200040c90c642000506d0c642000607a0c642000706c0c64200080790c642000906b0c642000a0780c642000b06a0c642000c06e0c642000d0690c642000e0630c642000f05e0c64200000620c642000105d0c64200020610c642000305c0c64200040600c642000505b0c642000605f0c642000705a0c64200080310c642000904a0c642000a0300c642000b0490c642000c02f0c642000d0480c642000e02e0c642000f0470c642000002d0c64200010460c64200020ca0c642000303b0c64200040cb0c642000503a0c64200060cc0c64200070390c64200080cd0c64200090380c642000a0ce0c642000b02c0c642000c0d00c642000d02b0c642000e0d10c642000f02a0c64200000d20c64200010290c64200020d30c64200030280c64200040d60c642000501c0c64200060d70c642000701b0c64200080d80c642000901a0c642000a0d90c642000b0190c642000c0da0c642000d0150c642000e0df0c642000f0140c64200000e00c64200010130c64200020e10c64200030120c64200040e20c64200050110c64200060e40c642000700e0c64200080e50c642000900d0c642000a0e60c642000b00c0c642000c0e70c642000d00b0c642000e0e80c642000f00a0c64200000ea0c64200010070c64200020eb0c64200030060c64200040ec0c64200050050c64200060ed0c64200070040c64200080ee0c64200090030c642000a0ef0c642000b0020c642000c0f00c642000d0010c642000e0f10c642000f0000c', '32000c000000008068110100641126003400180200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007e007e0102a13102a13102a120100000620102d0101000007c8078c060b5d00005e00004f80005080006d030059940b07010000240308a1089f08a2089e08a3089d08a4089c08a6089b08a7089a08a8089908a90898c0102c0308af089508b0089408b1089308b2089208b3088b08b7088a08b8088908b90888c0100308ba088708bb088108bf088008c0087f08c1087e08c2087d08c5087208c60871c010062807010308c7087008c8086f08c9086d087a086c0879086b0878086a086e08690863085ec010030862085d0861085c0860085b085f085a0831084a08300849082f0848082e0847c01003082d084608ca083b08cb083a08cc083908cd083808ce082c08d0082b08d1082ac010063007010308d2082908d3082808d6081c08d7081b08d8081a08d9081908da081508df0814c01059940b0308e0081308e1081208e2081108e4080e08e5080d08e6080c08e7080b08e8080ac010240308ea080708eb080608ec080508ed080408ee080308ef080208f0080108f10800c0100c0720070c2003040200004200080002089000000000002f00040038000000290004009000000035000400a0000000']), ]),
SensorCaptureProg(major=0x6, minor=0x14, build=0x0, u1=0x0, dev_type=0xb4b, a0=0x18, a1=0x19, blobs=['2300000020000800002000800000010032005c00000000802020040024200000382000002820df0b2c20df0b302000003420000050200a015c200000602000004c2003006c20660070206600742001007820010084202000b4200000bc201400c0200200c4200100c820020074030002330028000000008054202a2203005820272f03004420898103004820868e0300cc200000ef03d0200000ef033200400000000080dc20fa00e020fa00e420b400e820b400f0200500f8200500b8203a00002804001428000008280000082800001428300008280000142831001c281a00', '330064030000008064200000a10c642000109f0c64200020a20c642000309e0c64200040a30c642000509d0c64200060a40c642000709c0c64200080a60c642000909b0c642000a0a70c642000b09a0c642000c0a80c642000d0990c642000e0a90c642000f0980c64200000af0c64200010950c64200020b00c64200030940c64200040b10c64200050930c64200060b20c64200070920c64200080b30c642000908b0c642000a0b70c642000b08a0c642000c0b80c642000d0890c642000e0b90c642000f0880c64200000ba0c64200010870c64200020bb0c64200030810c64200040bf0c64200050800c64200060c00c642000707f0c64200080c10c642000907e0c642000a0c20c642000b07d0c642000c0c50c642000d0720c642000e0c60c642000f0710c64200000c70c64200010700c64200020c80c642000306f0c64200040c90c642000506d0c642000607a0c642000706c0c64200080790c642000906b0c642000a0780c642000b06a0c642000c06e0c642000d0690c642000e0630c642000f05e0c64200000620c642000105d0c64200020610c642000305c0c64200040600c642000505b0c642000605f0c642000705a0c64200080310c642000904a0c642000a0300c642000b0490c642000c02f0c642000d0480c642000e02e0c642000f0470c642000002d0c64200010460c64200020ca0c642000303b0c64200040cb0c642000503a0c64200060cc0c64200070390c64200080cd0c64200090380c642000a0ce0c642000b02c0c642000c0d00c642000d02b0c642000e0d10c642000f02a0c64200000d20c64200010290c64200020d30c64200030280c64200040d60c642000501c0c64200060d70c642000701b0c64200080d80c642000901a0c642000a0d90c642000b0190c642000c0da0c642000d0150c642000e0df0c642000f0140c64200000e00c64200010130c64200020e10c64200030120c64200040e20c64200050110c64200060e40c642000700e0c64200080e50c642000900d0c642000a0e60c642000b00c0c642000c0e70c642000d00b0c642000e0e80c642000f00a0c64200000ea0c64200010070c64200020eb0c64200030060c64200040ec0c64200050050c64200060ed0c64200070040c64200080ee0c64200090030c642000a0ef0c642000b0020c642000c0f00c642000d0010c642000e0f10c642000f0000c', '32000c000000008068110100641126003400180200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007e007e0102a13102a13102a12010000061e102d0101000007c8078c060b5d00005e00004f80005080006d030059940b07010000240308a1089f08a2089e08a3089d08a4089c08a6089b08a7089a08a8089908a90898c0102c0308af089508b0089408b1089308b2089208b3088b08b7088a08b8088908b90888c0100308ba088708bb088108bf088008c0087f08c1087e08c2087d08c5087208c60871c010062807010308c7087008c8086f08c9086d087a086c0879086b0878086a086e08690863085ec010030862085d0861085c0860085b085f085a0831084a08300849082f0848082e0847c01003082d084608ca083b08cb083a08cc083908cd083808ce082c08d0082b08d1082ac010063207010308d2082908d3082808d6081c08d7081b08d8081a08d9081908da081508df0814c01059940b0308e0081308e1081208e2081108e4080e08e5080d08e6080c08e7080b08e8080ac010240308ea080708eb080608ec080508ed080408ee080308ef080208f0080108f10800c0100c0720070c2003040200004200080002089000000000002f00040038000000290004009000000035000400a0000000']), SensorCaptureProg(
SensorCaptureProg(major=0x6, minor=0x15, build=0x0, u1=0x0, dev_type=0xb4b, a0=0x18, a1=0x19, blobs=['2300000020000800002000800000010032005c00000000802020040024200000382000002820df0b2c20df0b302000003420000050200a015c200000602000004c2003006c20660070206600742001007820010084202000b4200000bc201400c0200200c4200100c820020074030002330028000000008054202a2203005820272f03004420898103004820868e0300cc200000ef03d0200000ef033200400000000080dc20fa00e020fa00e420b400e820b400f0200500f8200500b8203a00002804001428000008280000082800001428300008280000142831001c281a00', '330064030000008064200000a10c642000109f0c64200020a20c642000309e0c64200040a30c642000509d0c64200060a40c642000709c0c64200080a60c642000909b0c642000a0a70c642000b09a0c642000c0a80c642000d0990c642000e0a90c642000f0980c64200000af0c64200010950c64200020b00c64200030940c64200040b10c64200050930c64200060b20c64200070920c64200080b30c642000908b0c642000a0b70c642000b08a0c642000c0b80c642000d0890c642000e0b90c642000f0880c64200000ba0c64200010870c64200020bb0c64200030810c64200040bf0c64200050800c64200060c00c642000707f0c64200080c10c642000907e0c642000a0c20c642000b07d0c642000c0c50c642000d0720c642000e0c60c642000f0710c64200000c70c64200010700c64200020c80c642000306f0c64200040c90c642000506d0c642000607a0c642000706c0c64200080790c642000906b0c642000a0780c642000b06a0c642000c06e0c642000d0690c642000e0630c642000f05e0c64200000620c642000105d0c64200020610c642000305c0c64200040600c642000505b0c642000605f0c642000705a0c64200080310c642000904a0c642000a0300c642000b0490c642000c02f0c642000d0480c642000e02e0c642000f0470c642000002d0c64200010460c64200020ca0c642000303b0c64200040cb0c642000503a0c64200060cc0c64200070390c64200080cd0c64200090380c642000a0ce0c642000b02c0c642000c0d00c642000d02b0c642000e0d10c642000f02a0c64200000d20c64200010290c64200020d30c64200030280c64200040d60c642000501c0c64200060d70c642000701b0c64200080d80c642000901a0c642000a0d90c642000b0190c642000c0da0c642000d0150c642000e0df0c642000f0140c64200000e00c64200010130c64200020e10c64200030120c64200040e20c64200050110c64200060e40c642000700e0c64200080e50c642000900d0c642000a0e60c642000b00c0c642000c0e70c642000d00b0c642000e0e80c642000f00a0c64200000ea0c64200010070c64200020eb0c64200030060c64200040ec0c64200050050c64200060ed0c64200070040c64200080ee0c64200090030c642000a0ef0c642000b0020c642000c0f00c642000d0010c642000e0f10c642000f0000c', '32000c000000008068110100641126003400180200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007e007e0102a13102a13102a12010000061e102d0101000007c8078c060b5d00005e00004f80005080006d030059940b07010000240308a1089f08a2089e08a3089d08a4089c08a6089b08a7089a08a8089908a90898c0102c0308af089508b0089408b1089308b2089208b3088b08b7088a08b8088908b90888c0100308ba088708bb088108bf088008c0087f08c1087e08c2087d08c5087208c60871c010062807010308c7087008c8086f08c9086d087a086c0879086b0878086a086e08690863085ec010030862085d0861085c0860085b085f085a0831084a08300849082f0848082e0847c01003082d084608ca083b08cb083a08cc083908cd083808ce082c08d0082b08d1082ac010063207010308d2082908d3082808d6081c08d7081b08d8081a08d9081908da081508df0814c01059940b0308e0081308e1081208e2081108e4080e08e5080d08e6080c08e7080b08e8080ac010240308ea080708eb080608ec080508ed080408ee080308ef080208f0080108f10800c0100c0720070c2003040200004200080002089000000000002f00040038000000290004009000000035000400a0000000']), major=0x6,
SensorCaptureProg(major=0x6, minor=0x14, build=0x0, u1=0x0, dev_type=0xb4b, a0=0x18, a1=0x19, blobs=['2300000020000800002000800000010032005c00000000802020040024200000382000002820df0b2c20df0b302000003420000050201f015c200000602000004c2003006c20720070207200742004007820040084202000b4200000bc201400c0200200c4200100c820020074030002330028000000008054202a2203005820272f03004420898103004820868e0300cc200000ef03d0200000ef033200400000000080dc20fa00e020fa00e420b400e820b400f0200500f8200500b8203a00002804001428000008280000082800001428300008280000142831001c281a00', '330064030000008064200000a10c642000109f0c64200020a20c642000309e0c64200040a30c642000509d0c64200060a40c642000709c0c64200080a60c642000909b0c642000a0a70c642000b09a0c642000c0a80c642000d0990c642000e0a90c642000f0980c64200000af0c64200010950c64200020b00c64200030940c64200040b10c64200050930c64200060b20c64200070920c64200080b30c642000908b0c642000a0b70c642000b08a0c642000c0b80c642000d0890c642000e0b90c642000f0880c64200000ba0c64200010870c64200020bb0c64200030810c64200040bf0c64200050800c64200060c00c642000707f0c64200080c10c642000907e0c642000a0c20c642000b07d0c642000c0c50c642000d0720c642000e0c60c642000f0710c64200000c70c64200010700c64200020c80c642000306f0c64200040c90c642000506d0c642000607a0c642000706c0c64200080790c642000906b0c642000a0780c642000b06a0c642000c06e0c642000d0690c642000e0630c642000f05e0c64200000620c642000105d0c64200020610c642000305c0c64200040600c642000505b0c642000605f0c642000705a0c64200080310c642000904a0c642000a0300c642000b0490c642000c02f0c642000d0480c642000e02e0c642000f0470c642000002d0c64200010460c64200020ca0c642000303b0c64200040cb0c642000503a0c64200060cc0c64200070390c64200080cd0c64200090380c642000a0ce0c642000b02c0c642000c0d00c642000d02b0c642000e0d10c642000f02a0c64200000d20c64200010290c64200020d30c64200030280c64200040d60c642000501c0c64200060d70c642000701b0c64200080d80c642000901a0c642000a0d90c642000b0190c642000c0da0c642000d0150c642000e0df0c642000f0140c64200000e00c64200010130c64200020e10c64200030120c64200040e20c64200050110c64200060e40c642000700e0c64200080e50c642000900d0c642000a0e60c642000b00c0c642000c0e70c642000d00b0c642000e0e80c642000f00a0c64200000ea0c64200010070c64200020eb0c64200030060c64200040ec0c64200050050c64200060ed0c64200070040c64200080ee0c64200090030c642000a0ef0c642000b0020c642000c0f00c642000d0010c642000e0f10c642000f0000c', '32000c000000008068110100641126003400180200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007e007e0102a13102a13102a12010000061e102d0101000007c8078c060b5d03005e03004f80005080006d030059940b07010000240308a1089f08a2089e08a3089d08a4089c08a6089b08a7089a08a8089908a90898c0102c0308af089508b0089408b1089308b2089208b3088b08b7088a08b8088908b90888c0100308ba088708bb088108bf088008c0087f08c1087e08c2087d08c5087208c60871c010062807010308c7087008c8086f08c9086d087a086c0879086b0878086a086e08690863085ec010030862085d0861085c0860085b085f085a0831084a08300849082f0848082e0847c01003082d084608ca083b08cb083a08cc083908cd083808ce082c08d0082b08d1082ac010063207010308d2082908d3082808d6081c08d7081b08d8081a08d9081908da081508df0814c01059940b0308e0081308e1081208e2081108e4080e08e5080d08e6080c08e7080b08e8080ac010240308ea080708eb080608ec080508ed080408ee080308ef080208f0080108f10800c0100c0720070c2003040200004200080002089000000000002f00040038000000290004009000000035000400a0000000']), minor=0x7,
SensorCaptureProg(major=0x6, minor=0x15, build=0x0, u1=0x0, dev_type=0xb4b, a0=0x18, a1=0x19, blobs=['2300000020000800002000800000010032005c00000000802020040024200000382000002820df0b2c20df0b302000003420000050201f015c200000602000004c2003006c20720070207200742004007820040084202000b4200000bc201400c0200200c4200100c820020074030002330028000000008054202a2203005820272f03004420898103004820868e0300cc200000ef03d0200000ef033200400000000080dc20fa00e020fa00e420b400e820b400f0200500f8200500b8203a00002804001428000008280000082800001428300008280000142831001c281a00', '330064030000008064200000a10c642000109f0c64200020a20c642000309e0c64200040a30c642000509d0c64200060a40c642000709c0c64200080a60c642000909b0c642000a0a70c642000b09a0c642000c0a80c642000d0990c642000e0a90c642000f0980c64200000af0c64200010950c64200020b00c64200030940c64200040b10c64200050930c64200060b20c64200070920c64200080b30c642000908b0c642000a0b70c642000b08a0c642000c0b80c642000d0890c642000e0b90c642000f0880c64200000ba0c64200010870c64200020bb0c64200030810c64200040bf0c64200050800c64200060c00c642000707f0c64200080c10c642000907e0c642000a0c20c642000b07d0c642000c0c50c642000d0720c642000e0c60c642000f0710c64200000c70c64200010700c64200020c80c642000306f0c64200040c90c642000506d0c642000607a0c642000706c0c64200080790c642000906b0c642000a0780c642000b06a0c642000c06e0c642000d0690c642000e0630c642000f05e0c64200000620c642000105d0c64200020610c642000305c0c64200040600c642000505b0c642000605f0c642000705a0c64200080310c642000904a0c642000a0300c642000b0490c642000c02f0c642000d0480c642000e02e0c642000f0470c642000002d0c64200010460c64200020ca0c642000303b0c64200040cb0c642000503a0c64200060cc0c64200070390c64200080cd0c64200090380c642000a0ce0c642000b02c0c642000c0d00c642000d02b0c642000e0d10c642000f02a0c64200000d20c64200010290c64200020d30c64200030280c64200040d60c642000501c0c64200060d70c642000701b0c64200080d80c642000901a0c642000a0d90c642000b0190c642000c0da0c642000d0150c642000e0df0c642000f0140c64200000e00c64200010130c64200020e10c64200030120c64200040e20c64200050110c64200060e40c642000700e0c64200080e50c642000900d0c642000a0e60c642000b00c0c642000c0e70c642000d00b0c642000e0e80c642000f00a0c64200000ea0c64200010070c64200020eb0c64200030060c64200040ec0c64200050050c64200060ed0c64200070040c64200080ee0c64200090030c642000a0ef0c642000b0020c642000c0f00c642000d0010c642000e0f10c642000f0000c', '32000c000000008068110100641126003400180200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007e007e0102a13102a13102a12010000061e102d0101000007c8078c060b5d03005e03004f80005080006d030059940b07010000240308a1089f08a2089e08a3089d08a4089c08a6089b08a7089a08a8089908a90898c0102c0308af089508b0089408b1089308b2089208b3088b08b7088a08b8088908b90888c0100308ba088708bb088108bf088008c0087f08c1087e08c2087d08c5087208c60871c010062807010308c7087008c8086f08c9086d087a086c0879086b0878086a086e08690863085ec010030862085d0861085c0860085b085f085a0831084a08300849082f0848082e0847c01003082d084608ca083b08cb083a08cc083908cd083808ce082c08d0082b08d1082ac010063207010308d2082908d3082808d6081c08d7081b08d8081a08d9081908da081508df0814c01059940b0308e0081308e1081208e2081108e4080e08e5080d08e6080c08e7080b08e8080ac010240308ea080708eb080608ec080508ed080408ee080308ef080208f0080108f10800c0100c0720070c2003040200004200080002089000000000002f00040038000000290004009000000035000400a0000000']), build=0x0,
SensorCaptureProg(major=0x6, minor=0x14, build=0x0, u1=0x0, dev_type=0xb4d, a0=0x18, a1=0x19, blobs=['2300000020000800002000800000010032005c00000000802020040024200000382000002820df0b2c20df0b302000003420000050200a015c200000602000004c2003006c20600070206000742002007820020084202000b4200000bc201400c0200200c4200100c820020074030002330028000000008054202a2203005820272f03004420898103004820868e0300cc200000ef03d0200000ef033200400000000080dc20fa00e020fa00e420b400e820b400f0200500f8200500b8203a00002804001428000008280000082800001428300008280000142831001c281a00', '330064030000008064200000a10c642000109f0c64200020a20c642000309e0c64200040a30c642000509d0c64200060a40c642000709c0c64200080a60c642000909b0c642000a0a70c642000b09a0c642000c0a80c642000d0990c642000e0a90c642000f0980c64200000af0c64200010950c64200020b00c64200030940c64200040b10c64200050930c64200060b20c64200070920c64200080b30c642000908b0c642000a0b70c642000b08a0c642000c0b80c642000d0890c642000e0b90c642000f0880c64200000ba0c64200010870c64200020bb0c64200030810c64200040bf0c64200050800c64200060c00c642000707f0c64200080c10c642000907e0c642000a0c20c642000b07d0c642000c0c50c642000d0720c642000e0c60c642000f0710c64200000c70c64200010700c64200020c80c642000306f0c64200040c90c642000506d0c642000607a0c642000706c0c64200080790c642000906b0c642000a0780c642000b06a0c642000c06e0c642000d0690c642000e0630c642000f05e0c64200000620c642000105d0c64200020610c642000305c0c64200040600c642000505b0c642000605f0c642000705a0c64200080310c642000904a0c642000a0300c642000b0490c642000c02f0c642000d0480c642000e02e0c642000f0470c642000002d0c64200010460c64200020ca0c642000303b0c64200040cb0c642000503a0c64200060cc0c64200070390c64200080cd0c64200090380c642000a0ce0c642000b02c0c642000c0d00c642000d02b0c642000e0d10c642000f02a0c64200000d20c64200010290c64200020d30c64200030280c64200040d60c642000501c0c64200060d70c642000701b0c64200080d80c642000901a0c642000a0d90c642000b0190c642000c0da0c642000d0150c642000e0df0c642000f0140c64200000e00c64200010130c64200020e10c64200030120c64200040e20c64200050110c64200060e40c642000700e0c64200080e50c642000900d0c642000a0e60c642000b00c0c642000c0e70c642000d00b0c642000e0e80c642000f00a0c64200000ea0c64200010070c64200020eb0c64200030060c64200040ec0c64200050050c64200060ed0c64200070040c64200080ee0c64200090030c642000a0ef0c642000b0020c642000c0f00c642000d0010c642000e0f10c642000f0000c', '32000c000000008068110100641126003400180200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007e007e0102a13102a13102a12010000061e102d0101000007c8078c060b5d01005e01004f80005080006d030059940b07010000240308a1089f08a2089e08a3089d08a4089c08a6089b08a7089a08a8089908a90898c0102c0308af089508b0089408b1089308b2089208b3088b08b7088a08b8088908b90888c0100308ba088708bb088108bf088008c0087f08c1087e08c2087d08c5087208c60871c010062807010308c7087008c8086f08c9086d087a086c0879086b0878086a086e08690863085ec010030862085d0861085c0860085b085f085a0831084a08300849082f0848082e0847c01003082d084608ca083b08cb083a08cc083908cd083808ce082c08d0082b08d1082ac010063207010308d2082908d3082808d6081c08d7081b08d8081a08d9081908da081508df0814c01059940b0308e0081308e1081208e2081108e4080e08e5080d08e6080c08e7080b08e8080ac010240308ea080708eb080608ec080508ed080408ee080308ef080208f0080108f10800c0100c0720070c2003040200004200080002089000000000002f00040038000000290004009000000035000400a0000000']), u1=0x0,
SensorCaptureProg(major=0x6, minor=0x15, build=0x0, u1=0x0, dev_type=0xb4d, a0=0x18, a1=0x19, blobs=['2300000020000800002000800000010032005c00000000802020040024200000382000002820df0b2c20df0b302000003420000050200a015c200000602000004c2003006c20600070206000742002007820020084202000b4200000bc201400c0200200c4200100c820020074030002330028000000008054202a2203005820272f03004420898103004820868e0300cc200000ef03d0200000ef033200400000000080dc20fa00e020fa00e420b400e820b400f0200500f8200500b8203a00002804001428000008280000082800001428300008280000142831001c281a00', '330064030000008064200000a10c642000109f0c64200020a20c642000309e0c64200040a30c642000509d0c64200060a40c642000709c0c64200080a60c642000909b0c642000a0a70c642000b09a0c642000c0a80c642000d0990c642000e0a90c642000f0980c64200000af0c64200010950c64200020b00c64200030940c64200040b10c64200050930c64200060b20c64200070920c64200080b30c642000908b0c642000a0b70c642000b08a0c642000c0b80c642000d0890c642000e0b90c642000f0880c64200000ba0c64200010870c64200020bb0c64200030810c64200040bf0c64200050800c64200060c00c642000707f0c64200080c10c642000907e0c642000a0c20c642000b07d0c642000c0c50c642000d0720c642000e0c60c642000f0710c64200000c70c64200010700c64200020c80c642000306f0c64200040c90c642000506d0c642000607a0c642000706c0c64200080790c642000906b0c642000a0780c642000b06a0c642000c06e0c642000d0690c642000e0630c642000f05e0c64200000620c642000105d0c64200020610c642000305c0c64200040600c642000505b0c642000605f0c642000705a0c64200080310c642000904a0c642000a0300c642000b0490c642000c02f0c642000d0480c642000e02e0c642000f0470c642000002d0c64200010460c64200020ca0c642000303b0c64200040cb0c642000503a0c64200060cc0c64200070390c64200080cd0c64200090380c642000a0ce0c642000b02c0c642000c0d00c642000d02b0c642000e0d10c642000f02a0c64200000d20c64200010290c64200020d30c64200030280c64200040d60c642000501c0c64200060d70c642000701b0c64200080d80c642000901a0c642000a0d90c642000b0190c642000c0da0c642000d0150c642000e0df0c642000f0140c64200000e00c64200010130c64200020e10c64200030120c64200040e20c64200050110c64200060e40c642000700e0c64200080e50c642000900d0c642000a0e60c642000b00c0c642000c0e70c642000d00b0c642000e0e80c642000f00a0c64200000ea0c64200010070c64200020eb0c64200030060c64200040ec0c64200050050c64200060ed0c64200070040c64200080ee0c64200090030c642000a0ef0c642000b0020c642000c0f00c642000d0010c642000e0f10c642000f0000c', '32000c000000008068110100641126003400180200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007e007e0102a13102a13102a12010000061e102d0101000007c8078c060b5d01005e01004f80005080006d030059940b07010000240308a1089f08a2089e08a3089d08a4089c08a6089b08a7089a08a8089908a90898c0102c0308af089508b0089408b1089308b2089208b3088b08b7088a08b8088908b90888c0100308ba088708bb088108bf088008c0087f08c1087e08c2087d08c5087208c60871c010062807010308c7087008c8086f08c9086d087a086c0879086b0878086a086e08690863085ec010030862085d0861085c0860085b085f085a0831084a08300849082f0848082e0847c01003082d084608ca083b08cb083a08cc083908cd083808ce082c08d0082b08d1082ac010063207010308d2082908d3082808d6081c08d7081b08d8081a08d9081908da081508df0814c01059940b0308e0081308e1081208e2081108e4080e08e5080d08e6080c08e7080b08e8080ac010240308ea080708eb080608ec080508ed080408ee080308ef080208f0080108f10800c0100c0720070c2003040200004200080002089000000000002f00040038000000290004009000000035000400a0000000']), dev_type=0x0,
SensorCaptureProg(major=0x6, minor=0x15, build=0x0, u1=0x0, dev_type=0x130, a0=0x18, a1=0x19, blobs=['2300000020000800002000800000010032005c00000000802020040024200000382000002820df0b2c20df0b302000003420000050200a015c200000602000004c2003006c20400070204000742001007820010084202000b4200000bc201400c0200200c4200100c820020074030002330028000000008054202a2203005820272f03004420898103004820868e0300cc200000ef03d0200000ef033200400000000080dc20fa00e020fa00e420b400e820b400f0200500f8200500b8203a00002804001428000008280000082800001428300008280000142831001c281a003200b4020000008074030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030005740300077403000174030003740300157403001774030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030015740300177403000174030003', '330064030000008064200000e40c64200010050c64200020e60c64200030040c64200040e70c64200050020c64200060eb0c64200070000c64200080ec0c64200090010c642000a0ed0c642000b0030c642000c0f10c642000d0060c642000e0f00c642000f0070c64200000ef0c64200010080c64200020ee0c642000300a0c64200040ea0c642000500b0c64200060e80c642000700c0c64200080e50c642000900d0c642000a0e10c642000b0100c642000c0e00c642000d0140c642000e0df0c642000f0160c64200000de0c64200010190c64200020dc0c642000301d0c64200040db0c642000501e0c64200060da0c64200070220c64200080d30c64200090250c642000a0d10c642000b0270c642000c0cb0c642000d02b0c642000e0ca0c642000f02d0c642000003a0c64200010310c642000203b0c64200030320c642000403d0c64200050370c642000603e0c64200070390c64200080460c642000903c0c642000a0470c642000b03f0c642000c0490c642000d0400c642000e04a0c642000f0450c642000004c0c64200010480c642000204d0c642000304b0c642000405c0c642000504e0c642000605d0c642000704f0c642000805e0c64200090500c642000a0610c642000b0550c642000c0620c642000d05a0c642000e0630c642000f05b0c64200000680c642000105f0c64200020690c64200030600c642000406a0c64200050640c642000606d0c64200070650c642000806e0c642000906b0c642000a06f0c642000b06c0c642000c0700c642000d0710c642000e0c90c642000f0720c64200000c80c64200010770c64200020c60c64200030780c64200040c20c642000507c0c64200060c10c642000707f0c64200080c00c64200090820c642000a0bd0c642000b0840c642000c0bc0c642000d0870c642000e0b80c642000f08b0c64200000b50c642000108f0c64200020b20c64200030910c64200040af0c64200050940c64200060ae0c64200070980c64200080ad0c642000909a0c642000a0ac0c642000b09e0c642000c0ab0c642000d09f0c642000e0a90c642000f09d0c64200000a80c642000109c0c64200020a70c642000309b0c64200040a60c64200050990c64200060a40c64200070960c64200080a30c64200090950c642000a0a20c642000b0930c642000c0a10c642000d0920c642000e0a90c642000f09d0c', '32000c0000000080681101006411260034000c0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007e007e0102a0d102a0d102a0e0100000628102c0101000007c8078c061400004f80005080006d030059940b07010000240308e4080508e6080408e7080208eb080008ec080108ed080308f1080608f00807c0102c0308ef080808ee080a08ea080b08e8080c08e5080d08e1081008e0081408df0816c0100308de081908dc081d08db081e08da082208d3082508d1082708cb082b08ca082dc01003083a0831083b0832083d0837083e08390846083c0847083f08490840084a0845c01003084c0848084d084b085c084e085d084f085e0850086108550862085a0863085bc010030868085f08690860086a0864086d0865086e086b086f086c0870087108c90872c0100308c8087708c6087808c2087c08c1087f08c0088208bd088408bc088708b8088bc0100308b5088f08b2089108af089408ae089808ad089a08ac089e08ab089f08a9089dc010240308a9089d08a8089c08a7089b08a6089908a4089608a3089508a2089308a10892c0100c072c20030703070304020000004200080002089000000000002f00040028000000290004009000000035000400a0000000']), a0=0x0,
SensorCaptureProg(major=0x6, minor=0x15, build=0x0, u1=0x0, dev_type=0x518, a0=0x18, a1=0x19, blobs=['2300000020000800002000800000010032005c00000000802020040024200000382000002820df0b2c20df0b302000003420000050200a015c200000602000004c2003006c20640070206400742001007820010084202000b4200000bc201400c0200200c4200100c820020074030002330028000000008054202a2203005820272f03004420898103004820868e0300cc200000ef03d0200000ef033200400000000080dc20fa00e020fa00e420b400e820b400f0200500f8200500b8203a00002804001428000008280000082800001428300008280000142831001c281a003200b4020000008074030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030005740300077403000174030003740300157403001774030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030015740300177403000174030003', '330064030000008064200000e40c64200010050c64200020e60c64200030040c64200040e70c64200050020c64200060eb0c64200070000c64200080ec0c64200090010c642000a0ed0c642000b0030c642000c0f10c642000d0060c642000e0f00c642000f0070c64200000ef0c64200010080c64200020ee0c642000300a0c64200040ea0c642000500b0c64200060e80c642000700c0c64200080e50c642000900d0c642000a0e10c642000b0100c642000c0e00c642000d0140c642000e0df0c642000f0160c64200000de0c64200010190c64200020dc0c642000301d0c64200040db0c642000501e0c64200060da0c64200070220c64200080d30c64200090250c642000a0d10c642000b0270c642000c0cb0c642000d02b0c642000e0ca0c642000f02d0c642000003a0c64200010310c642000203b0c64200030320c642000403d0c64200050370c642000603e0c64200070390c64200080460c642000903c0c642000a0470c642000b03f0c642000c0490c642000d0400c642000e04a0c642000f0450c642000004c0c64200010480c642000204d0c642000304b0c642000405c0c642000504e0c642000605d0c642000704f0c642000805e0c64200090500c642000a0610c642000b0550c642000c0620c642000d05a0c642000e0630c642000f05b0c64200000680c642000105f0c64200020690c64200030600c642000406a0c64200050640c642000606d0c64200070650c642000806e0c642000906b0c642000a06f0c642000b06c0c642000c0700c642000d0710c642000e0c90c642000f0720c64200000c80c64200010770c64200020c60c64200030780c64200040c20c642000507c0c64200060c10c642000707f0c64200080c00c64200090820c642000a0bd0c642000b0840c642000c0bc0c642000d0870c642000e0b80c642000f08b0c64200000b50c642000108f0c64200020b20c64200030910c64200040af0c64200050940c64200060ae0c64200070980c64200080ad0c642000909a0c642000a0ac0c642000b09e0c642000c0ab0c642000d09f0c642000e0a90c642000f09d0c64200000a80c642000109c0c64200020a70c642000309b0c64200040a60c64200050990c64200060a40c64200070960c64200080a30c64200090950c642000a0a20c642000b0930c642000c0a10c642000d0920c642000e0a90c642000f09d0c', '32000c0000000080681101006411260034000c0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007e007e0102a0d102a0d102a0e0100000628102c0101000007c8078c061400004f80005080006d030059940b07010000240308e4080508e6080408e7080208eb080008ec080108ed080308f1080608f00807c0102c0308ef080808ee080a08ea080b08e8080c08e5080d08e1081008e0081408df0816c0100308de081908dc081d08db081e08da082208d3082508d1082708cb082b08ca082dc01003083a0831083b0832083d0837083e08390846083c0847083f08490840084a0845c01003084c0848084d084b085c084e085d084f085e0850086108550862085a0863085bc010030868085f08690860086a0864086d0865086e086b086f086c0870087108c90872c0100308c8087708c6087808c2087c08c1087f08c0088208bd088408bc088708b8088bc0100308b5088f08b2089108af089408ae089808ad089a08ac089e08ab089f08a9089dc010240308a9089d08a8089c08a7089b08a6089908a4089608a3089508a2089308a10892c0100c072c20030703070304020000004200080002089000000000002f00040028000000290004009000000035000400a0000000']), a1=0x0,
SensorCaptureProg(major=0x6, minor=0x15, build=0x0, u1=0x0, dev_type=0xbe1, a0=0x18, a1=0x19, blobs=['2300000020000800002000800000010032005c00000000802020040024200000382000002820df0b2c20df0b302000003420000050200a015c200000602000004c2003006c20550070205500742001007820010084202000b4200000bc201400c0200200c4200100c820020074030002330028000000008054202a2203005820272f03004420898103004820868e0300cc200000ef03d0200000ef033200400000000080dc20fa00e020fa00e420b400e820b400f0200500f8200500b8203a00002804001428000008280000082800001428300008280000142831001c281a003200b4020000008074030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030005740300077403000174030003740300157403001774030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030015740300177403000174030003', '330064030000008064200000e40c64200010050c64200020e60c64200030040c64200040e70c64200050020c64200060eb0c64200070000c64200080ec0c64200090010c642000a0ed0c642000b0030c642000c0f10c642000d0060c642000e0f00c642000f0070c64200000ef0c64200010080c64200020ee0c642000300a0c64200040ea0c642000500b0c64200060e80c642000700c0c64200080e50c642000900d0c642000a0e10c642000b0100c642000c0e00c642000d0140c642000e0df0c642000f0160c64200000de0c64200010190c64200020dc0c642000301d0c64200040db0c642000501e0c64200060da0c64200070220c64200080d30c64200090250c642000a0d10c642000b0270c642000c0cb0c642000d02b0c642000e0ca0c642000f02d0c642000003a0c64200010310c642000203b0c64200030320c642000403d0c64200050370c642000603e0c64200070390c64200080460c642000903c0c642000a0470c642000b03f0c642000c0490c642000d0400c642000e04a0c642000f0450c642000004c0c64200010480c642000204d0c642000304b0c642000405c0c642000504e0c642000605d0c642000704f0c642000805e0c64200090500c642000a0610c642000b0550c642000c0620c642000d05a0c642000e0630c642000f05b0c64200000680c642000105f0c64200020690c64200030600c642000406a0c64200050640c642000606d0c64200070650c642000806e0c642000906b0c642000a06f0c642000b06c0c642000c0700c642000d0710c642000e0c90c642000f0720c64200000c80c64200010770c64200020c60c64200030780c64200040c20c642000507c0c64200060c10c642000707f0c64200080c00c64200090820c642000a0bd0c642000b0840c642000c0bc0c642000d0870c642000e0b80c642000f08b0c64200000b50c642000108f0c64200020b20c64200030910c64200040af0c64200050940c64200060ae0c64200070980c64200080ad0c642000909a0c642000a0ac0c642000b09e0c642000c0ab0c642000d09f0c642000e0a90c642000f09d0c64200000a80c642000109c0c64200020a70c642000309b0c64200040a60c64200050990c64200060a40c64200070960c64200080a30c64200090950c642000a0a20c642000b0930c642000c0a10c642000d0920c642000e0a90c642000f09d0c', '32000c0000000080681101006411260034000c0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007e007e0102a0d102a0d102a0e0100000628102c0101000007c8078c061400004f80005080006d030059940b07010000240308e4080508e6080408e7080208eb080008ec080108ed080308f1080608f00807c0102c0308ef080808ee080a08ea080b08e8080c08e5080d08e1081008e0081408df0816c0100308de081908dc081d08db081e08da082208d3082508d1082708cb082b08ca082dc01003083a0831083b0832083d0837083e08390846083c0847083f08490840084a0845c01003084c0848084d084b085c084e085d084f085e0850086108550862085a0863085bc010030868085f08690860086a0864086d0865086e086b086f086c0870087108c90872c0100308c8087708c6087808c2087c08c1087f08c0088208bd088408bc088708b8088bc0100308b5088f08b2089108af089408ae089808ad089a08ac089e08ab089f08a9089dc010240308a9089d08a8089c08a7089b08a6089908a4089608a3089508a2089308a10892c0100c072c20030703070304020000004200080002089000000000002f00040028000000290004009000000035000400a0000000']), blobs=[
SensorCaptureProg(major=0x6, minor=0x15, build=0x0, u1=0x0, dev_type=0xbe2, a0=0x18, a1=0x19, blobs=['2300000020000800002000800000010032005c00000000802020040024200000382000002820df0b2c20df0b302000003420000050200a015c200000602000004c2003006c20500070205000742001007820010084202000b4200000bc201400c0200200c4200100c820020074030002330028000000008054202a2203005820272f03004420898103004820868e0300cc200000ef03d0200000ef033200400000000080dc20fa00e020fa00e420b400e820b400f0200500f8200500b8203a00002804001428000008280000082800001428300008280000142831001c281a003200b4020000008074030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030005740300077403000174030003740300157403001774030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030015740300177403000174030003', '330064030000008064200000e40c64200010050c64200020e60c64200030040c64200040e70c64200050020c64200060eb0c64200070000c64200080ec0c64200090010c642000a0ed0c642000b0030c642000c0f10c642000d0060c642000e0f00c642000f0070c64200000ef0c64200010080c64200020ee0c642000300a0c64200040ea0c642000500b0c64200060e80c642000700c0c64200080e50c642000900d0c642000a0e10c642000b0100c642000c0e00c642000d0140c642000e0df0c642000f0160c64200000de0c64200010190c64200020dc0c642000301d0c64200040db0c642000501e0c64200060da0c64200070220c64200080d30c64200090250c642000a0d10c642000b0270c642000c0cb0c642000d02b0c642000e0ca0c642000f02d0c642000003a0c64200010310c642000203b0c64200030320c642000403d0c64200050370c642000603e0c64200070390c64200080460c642000903c0c642000a0470c642000b03f0c642000c0490c642000d0400c642000e04a0c642000f0450c642000004c0c64200010480c642000204d0c642000304b0c642000405c0c642000504e0c642000605d0c642000704f0c642000805e0c64200090500c642000a0610c642000b0550c642000c0620c642000d05a0c642000e0630c642000f05b0c64200000680c642000105f0c64200020690c64200030600c642000406a0c64200050640c642000606d0c64200070650c642000806e0c642000906b0c642000a06f0c642000b06c0c642000c0700c642000d0710c642000e0c90c642000f0720c64200000c80c64200010770c64200020c60c64200030780c64200040c20c642000507c0c64200060c10c642000707f0c64200080c00c64200090820c642000a0bd0c642000b0840c642000c0bc0c642000d0870c642000e0b80c642000f08b0c64200000b50c642000108f0c64200020b20c64200030910c64200040af0c64200050940c64200060ae0c64200070980c64200080ad0c642000909a0c642000a0ac0c642000b09e0c642000c0ab0c642000d09f0c642000e0a90c642000f09d0c64200000a80c642000109c0c64200020a70c642000309b0c64200040a60c64200050990c64200060a40c64200070960c64200080a30c64200090950c642000a0a20c642000b0930c642000c0a10c642000d0920c642000e0a90c642000f09d0c', '32000c0000000080681101006411260034000c0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007e007e0102a0d102a0d102a0e0100000628102c0101000007c8078c061400004f80005080006d030059940b07010000240308e4080508e6080408e7080208eb080008ec080108ed080308f1080608f00807c0102c0308ef080808ee080a08ea080b08e8080c08e5080d08e1081008e0081408df0816c0100308de081908dc081d08db081e08da082208d3082508d1082708cb082b08ca082dc01003083a0831083b0832083d0837083e08390846083c0847083f08490840084a0845c01003084c0848084d084b085c084e085d084f085e0850086108550862085a0863085bc010030868085f08690860086a0864086d0865086e086b086f086c0870087108c90872c0100308c8087708c6087808c2087c08c1087f08c0088208bd088408bc088708b8088bc0100308b5088f08b2089108af089408ae089808ad089a08ac089e08ab089f08a9089dc010240308a9089d08a8089c08a7089b08a6089908a4089608a3089508a2089308a10892c0100c072c20030703070304020000004200080002089000000000002f00040028000000290004009000000035000400a0000000']), '23000000320074000000008000200000502077322820020030200000082110000c211000482105004c2105002020000024200000582000005c20000060204300682014006c2001247020012c842020008c20900190202c01942001809c200902a0200b19b4200000b8203a00bc201400c0200200c4200200c82008003300100000000080cc200000a101d0200000a10132004c0000000080dc20e803e0206401e420d002e8200001ec201400f0200500fc200000b8203a00140800000008040008080000080802001408300008080300140831001c081a004c11240050110000',
SensorCaptureProg(major=0x6, minor=0xb, build=0x0, u1=0x0, dev_type=0x194, a0=0x18, a1=0x19, blobs=['2300000020000800002000800000010032005c0000000080202004002820ff0b2c20f60b6c202f007020000074201000782000005c2000006020000064200000502000005420151d84202000942001809c200902a0200b19b4200000b8203a00bc201400c0200200c4200200c82008003300100000000080cc2000004900d0200000a1013200440000000080dc20e803e0206401e420d002e8200001f0201400f8200500fc200000b8203b00002804001428000008280000082810001428180008281100142819001c281a00', '32001400000000806811010064111f007c1700007017010033001c00000000809c1701000000ac1700900100b01754000000b417007200003400500010061110061110061110061110061001068010080101000007c80764060000002003070107010c07840a640863c91e2cc9159107010a9dc9110701030a3208330701c90f20c91e070304020000000000', '2f0004005400000029000400000000003500040010000000']), '2a00080020010100100100002c002800802080200000000000013f4000000000080f080f00000000279c1000279c10000000000000000000340040000300000007160000240a59085a0701c9500aaa07010ada08db0701c9460b2107010800800a0088c9590a5a07010aa908aa0701c91f0ac900000c040100000000',
SensorCaptureProg(major=0x6, minor=0x0, build=0x0, u1=0x0, dev_type=0x179, a0=0x18, a1=0x19, blobs=['2300000020000800002000800000010032007800000000802020040024200000382000002820df0b2c20df0b30200000342000003c20000040200000442000004820000050200a005c20000060200000642000004c200300002100006c2030007020300040210000742006007820060084202000b4200000b8203a00bc201400c0200200c4200100c820020033001c000000008054202f27030058202f270300cc200000ef03d0200000ef033200440000000080dc20e803e020e803e420d002e820d002f0200500f8200500fc200000b8203a00002804001428000008280000082800001428300008280000142831001c281a00', '320014000000008068110100641126007c1700007017010033001c00000000809c1701000000ac1700900100b01738000000b417009000003400040310060b10060b10060b10060b10060c01064e10080101000007c80764060000002003070107010c2c078408a180089f800aa108a2800a9f089e800aa208a3800a9e089d800aa308a4800a9d089c800aa408a6800a9c089b800aa608a7800a9b089a800aa708a8800a9a0899800aa808a9800a990898800aa908af800a980895800aaf08b0800a950894800ab008b1800a940893800ab108b2800a930892800ab208b3800a92088b800ab308b7800a8b088a800ab708b8800a8a0889800ab808b9800a890888800ab908ba800a880887800aba08bb800a870881800abb08bf800a810880800abf08c0800a80087f800ac008c1800a7f087e800ac108c2800a7e087d800ac208c5800a7d0872800ac508c6800a720871800ac608c7800a710870800ac708c8800a70086f800ac808c9800a6f0863800ac9086c800a630862800a6c086b800a620861800a6b086a800a610860800a6a0869800a60085f800a69085e800a5f084f800a5e085d800a4f084e800a5d085c800a4e084d800a5c085b800a4d084c800a5b085a800a4c084b800a5a0831800a4b084a800a310830800a4a0849800a30082f800a490848800a2f082e800a480847800a2e082d800a470846800a2d08ca800a46083b800aca08cb800a3b083a800acb08cc800a3a0839800acc08cd800a390838800acd08ce800a38082c800ace08d1800a2c082b800ad108d2800a2b082a800ad208d3800a2a0829800ad308d6800a290828800ad608d7800a28081d800ad708d8800a1d081c800ad808d9800a1c081b800ad908da800a1b081a800ada08de800a1a0819800ade08df800a190815800adf08e0800a150814800ae008e1800a140813800ae108e2800a130812800ae208e4800a120811800ae408e5800a11080d800ae508e6800a0d080c800ae608e7800a0c080b800ae708ea800a0b080a800aea08eb800a0a0807800aeb08ec800a070806800aec08ed800a060805800aed08ee800a050804800aee08ef800a040803800aef08f0800a030802800af008f1800a020801800af108f2800a010800802007032003070307030402000000', '2f0004003800000029000400000000003500040010000000']), '29000400000000003500040000000000'
SensorCaptureProg(major=0x6, minor=0xa, build=0x0, u1=0x0, dev_type=0x117, a0=0x18, a1=0x19, blobs=['2300000020000800002000800000010032006400000000802020040024200000382000002820df0b2c20df0b30200000342000003c2080004020800050200a005c200000602000004c2003006c20680070206800742001007820010084202000b4200000bc201400c0200200c4200100c820020074030002330028000000008054202a2203005820272f03004420898103004820868e0300cc200000ef03d0200000ef033200400000000080dc20fa00e020fa00e420b400e820b400f0200500f8200500b8203a00002804001428000008280000082800001428300008280000142831001c281a00', '32000c000000008068110100641126003400ac0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000102b0e102b0e102b0e102b0e01000000061e10301001000007c80764060b4f80005080006d030007010000006d0300200307010007032408a180089f800aa108a2800a9f089e800aa208a3800a9e089d800aa308a4800a9d089c800aa408a6800a9c089b802c0aa608a7800a9b089a800aa708a8800a9a0899800aa808a9800a990898800aa908af800a980895800aaf08b0800a950894800ab008b1800a940893800ab108b2800a930892800ab208b3800a92088b800ab308b7800a8b088a800ab708b8800a8a0889800ab808b9800a890888800ab908ba800a880887800aba08bb800a870881800abb08bf800a810880800abf08c0800a80087f800ac008c1800a7f087e800ac108c2800a7e087d800ac208c5800a7d0872800ac508c6800a72087180062807010ac608c7800a710870800ac708c8800a70086f800ac808c9800a6f0863800ac9086c800a630862800a6c086b800a620861800a6b086a800a610860800a6a0869800a60085f800a69085e800a5f084f800a5e085d800a4f084e800a5d085c800a4e084d800a5c085b800a4d084c800a5b085a800a4c084b800a5a0831800a4b084a800a310830800a4a0849800a30082f800a490848800a2f082e800a480847800a2e082d800a470846800a2d08ca800a46083b800aca08cb800a3b083a800acb08cc800a3a0839800acc08cd800a390838800acd08ce800a38082c800ace08d1800a2c082b800ad108d2800a2b082a80063207010ad208d3800a2a0829800ad308d6800a290828800ad608d7800a28081d800ad708d8800a1d081c800ad808d9800a1c081b800ad908da800a1b081a800ada08de800a1a0819800ade08df800a190815800adf08e0800a150814800ae008e1800a140813800ae108e2800a130812800ae208e4800a120811800ae408e5800a11080d800ae508e6800a0d080c800ae608e7800a0c080b800ae708ea800a0b080a800aea08eb800a0a0807800aeb08ec800a070806800aec08ed800a06080580240aed08ee800a050804800aee08ef800a040803800aef08f0800a030802800af008f1800a020801800af108f2800c0a01080080070103040200000000002f00040038000000', '290004009400000035000400a4000000']), ]),
SensorCaptureProg(major=0x6, minor=0xb, build=0x0, u1=0x0, dev_type=0x117, a0=0x18, a1=0x19, blobs=['2300000020000800002000800000010032006400000000802020040024200000382000002820df0b2c20df0b30200000342000003c2080004020800050200a005c200000602000004c2003006c20680070206800742001007820010084202000b4200000bc201400c0200200c4200100c820020074030002330028000000008054202a2203005820272f03004420898103004820868e0300cc200000ef03d0200000ef033200400000000080dc20fa00e020fa00e420b400e820b400f0200500f8200500b8203a00002804001428000008280000082800001428300008280000142831001c281a00', '32000c000000008068110100641126003400ac0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000102b0e102b0e102b0e102b0e01000000061e10301001000007c80764060b4f80005080006d030007010000006d0300200307010007032408a180089f800aa108a2800a9f089e800aa208a3800a9e089d800aa308a4800a9d089c800aa408a6800a9c089b802c0aa608a7800a9b089a800aa708a8800a9a0899800aa808a9800a990898800aa908af800a980895800aaf08b0800a950894800ab008b1800a940893800ab108b2800a930892800ab208b3800a92088b800ab308b7800a8b088a800ab708b8800a8a0889800ab808b9800a890888800ab908ba800a880887800aba08bb800a870881800abb08bf800a810880800abf08c0800a80087f800ac008c1800a7f087e800ac108c2800a7e087d800ac208c5800a7d0872800ac508c6800a72087180062807010ac608c7800a710870800ac708c8800a70086f800ac808c9800a6f0863800ac9086c800a630862800a6c086b800a620861800a6b086a800a610860800a6a0869800a60085f800a69085e800a5f084f800a5e085d800a4f084e800a5d085c800a4e084d800a5c085b800a4d084c800a5b085a800a4c084b800a5a0831800a4b084a800a310830800a4a0849800a30082f800a490848800a2f082e800a480847800a2e082d800a470846800a2d08ca800a46083b800aca08cb800a3b083a800acb08cc800a3a0839800acc08cd800a390838800acd08ce800a38082c800ace08d1800a2c082b800ad108d2800a2b082a80063207010ad208d3800a2a0829800ad308d6800a290828800ad608d7800a28081d800ad708d8800a1d081c800ad808d9800a1c081b800ad908da800a1b081a800ada08de800a1a0819800ade08df800a190815800adf08e0800a150814800ae008e1800a140813800ae108e2800a130812800ae208e4800a120811800ae408e5800a11080d800ae508e6800a0d080c800ae608e7800a0c080b800ae708ea800a0b080a800aea08eb800a0a0807800aeb08ec800a070806800aec08ed800a06080580240aed08ee800a050804800aee08ef800a040803800aef08f0800a030802800af008f1800a020801800af108f2800c0a01080080070103040200000000002f00040038000000', '290004009400000035000400a4000000']), SensorCaptureProg(
SensorCaptureProg(major=0x6, minor=0xb, build=0x0, u1=0x0, dev_type=0x126, a0=0x18, a1=0x19, blobs=['2300000020000800002000800000010032007000000000802020040024200000382000002820df0b2c20df0b30200000342000003c2080004020800050200a005c200000602000004c2003006c2068007020680074200100782001006420000084202000b4200000b8203a00bc201400c0200200c4200100c820020074030000a0030f00330028000000008054202a2203005820272f03004420898103004820868e0300cc200000ef03d0200000ef033200400000000080dc20fa00e020fa00e420b400e820b400f0200500f8200500b8203a00002804001428000008280000082800001428300008280000142831001c281a00', '32000c000000008068110100641126003400ac0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000102b0e102b0e102b0e102b0e01000000061e10301001000007c80764060b4f80005080006d030007010000006d0300200307010007032408a180089f800aa108a2800a9f089e800aa208a3800a9e089d800aa308a4800a9d089c800aa408a6800a9c089b802c0aa608a7800a9b089a800aa708a8800a9a0899800aa808a9800a990898800aa908af800a980895800aaf08b0800a950894800ab008b1800a940893800ab108b2800a930892800ab208b3800a92088b800ab308b7800a8b088a800ab708b8800a8a0889800ab808b9800a890888800ab908ba800a880887800aba08bb800a870881800abb08bf800a810880800abf08c0800a80087f800ac008c1800a7f087e800ac108c2800a7e087d800ac208c5800a7d0872800ac508c6800a72087180062807010ac608c7800a710870800ac708c8800a70086f800ac808c9800a6f0863800ac9086c800a630862800a6c086b800a620861800a6b086a800a610860800a6a0869800a60085f800a69085e800a5f084f800a5e085d800a4f084e800a5d085c800a4e084d800a5c085b800a4d084c800a5b085a800a4c084b800a5a0831800a4b084a800a310830800a4a0849800a30082f800a490848800a2f082e800a480847800a2e082d800a470846800a2d08ca800a46083b800aca08cb800a3b083a800acb08cc800a3a0839800acc08cd800a390838800acd08ce800a38082c800ace08d0800a2c082b800ad008d1800a2b082a80063207010ad108d2800a2a0829800ad208d3800a290828800ad308d6800a28081c800ad608d7800a1c081b800ad708d8800a1b081a800ad808d9800a1a0819800ad908da800a190815800ada08df800a150814800adf08e0800a140813800ae008e1800a130812800ae108e2800a120811800ae208e4800a11080e800ae408e5800a0e080d800ae508e6800a0d080c800ae608e7800a0c080b800ae708e8800a0b080a800ae808ea800a0a0807800aea08eb800a070806800aeb08ec800a06080580240aec08ed800a050804800aed08ee800a040803800aee08ef800a030802800aef08f0800a020801800af008f1800c0a01080080070c03040200000000002f00040038000000290004009400000035000400a4000000']), major=0x6,
SensorCaptureProg(major=0x6, minor=0x0, build=0x0, u1=0x0, dev_type=0xdb, a0=0x18, a1=0x19, blobs=['2300000020000800002000800000010032007000000000802020050024200000502077362820010030200100082170000c210000482102004c210000582000005c20000060200000682005006c20012970200121742001887820018084202000942001809c200902a0200b19b4200000b8203b04bc201400c0200200c4200100c82002003300100000000080cc200000f503d0200000a1013200440000000080dc20e803e0206401e420d002e8200001f0200500f8200500fc200000b8203b00000804001408000008080000080800001408300008080000140831001c081a00', '32000c0000000080501101004c1126003400080310061d10061d10061d10061d10061c01065810080101000007c8078c06100000204f80007f000003070107010c07032c08fc80095a800afc08fb800b5a095b800afb08fa800b5b095c800afa08f9800b5c095d800af908f8800b5d095e800af808f7800b5e095f800af708f6800b5f0960800af608f5800b600961800af508f4800b610962800af408f3800b620963800af308f2800b630964800af208f1800b640965800af108f0800b650966800af008ef800b660967800aef08ee800b670968800aee08ed800b68096c800aed08ec800b6c096d800aec08eb800b6d096e800aeb08ea800b6e096f800aea08e9800b6f0970800ae908e8800b700971800ae808e7800b710972800ae708e6800b720973800ae608e5800b730974800ae508e4800b740975800ae408e3800b750976800ae308e2800b760977800ae208e1800b770978800ae108e0800b780979800ae008df800b79097a800adf08de800b7a097b800ade08dd800b7b097c800add08dc800b7c097d800adc08db800b7d097e800adb08da800b7e097f800ada08d9800b7f0980800ad908d8800b800981800ad808d7800b810982800ad708d6800b820983800ad608d5800b830984800ad508d4800b840985800ad408d3800b850986800ad308d2800b860987800ad208d1800b870988800ad108d0800b880989800ad008cf800b89098a800acf08ce800b8a098b800ace08cd800b8b098c800acd08cc800b8c098d800acc08cb800b8d098e800acb08ca800b8e098f800aca08c9800b8f0990800ac908c8800b900991800ac808c7800b910992800ac708c6800b920993800ac608c5800b930994800ac508c4800b940995800ac408c3800b950996800ac308c2800b960997800ac208c1800b970998800ac108c0800b980999800ac008bf800b99099a800abf08be800b9a099b800abe08bd800b9b099c800abd08bc800b9c099d800abc08bb800b9d099e800abb08ba800b9e099f800aba08b9800b9f09a0800ab908b8800ba00801800ab808b7800a010802800ab708b6800a020803800ab608b5800a030804802003070404020000000000002f0004009000000029000400000000003500040010000000']), minor=0x8,
build=0x0,
u1=0x0,
dev_type=0x0,
a0=0x0,
a1=0x0,
blobs=[
'23000000320074000000008000200000502077322820020030200000082110000c211000482105004c2105002020000024200000582000005c20000060204300682014006c2001247020012c842020008c20900190202c01942001809c200902a0200b19b4200000b8203a00bc201400c0200200c4200200c82008003300100000000080cc200000a101d0200000a10132004c0000000080dc20e803e0206401e420d002e8200001ec201400f0200500fc200000b8203a00140800000008040008080000080802001408300008080300140831001c081a004c11240050110000',
'2a00080020010100100100002c002800802080200000000000013f4000000000080f080f00000000279c1000279c10000000000000000000340040000300000007160000240a59085a0701c9500aaa07010ada08db0701c9460b2107010800800a0088c9590a5a07010aa908aa0701c91f0ac900000c040100000000',
'29000400000000003500040000000000'
]),
SensorCaptureProg(
major=0x6,
minor=0xa,
build=0x0,
u1=0x0,
dev_type=0x0,
a0=0x0,
a1=0x0,
blobs=[
'230000003200680000000080002000002020000024200000382000002820df0b2c20df0b302000003420000050200a005c20000064204300602000004c2000006c20100070201000742005007820050084202000b4200000b8203b00bc201400c0200200c4200100c82002007403000233001c000000008054202a2203005820272f0300cc200000ef03d0200000ef033200480000000080dc20fa00e020fa00e420b400e820b400f0200500f8200500b8203b00002804001428000008280000082800001428300008280000142831001c281a006411240068110000',
'2a00080020010100100100002c002800802080200000000000013f4000000000080f080f00000000279c1000279c10000000000000000000340040000300000007160000240a59085a0701c9500aaa07010ada08db0701c9460b2107010800800a0088c9590a5a07010aa908aa0701c91f0ac900000c040100000000',
'29000400000000003500040000000000'
]),
SensorCaptureProg(
major=0x6,
minor=0xb,
build=0x0,
u1=0x0,
dev_type=0x0,
a0=0x0,
a1=0x0,
blobs=[
'230000003200680000000080002000002020000024200000382000002820df0b2c20df0b302000003420000050200a005c20000064204300602000004c2000006c20100070201000742005007820050084202000b4200000b8203b00bc201400c0200200c4200100c82002007403000233001c000000008054202a2203005820272f0300cc200000ef03d0200000ef033200480000000080dc20fa00e020fa00e420b400e820b400f0200500f8200500b8203b00002804001428000008280000082800001428300008280000142831001c281a006411240068110000',
'2a00080020010100100100002c002800802080200000000000013f4000000000080f080f00000000279c1000279c10000000000000000000340040000300000007160000240a59085a0701c9500aaa07010ada08db0701c9460b2107010800800a0088c9590a5a07010aa908aa0701c91f0ac900000c040100000000',
'29000400000000003500040000000000'
]),
SensorCaptureProg(
major=0x6,
minor=0x14,
build=0x0,
u1=0x0,
dev_type=0x0,
a0=0x0,
a1=0x0,
blobs=[
'230000003200680000000080002000002020000024200000382000002820df0b2c20df0b302000003420000050200a005c20000064204300602000004c2000006c20100070201000742005007820050084202000b4200000b8203b00bc201400c0200200c4200100c82002007403000233001c000000008054202a2203005820272f0300cc200000ef03d0200000ef033200480000000080dc20fa00e020fa00e420b400e820b400f0200500f8200500b8203b00002804001428000008280000082800001428300008280000142831001c281a006411240068110000',
'2a00080020010100100100002c002800802080200000000000013f4000000000080f080f00000000279c1000279c10000000000000000000340040000300000007160000240a59085a0701c9500aaa07010ada08db0701c9460b2107010800800a0088c9590a5a07010aa908aa0701c91f0ac900000c040100000000',
'29000400000000003500040000000000'
]),
SensorCaptureProg(
major=0x6,
minor=0x6,
build=0x0,
u1=0x0,
dev_type=0x885,
a0=0x18,
a1=0x19,
blobs=[
'23000000200008000020008000000100320074000000008020200400242000005020773628200100302001003c208000082150000c210000482105004c210000582000005c2000006020000068200a006c20014970200141742001887820018084202000942001809c200902a0200b19b4200300b8203b04bc201400c0200200c4200100c82002003300100000000080cc200000f503d0200000a1013200440000000080dc20e803e0206401e420d002e8200001f0200500f8200500fc200000b8203a00000804001408000008080000080800001408300008080000140831001c081a00',
'32000c0000000080501101004c111e00340070010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010221710221710221610221610221601066310250101000007c8078c06ff4f80006d0300200307030b90098db08d099186890b9108c180910ac190ba2c928f099382890b938889898908c881910ac8888a9189099a82890b9a8889898908d081910ad0888a9189080282890a02095a80890b5a888908d981890ad98891898a095e81890b5e8889898908e181890ae18891898a096481890b64888989096e8108e9810b6e880ae9889191ba096f828f0b6f8889918908f082890af08891898a097681890b7690b9928f08f882910af8908a8a91097c818a0b7c88090181890b018889892491097f818a0b7f900908818a0b0890898a910c0703030720040200002f0004007000000029000400700000003500040080000000'
]),
SensorCaptureProg(
major=0x6,
minor=0x7,
build=0x0,
u1=0x0,
dev_type=0x885,
a0=0x18,
a1=0x19,
blobs=[
'23000000200008000020008000000100320074000000008020200400242000005020773628200100302001003c208000082150000c210000482105004c210000582000005c2000006020000068200a006c20014970200141742001887820018084202000942001809c200902a0200b19b4200300b8203b04bc201400c0200200c4200100c82002003300100000000080cc200000f503d0200000a1013200440000000080dc20e803e0206401e420d002e8200001f0200500f8200500fc200000b8203a00000804001408000008080000080800001408300008080000140831001c081a00',
'32000c0000000080501101004c111e00340070010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010221710221710221610221610221601066310250101000007c8078c06ff4f80006d0300200307030b90098db08d099186890b9108c180910ac190ba2c928f099382890b938889898908c881910ac8888a9189099a82890b9a8889898908d081910ad0888a9189080282890a02095a80890b5a888908d981890ad98891898a095e81890b5e8889898908e181890ae18891898a096481890b64888989096e8108e9810b6e880ae9889191ba096f828f0b6f8889918908f082890af08891898a097681890b7690b9928f08f882910af8908a8a91097c818a0b7c88090181890b018889892491097f818a0b7f900908818a0b0890898a910c0703030720040200002f0004007000000029000400700000003500040080000000'
]),
SensorCaptureProg(
major=0x6,
minor=0x0,
build=0x0,
u1=0x0,
dev_type=0x1055,
a0=0x18,
a1=0x19,
blobs=[
'23000000200008000020008000000100320074000000008020200400242000005020773628200100302001003c208000082138000c210000482103004c210000582000005c20000060200000682005006c20014970200141742001887820018084202000942001809c200902a0200b19b4200300b8203b04bc201400c0200200c4200100c82002003300100000000080cc200000f503d0200000a1013200440000000080dc20e803e0206401e420d002e8200001f0200500f8200500fc200000b8203a00000804001408000008080000080800001408300008080000140831001c081a00',
'32000c0000000080501101004c111e00340070010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010221710221710221610221610221601066310250101000007c8078c06ff4f80006d0300200307030b90098db08d099186890b9108c180910ac190ba2c928f099382890b938889898908c881910ac8888a9189099a82890b9a8889898908d081910ad0888a9189080282890a02095a80890b5a888908d981890ad98891898a095e81890b5e8889898908e181890ae18891898a096481890b64888989096e8108e9810b6e880ae9889191ba096f828f0b6f8889918908f082890af08891898a097681890b7690b9928f08f882910af8908a8a91097c818a0b7c88090181890b018889892491097f818a0b7f900908818a0b0890898a910c0703030720040200002f0004007000000029000400700000003500040080000000'
]),
SensorCaptureProg(
major=0x6,
minor=0x0,
build=0x0,
u1=0x0,
dev_type=0x1825,
a0=0x18,
a1=0x19,
blobs=[
'23000000200008000020008000000100320074000000008020200400242000005020773628200100302001003c208000082138000c210000482108004c210000582000005c20000060200000682005006c20014970200141742001887820018084202000942001809c200902a0200b19b4200300b8203b04bc201400c0200200c4200100c82002003300100000000080cc200000f503d0200000a1013200440000000080dc20e803e0206401e420d002e8200001f0200500f8200500fc200000b8203a00000804001408000008080000080800001408300008080000140831001c081a00',
'32000c0000000080501101004c111e00340074010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010221710221710221610221610221601062810250101000007c8078c06ff4f80006d0300200307030990098db00b90880991858e08c1810b9190910ac1b828928a0993878a890b9388898908c88191890ac8889289099a818a890b9a88898908d08191890ad08892890802818a095a810a0288890b5a8808d98189890ad9908989095e8289890b5e88898908e18189890ae190898909648289890b648889096e8108e981890b6e880ae99091b9096f828a8f0b6f88918908f0818a890af090898909768289910b76b8918a08f88792910af8888a92097c81898a0b7c09018089890b01888991097f812089920b7f09088089920b088889920c07030307200402000000002f0004007000000029000400700000003500040080000000'
]),
SensorCaptureProg(
major=0x6,
minor=0x0,
build=0x0,
u1=0x0,
dev_type=0xb5,
a0=0x18,
a1=0x19,
blobs=[
'23000000200008000020008000000100320074000000008020200400242000005020773628200100302001003c208000082138000c210000482106004c210000582000005c20000060200000682005006c20014970200141742001887820018084202000942001809c200902a0200b19b4200300b8203b04bc201400c0200200c4200100c82002003300100000000080cc200000f503d0200000a1013200440000000080dc20e803e0206401e420d002e8200001f0200500f8200500fc200000b8203a00000804001408000008080000080800001408300008080000140831001c081a00',
'32000c0000000080501101004c111e0034007801000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001023171023171023161023161023160106635205001025010100000007c8078c06ff00004f80006d0300280307030990098db00b90880991858e08c1810b9190910ac1b8928a0993878a890b9388898908c88191890ac8889289099a818a890b9a88898908d08191890ad08892890802818a095a810a0288890b5a8808d98189890ad9908989095e8289890b5e88898908e18189890ae190898909648289890b648889096e8108e981890b6e880ae99091b9096f828a8f0b6f88918908f0818a890af090898909768289910b76b8918a08f88792910af8888a92097c81898a0b7c09018089890b01888991097f8189920b7f09088089920b088889920c07030307200402000000002f0004007000000029000400700000003500040080000000'
]),
SensorCaptureProg(
major=0x6,
minor=0x0,
build=0x0,
u1=0x0,
dev_type=0x1ff5,
a0=0x18,
a1=0x19,
blobs=[
'23000000200008000020008000000100320074000000008020200400242000005020773628200100302001003c208000082138000c210000482106004c210000582000005c20000060200000682005006c20014970200141742001887820018084202000942001809c200902a0200b19b4200300b8203b04bc201400c0200200c4200100c82002003300100000000080cc200000f503d0200000a1013200440000000080dc20e803e0206401e420d002e8200001f0200500f8200500fc200000b8203a00000804001408000008080000080800001408300008080000140831001c081a00',
'32000c0000000080501101004c111e00340074010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010221710221710221610221610221601062810250101000007c8078c06ff4f80006d0300200307030990098db00b90880991858e08c1810b9190910ac1b828928a0993878a890b9388898908c88191890ac8889289099a818a890b9a88898908d08191890ad08892890802818a095a810a0288890b5a8808d98189890ad9908989095e8289890b5e88898908e18189890ae190898909648289890b648889096e8108e981890b6e880ae99091b9096f828a8f0b6f88918908f0818a890af090898909768289910b76b8918a08f88792910af8888a92097c81898a0b7c09018089890b01888991097f812089920b7f09088089920b088889920c07030307200402000000002f0004007000000029000400700000003500040080000000'
]),
SensorCaptureProg(
major=0x6,
minor=0x7,
build=0x0,
u1=0x0,
dev_type=0x1825,
a0=0x18,
a1=0x19,
blobs=[
'23000000200008000020008000000100320074000000008020200400242000005020773628200100302001003c208000082138000c210000482108004c210000582000005c20000060200000682005006c20014970200141742001887820018084202000942001809c200902a0200b19b4200300b8203b04bc201400c0200200c4200100c82002003300100000000080cc200000f503d0200000a1013200440000000080dc20e803e0206401e420d002e8200001f0200500f8200500fc200000b8203a00000804001408000008080000080800001408300008080000140831001c081a00',
'32000c0000000080501101004c111e00340074010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010221710221710221610221610221601065010240101000007c8078c06ff00004f80006d0300280307030990098db00b90880991858e08c1810b9190910ac1b8928a0993878a890b9388898908c88191890ac8889289099a818a890b9a88898908d08191890ad08892890802818a095a810a0288890b5a8808d98189890ad9908989095e8289890b5e88898908e18189890ae190898909648289890b648889096e8108e981890b6e880ae99091b9096f828a8f0b6f88918908f0818a890af090898909768289910b76b8918a08f88792910af8888a92097c81898a0b7c09018089890b01888991097f8189920b7f09088089920b088889920c07030307200402000000002f0004007000000029000400700000003500040080000000'
]),
SensorCaptureProg(
major=0x6,
minor=0x0,
build=0x0,
u1=0x0,
dev_type=0xe4,
a0=0x18,
a1=0x19,
blobs=[
'23000000200008000020008000000100320070000000008020200400242000005020773628200100302001003c208000082138000c210000482108004c210000582000005c20000060200000682005006c20014970200141742001887820018084202000942001809c200902a0200b19b4200300bc201400c0200200c4200100c82002003300100000000080cc200000f503d0200000a1013200440000000080dc20e803e0206401e420d002e8200001f0200500f8200500fc200000b8203a00000804001408000008080000080800001408300008080000140831001c081a00',
'32000c0000000080501101004c111e00340070010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010221410221410221410221410221401066510250101000007c8078c06ff4f80006d0300280307030990098db00b90880991858e08c1810b9190910ac1b8928a0993878a890b9388898908c88191890ac8889289099a818a890b9a88898908d08191890ad08892890802818a095a810a0288890b5a8808d98189890ad9908989095e8289890b5e88898908e18189890ae190898909648289890b648889096e8108e981890b6e880ae99091b9096f828a8f0b6f88918908f0818a890af090898909768289910b76b8918a08f88792910af8888a92097c81898a0b7c09018089890b01888991097f8189920b7f09088089920b088889920c0703030720040200002f0004006400000029000400700000003500040080000000'
]),
SensorCaptureProg(
major=0x6,
minor=0x0,
build=0x0,
u1=0x0,
dev_type=0xed,
a0=0x18,
a1=0x19,
blobs=[
'23000000200008000020008000000100320074000000008020200400242000005020773628200100302001003c208000082138000c210000482104004c210000582000005c20000060200000682005006c20014970200141742001887820018084202000942001809c200902a0200b19b4200300b8203b04bc201400c0200200c4200100c82002003300100000000080cc200000f503d0200000a1013200440000000080dc20e803e0206401e420d002e8200001f0200500f8200500fc200000b8203a00000804001408000008080000080800001408300008080000140831001c081a00',
'32000c0000000080501101004c111e00340074010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010221710221710221610221610221601065010240101000007c8078c06ff00004f80006d0300280307030990098db00b90880991858e08c1810b9190910ac1b8928a0993878a890b9388898908c88191890ac8889289099a818a890b9a88898908d08191890ad08892890802818a095a810a0288890b5a8808d98189890ad9908989095e8289890b5e88898908e18189890ae190898909648289890b648889096e8108e981890b6e880ae99091b9096f828a8f0b6f88918908f0818a890af090898909768289910b76b8918a08f88792910af8888a92097c81898a0b7c09018089890b01888991097f8189920b7f09088089920b088889920c07030307200402000000002f0004007000000029000400700000003500040080000000'
]),
SensorCaptureProg(
major=0x6,
minor=0x7,
build=0x0,
u1=0x0,
dev_type=0x143b,
a0=0x18,
a1=0x19,
blobs=[
'23000000200008000020008000000100320070000000008020200400242000005020773628200100302001003c208000082138000c210000482108004c210000582000005c2000006020000068200a006c20014970200141742001887820018084202000942001809c200902a0200b19b4200300bc201400c0200200c4200100c82002003300100000000080cc200000d600d0200000a1013200440000000080dc20e803e0206401e420d002e8200001f0200500f8200500fc200000b8203a00000804001408000008080000080800001408300008080000140831001c081a00',
'32000c0000000080501101004c1117003400340200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101c11101c11101c11101c11101c10010657101e0101000007c8078c06ff00004f80006d03002c03070308c608c709930703800ac60994800ac70995800b930996800b940997800b950998800b9608c8800b9708ca800b9808cb800ac808cc800aca08ce800acb08cf800acc099a800ace099b800acf099c800b9a099d800b9b099e800b9c099f800b9d08d0800b9e08d2800b9f08d3800ad008d4800ad208d6800ad308d7800ad40802800ad60803800ad7095a800a02095b800a03095c800b5a095d800b5b08d9800b5c08da800b5d08db800ad908dd800ada08de800adb08df800add095e800ade095f800adf0960800b5e0961800b5f0962800b600963800b6108e1800b6208e2800b6308e3800ae108e5800ae208e6800ae308e7800ae50964800ae60965800ae70966800b640967800b650968800b66096e800b6708e9800b6808ea800b6e08eb800ae908ed800aea08ef800aeb08ee800aed096f800aef0970800aee0971800b6f0972800b700974800b710975800b7208f0800b7408f1800b7508f2800af008f4800af108f5800af208f6800af40976800af50977800af60979800b760978800b77097a800b79097b800b7808f8800b7a08fa800b7b08fc800af808fd800afa08fe800afc0900800c2007030307200402002f0004005400000029000400580000003500040068000000'
]),
SensorCaptureProg(
major=0x6,
minor=0x7,
build=0x0,
u1=0x0,
dev_type=0xb3,
a0=0x18,
a1=0x19,
blobs=[
'23000000200008000020008000000100320070000000008020200400242000005020773628200100302001003c208000082140000c210000482106004c210000582000005c2000006020000068200a006c20012970200121742001887820018084202000942001809c200902a0200b19b4200300bc201400c0200100c4200100c82002003300100000000080cc2000002c01d0200000a1013200440000000080dc205302e0206401e420a901e8200001f0200500f8200500fc200000b8203a00000804001408000008080000080800001408300008080000140831001c081a00',
'32000c0000000080501101004c11180034003c0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101c11101c11101c11101c11101c10010657101e0101000007c8078c06ff00004f80006d03002c0308c608c70703800ac60993800ac70994800b930995800b940996800b950997800b960998800b9708c8800b9808ca800ac808cb800aca08cc800acb08ce800acc08cf800ace099a800acf099b800b9a099c800b9b099d800b9c099e800b9d099f800b9e08d0800b9f08d2800ad008d3800ad208d4800ad308d6800ad408d7800ad60802800ad70803800a02095a800a03095b800b5a095c800b5b095d800b5c08d9800b5d08da800ad908db800ada08dd800adb08de800add08df800ade095e800adf095f800b5e0960800b5f0961800b600962800b610963800b6208e1800b6308e2800ae108e3800ae208e5800ae308e6800ae508e7800ae60964800ae70965800b640966800b650967800b660968800b67096e800b6808e9800b6e08ea800ae908eb800aea08ed800aeb08ef800aed08ee800aef096f800aee0970800b6f0971800b700972800b710974800b720975800b7408f0800b7508f1800af008f2800af108f4800af208f5800af408f6800af50976800af60977800b760979800b770978800b79097a800b78097b800b7a08f8800b7b08fa800af808fc800afa08fd800afc08fe800afd090080808080240c0703030720040200000000002f0004005400000029000400580000003500040068000000'
]),
SensorCaptureProg(
major=0x6,
minor=0x0,
build=0x0,
u1=0x0,
dev_type=0xe1,
a0=0x18,
a1=0x19,
blobs=[
'2300000020000800002000800000010032006c000000008020200400242000005020773628200100302001003c208000082138000c210000482105004c210000582000005c2000006020000068200a006c20014970200141742001887820018084203000942001809c200902a0200b19bc201400c0200200c4200100c82002003300100000000080cc2000006401d0200000a1013200440000000080dc20e803e0206401e420d002e8200001f0200500f8200500fc200000b8203b00000804001408000008080000080800001408300008080000140831001c081a00',
'32000c0000000080501101004c11160034001402000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101b10101b10101b10101b0f101b0f010656101e0101000007c8078c06ff4f80006d03002c03070308c108bf098f0703800ac10990800abf098d800b8f0991800b900992800b8d08c5800b9108c3800b9208c6800ac508c4800ac308cb800ac608c7800ac40993800acb0994800ac70995800b930997800b940996800b950998800b9708ce800b9608cc800b9808cf800ace08d0800acc08d2800acf08dd800ad0099a800ad2099b800add099c800b9a0803800b9b095a800b9c095b800a0308de800b5a08df800b5b08e1800ade08eb800adf08ed800ae108f1800aeb095c800aed0962800af10963800b5c096f800b620970800b630971800b6f08f2800b7008f5800b7108f6800af208fa800af508f8800af608fc800afa0974800af80976800afc097b800b74097a800b76097f800b7b097e800b7a08fd800b7f08fe800b7e090b800afd090c800afe090d800b0b090f800b0c0980800b0d0982800b0f0983800b80097d800b820978800b83097c800b7d0914800b780908800b7c0909800b140907800b080905800b090904800b070979800b050977800b040975800b790972800b77096c800b750936800b7209348080800c20070303072004020000002f0004004e00000029000400540000003500040064000000'
]),
SensorCaptureProg(
major=0x6,
minor=0x0,
build=0x0,
u1=0x0,
dev_type=0x8b1,
a0=0x18,
a1=0x19,
blobs=[
'2300000020000800002000800000010032006c000000008020200400242000005020773628200100302001003c208000082138000c210000482107004c210000582000005c2000006020000068200a006c20014970200141742001887820018084203000942001809c200902a0200b19bc201400c0200200c4200100c82002003300100000000080cc2000002c00d0200000a1013200440000000080dc20e803e0206401e420d002e8200001f0200500f8200500fc200000b8203a00000804001408000008080000080800001408300008080000140831001c081a00',
'32000c0000000080501101004c11160034001402000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101b10101b10101b10101b0f101b0f010656101e0101000007c8078c06ff4f80006d03002c03070308c108bf098f0703800ac10990800abf098d800b8f0991800b900992800b8d08c5800b9108c3800b9208c6800ac508c4800ac308cb800ac608c7800ac40993800acb0994800ac70995800b930997800b940996800b950998800b9708ce800b9608cc800b9808cf800ace08d0800acc08d2800acf08dd800ad0099a800ad2099b800add099c800b9a0803800b9b095a800b9c095b800a0308de800b5a08df800b5b08e1800ade08eb800adf08ed800ae108f1800aeb095c800aed0962800af10963800b5c096f800b620970800b630971800b6f08f2800b7008f5800b7108f6800af208fa800af508f8800af608fc800afa0974800af80976800afc097b800b74097a800b76097f800b7b097e800b7a08fd800b7f08fe800b7e090b800afd090c800afe090d800b0b090f800b0c0980800b0d0982800b0f0983800b80097d800b820978800b83097c800b7d0914800b780908800b7c0909800b140907800b080905800b090904800b070979800b050977800b040975800b790972800b77096c800b750936800b7209348080800c20070303072004020000002f0004004e00000029000400540000003500040064000000'
]),
SensorCaptureProg(
major=0x6,
minor=0x0,
build=0x0,
u1=0x0,
dev_type=0xea,
a0=0x18,
a1=0x19,
blobs=[
'23000000200008000020008000000100320070000000008020200400242000005020773628200100302001003c208000082138000c210000482106004c210000582000005c2000006020000068200a006c20014970200141742001887820018084202000942001809c200902a0200b19b4200300bc201400c0200200c4200100c82002003300100000000080cc200000d600d0200000a1013200440000000080dc20e803e0206401e420d002e8200001f0200500f8200500fc200000b8203b00000804001408000008080000080800001408300008080000140831001c081a00',
'32000c0000000080501101004c11170034003002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101b11101b11101b11101b11101b1001064d101d0101000007c8078c06ff00004f80006d03002c03070308c608c709930703800ac60994800ac70995800b930996800b940997800b950998800b9608c8800b9708ca800b9808cb800ac808cc800aca08ce800acb08cf800acc099a800ace099b800acf099c800b9a099d800b9b099e800b9c099f800b9d08d0800b9e08d2800b9f08d3800ad008d4800ad208d6800ad308d7800ad40802800ad60803800ad7095a800a02095b800a03095c800b5a095d800b5b08d9800b5c08da800b5d08db800ad908dd800ada08de800adb08df800add095e800ade095f800adf0960800b5e0961800b5f0962800b600963800b6108e1800b6208e2800b6308e3800ae108e5800ae208e6800ae308e7800ae50964800ae60965800ae70966800b640967800b650968800b66096e800b6708e9800b6808ea800b6e08eb800ae908ed800aea08ef800aeb08ee800aed096f800aef0970800aee0971800b6f0972800b700974800b710975800b7208f0800b7408f1800b7508f2800af008f4800af108f5800af208f6800af40976800af50977800af60979800b760978800b77097a800b79097b800b7808f8800b7a08fa800b7b08fc800af808fd800afa08fe800afc0900800c2007030307200402002f0004005400000029000400540000003500040064000000'
]),
SensorCaptureProg(
major=0x6,
minor=0x0,
build=0x0,
u1=0x0,
dev_type=0x199,
a0=0x18,
a1=0x19,
blobs=[
'23000000200008000020008000000100320074000000008020200400242000005020773628200100302001003c208000082138000c210000482107004c210000582000005c20000060200000682005006c20014970200141742001887820018084202000942001809c200902a0200b19b4200300b8203b04bc201400c0200200c4200100c82002003300100000000080cc200000f503d0200000a1013200440000000080dc20e803e0206401e420d002e8200001f0200500f8200500fc200000b8203a00000804001408000008080000080800001408300008080000140831001c081a00',
'32000c0000000080501101004c111e00340078010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010221710221710221610221610221601065010250101000007c8078c06ff0000000000004f80006d0300280307030990098db00b90880991858e08c1810b9190910ac1b8928a0993878a890b9388898908c88191890ac8889289099a818a890b9a88898908d08191890ad08892890802818a095a810a0288890b5a8808d98189890ad9908989095e8289890b5e88898908e18189890ae190898909648289890b648889096e8108e981890b6e880ae99091b9096f828a8f0b6f88918908f0818a890af090898909768289910b76b8918a08f88792910af8888a92097c81898a0b7c09018089890b01888991097f8189920b7f09088089920b088889920c07030307200402000000002f0004007000000029000400700000003500040080000000'
]),
SensorCaptureProg(
major=0x6,
minor=0x14,
build=0x0,
u1=0x0,
dev_type=0x8f3,
a0=0x18,
a1=0x19,
blobs=[
'2300000020000800002000800000010032006000000000802020040024200000382000002820df0b2c20df0b302000003420000050200a015c200000602000004c2003006c20700070207000742001007820010084202000b4200000bc201400c0200200c4200100c820020074030002a0030000330028000000008054202a2203005820272f03004420898103004820868e0300cc200000ef03d0200000ef033200400000000080dc20fa00e020fa00e420b400e820b400f0200500f8200500b8203a00002804001428000008280000082800001428300008280000142831001c281a00',
'330064030000008064200000a10c642000109f0c64200020a20c642000309e0c64200040a30c642000509d0c64200060a40c642000709c0c64200080a60c642000909b0c642000a0a70c642000b09a0c642000c0a80c642000d0990c642000e0a90c642000f0980c64200000af0c64200010950c64200020b00c64200030940c64200040b10c64200050930c64200060b20c64200070920c64200080b30c642000908b0c642000a0b70c642000b08a0c642000c0b80c642000d0890c642000e0b90c642000f0880c64200000ba0c64200010870c64200020bb0c64200030810c64200040bf0c64200050800c64200060c00c642000707f0c64200080c10c642000907e0c642000a0c20c642000b07d0c642000c0c50c642000d0720c642000e0c60c642000f0710c64200000c70c64200010700c64200020c80c642000306f0c64200040c90c64200050630c642000606c0c64200070620c642000806b0c64200090610c642000a06a0c642000b0600c642000c0690c642000d05f0c642000e05e0c642000f04f0c642000005d0c642000104e0c642000205c0c642000304d0c642000405b0c642000504c0c642000605a0c642000704b0c64200080310c642000904a0c642000a0300c642000b0490c642000c02f0c642000d0480c642000e02e0c642000f0470c642000002d0c64200010460c64200020ca0c642000303b0c64200040cb0c642000503a0c64200060cc0c64200070390c64200080cd0c64200090380c642000a0ce0c642000b02c0c642000c0d10c642000d02b0c642000e0d20c642000f02a0c64200000d30c64200010290c64200020d60c64200030280c64200040d70c642000501d0c64200060d80c642000701c0c64200080d90c642000901b0c642000a0da0c642000b01a0c642000c0de0c642000d0190c642000e0df0c642000f0150c64200000e00c64200010140c64200020e10c64200030130c64200040e20c64200050120c64200060e40c64200070110c64200080e50c642000900d0c642000a0e60c642000b00c0c642000c0e70c642000d00b0c642000e0e80c642000f00a0c64200000ea0c64200010070c64200020eb0c64200030060c64200040ec0c64200050050c64200060ed0c64200070040c64200080ee0c64200090030c642000a0ef0c642000b0020c642000c0f00c642000d0010c642000e0f10c642000f0000c',
'32000c000000008068110100641126003400180200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007e007e0102a13102a13102a12010000061e102d0101000007c8078c060b5d00005e00004f80005080006d030059940b070100002403089808a9089908a8089a08a7089b08a6089c08a4089d08a3089e08a2089f08a1c0102c03088808b9088908b8088a08b7088b08b3089208b2089308b1089408b0089508afc01003087108c6087208c5087d08c2087e08c1087f08c0088008bf088108bb088708bac0100628070103084f085e085f08690860086a0861086b0862086c086308c9086f08c8087008c7c010030847082e0848082f08490830084a0831084b085a084c085b084d085c084e085dc01003082a08d2082b08d1082c08ce083808cd083908cc083a08cb083b08ca0846082dc0100632070103081508df081908de081a08da081b08d9081c08d8081d08d7082808d6082908d3c01059940b03080a08e8080b08e7080c08e6080d08e5081108e4081208e2081308e1081408e0c0102403080008f1080108f0080208ef080308ee080408ed080508ec080608eb080708eac0100c0720070c2003040200004200080002089000000000002f00040038000000290004009000000035000400a0000000'
]),
SensorCaptureProg(
major=0x6,
minor=0x14,
build=0x0,
u1=0x0,
dev_type=0x8f6,
a0=0x18,
a1=0x19,
blobs=[
'2300000020000800002000800000010032005c00000000802020040024200000382000002820df0b2c20df0b302000003420000050200a015c200000602000004c2003006c20500070205000742000007820000084202000b4200000bc201400c0200200c4200100c820020074030002330028000000008054202a2203005820272f03004420898103004820868e0300cc200000ef03d0200000ef033200400000000080dc20fa00e020fa00e420b400e820b400f0200500f8200500b8203a00002804001428000008280000082800001428300008280000142831001c281a00330064030000008064200000a10c642000109f0c64200020a20c642000309e0c64200040a30c642000509d0c64200060a40c642000709c0c64200080a60c642000909b0c642000a0a70c642000b09a0c642000c0a80c642000d0990c642000e0a90c642000f0980c64200000af0c64200010950c64200020b00c64200030940c64200040b10c64200050930c64200060b20c64200070920c64200080b30c642000908b0c642000a0b70c642000b08a0c642000c0b80c642000d0890c642000e0b90c642000f0880c64200000ba0c64200010870c64200020bb0c64200030810c64200040bf0c64200050800c64200060c00c642000707f0c64200080c10c642000907e0c642000a0c20c642000b07d0c642000c0c50c642000d0720c642000e0c60c642000f0710c64200000c70c64200010700c64200020c80c642000306f0c64200040c90c64200050630c642000606c0c64200070620c642000806b0c64200090610c642000a06a0c642000b0600c642000c0690c642000d05f0c642000e05e0c642000f04f0c642000005d0c642000104e0c642000205c0c642000304d0c642000405b0c642000504c0c642000605a0c642000704b0c64200080310c642000904a0c642000a0300c642000b0490c642000c02f0c642000d0480c642000e02e0c642000f0470c642000002d0c64200010460c64200020ca0c642000303b0c64200040cb0c642000503a0c64200060cc0c64200070390c64200080cd0c64200090380c642000a0ce0c642000b02c0c642000c0d00c642000d02b0c642000e0d10c642000f02a0c64200000d20c64200010290c64200020d30c64200030280c64200040d60c642000501c0c64200060d70c642000701b0c64200080d80c642000901a0c642000a0d90c642000b0190c642000c0da0c642000d0150c642000e0df0c642000f0140c64200000e00c64200010130c64200020e10c64200030120c64200040e20c64200050110c64200060e40c642000700e0c64200080e50c642000900d0c642000a0e60c642000b00c0c642000c0e70c642000d00b0c642000e0e80c642000f00a0c64200000ea0c64200010070c64200020eb0c64200030060c64200040ec0c64200050050c64200060ed0c64200070040c64200080ee0c64200090030c642000a0ef0c642000b0020c642000c0f00c642000d0010c642000e0f10c642000f0000c',
'32000c0000000080681101006411260034001c0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007e007e0102a13102a13102a12010000061e102d0101000007c8078c060b5d00005e00004f80005080006d030059940b070100000720240308a1089f08a2089e08a3089d08a4089c08a6089b08a7089a08a8089908a90898c0102c0308af089508b0089408b1089308b2089208b3088b08b7088a08b8088908b90888c0100308ba088708bb088108bf088008c0087f08c1087e08c2087d08c5087208c60871c010062807010308c7087008c8086f08c90863086c0862086b0861086a08600869085f085e084fc01003085d084e085c084d085b084c085a084b0831084a08300849082f0848082e0847c01003082d084608ca083b08cb083a08cc083908cd083808ce082c08d0082b08d1082ac010063207010308d2082908d3082808d6081c08d7081b08d8081a08d9081908da081508df0814c0100308e0081308e1081208e2081108e4080e08e5080d08e6080c08e7080b08e8080ac010240308ea080708eb080608ec080508ed080408ee080308ef080208f0080108f10800c010070320030c07030703072004020000004200080002089000000000002f00040038000000',
'2f00040038000000290004009000000035000400a0000000'
]),
SensorCaptureProg(
major=0x6,
minor=0x14,
build=0x0,
u1=0x0,
dev_type=0x121,
a0=0x18,
a1=0x19,
blobs=[
'2300000020000800002000800000010032005c00000000802020040024200000382000002820df0b2c20df0b302000003420000050200a015c200000602000004c2003006c20720070207200742001007820010084202000b4200000bc201400c0200200c4200100c820020074030002330028000000008054202a2203005820272f03004420898103004820868e0300cc200000ef03d0200000ef033200400000000080dc20fa00e020fa00e420b400e820b400f0200500f8200500b8203a00002804001428000008280000082800001428300008280000142831001c281a00',
'330064030000008064200000a10c642000109f0c64200020a20c642000309e0c64200040a30c642000509d0c64200060a40c642000709c0c64200080a60c642000909b0c642000a0a70c642000b09a0c642000c0a80c642000d0990c642000e0a90c642000f0980c64200000af0c64200010950c64200020b00c64200030940c64200040b10c64200050930c64200060b20c64200070920c64200080b30c642000908b0c642000a0b70c642000b08a0c642000c0b80c642000d0890c642000e0b90c642000f0880c64200000ba0c64200010870c64200020bb0c64200030810c64200040bf0c64200050800c64200060c00c642000707f0c64200080c10c642000907e0c642000a0c20c642000b07d0c642000c0c50c642000d0720c642000e0c60c642000f0710c64200000c70c64200010700c64200020c80c642000306f0c64200040c90c642000506d0c642000607a0c642000706c0c64200080790c642000906b0c642000a0780c642000b06a0c642000c06e0c642000d0690c642000e0630c642000f05e0c64200000620c642000105d0c64200020610c642000305c0c64200040600c642000505b0c642000605f0c642000705a0c64200080310c642000904a0c642000a0300c642000b0490c642000c02f0c642000d0480c642000e02e0c642000f0470c642000002d0c64200010460c64200020ca0c642000303b0c64200040cb0c642000503a0c64200060cc0c64200070390c64200080cd0c64200090380c642000a0ce0c642000b02c0c642000c0d00c642000d02b0c642000e0d10c642000f02a0c64200000d20c64200010290c64200020d30c64200030280c64200040d60c642000501c0c64200060d70c642000701b0c64200080d80c642000901a0c642000a0d90c642000b0190c642000c0da0c642000d0150c642000e0df0c642000f0140c64200000e00c64200010130c64200020e10c64200030120c64200040e20c64200050110c64200060e40c642000700e0c64200080e50c642000900d0c642000a0e60c642000b00c0c642000c0e70c642000d00b0c642000e0e80c642000f00a0c64200000ea0c64200010070c64200020eb0c64200030060c64200040ec0c64200050050c64200060ed0c64200070040c64200080ee0c64200090030c642000a0ef0c642000b0020c642000c0f00c642000d0010c642000e0f10c642000f0000c',
'32000c000000008068110100641126003400180200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007e007e0102a13102a13102a120100000620102d0101000007c8078c060b5d00005e00004f80005080006d030059940b07010000240308a1089f08a2089e08a3089d08a4089c08a6089b08a7089a08a8089908a90898c0102c0308af089508b0089408b1089308b2089208b3088b08b7088a08b8088908b90888c0100308ba088708bb088108bf088008c0087f08c1087e08c2087d08c5087208c60871c010062807010308c7087008c8086f08c9086d087a086c0879086b0878086a086e08690863085ec010030862085d0861085c0860085b085f085a0831084a08300849082f0848082e0847c01003082d084608ca083b08cb083a08cc083908cd083808ce082c08d0082b08d1082ac010063007010308d2082908d3082808d6081c08d7081b08d8081a08d9081908da081508df0814c01059940b0308e0081308e1081208e2081108e4080e08e5080d08e6080c08e7080b08e8080ac010240308ea080708eb080608ec080508ed080408ee080308ef080208f0080108f10800c0100c0720070c2003040200004200080002089000000000002f00040038000000290004009000000035000400a0000000'
]),
SensorCaptureProg(
major=0x6,
minor=0x15,
build=0x0,
u1=0x0,
dev_type=0x121,
a0=0x18,
a1=0x19,
blobs=[
'2300000020000800002000800000010032005c00000000802020040024200000382000002820df0b2c20df0b302000003420000050200a015c200000602000004c2003006c20720070207200742001007820010084202000b4200000bc201400c0200200c4200100c820020074030002330028000000008054202a2203005820272f03004420898103004820868e0300cc200000ef03d0200000ef033200400000000080dc20fa00e020fa00e420b400e820b400f0200500f8200500b8203a00002804001428000008280000082800001428300008280000142831001c281a00',
'330064030000008064200000a10c642000109f0c64200020a20c642000309e0c64200040a30c642000509d0c64200060a40c642000709c0c64200080a60c642000909b0c642000a0a70c642000b09a0c642000c0a80c642000d0990c642000e0a90c642000f0980c64200000af0c64200010950c64200020b00c64200030940c64200040b10c64200050930c64200060b20c64200070920c64200080b30c642000908b0c642000a0b70c642000b08a0c642000c0b80c642000d0890c642000e0b90c642000f0880c64200000ba0c64200010870c64200020bb0c64200030810c64200040bf0c64200050800c64200060c00c642000707f0c64200080c10c642000907e0c642000a0c20c642000b07d0c642000c0c50c642000d0720c642000e0c60c642000f0710c64200000c70c64200010700c64200020c80c642000306f0c64200040c90c642000506d0c642000607a0c642000706c0c64200080790c642000906b0c642000a0780c642000b06a0c642000c06e0c642000d0690c642000e0630c642000f05e0c64200000620c642000105d0c64200020610c642000305c0c64200040600c642000505b0c642000605f0c642000705a0c64200080310c642000904a0c642000a0300c642000b0490c642000c02f0c642000d0480c642000e02e0c642000f0470c642000002d0c64200010460c64200020ca0c642000303b0c64200040cb0c642000503a0c64200060cc0c64200070390c64200080cd0c64200090380c642000a0ce0c642000b02c0c642000c0d00c642000d02b0c642000e0d10c642000f02a0c64200000d20c64200010290c64200020d30c64200030280c64200040d60c642000501c0c64200060d70c642000701b0c64200080d80c642000901a0c642000a0d90c642000b0190c642000c0da0c642000d0150c642000e0df0c642000f0140c64200000e00c64200010130c64200020e10c64200030120c64200040e20c64200050110c64200060e40c642000700e0c64200080e50c642000900d0c642000a0e60c642000b00c0c642000c0e70c642000d00b0c642000e0e80c642000f00a0c64200000ea0c64200010070c64200020eb0c64200030060c64200040ec0c64200050050c64200060ed0c64200070040c64200080ee0c64200090030c642000a0ef0c642000b0020c642000c0f00c642000d0010c642000e0f10c642000f0000c',
'32000c000000008068110100641126003400180200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007e007e0102a13102a13102a120100000620102d0101000007c8078c060b5d00005e00004f80005080006d030059940b07010000240308a1089f08a2089e08a3089d08a4089c08a6089b08a7089a08a8089908a90898c0102c0308af089508b0089408b1089308b2089208b3088b08b7088a08b8088908b90888c0100308ba088708bb088108bf088008c0087f08c1087e08c2087d08c5087208c60871c010062807010308c7087008c8086f08c9086d087a086c0879086b0878086a086e08690863085ec010030862085d0861085c0860085b085f085a0831084a08300849082f0848082e0847c01003082d084608ca083b08cb083a08cc083908cd083808ce082c08d0082b08d1082ac010063007010308d2082908d3082808d6081c08d7081b08d8081a08d9081908da081508df0814c01059940b0308e0081308e1081208e2081108e4080e08e5080d08e6080c08e7080b08e8080ac010240308ea080708eb080608ec080508ed080408ee080308ef080208f0080108f10800c0100c0720070c2003040200004200080002089000000000002f00040038000000290004009000000035000400a0000000'
]),
SensorCaptureProg(
major=0x6,
minor=0x14,
build=0x0,
u1=0x0,
dev_type=0xb4b,
a0=0x18,
a1=0x19,
blobs=[
'2300000020000800002000800000010032005c00000000802020040024200000382000002820df0b2c20df0b302000003420000050200a015c200000602000004c2003006c20660070206600742001007820010084202000b4200000bc201400c0200200c4200100c820020074030002330028000000008054202a2203005820272f03004420898103004820868e0300cc200000ef03d0200000ef033200400000000080dc20fa00e020fa00e420b400e820b400f0200500f8200500b8203a00002804001428000008280000082800001428300008280000142831001c281a00',
'330064030000008064200000a10c642000109f0c64200020a20c642000309e0c64200040a30c642000509d0c64200060a40c642000709c0c64200080a60c642000909b0c642000a0a70c642000b09a0c642000c0a80c642000d0990c642000e0a90c642000f0980c64200000af0c64200010950c64200020b00c64200030940c64200040b10c64200050930c64200060b20c64200070920c64200080b30c642000908b0c642000a0b70c642000b08a0c642000c0b80c642000d0890c642000e0b90c642000f0880c64200000ba0c64200010870c64200020bb0c64200030810c64200040bf0c64200050800c64200060c00c642000707f0c64200080c10c642000907e0c642000a0c20c642000b07d0c642000c0c50c642000d0720c642000e0c60c642000f0710c64200000c70c64200010700c64200020c80c642000306f0c64200040c90c642000506d0c642000607a0c642000706c0c64200080790c642000906b0c642000a0780c642000b06a0c642000c06e0c642000d0690c642000e0630c642000f05e0c64200000620c642000105d0c64200020610c642000305c0c64200040600c642000505b0c642000605f0c642000705a0c64200080310c642000904a0c642000a0300c642000b0490c642000c02f0c642000d0480c642000e02e0c642000f0470c642000002d0c64200010460c64200020ca0c642000303b0c64200040cb0c642000503a0c64200060cc0c64200070390c64200080cd0c64200090380c642000a0ce0c642000b02c0c642000c0d00c642000d02b0c642000e0d10c642000f02a0c64200000d20c64200010290c64200020d30c64200030280c64200040d60c642000501c0c64200060d70c642000701b0c64200080d80c642000901a0c642000a0d90c642000b0190c642000c0da0c642000d0150c642000e0df0c642000f0140c64200000e00c64200010130c64200020e10c64200030120c64200040e20c64200050110c64200060e40c642000700e0c64200080e50c642000900d0c642000a0e60c642000b00c0c642000c0e70c642000d00b0c642000e0e80c642000f00a0c64200000ea0c64200010070c64200020eb0c64200030060c64200040ec0c64200050050c64200060ed0c64200070040c64200080ee0c64200090030c642000a0ef0c642000b0020c642000c0f00c642000d0010c642000e0f10c642000f0000c',
'32000c000000008068110100641126003400180200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007e007e0102a13102a13102a12010000061e102d0101000007c8078c060b5d00005e00004f80005080006d030059940b07010000240308a1089f08a2089e08a3089d08a4089c08a6089b08a7089a08a8089908a90898c0102c0308af089508b0089408b1089308b2089208b3088b08b7088a08b8088908b90888c0100308ba088708bb088108bf088008c0087f08c1087e08c2087d08c5087208c60871c010062807010308c7087008c8086f08c9086d087a086c0879086b0878086a086e08690863085ec010030862085d0861085c0860085b085f085a0831084a08300849082f0848082e0847c01003082d084608ca083b08cb083a08cc083908cd083808ce082c08d0082b08d1082ac010063207010308d2082908d3082808d6081c08d7081b08d8081a08d9081908da081508df0814c01059940b0308e0081308e1081208e2081108e4080e08e5080d08e6080c08e7080b08e8080ac010240308ea080708eb080608ec080508ed080408ee080308ef080208f0080108f10800c0100c0720070c2003040200004200080002089000000000002f00040038000000290004009000000035000400a0000000'
]),
SensorCaptureProg(
major=0x6,
minor=0x15,
build=0x0,
u1=0x0,
dev_type=0xb4b,
a0=0x18,
a1=0x19,
blobs=[
'2300000020000800002000800000010032005c00000000802020040024200000382000002820df0b2c20df0b302000003420000050200a015c200000602000004c2003006c20660070206600742001007820010084202000b4200000bc201400c0200200c4200100c820020074030002330028000000008054202a2203005820272f03004420898103004820868e0300cc200000ef03d0200000ef033200400000000080dc20fa00e020fa00e420b400e820b400f0200500f8200500b8203a00002804001428000008280000082800001428300008280000142831001c281a00',
'330064030000008064200000a10c642000109f0c64200020a20c642000309e0c64200040a30c642000509d0c64200060a40c642000709c0c64200080a60c642000909b0c642000a0a70c642000b09a0c642000c0a80c642000d0990c642000e0a90c642000f0980c64200000af0c64200010950c64200020b00c64200030940c64200040b10c64200050930c64200060b20c64200070920c64200080b30c642000908b0c642000a0b70c642000b08a0c642000c0b80c642000d0890c642000e0b90c642000f0880c64200000ba0c64200010870c64200020bb0c64200030810c64200040bf0c64200050800c64200060c00c642000707f0c64200080c10c642000907e0c642000a0c20c642000b07d0c642000c0c50c642000d0720c642000e0c60c642000f0710c64200000c70c64200010700c64200020c80c642000306f0c64200040c90c642000506d0c642000607a0c642000706c0c64200080790c642000906b0c642000a0780c642000b06a0c642000c06e0c642000d0690c642000e0630c642000f05e0c64200000620c642000105d0c64200020610c642000305c0c64200040600c642000505b0c642000605f0c642000705a0c64200080310c642000904a0c642000a0300c642000b0490c642000c02f0c642000d0480c642000e02e0c642000f0470c642000002d0c64200010460c64200020ca0c642000303b0c64200040cb0c642000503a0c64200060cc0c64200070390c64200080cd0c64200090380c642000a0ce0c642000b02c0c642000c0d00c642000d02b0c642000e0d10c642000f02a0c64200000d20c64200010290c64200020d30c64200030280c64200040d60c642000501c0c64200060d70c642000701b0c64200080d80c642000901a0c642000a0d90c642000b0190c642000c0da0c642000d0150c642000e0df0c642000f0140c64200000e00c64200010130c64200020e10c64200030120c64200040e20c64200050110c64200060e40c642000700e0c64200080e50c642000900d0c642000a0e60c642000b00c0c642000c0e70c642000d00b0c642000e0e80c642000f00a0c64200000ea0c64200010070c64200020eb0c64200030060c64200040ec0c64200050050c64200060ed0c64200070040c64200080ee0c64200090030c642000a0ef0c642000b0020c642000c0f00c642000d0010c642000e0f10c642000f0000c',
'32000c000000008068110100641126003400180200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007e007e0102a13102a13102a12010000061e102d0101000007c8078c060b5d00005e00004f80005080006d030059940b07010000240308a1089f08a2089e08a3089d08a4089c08a6089b08a7089a08a8089908a90898c0102c0308af089508b0089408b1089308b2089208b3088b08b7088a08b8088908b90888c0100308ba088708bb088108bf088008c0087f08c1087e08c2087d08c5087208c60871c010062807010308c7087008c8086f08c9086d087a086c0879086b0878086a086e08690863085ec010030862085d0861085c0860085b085f085a0831084a08300849082f0848082e0847c01003082d084608ca083b08cb083a08cc083908cd083808ce082c08d0082b08d1082ac010063207010308d2082908d3082808d6081c08d7081b08d8081a08d9081908da081508df0814c01059940b0308e0081308e1081208e2081108e4080e08e5080d08e6080c08e7080b08e8080ac010240308ea080708eb080608ec080508ed080408ee080308ef080208f0080108f10800c0100c0720070c2003040200004200080002089000000000002f00040038000000290004009000000035000400a0000000'
]),
SensorCaptureProg(
major=0x6,
minor=0x14,
build=0x0,
u1=0x0,
dev_type=0xb4b,
a0=0x18,
a1=0x19,
blobs=[
'2300000020000800002000800000010032005c00000000802020040024200000382000002820df0b2c20df0b302000003420000050201f015c200000602000004c2003006c20720070207200742004007820040084202000b4200000bc201400c0200200c4200100c820020074030002330028000000008054202a2203005820272f03004420898103004820868e0300cc200000ef03d0200000ef033200400000000080dc20fa00e020fa00e420b400e820b400f0200500f8200500b8203a00002804001428000008280000082800001428300008280000142831001c281a00',
'330064030000008064200000a10c642000109f0c64200020a20c642000309e0c64200040a30c642000509d0c64200060a40c642000709c0c64200080a60c642000909b0c642000a0a70c642000b09a0c642000c0a80c642000d0990c642000e0a90c642000f0980c64200000af0c64200010950c64200020b00c64200030940c64200040b10c64200050930c64200060b20c64200070920c64200080b30c642000908b0c642000a0b70c642000b08a0c642000c0b80c642000d0890c642000e0b90c642000f0880c64200000ba0c64200010870c64200020bb0c64200030810c64200040bf0c64200050800c64200060c00c642000707f0c64200080c10c642000907e0c642000a0c20c642000b07d0c642000c0c50c642000d0720c642000e0c60c642000f0710c64200000c70c64200010700c64200020c80c642000306f0c64200040c90c642000506d0c642000607a0c642000706c0c64200080790c642000906b0c642000a0780c642000b06a0c642000c06e0c642000d0690c642000e0630c642000f05e0c64200000620c642000105d0c64200020610c642000305c0c64200040600c642000505b0c642000605f0c642000705a0c64200080310c642000904a0c642000a0300c642000b0490c642000c02f0c642000d0480c642000e02e0c642000f0470c642000002d0c64200010460c64200020ca0c642000303b0c64200040cb0c642000503a0c64200060cc0c64200070390c64200080cd0c64200090380c642000a0ce0c642000b02c0c642000c0d00c642000d02b0c642000e0d10c642000f02a0c64200000d20c64200010290c64200020d30c64200030280c64200040d60c642000501c0c64200060d70c642000701b0c64200080d80c642000901a0c642000a0d90c642000b0190c642000c0da0c642000d0150c642000e0df0c642000f0140c64200000e00c64200010130c64200020e10c64200030120c64200040e20c64200050110c64200060e40c642000700e0c64200080e50c642000900d0c642000a0e60c642000b00c0c642000c0e70c642000d00b0c642000e0e80c642000f00a0c64200000ea0c64200010070c64200020eb0c64200030060c64200040ec0c64200050050c64200060ed0c64200070040c64200080ee0c64200090030c642000a0ef0c642000b0020c642000c0f00c642000d0010c642000e0f10c642000f0000c',
'32000c000000008068110100641126003400180200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007e007e0102a13102a13102a12010000061e102d0101000007c8078c060b5d03005e03004f80005080006d030059940b07010000240308a1089f08a2089e08a3089d08a4089c08a6089b08a7089a08a8089908a90898c0102c0308af089508b0089408b1089308b2089208b3088b08b7088a08b8088908b90888c0100308ba088708bb088108bf088008c0087f08c1087e08c2087d08c5087208c60871c010062807010308c7087008c8086f08c9086d087a086c0879086b0878086a086e08690863085ec010030862085d0861085c0860085b085f085a0831084a08300849082f0848082e0847c01003082d084608ca083b08cb083a08cc083908cd083808ce082c08d0082b08d1082ac010063207010308d2082908d3082808d6081c08d7081b08d8081a08d9081908da081508df0814c01059940b0308e0081308e1081208e2081108e4080e08e5080d08e6080c08e7080b08e8080ac010240308ea080708eb080608ec080508ed080408ee080308ef080208f0080108f10800c0100c0720070c2003040200004200080002089000000000002f00040038000000290004009000000035000400a0000000'
]),
SensorCaptureProg(
major=0x6,
minor=0x15,
build=0x0,
u1=0x0,
dev_type=0xb4b,
a0=0x18,
a1=0x19,
blobs=[
'2300000020000800002000800000010032005c00000000802020040024200000382000002820df0b2c20df0b302000003420000050201f015c200000602000004c2003006c20720070207200742004007820040084202000b4200000bc201400c0200200c4200100c820020074030002330028000000008054202a2203005820272f03004420898103004820868e0300cc200000ef03d0200000ef033200400000000080dc20fa00e020fa00e420b400e820b400f0200500f8200500b8203a00002804001428000008280000082800001428300008280000142831001c281a00',
'330064030000008064200000a10c642000109f0c64200020a20c642000309e0c64200040a30c642000509d0c64200060a40c642000709c0c64200080a60c642000909b0c642000a0a70c642000b09a0c642000c0a80c642000d0990c642000e0a90c642000f0980c64200000af0c64200010950c64200020b00c64200030940c64200040b10c64200050930c64200060b20c64200070920c64200080b30c642000908b0c642000a0b70c642000b08a0c642000c0b80c642000d0890c642000e0b90c642000f0880c64200000ba0c64200010870c64200020bb0c64200030810c64200040bf0c64200050800c64200060c00c642000707f0c64200080c10c642000907e0c642000a0c20c642000b07d0c642000c0c50c642000d0720c642000e0c60c642000f0710c64200000c70c64200010700c64200020c80c642000306f0c64200040c90c642000506d0c642000607a0c642000706c0c64200080790c642000906b0c642000a0780c642000b06a0c642000c06e0c642000d0690c642000e0630c642000f05e0c64200000620c642000105d0c64200020610c642000305c0c64200040600c642000505b0c642000605f0c642000705a0c64200080310c642000904a0c642000a0300c642000b0490c642000c02f0c642000d0480c642000e02e0c642000f0470c642000002d0c64200010460c64200020ca0c642000303b0c64200040cb0c642000503a0c64200060cc0c64200070390c64200080cd0c64200090380c642000a0ce0c642000b02c0c642000c0d00c642000d02b0c642000e0d10c642000f02a0c64200000d20c64200010290c64200020d30c64200030280c64200040d60c642000501c0c64200060d70c642000701b0c64200080d80c642000901a0c642000a0d90c642000b0190c642000c0da0c642000d0150c642000e0df0c642000f0140c64200000e00c64200010130c64200020e10c64200030120c64200040e20c64200050110c64200060e40c642000700e0c64200080e50c642000900d0c642000a0e60c642000b00c0c642000c0e70c642000d00b0c642000e0e80c642000f00a0c64200000ea0c64200010070c64200020eb0c64200030060c64200040ec0c64200050050c64200060ed0c64200070040c64200080ee0c64200090030c642000a0ef0c642000b0020c642000c0f00c642000d0010c642000e0f10c642000f0000c',
'32000c000000008068110100641126003400180200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007e007e0102a13102a13102a12010000061e102d0101000007c8078c060b5d03005e03004f80005080006d030059940b07010000240308a1089f08a2089e08a3089d08a4089c08a6089b08a7089a08a8089908a90898c0102c0308af089508b0089408b1089308b2089208b3088b08b7088a08b8088908b90888c0100308ba088708bb088108bf088008c0087f08c1087e08c2087d08c5087208c60871c010062807010308c7087008c8086f08c9086d087a086c0879086b0878086a086e08690863085ec010030862085d0861085c0860085b085f085a0831084a08300849082f0848082e0847c01003082d084608ca083b08cb083a08cc083908cd083808ce082c08d0082b08d1082ac010063207010308d2082908d3082808d6081c08d7081b08d8081a08d9081908da081508df0814c01059940b0308e0081308e1081208e2081108e4080e08e5080d08e6080c08e7080b08e8080ac010240308ea080708eb080608ec080508ed080408ee080308ef080208f0080108f10800c0100c0720070c2003040200004200080002089000000000002f00040038000000290004009000000035000400a0000000'
]),
SensorCaptureProg(
major=0x6,
minor=0x14,
build=0x0,
u1=0x0,
dev_type=0xb4d,
a0=0x18,
a1=0x19,
blobs=[
'2300000020000800002000800000010032005c00000000802020040024200000382000002820df0b2c20df0b302000003420000050200a015c200000602000004c2003006c20600070206000742002007820020084202000b4200000bc201400c0200200c4200100c820020074030002330028000000008054202a2203005820272f03004420898103004820868e0300cc200000ef03d0200000ef033200400000000080dc20fa00e020fa00e420b400e820b400f0200500f8200500b8203a00002804001428000008280000082800001428300008280000142831001c281a00',
'330064030000008064200000a10c642000109f0c64200020a20c642000309e0c64200040a30c642000509d0c64200060a40c642000709c0c64200080a60c642000909b0c642000a0a70c642000b09a0c642000c0a80c642000d0990c642000e0a90c642000f0980c64200000af0c64200010950c64200020b00c64200030940c64200040b10c64200050930c64200060b20c64200070920c64200080b30c642000908b0c642000a0b70c642000b08a0c642000c0b80c642000d0890c642000e0b90c642000f0880c64200000ba0c64200010870c64200020bb0c64200030810c64200040bf0c64200050800c64200060c00c642000707f0c64200080c10c642000907e0c642000a0c20c642000b07d0c642000c0c50c642000d0720c642000e0c60c642000f0710c64200000c70c64200010700c64200020c80c642000306f0c64200040c90c642000506d0c642000607a0c642000706c0c64200080790c642000906b0c642000a0780c642000b06a0c642000c06e0c642000d0690c642000e0630c642000f05e0c64200000620c642000105d0c64200020610c642000305c0c64200040600c642000505b0c642000605f0c642000705a0c64200080310c642000904a0c642000a0300c642000b0490c642000c02f0c642000d0480c642000e02e0c642000f0470c642000002d0c64200010460c64200020ca0c642000303b0c64200040cb0c642000503a0c64200060cc0c64200070390c64200080cd0c64200090380c642000a0ce0c642000b02c0c642000c0d00c642000d02b0c642000e0d10c642000f02a0c64200000d20c64200010290c64200020d30c64200030280c64200040d60c642000501c0c64200060d70c642000701b0c64200080d80c642000901a0c642000a0d90c642000b0190c642000c0da0c642000d0150c642000e0df0c642000f0140c64200000e00c64200010130c64200020e10c64200030120c64200040e20c64200050110c64200060e40c642000700e0c64200080e50c642000900d0c642000a0e60c642000b00c0c642000c0e70c642000d00b0c642000e0e80c642000f00a0c64200000ea0c64200010070c64200020eb0c64200030060c64200040ec0c64200050050c64200060ed0c64200070040c64200080ee0c64200090030c642000a0ef0c642000b0020c642000c0f00c642000d0010c642000e0f10c642000f0000c',
'32000c000000008068110100641126003400180200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007e007e0102a13102a13102a12010000061e102d0101000007c8078c060b5d01005e01004f80005080006d030059940b07010000240308a1089f08a2089e08a3089d08a4089c08a6089b08a7089a08a8089908a90898c0102c0308af089508b0089408b1089308b2089208b3088b08b7088a08b8088908b90888c0100308ba088708bb088108bf088008c0087f08c1087e08c2087d08c5087208c60871c010062807010308c7087008c8086f08c9086d087a086c0879086b0878086a086e08690863085ec010030862085d0861085c0860085b085f085a0831084a08300849082f0848082e0847c01003082d084608ca083b08cb083a08cc083908cd083808ce082c08d0082b08d1082ac010063207010308d2082908d3082808d6081c08d7081b08d8081a08d9081908da081508df0814c01059940b0308e0081308e1081208e2081108e4080e08e5080d08e6080c08e7080b08e8080ac010240308ea080708eb080608ec080508ed080408ee080308ef080208f0080108f10800c0100c0720070c2003040200004200080002089000000000002f00040038000000290004009000000035000400a0000000'
]),
SensorCaptureProg(
major=0x6,
minor=0x15,
build=0x0,
u1=0x0,
dev_type=0xb4d,
a0=0x18,
a1=0x19,
blobs=[
'2300000020000800002000800000010032005c00000000802020040024200000382000002820df0b2c20df0b302000003420000050200a015c200000602000004c2003006c20600070206000742002007820020084202000b4200000bc201400c0200200c4200100c820020074030002330028000000008054202a2203005820272f03004420898103004820868e0300cc200000ef03d0200000ef033200400000000080dc20fa00e020fa00e420b400e820b400f0200500f8200500b8203a00002804001428000008280000082800001428300008280000142831001c281a00',
'330064030000008064200000a10c642000109f0c64200020a20c642000309e0c64200040a30c642000509d0c64200060a40c642000709c0c64200080a60c642000909b0c642000a0a70c642000b09a0c642000c0a80c642000d0990c642000e0a90c642000f0980c64200000af0c64200010950c64200020b00c64200030940c64200040b10c64200050930c64200060b20c64200070920c64200080b30c642000908b0c642000a0b70c642000b08a0c642000c0b80c642000d0890c642000e0b90c642000f0880c64200000ba0c64200010870c64200020bb0c64200030810c64200040bf0c64200050800c64200060c00c642000707f0c64200080c10c642000907e0c642000a0c20c642000b07d0c642000c0c50c642000d0720c642000e0c60c642000f0710c64200000c70c64200010700c64200020c80c642000306f0c64200040c90c642000506d0c642000607a0c642000706c0c64200080790c642000906b0c642000a0780c642000b06a0c642000c06e0c642000d0690c642000e0630c642000f05e0c64200000620c642000105d0c64200020610c642000305c0c64200040600c642000505b0c642000605f0c642000705a0c64200080310c642000904a0c642000a0300c642000b0490c642000c02f0c642000d0480c642000e02e0c642000f0470c642000002d0c64200010460c64200020ca0c642000303b0c64200040cb0c642000503a0c64200060cc0c64200070390c64200080cd0c64200090380c642000a0ce0c642000b02c0c642000c0d00c642000d02b0c642000e0d10c642000f02a0c64200000d20c64200010290c64200020d30c64200030280c64200040d60c642000501c0c64200060d70c642000701b0c64200080d80c642000901a0c642000a0d90c642000b0190c642000c0da0c642000d0150c642000e0df0c642000f0140c64200000e00c64200010130c64200020e10c64200030120c64200040e20c64200050110c64200060e40c642000700e0c64200080e50c642000900d0c642000a0e60c642000b00c0c642000c0e70c642000d00b0c642000e0e80c642000f00a0c64200000ea0c64200010070c64200020eb0c64200030060c64200040ec0c64200050050c64200060ed0c64200070040c64200080ee0c64200090030c642000a0ef0c642000b0020c642000c0f00c642000d0010c642000e0f10c642000f0000c',
'32000c000000008068110100641126003400180200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007e007e0102a13102a13102a12010000061e102d0101000007c8078c060b5d01005e01004f80005080006d030059940b07010000240308a1089f08a2089e08a3089d08a4089c08a6089b08a7089a08a8089908a90898c0102c0308af089508b0089408b1089308b2089208b3088b08b7088a08b8088908b90888c0100308ba088708bb088108bf088008c0087f08c1087e08c2087d08c5087208c60871c010062807010308c7087008c8086f08c9086d087a086c0879086b0878086a086e08690863085ec010030862085d0861085c0860085b085f085a0831084a08300849082f0848082e0847c01003082d084608ca083b08cb083a08cc083908cd083808ce082c08d0082b08d1082ac010063207010308d2082908d3082808d6081c08d7081b08d8081a08d9081908da081508df0814c01059940b0308e0081308e1081208e2081108e4080e08e5080d08e6080c08e7080b08e8080ac010240308ea080708eb080608ec080508ed080408ee080308ef080208f0080108f10800c0100c0720070c2003040200004200080002089000000000002f00040038000000290004009000000035000400a0000000'
]),
SensorCaptureProg(
major=0x6,
minor=0x15,
build=0x0,
u1=0x0,
dev_type=0x130,
a0=0x18,
a1=0x19,
blobs=[
'2300000020000800002000800000010032005c00000000802020040024200000382000002820df0b2c20df0b302000003420000050200a015c200000602000004c2003006c20400070204000742001007820010084202000b4200000bc201400c0200200c4200100c820020074030002330028000000008054202a2203005820272f03004420898103004820868e0300cc200000ef03d0200000ef033200400000000080dc20fa00e020fa00e420b400e820b400f0200500f8200500b8203a00002804001428000008280000082800001428300008280000142831001c281a003200b4020000008074030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030005740300077403000174030003740300157403001774030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030015740300177403000174030003',
'330064030000008064200000e40c64200010050c64200020e60c64200030040c64200040e70c64200050020c64200060eb0c64200070000c64200080ec0c64200090010c642000a0ed0c642000b0030c642000c0f10c642000d0060c642000e0f00c642000f0070c64200000ef0c64200010080c64200020ee0c642000300a0c64200040ea0c642000500b0c64200060e80c642000700c0c64200080e50c642000900d0c642000a0e10c642000b0100c642000c0e00c642000d0140c642000e0df0c642000f0160c64200000de0c64200010190c64200020dc0c642000301d0c64200040db0c642000501e0c64200060da0c64200070220c64200080d30c64200090250c642000a0d10c642000b0270c642000c0cb0c642000d02b0c642000e0ca0c642000f02d0c642000003a0c64200010310c642000203b0c64200030320c642000403d0c64200050370c642000603e0c64200070390c64200080460c642000903c0c642000a0470c642000b03f0c642000c0490c642000d0400c642000e04a0c642000f0450c642000004c0c64200010480c642000204d0c642000304b0c642000405c0c642000504e0c642000605d0c642000704f0c642000805e0c64200090500c642000a0610c642000b0550c642000c0620c642000d05a0c642000e0630c642000f05b0c64200000680c642000105f0c64200020690c64200030600c642000406a0c64200050640c642000606d0c64200070650c642000806e0c642000906b0c642000a06f0c642000b06c0c642000c0700c642000d0710c642000e0c90c642000f0720c64200000c80c64200010770c64200020c60c64200030780c64200040c20c642000507c0c64200060c10c642000707f0c64200080c00c64200090820c642000a0bd0c642000b0840c642000c0bc0c642000d0870c642000e0b80c642000f08b0c64200000b50c642000108f0c64200020b20c64200030910c64200040af0c64200050940c64200060ae0c64200070980c64200080ad0c642000909a0c642000a0ac0c642000b09e0c642000c0ab0c642000d09f0c642000e0a90c642000f09d0c64200000a80c642000109c0c64200020a70c642000309b0c64200040a60c64200050990c64200060a40c64200070960c64200080a30c64200090950c642000a0a20c642000b0930c642000c0a10c642000d0920c642000e0a90c642000f09d0c',
'32000c0000000080681101006411260034000c0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007e007e0102a0d102a0d102a0e0100000628102c0101000007c8078c061400004f80005080006d030059940b07010000240308e4080508e6080408e7080208eb080008ec080108ed080308f1080608f00807c0102c0308ef080808ee080a08ea080b08e8080c08e5080d08e1081008e0081408df0816c0100308de081908dc081d08db081e08da082208d3082508d1082708cb082b08ca082dc01003083a0831083b0832083d0837083e08390846083c0847083f08490840084a0845c01003084c0848084d084b085c084e085d084f085e0850086108550862085a0863085bc010030868085f08690860086a0864086d0865086e086b086f086c0870087108c90872c0100308c8087708c6087808c2087c08c1087f08c0088208bd088408bc088708b8088bc0100308b5088f08b2089108af089408ae089808ad089a08ac089e08ab089f08a9089dc010240308a9089d08a8089c08a7089b08a6089908a4089608a3089508a2089308a10892c0100c072c20030703070304020000004200080002089000000000002f00040028000000290004009000000035000400a0000000'
]),
SensorCaptureProg(
major=0x6,
minor=0x15,
build=0x0,
u1=0x0,
dev_type=0x518,
a0=0x18,
a1=0x19,
blobs=[
'2300000020000800002000800000010032005c00000000802020040024200000382000002820df0b2c20df0b302000003420000050200a015c200000602000004c2003006c20640070206400742001007820010084202000b4200000bc201400c0200200c4200100c820020074030002330028000000008054202a2203005820272f03004420898103004820868e0300cc200000ef03d0200000ef033200400000000080dc20fa00e020fa00e420b400e820b400f0200500f8200500b8203a00002804001428000008280000082800001428300008280000142831001c281a003200b4020000008074030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030005740300077403000174030003740300157403001774030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030015740300177403000174030003',
'330064030000008064200000e40c64200010050c64200020e60c64200030040c64200040e70c64200050020c64200060eb0c64200070000c64200080ec0c64200090010c642000a0ed0c642000b0030c642000c0f10c642000d0060c642000e0f00c642000f0070c64200000ef0c64200010080c64200020ee0c642000300a0c64200040ea0c642000500b0c64200060e80c642000700c0c64200080e50c642000900d0c642000a0e10c642000b0100c642000c0e00c642000d0140c642000e0df0c642000f0160c64200000de0c64200010190c64200020dc0c642000301d0c64200040db0c642000501e0c64200060da0c64200070220c64200080d30c64200090250c642000a0d10c642000b0270c642000c0cb0c642000d02b0c642000e0ca0c642000f02d0c642000003a0c64200010310c642000203b0c64200030320c642000403d0c64200050370c642000603e0c64200070390c64200080460c642000903c0c642000a0470c642000b03f0c642000c0490c642000d0400c642000e04a0c642000f0450c642000004c0c64200010480c642000204d0c642000304b0c642000405c0c642000504e0c642000605d0c642000704f0c642000805e0c64200090500c642000a0610c642000b0550c642000c0620c642000d05a0c642000e0630c642000f05b0c64200000680c642000105f0c64200020690c64200030600c642000406a0c64200050640c642000606d0c64200070650c642000806e0c642000906b0c642000a06f0c642000b06c0c642000c0700c642000d0710c642000e0c90c642000f0720c64200000c80c64200010770c64200020c60c64200030780c64200040c20c642000507c0c64200060c10c642000707f0c64200080c00c64200090820c642000a0bd0c642000b0840c642000c0bc0c642000d0870c642000e0b80c642000f08b0c64200000b50c642000108f0c64200020b20c64200030910c64200040af0c64200050940c64200060ae0c64200070980c64200080ad0c642000909a0c642000a0ac0c642000b09e0c642000c0ab0c642000d09f0c642000e0a90c642000f09d0c64200000a80c642000109c0c64200020a70c642000309b0c64200040a60c64200050990c64200060a40c64200070960c64200080a30c64200090950c642000a0a20c642000b0930c642000c0a10c642000d0920c642000e0a90c642000f09d0c',
'32000c0000000080681101006411260034000c0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007e007e0102a0d102a0d102a0e0100000628102c0101000007c8078c061400004f80005080006d030059940b07010000240308e4080508e6080408e7080208eb080008ec080108ed080308f1080608f00807c0102c0308ef080808ee080a08ea080b08e8080c08e5080d08e1081008e0081408df0816c0100308de081908dc081d08db081e08da082208d3082508d1082708cb082b08ca082dc01003083a0831083b0832083d0837083e08390846083c0847083f08490840084a0845c01003084c0848084d084b085c084e085d084f085e0850086108550862085a0863085bc010030868085f08690860086a0864086d0865086e086b086f086c0870087108c90872c0100308c8087708c6087808c2087c08c1087f08c0088208bd088408bc088708b8088bc0100308b5088f08b2089108af089408ae089808ad089a08ac089e08ab089f08a9089dc010240308a9089d08a8089c08a7089b08a6089908a4089608a3089508a2089308a10892c0100c072c20030703070304020000004200080002089000000000002f00040028000000290004009000000035000400a0000000'
]),
SensorCaptureProg(
major=0x6,
minor=0x15,
build=0x0,
u1=0x0,
dev_type=0xbe1,
a0=0x18,
a1=0x19,
blobs=[
'2300000020000800002000800000010032005c00000000802020040024200000382000002820df0b2c20df0b302000003420000050200a015c200000602000004c2003006c20550070205500742001007820010084202000b4200000bc201400c0200200c4200100c820020074030002330028000000008054202a2203005820272f03004420898103004820868e0300cc200000ef03d0200000ef033200400000000080dc20fa00e020fa00e420b400e820b400f0200500f8200500b8203a00002804001428000008280000082800001428300008280000142831001c281a003200b4020000008074030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030005740300077403000174030003740300157403001774030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030015740300177403000174030003',
'330064030000008064200000e40c64200010050c64200020e60c64200030040c64200040e70c64200050020c64200060eb0c64200070000c64200080ec0c64200090010c642000a0ed0c642000b0030c642000c0f10c642000d0060c642000e0f00c642000f0070c64200000ef0c64200010080c64200020ee0c642000300a0c64200040ea0c642000500b0c64200060e80c642000700c0c64200080e50c642000900d0c642000a0e10c642000b0100c642000c0e00c642000d0140c642000e0df0c642000f0160c64200000de0c64200010190c64200020dc0c642000301d0c64200040db0c642000501e0c64200060da0c64200070220c64200080d30c64200090250c642000a0d10c642000b0270c642000c0cb0c642000d02b0c642000e0ca0c642000f02d0c642000003a0c64200010310c642000203b0c64200030320c642000403d0c64200050370c642000603e0c64200070390c64200080460c642000903c0c642000a0470c642000b03f0c642000c0490c642000d0400c642000e04a0c642000f0450c642000004c0c64200010480c642000204d0c642000304b0c642000405c0c642000504e0c642000605d0c642000704f0c642000805e0c64200090500c642000a0610c642000b0550c642000c0620c642000d05a0c642000e0630c642000f05b0c64200000680c642000105f0c64200020690c64200030600c642000406a0c64200050640c642000606d0c64200070650c642000806e0c642000906b0c642000a06f0c642000b06c0c642000c0700c642000d0710c642000e0c90c642000f0720c64200000c80c64200010770c64200020c60c64200030780c64200040c20c642000507c0c64200060c10c642000707f0c64200080c00c64200090820c642000a0bd0c642000b0840c642000c0bc0c642000d0870c642000e0b80c642000f08b0c64200000b50c642000108f0c64200020b20c64200030910c64200040af0c64200050940c64200060ae0c64200070980c64200080ad0c642000909a0c642000a0ac0c642000b09e0c642000c0ab0c642000d09f0c642000e0a90c642000f09d0c64200000a80c642000109c0c64200020a70c642000309b0c64200040a60c64200050990c64200060a40c64200070960c64200080a30c64200090950c642000a0a20c642000b0930c642000c0a10c642000d0920c642000e0a90c642000f09d0c',
'32000c0000000080681101006411260034000c0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007e007e0102a0d102a0d102a0e0100000628102c0101000007c8078c061400004f80005080006d030059940b07010000240308e4080508e6080408e7080208eb080008ec080108ed080308f1080608f00807c0102c0308ef080808ee080a08ea080b08e8080c08e5080d08e1081008e0081408df0816c0100308de081908dc081d08db081e08da082208d3082508d1082708cb082b08ca082dc01003083a0831083b0832083d0837083e08390846083c0847083f08490840084a0845c01003084c0848084d084b085c084e085d084f085e0850086108550862085a0863085bc010030868085f08690860086a0864086d0865086e086b086f086c0870087108c90872c0100308c8087708c6087808c2087c08c1087f08c0088208bd088408bc088708b8088bc0100308b5088f08b2089108af089408ae089808ad089a08ac089e08ab089f08a9089dc010240308a9089d08a8089c08a7089b08a6089908a4089608a3089508a2089308a10892c0100c072c20030703070304020000004200080002089000000000002f00040028000000290004009000000035000400a0000000'
]),
SensorCaptureProg(
major=0x6,
minor=0x15,
build=0x0,
u1=0x0,
dev_type=0xbe2,
a0=0x18,
a1=0x19,
blobs=[
'2300000020000800002000800000010032005c00000000802020040024200000382000002820df0b2c20df0b302000003420000050200a015c200000602000004c2003006c20500070205000742001007820010084202000b4200000bc201400c0200200c4200100c820020074030002330028000000008054202a2203005820272f03004420898103004820868e0300cc200000ef03d0200000ef033200400000000080dc20fa00e020fa00e420b400e820b400f0200500f8200500b8203a00002804001428000008280000082800001428300008280000142831001c281a003200b4020000008074030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030001740300037403000174030003740300017403000374030005740300077403000174030003740300157403001774030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030001740300037403001574030017740300017403000374030015740300177403000174030003740300157403001774030015740300177403000174030003',
'330064030000008064200000e40c64200010050c64200020e60c64200030040c64200040e70c64200050020c64200060eb0c64200070000c64200080ec0c64200090010c642000a0ed0c642000b0030c642000c0f10c642000d0060c642000e0f00c642000f0070c64200000ef0c64200010080c64200020ee0c642000300a0c64200040ea0c642000500b0c64200060e80c642000700c0c64200080e50c642000900d0c642000a0e10c642000b0100c642000c0e00c642000d0140c642000e0df0c642000f0160c64200000de0c64200010190c64200020dc0c642000301d0c64200040db0c642000501e0c64200060da0c64200070220c64200080d30c64200090250c642000a0d10c642000b0270c642000c0cb0c642000d02b0c642000e0ca0c642000f02d0c642000003a0c64200010310c642000203b0c64200030320c642000403d0c64200050370c642000603e0c64200070390c64200080460c642000903c0c642000a0470c642000b03f0c642000c0490c642000d0400c642000e04a0c642000f0450c642000004c0c64200010480c642000204d0c642000304b0c642000405c0c642000504e0c642000605d0c642000704f0c642000805e0c64200090500c642000a0610c642000b0550c642000c0620c642000d05a0c642000e0630c642000f05b0c64200000680c642000105f0c64200020690c64200030600c642000406a0c64200050640c642000606d0c64200070650c642000806e0c642000906b0c642000a06f0c642000b06c0c642000c0700c642000d0710c642000e0c90c642000f0720c64200000c80c64200010770c64200020c60c64200030780c64200040c20c642000507c0c64200060c10c642000707f0c64200080c00c64200090820c642000a0bd0c642000b0840c642000c0bc0c642000d0870c642000e0b80c642000f08b0c64200000b50c642000108f0c64200020b20c64200030910c64200040af0c64200050940c64200060ae0c64200070980c64200080ad0c642000909a0c642000a0ac0c642000b09e0c642000c0ab0c642000d09f0c642000e0a90c642000f09d0c64200000a80c642000109c0c64200020a70c642000309b0c64200040a60c64200050990c64200060a40c64200070960c64200080a30c64200090950c642000a0a20c642000b0930c642000c0a10c642000d0920c642000e0a90c642000f09d0c',
'32000c0000000080681101006411260034000c0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007e007e0102a0d102a0d102a0e0100000628102c0101000007c8078c061400004f80005080006d030059940b07010000240308e4080508e6080408e7080208eb080008ec080108ed080308f1080608f00807c0102c0308ef080808ee080a08ea080b08e8080c08e5080d08e1081008e0081408df0816c0100308de081908dc081d08db081e08da082208d3082508d1082708cb082b08ca082dc01003083a0831083b0832083d0837083e08390846083c0847083f08490840084a0845c01003084c0848084d084b085c084e085d084f085e0850086108550862085a0863085bc010030868085f08690860086a0864086d0865086e086b086f086c0870087108c90872c0100308c8087708c6087808c2087c08c1087f08c0088208bd088408bc088708b8088bc0100308b5088f08b2089108af089408ae089808ad089a08ac089e08ab089f08a9089dc010240308a9089d08a8089c08a7089b08a6089908a4089608a3089508a2089308a10892c0100c072c20030703070304020000004200080002089000000000002f00040028000000290004009000000035000400a0000000'
]),
SensorCaptureProg(
major=0x6,
minor=0xb,
build=0x0,
u1=0x0,
dev_type=0x194,
a0=0x18,
a1=0x19,
blobs=[
'2300000020000800002000800000010032005c0000000080202004002820ff0b2c20f60b6c202f007020000074201000782000005c2000006020000064200000502000005420151d84202000942001809c200902a0200b19b4200000b8203a00bc201400c0200200c4200200c82008003300100000000080cc2000004900d0200000a1013200440000000080dc20e803e0206401e420d002e8200001f0201400f8200500fc200000b8203b00002804001428000008280000082810001428180008281100142819001c281a00',
'32001400000000806811010064111f007c1700007017010033001c00000000809c1701000000ac1700900100b01754000000b417007200003400500010061110061110061110061110061001068010080101000007c80764060000002003070107010c07840a640863c91e2cc9159107010a9dc9110701030a3208330701c90f20c91e070304020000000000',
'2f0004005400000029000400000000003500040010000000'
]),
SensorCaptureProg(
major=0x6,
minor=0x0,
build=0x0,
u1=0x0,
dev_type=0x179,
a0=0x18,
a1=0x19,
blobs=[
'2300000020000800002000800000010032007800000000802020040024200000382000002820df0b2c20df0b30200000342000003c20000040200000442000004820000050200a005c20000060200000642000004c200300002100006c2030007020300040210000742006007820060084202000b4200000b8203a00bc201400c0200200c4200100c820020033001c000000008054202f27030058202f270300cc200000ef03d0200000ef033200440000000080dc20e803e020e803e420d002e820d002f0200500f8200500fc200000b8203a00002804001428000008280000082800001428300008280000142831001c281a00',
'320014000000008068110100641126007c1700007017010033001c00000000809c1701000000ac1700900100b01738000000b417009000003400040310060b10060b10060b10060b10060c01064e10080101000007c80764060000002003070107010c2c078408a180089f800aa108a2800a9f089e800aa208a3800a9e089d800aa308a4800a9d089c800aa408a6800a9c089b800aa608a7800a9b089a800aa708a8800a9a0899800aa808a9800a990898800aa908af800a980895800aaf08b0800a950894800ab008b1800a940893800ab108b2800a930892800ab208b3800a92088b800ab308b7800a8b088a800ab708b8800a8a0889800ab808b9800a890888800ab908ba800a880887800aba08bb800a870881800abb08bf800a810880800abf08c0800a80087f800ac008c1800a7f087e800ac108c2800a7e087d800ac208c5800a7d0872800ac508c6800a720871800ac608c7800a710870800ac708c8800a70086f800ac808c9800a6f0863800ac9086c800a630862800a6c086b800a620861800a6b086a800a610860800a6a0869800a60085f800a69085e800a5f084f800a5e085d800a4f084e800a5d085c800a4e084d800a5c085b800a4d084c800a5b085a800a4c084b800a5a0831800a4b084a800a310830800a4a0849800a30082f800a490848800a2f082e800a480847800a2e082d800a470846800a2d08ca800a46083b800aca08cb800a3b083a800acb08cc800a3a0839800acc08cd800a390838800acd08ce800a38082c800ace08d1800a2c082b800ad108d2800a2b082a800ad208d3800a2a0829800ad308d6800a290828800ad608d7800a28081d800ad708d8800a1d081c800ad808d9800a1c081b800ad908da800a1b081a800ada08de800a1a0819800ade08df800a190815800adf08e0800a150814800ae008e1800a140813800ae108e2800a130812800ae208e4800a120811800ae408e5800a11080d800ae508e6800a0d080c800ae608e7800a0c080b800ae708ea800a0b080a800aea08eb800a0a0807800aeb08ec800a070806800aec08ed800a060805800aed08ee800a050804800aee08ef800a040803800aef08f0800a030802800af008f1800a020801800af108f2800a010800802007032003070307030402000000',
'2f0004003800000029000400000000003500040010000000'
]),
SensorCaptureProg(
major=0x6,
minor=0xa,
build=0x0,
u1=0x0,
dev_type=0x117,
a0=0x18,
a1=0x19,
blobs=[
'2300000020000800002000800000010032006400000000802020040024200000382000002820df0b2c20df0b30200000342000003c2080004020800050200a005c200000602000004c2003006c20680070206800742001007820010084202000b4200000bc201400c0200200c4200100c820020074030002330028000000008054202a2203005820272f03004420898103004820868e0300cc200000ef03d0200000ef033200400000000080dc20fa00e020fa00e420b400e820b400f0200500f8200500b8203a00002804001428000008280000082800001428300008280000142831001c281a00',
'32000c000000008068110100641126003400ac0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000102b0e102b0e102b0e102b0e01000000061e10301001000007c80764060b4f80005080006d030007010000006d0300200307010007032408a180089f800aa108a2800a9f089e800aa208a3800a9e089d800aa308a4800a9d089c800aa408a6800a9c089b802c0aa608a7800a9b089a800aa708a8800a9a0899800aa808a9800a990898800aa908af800a980895800aaf08b0800a950894800ab008b1800a940893800ab108b2800a930892800ab208b3800a92088b800ab308b7800a8b088a800ab708b8800a8a0889800ab808b9800a890888800ab908ba800a880887800aba08bb800a870881800abb08bf800a810880800abf08c0800a80087f800ac008c1800a7f087e800ac108c2800a7e087d800ac208c5800a7d0872800ac508c6800a72087180062807010ac608c7800a710870800ac708c8800a70086f800ac808c9800a6f0863800ac9086c800a630862800a6c086b800a620861800a6b086a800a610860800a6a0869800a60085f800a69085e800a5f084f800a5e085d800a4f084e800a5d085c800a4e084d800a5c085b800a4d084c800a5b085a800a4c084b800a5a0831800a4b084a800a310830800a4a0849800a30082f800a490848800a2f082e800a480847800a2e082d800a470846800a2d08ca800a46083b800aca08cb800a3b083a800acb08cc800a3a0839800acc08cd800a390838800acd08ce800a38082c800ace08d1800a2c082b800ad108d2800a2b082a80063207010ad208d3800a2a0829800ad308d6800a290828800ad608d7800a28081d800ad708d8800a1d081c800ad808d9800a1c081b800ad908da800a1b081a800ada08de800a1a0819800ade08df800a190815800adf08e0800a150814800ae008e1800a140813800ae108e2800a130812800ae208e4800a120811800ae408e5800a11080d800ae508e6800a0d080c800ae608e7800a0c080b800ae708ea800a0b080a800aea08eb800a0a0807800aeb08ec800a070806800aec08ed800a06080580240aed08ee800a050804800aee08ef800a040803800aef08f0800a030802800af008f1800a020801800af108f2800c0a01080080070103040200000000002f00040038000000',
'290004009400000035000400a4000000'
]),
SensorCaptureProg(
major=0x6,
minor=0xb,
build=0x0,
u1=0x0,
dev_type=0x117,
a0=0x18,
a1=0x19,
blobs=[
'2300000020000800002000800000010032006400000000802020040024200000382000002820df0b2c20df0b30200000342000003c2080004020800050200a005c200000602000004c2003006c20680070206800742001007820010084202000b4200000bc201400c0200200c4200100c820020074030002330028000000008054202a2203005820272f03004420898103004820868e0300cc200000ef03d0200000ef033200400000000080dc20fa00e020fa00e420b400e820b400f0200500f8200500b8203a00002804001428000008280000082800001428300008280000142831001c281a00',
'32000c000000008068110100641126003400ac0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000102b0e102b0e102b0e102b0e01000000061e10301001000007c80764060b4f80005080006d030007010000006d0300200307010007032408a180089f800aa108a2800a9f089e800aa208a3800a9e089d800aa308a4800a9d089c800aa408a6800a9c089b802c0aa608a7800a9b089a800aa708a8800a9a0899800aa808a9800a990898800aa908af800a980895800aaf08b0800a950894800ab008b1800a940893800ab108b2800a930892800ab208b3800a92088b800ab308b7800a8b088a800ab708b8800a8a0889800ab808b9800a890888800ab908ba800a880887800aba08bb800a870881800abb08bf800a810880800abf08c0800a80087f800ac008c1800a7f087e800ac108c2800a7e087d800ac208c5800a7d0872800ac508c6800a72087180062807010ac608c7800a710870800ac708c8800a70086f800ac808c9800a6f0863800ac9086c800a630862800a6c086b800a620861800a6b086a800a610860800a6a0869800a60085f800a69085e800a5f084f800a5e085d800a4f084e800a5d085c800a4e084d800a5c085b800a4d084c800a5b085a800a4c084b800a5a0831800a4b084a800a310830800a4a0849800a30082f800a490848800a2f082e800a480847800a2e082d800a470846800a2d08ca800a46083b800aca08cb800a3b083a800acb08cc800a3a0839800acc08cd800a390838800acd08ce800a38082c800ace08d1800a2c082b800ad108d2800a2b082a80063207010ad208d3800a2a0829800ad308d6800a290828800ad608d7800a28081d800ad708d8800a1d081c800ad808d9800a1c081b800ad908da800a1b081a800ada08de800a1a0819800ade08df800a190815800adf08e0800a150814800ae008e1800a140813800ae108e2800a130812800ae208e4800a120811800ae408e5800a11080d800ae508e6800a0d080c800ae608e7800a0c080b800ae708ea800a0b080a800aea08eb800a0a0807800aeb08ec800a070806800aec08ed800a06080580240aed08ee800a050804800aee08ef800a040803800aef08f0800a030802800af008f1800a020801800af108f2800c0a01080080070103040200000000002f00040038000000',
'290004009400000035000400a4000000'
]),
SensorCaptureProg(
major=0x6,
minor=0xb,
build=0x0,
u1=0x0,
dev_type=0x126,
a0=0x18,
a1=0x19,
blobs=[
'2300000020000800002000800000010032007000000000802020040024200000382000002820df0b2c20df0b30200000342000003c2080004020800050200a005c200000602000004c2003006c2068007020680074200100782001006420000084202000b4200000b8203a00bc201400c0200200c4200100c820020074030000a0030f00330028000000008054202a2203005820272f03004420898103004820868e0300cc200000ef03d0200000ef033200400000000080dc20fa00e020fa00e420b400e820b400f0200500f8200500b8203a00002804001428000008280000082800001428300008280000142831001c281a00',
'32000c000000008068110100641126003400ac0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000102b0e102b0e102b0e102b0e01000000061e10301001000007c80764060b4f80005080006d030007010000006d0300200307010007032408a180089f800aa108a2800a9f089e800aa208a3800a9e089d800aa308a4800a9d089c800aa408a6800a9c089b802c0aa608a7800a9b089a800aa708a8800a9a0899800aa808a9800a990898800aa908af800a980895800aaf08b0800a950894800ab008b1800a940893800ab108b2800a930892800ab208b3800a92088b800ab308b7800a8b088a800ab708b8800a8a0889800ab808b9800a890888800ab908ba800a880887800aba08bb800a870881800abb08bf800a810880800abf08c0800a80087f800ac008c1800a7f087e800ac108c2800a7e087d800ac208c5800a7d0872800ac508c6800a72087180062807010ac608c7800a710870800ac708c8800a70086f800ac808c9800a6f0863800ac9086c800a630862800a6c086b800a620861800a6b086a800a610860800a6a0869800a60085f800a69085e800a5f084f800a5e085d800a4f084e800a5d085c800a4e084d800a5c085b800a4d084c800a5b085a800a4c084b800a5a0831800a4b084a800a310830800a4a0849800a30082f800a490848800a2f082e800a480847800a2e082d800a470846800a2d08ca800a46083b800aca08cb800a3b083a800acb08cc800a3a0839800acc08cd800a390838800acd08ce800a38082c800ace08d0800a2c082b800ad008d1800a2b082a80063207010ad108d2800a2a0829800ad208d3800a290828800ad308d6800a28081c800ad608d7800a1c081b800ad708d8800a1b081a800ad808d9800a1a0819800ad908da800a190815800ada08df800a150814800adf08e0800a140813800ae008e1800a130812800ae108e2800a120811800ae208e4800a11080e800ae408e5800a0e080d800ae508e6800a0d080c800ae608e7800a0c080b800ae708e8800a0b080a800ae808ea800a0a0807800aea08eb800a070806800aeb08ec800a06080580240aec08ed800a050804800aed08ee800a040803800aee08ef800a030802800aef08f0800a020801800af008f1800c0a01080080070c03040200000000002f00040038000000290004009400000035000400a4000000'
]),
SensorCaptureProg(
major=0x6,
minor=0x0,
build=0x0,
u1=0x0,
dev_type=0xdb,
a0=0x18,
a1=0x19,
blobs=[
'2300000020000800002000800000010032007000000000802020050024200000502077362820010030200100082170000c210000482102004c210000582000005c20000060200000682005006c20012970200121742001887820018084202000942001809c200902a0200b19b4200000b8203b04bc201400c0200200c4200100c82002003300100000000080cc200000f503d0200000a1013200440000000080dc20e803e0206401e420d002e8200001f0200500f8200500fc200000b8203b00000804001408000008080000080800001408300008080000140831001c081a00',
'32000c0000000080501101004c1126003400080310061d10061d10061d10061d10061c01065810080101000007c8078c06100000204f80007f000003070107010c07032c08fc80095a800afc08fb800b5a095b800afb08fa800b5b095c800afa08f9800b5c095d800af908f8800b5d095e800af808f7800b5e095f800af708f6800b5f0960800af608f5800b600961800af508f4800b610962800af408f3800b620963800af308f2800b630964800af208f1800b640965800af108f0800b650966800af008ef800b660967800aef08ee800b670968800aee08ed800b68096c800aed08ec800b6c096d800aec08eb800b6d096e800aeb08ea800b6e096f800aea08e9800b6f0970800ae908e8800b700971800ae808e7800b710972800ae708e6800b720973800ae608e5800b730974800ae508e4800b740975800ae408e3800b750976800ae308e2800b760977800ae208e1800b770978800ae108e0800b780979800ae008df800b79097a800adf08de800b7a097b800ade08dd800b7b097c800add08dc800b7c097d800adc08db800b7d097e800adb08da800b7e097f800ada08d9800b7f0980800ad908d8800b800981800ad808d7800b810982800ad708d6800b820983800ad608d5800b830984800ad508d4800b840985800ad408d3800b850986800ad308d2800b860987800ad208d1800b870988800ad108d0800b880989800ad008cf800b89098a800acf08ce800b8a098b800ace08cd800b8b098c800acd08cc800b8c098d800acc08cb800b8d098e800acb08ca800b8e098f800aca08c9800b8f0990800ac908c8800b900991800ac808c7800b910992800ac708c6800b920993800ac608c5800b930994800ac508c4800b940995800ac408c3800b950996800ac308c2800b960997800ac208c1800b970998800ac108c0800b980999800ac008bf800b99099a800abf08be800b9a099b800abe08bd800b9b099c800abd08bc800b9c099d800abc08bb800b9d099e800abb08ba800b9e099f800aba08b9800b9f09a0800ab908b8800ba00801800ab808b7800a010802800ab708b6800a020803800ab608b5800a030804802003070404020000000000002f0004009000000029000400000000003500040010000000'
]),
] ]

View file

@ -1,12 +1,11 @@
class DeviceInfo:
class DeviceInfo(): def __init__(self, major: int, type: int, version: int, version_mask: int, name: str):
def __init__(self, major, type, version, version_mask, name):
self.major, self.type, self.version, self.version_mask, self.name = major, type, version, version_mask, name self.major, self.type, self.version, self.version_mask, self.name = major, type, version, version_mask, name
def __repr__(self): def __repr__(self):
return "DeviceInfo(0x%04x, 0x%04x, 0x%02x, 0x%02x, '%s')" % ( return "DeviceInfo(0x%04x, 0x%04x, 0x%02x, 0x%02x, '%s')" % (
self.major, self.type, self.version, self.version_mask, self.name self.major, self.type, self.version, self.version_mask, self.name)
)
dev_info_table = [ dev_info_table = [
DeviceInfo(0x0000, 0x0080, 0x00, 0x00, 'VSI 15A '), DeviceInfo(0x0000, 0x0080, 0x00, 0x00, 'VSI 15A '),
@ -428,7 +427,8 @@ dev_info_table=[
DeviceInfo(0x0190, 0x2449, 0xa3, 0xff, '86C TM-P3569-001 '), DeviceInfo(0x0190, 0x2449, 0xa3, 0xff, '86C TM-P3569-001 '),
] ]
def dev_info_lookup(major, ver):
def dev_info_lookup(major: int, ver: int):
fuzzy_match = None fuzzy_match = None
for i in dev_info_table: for i in dev_info_table:
@ -444,13 +444,16 @@ def dev_info_lookup(major, ver):
return fuzzy_match return fuzzy_match
class FlashIcInfo():
def __init__(self, name, size, f18, jid0, jid1, f1b, f1c, f1e, secror_size, sector_erase_cmd, f25, f26): class FlashIcInfo:
def __init__(self, name: str, size: int, f18: int, jid0: int, jid1: int, f1b: int, f1c: int,
f1e: int, secror_size: int, sector_erase_cmd: int, f25: int, f26: int):
self.name, self.size, self.f18, self.jid0, self.jid1, self.f1b, self.f1c, self.f1e, self.secror_size, self.sector_erase_cmd, self.f25, self.f26 = name, size, f18, jid0, jid1, f1b, f1c, f1e, secror_size, sector_erase_cmd, f25, f26 self.name, self.size, self.f18, self.jid0, self.jid1, self.f1b, self.f1c, self.f1e, self.secror_size, self.sector_erase_cmd, self.f25, self.f26 = name, size, f18, jid0, jid1, f1b, f1c, f1e, secror_size, sector_erase_cmd, f25, f26
def __repr__(self): def __repr__(self):
return "FlashIcInfo('%s', %d, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)" % ( return "FlashIcInfo('%s', %d, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)" % (
self.name, self.size, self.f18, self.jid0, self.jid1, self.f1b, self.f1c, self.f1e, self.secror_size, self.sector_erase_cmd, self.f25, self.f26) self.name, self.size, self.f18, self.jid0, self.jid1, self.f1b, self.f1c, self.f1e,
self.secror_size, self.sector_erase_cmd, self.f25, self.f26)
flash_ic_table = [ flash_ic_table = [
@ -476,10 +479,10 @@ flash_ic_table=[
FlashIcInfo('GD25Q80C', 1048576, 0x13, 0xc8, 0x40, 0x14, 0x0, 0x1, 0x1000, 0x20, 0x0, 0x4), FlashIcInfo('GD25Q80C', 1048576, 0x13, 0xc8, 0x40, 0x14, 0x0, 0x1, 0x1000, 0x20, 0x0, 0x4),
] ]
def flash_ic_table_lookup(jedec_id0, jedec_id1, size):
def flash_ic_table_lookup(jedec_id0: int, jedec_id1: int, size: int):
for i in flash_ic_table: for i in flash_ic_table:
if i.jid0 == jedec_id0 and i.jid1 == jedec_id1 and i.size == size: if i.jid0 == jedec_id0 and i.jid1 == jedec_id1 and i.size == size:
return i return i
return None return None

View file

@ -1,14 +1,14 @@
import atexit import atexit
import logging import logging
from validitysensor.usb import usb
from validitysensor.tls import tls
from validitysensor.sensor import sensor, reboot, RebootException
from validitysensor.flash import read_tls_flash from validitysensor.flash import read_tls_flash
from validitysensor.init_flash import init_flash
from validitysensor.upload_fwext import upload_fwext
from validitysensor.init_db import init_db from validitysensor.init_db import init_db
from validitysensor.init_flash import init_flash
from validitysensor.sensor import sensor, reboot, RebootException
from validitysensor.tls import tls
from validitysensor.upload_fwext import upload_fwext
from validitysensor.usb import usb
def close(): def close():
logging.debug('In atexit handler') logging.debug('In atexit handler')
@ -24,10 +24,11 @@ def close():
finally: finally:
usb.close() usb.close()
def open_common(): def open_common():
init_flash() init_flash()
usb.send_init() usb.send_init()
tls.parseTlsFlash(read_tls_flash()) tls.parse_tls_flash(read_tls_flash())
tls.open() tls.open()
upload_fwext() upload_fwext()
sensor.open() sensor.open()
@ -41,10 +42,12 @@ def open_common():
atexit.register(close) atexit.register(close)
logging.debug('atexit registered') logging.debug('atexit registered')
def open(): def open():
usb.open() usb.open()
open_common() open_common()
def open_devpath(busnum, address):
def open_devpath(busnum: int, address: int):
usb.open_devpath(busnum, address) usb.open_devpath(busnum, address)
open_common() open_common()

View file

@ -1,14 +1,15 @@
from struct import pack, unpack
import logging import logging
from struct import pack, unpack
from .db import db from .db import db
def machine_id_rec_value(b):
def machine_id_rec_value(b: str):
b = b.encode('utf-16le') b = b.encode('utf-16le')
b = b + b'\0' * (0x94 - len(b)) b = b + b'\0' * (0x94 - len(b))
return pack('<HH', 0x102, len(b)) + b # 0x102 = Machine ID/GUID? return pack('<HH', 0x102, len(b)) + b # 0x102 = Machine ID/GUID?
# This function is unused. It simply describes the Windows driver behavior. # This function is unused. It simply describes the Windows driver behavior.
# TODO: make this GUID unique! # TODO: make this GUID unique!
def init_machine_guid(machine_guid='e7260876-58db-4d27-8c40-8d13110d6a71'): def init_machine_guid(machine_guid='e7260876-58db-4d27-8c40-8d13110d6a71'):
@ -28,11 +29,11 @@ def init_machine_guid(machine_guid='e7260876-58db-4d27-8c40-8d13110d6a71'):
b = b.decode('utf-16le') b = b.decode('utf-16le')
raise Exception('Machine GUID does not match the DB flash ownership record (%s).' % b) raise Exception('Machine GUID does not match the DB flash ownership record (%s).' % b)
def init_db(): def init_db():
stg = db.get_user_storage(name='StgWindsor') stg = db.get_user_storage(name='StgWindsor')
if stg == None: if stg is None:
logging.info('Creating a new user storage object') logging.info('Creating a new user storage object')
db.new_user_storate() db.new_user_storate()
# init_machine_guid() # init_machine_guid()

View file

@ -1,22 +1,23 @@
import os
from struct import pack, unpack
from binascii import unhexlify
import logging
from hashlib import sha256
import hmac import hmac
import logging
import os
import typing
from binascii import unhexlify
from hashlib import sha256
from struct import pack, unpack
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import ec from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
from .blobs import reset_blob
from .flash import write_flash, erase_flash, call_cleanups, PartitionInfo, get_flash_info, FlashInfo
from .hw_tables import FlashIcInfo
from .sensor import reboot, RomInfo
from .tls import tls, hs_key, crt_hardcoded from .tls import tls, hs_key, crt_hardcoded
from .usb import usb from .usb import usb
from .flash import write_flash, erase_flash, call_cleanups, PartitionInfo, get_flash_info
from .sensor import reboot, RomInfo
from .util import assert_status, unhex from .util import assert_status, unhex
from .blobs import reset_blob
flash_layout_hardcoded = [ flash_layout_hardcoded = [
# id type access offset size # id type access offset size
@ -37,6 +38,7 @@ dbd0df42d534904de00b6389f68867646e9d7c3d0b1dffd74070b2d0f2049b9f1dc7b0c9651c59be
crypto_backend = default_backend() crypto_backend = default_backend()
def get_partition_signature(): def get_partition_signature():
if usb.usb_dev().idVendor == 0x138a: if usb.usb_dev().idVendor == 0x138a:
if usb.usb_dev().idProduct == 0x0090: if usb.usb_dev().idProduct == 0x0090:
@ -45,9 +47,10 @@ def get_partition_signature():
return partition_signature return partition_signature
def with_hdr(id, buf): def with_hdr(id: int, buf: bytes):
return pack('<HH', id, len(buf)) + buf return pack('<HH', id, len(buf)) + buf
def encrypt_key(client_private, client_public): def encrypt_key(client_private, client_public):
x = unhexlify('%064x' % client_public.x)[::-1] x = unhexlify('%064x' % client_public.x)[::-1]
y = unhexlify('%064x' % client_public.y)[::-1] y = unhexlify('%064x' % client_public.y)[::-1]
@ -65,12 +68,10 @@ def encrypt_key(client_private, client_public):
sig = hmac.new(tls.psk_validation_key, c, sha256).digest() sig = hmac.new(tls.psk_validation_key, c, sha256).digest()
return b'\x02' + c + sig return b'\x02' + c + sig
def make_cert(client_public): def make_cert(client_public):
msg=(pack('<LL', 0x17, 0x20) + msg = (pack('<LL', 0x17, 0x20) + unhexlify('%064x' % client_public.x)[::-1] + (b'\0' * 0x24) +
unhexlify('%064x' % client_public.x)[::-1] + unhexlify('%064x' % client_public.y)[::-1] + (b'\0' * 0x4c))
(b'\0'*0x24) +
unhexlify('%064x' % client_public.y)[::-1] +
(b'\0'*0x4c))
pk = ec.derive_private_key(hs_key(), ec.SECP256R1(), backend=crypto_backend) pk = ec.derive_private_key(hs_key(), ec.SECP256R1(), backend=crypto_backend)
s = pk.sign(msg, ec.ECDSA(hashes.SHA256())) s = pk.sign(msg, ec.ECDSA(hashes.SHA256()))
s = pack('<L', len(s)) + s s = pack('<L', len(s)) + s
@ -78,20 +79,24 @@ def make_cert(client_public):
msg += b'\0' * (444 - len(msg)) # FIXME not sure this math is right msg += b'\0' * (444 - len(msg)) # FIXME not sure this math is right
return msg return msg
def serialize_flash_params(ic):
def serialize_flash_params(ic: FlashIcInfo):
return pack('<LLxxBx', ic.size, ic.secror_size, ic.sector_erase_cmd) return pack('<LLxxBx', ic.size, ic.secror_size, ic.sector_erase_cmd)
def serialize_partition(p):
def serialize_partition(p: PartitionInfo):
b = pack('<BBHLL', p.id, p.type, p.access_lvl, p.offset, p.size) b = pack('<BBHLL', p.id, p.type, p.access_lvl, p.offset, p.size)
b = b + b'\0' * 4 + sha256(b).digest() b = b + b'\0' * 4 + sha256(b).digest()
return b return b
def partition_flash(info, layout, client_public):
def partition_flash(info: FlashInfo, layout: typing.List[PartitionInfo], client_public):
logging.info('Detected Flash IC: %s, %d bytes' % (info.ic.name, info.ic.size)) logging.info('Detected Flash IC: %s, %d bytes' % (info.ic.name, info.ic.size))
cmd = unhex('4f 0000 0000') cmd = unhex('4f 0000 0000')
cmd += with_hdr(0, serialize_flash_params(info.ic)) cmd += with_hdr(0, serialize_flash_params(info.ic))
cmd += with_hdr(1, b''.join([serialize_partition(p) for p in layout]) + get_partition_signature()) cmd += with_hdr(1,
b''.join([serialize_partition(p) for p in layout]) + get_partition_signature())
cmd += with_hdr(5, make_cert(client_public)) cmd += with_hdr(5, make_cert(client_public))
cmd += with_hdr(3, crt_hardcoded) cmd += with_hdr(3, crt_hardcoded)
rsp = tls.cmd(cmd) rsp = tls.cmd(cmd)
@ -103,6 +108,7 @@ def partition_flash(info, layout, client_public):
rsp = rsp[crt_len:] rsp = rsp[crt_len:]
# ^ TODO - figure out what the rest of rsp means # ^ TODO - figure out what the rest of rsp means
def init_flash(): def init_flash():
info = get_flash_info() info = get_flash_info()
@ -153,7 +159,7 @@ def init_flash():
erase_flash(4) erase_flash(4)
# Persist certs and keys on cert partition. # Persist certs and keys on cert partition.
write_flash(1, 0, tls.makeTlsFlash()) write_flash(1, 0, tls.make_tls_flash())
# Reboot. # Reboot.
# The device will disconnect and our service will be started by udev as soon as it is connected again. # The device will disconnect and our service will be started by udev as soon as it is connected again.

View file

@ -1,39 +1,51 @@
import logging
import os.path
import typing import typing
from binascii import hexlify, unhexlify
from enum import Enum from enum import Enum
from hashlib import sha256 from hashlib import sha256
import os.path from struct import pack, unpack
import logging from time import sleep
from usb import core as usb_core from usb import core as usb_core
from .tls import tls
from .usb import usb, CancelledException from . import timeslot as prg
from .blobs import reset_blob
from .db import db, SidIdentity from .db import db, SidIdentity
from .flash import write_enable, call_cleanups, read_flash, erase_flash, write_flash_all, read_flash_all from .flash import write_enable, call_cleanups, read_flash, erase_flash, write_flash_all, read_flash_all
from time import sleep
from struct import pack, unpack
from .table_types import SensorTypeInfo, SensorCaptureProg
from binascii import hexlify, unhexlify
from .util import assert_status, unhex
from .hw_tables import dev_info_lookup from .hw_tables import dev_info_lookup
from .blobs import reset_blob from .table_types import SensorTypeInfo, SensorCaptureProg
from . import timeslot as prg from .tls import tls
from .usb import usb, CancelledException
from .util import assert_status, unhex
# TODO: this should be specific to an individual device (system may have more than one sensor) # TODO: this should be specific to an individual device (system may have more than one sensor)
calib_data_path = '/usr/share/python-validity/calib-data.bin' calib_data_path = '/usr/share/python-validity/calib-data.bin'
line_update_type1_devices = [ 0xB5, 0x885, 0xB3, 0x143B, 0x1055, 0xE1, 0x8B1, 0xEA, 0xE4, 0xED, 0x1825, 0x1FF5, 0x199 ] line_update_type1_devices = [
0xB5, 0x885, 0xB3, 0x143B, 0x1055, 0xE1, 0x8B1, 0xEA, 0xE4, 0xED, 0x1825, 0x1FF5, 0x199
]
# TODO use more sophisticated glow patters in different cases # TODO use more sophisticated glow patters in different cases
def glow_start_scan(): def glow_start_scan():
cmd=unhexlify('3920bf0200ffff0000019900200000000099990000000000000000000000000020000000000000000000000000ffff000000990020000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000') cmd = unhexlify(
'3920bf0200ffff0000019900200000000099990000000000000000000000000020000000000000000000000000ffff000000990020000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
)
assert_status(tls.app(cmd)) assert_status(tls.app(cmd))
def glow_end_scan(): def glow_end_scan():
cmd=unhexlify('39f4010000f401000001ff002000000000ffff0000000000000000000000000020000000000000000000000000f401000000ff0020000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000') cmd = unhexlify(
'39f4010000f401000001ff002000000000ffff0000000000000000000000000020000000000000000000000000f401000000ff0020000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
)
assert_status(tls.app(cmd)) assert_status(tls.app(cmd))
def get_prg_status(): def get_prg_status():
return tls.app(unhexlify('5100000000')) return tls.app(unhexlify('5100000000'))
def wait_till_finished(): def wait_till_finished():
while True: while True:
status = get_prg_status() status = get_prg_status()
@ -43,33 +55,39 @@ def wait_till_finished():
sleep(0.2) sleep(0.2)
def get_prg_status2(): def get_prg_status2():
return tls.app(unhexlify('5100200000')) return tls.app(unhexlify('5100200000'))
def read_hw_reg32(addr): def read_hw_reg32(addr: int):
rsp = tls.cmd(pack('<BLB', 7, addr, 4)) rsp = tls.cmd(pack('<BLB', 7, addr, 4))
assert_status(rsp) assert_status(rsp)
rsp, = unpack('<L', rsp[2:]) rsp, = unpack('<L', rsp[2:])
return rsp return rsp
def write_hw_reg32(addr, val):
def write_hw_reg32(addr: int, val: int):
rsp = tls.cmd(pack('<BLLB', 8, addr, val, 4)) rsp = tls.cmd(pack('<BLLB', 8, addr, val, 4))
assert_status(rsp) assert_status(rsp)
class RebootException(Exception): class RebootException(Exception):
pass pass
def reboot(): def reboot():
assert_status(tls.cmd(unhex('050200'))) assert_status(tls.cmd(unhex('050200')))
raise RebootException() raise RebootException()
def factory_reset(): def factory_reset():
assert_status(usb.cmd(reset_blob)) assert_status(usb.cmd(reset_blob))
assert_status(usb.cmd(b'\x10' + b'\0' * 0x61)) assert_status(usb.cmd(b'\x10' + b'\0' * 0x61))
reboot() reboot()
class RomInfo():
class RomInfo:
@classmethod @classmethod
def get(cls): def get(cls):
rsp = tls.cmd(b'\x01') rsp = tls.cmd(b'\x01')
@ -77,7 +95,7 @@ class RomInfo():
rsp = rsp[2:] rsp = rsp[2:]
return cls(*unpack('<LLBBxBxxxB', rsp[0:0x10])) return cls(*unpack('<LLBBxBxxxB', rsp[0:0x10]))
def __init__(self, timestamp, build, major, minor, product, u1): def __init__(self, timestamp: int, build: int, major: int, minor: int, product: int, u1: int):
self.timestamp, self.build, self.major, self.minor, self.product, self.u1 = timestamp, build, major, minor, product, u1 self.timestamp, self.build, self.major, self.minor, self.product, self.u1 = timestamp, build, major, minor, product, u1
def __repr__(self): def __repr__(self):
@ -97,6 +115,7 @@ def identify_sensor():
return dev_info_lookup(major, minor) return dev_info_lookup(major, minor)
# <<< 0000 880d 0000 07000000 # <<< 0000 880d 0000 07000000
# 08000000 9400 0e00 0300 0080 07000000 7e7f807f808080808080808080808080808080808080818081808180818080808080818081808080818081808180 # 08000000 9400 0e00 0300 0080 07000000 7e7f807f808080808080808080808080808080808080818081808180818080808080818081808080818081808180
# a4000000 0800 0e00 0200 0000 00000000 0d007100 # a4000000 0800 0e00 0200 0000 00000000 0d007100
@ -105,7 +124,7 @@ def identify_sensor():
# d0000000 9400 0e00 0700 0080 07000000 2b23203c2d182e1e30182e1c321d341d341e321c301e1e241e201f201d1c321a301e1c211e21341f1e202024201f # d0000000 9400 0e00 0700 0080 07000000 2b23203c2d182e1e30182e1c321d341d341e321c301e1e241e201f201d1c321a301e1c211e21341f1e202024201f
# 6c010000 1400 0e00 0f00 0080 05550007 7701002805720000080100020811e107 # 6c010000 1400 0e00 0f00 0080 05550007 7701002805720000080100020811e107
# 88010000 0c00 0e00 1200 0080 07000000 7002 7800 7002 7800 # 88010000 0c00 0e00 1200 0080 07000000 7002 7800 7002 7800
def get_factory_bits(tag): def get_factory_bits(tag: int):
rsp = tls.cmd(pack('<B H HL', 0x6f, tag, 0, 0)) rsp = tls.cmd(pack('<B H HL', 0x6f, tag, 0, 0))
assert_status(rsp) assert_status(rsp)
rsp = rsp[2:] rsp = rsp[2:]
@ -154,17 +173,20 @@ def bitpack(b):
# convert back to bytes # convert back to bytes
b = b.to_bytes((u * l + 7) // 8, 'little') b = b.to_bytes((u * l + 7) // 8, 'little')
return (u, m, b) return u, m, b
class Line():
mask=None
flags=None
data=None
v0=0
v1=0
v2=0
def clip(x): class Line:
def __init__(self):
self.mask: typing.Optional[int] = None
self.flags: typing.Optional[int] = None
self.data: typing.Optional[bytes] = None
self.v0 = 0
self.v1 = 0
self.v2 = 0
def clip(x: int):
if x < -128: if x < -128:
x = -128 x = -128
@ -173,26 +195,30 @@ def clip(x):
return x & 0xff return x & 0xff
def scale(x):
def scale(x: int):
x -= 0x80 x -= 0x80
x = int(x * 10 / 0x22) # TODO: scaling factor depends on a device x = int(x * 10 / 0x22) # TODO: scaling factor depends on a device
return clip(x) return clip(x)
def add(l, r): def add(l: int, r: int):
# Make signed # Make signed
l, r = unpack('bb', pack('BB', l, r)) l, r = unpack('bb', pack('BB', l, r))
return clip(l + r) return clip(l + r)
def chunks(b, l):
def chunks(b: bytes, l: int):
return [b[i:i + l] for i in range(0, len(b), l)] return [b[i:i + l] for i in range(0, len(b), l)]
class CaptureMode(Enum): class CaptureMode(Enum):
CALIBRATE = 1 CALIBRATE = 1
IDENTIFY = 2 IDENTIFY = 2
ENROLL = 3 ENROLL = 3
class Sensor():
class Sensor:
calib_data = b'' calib_data = b''
def open(self): def open(self):
@ -210,16 +236,20 @@ class Sensor():
self.calibration_frames = 6 # TODO: workout where it's really comming from self.calibration_frames = 6 # TODO: workout where it's really comming from
self.calibration_iterations = 0 self.calibration_iterations = 0
else: else:
raise Exception('Device %s is not supported (sensor type 0x%x)' % (self.device_info.name, self.device_info.type)) raise Exception('Device %s is not supported (sensor type 0x%x)' %
(self.device_info.name, self.device_info.type))
self.rom_info = RomInfo.get() self.rom_info = RomInfo.get()
self.hardcoded_prog = SensorCaptureProg.get(self.rom_info, self.device_info.type, 0x18, 0x19) # TODO: find where 0x18, 0x19 coming from self.hardcoded_prog = SensorCaptureProg.get(self.rom_info, self.device_info.type, 0x18,
0x19) # TODO: find where 0x18, 0x19 coming from
if self.hardcoded_prog is None: if self.hardcoded_prog is None:
raise Exception('Can\'t find initial capture program for rom %s and sensor type %x' % (repr(self.rom_info), self.device_info.type)) raise Exception('Can\'t find initial capture program for rom %s and sensor type %x' %
(repr(self.rom_info), self.device_info.type))
# Look for a "2D" chunk. It must have a 32 bit integer which represent the number of lines per frame # Look for a "2D" chunk. It must have a 32 bit integer which represent the number of lines per frame
lines_2d = [unpack('<L', v)[0] for [k, v] in prg.split_chunks(self.hardcoded_prog) if k == 0x2f][0] lines_2d = [
unpack('<L', v)[0] for [k, v] in prg.split_chunks(self.hardcoded_prog) if k == 0x2f
][0]
self.lines_per_frame = lines_2d * self.type_info.repeat_multiplier self.lines_per_frame = lines_2d * self.type_info.repeat_multiplier
self.bytes_per_line = self.type_info.bytes_per_line self.bytes_per_line = self.type_info.bytes_per_line
@ -237,7 +267,7 @@ class Sensor():
# This is the exact logic from the DLL. # This is the exact logic from the DLL.
# If it looks broken that was probably intended. # If it looks broken that was probably intended.
def patch_timeslot_table(self, b, inc_address, mult): def patch_timeslot_table(self, b: bytes, inc_address: bool, mult: int):
b = bytearray(b) b = bytearray(b)
i = 0 i = 0
while i + 3 < len(b): while i + 3 < len(b):
@ -261,7 +291,7 @@ class Sensor():
return bytes(b) return bytes(b)
def patch_timeslot_again(self, b): def patch_timeslot_again(self, b: bytes):
b = bytearray(b) b = bytearray(b)
pc = 0 pc = 0
@ -307,7 +337,7 @@ class Sensor():
return bytes(b) return bytes(b)
def average(self, raw_calib_data): def average(self, raw_calib_data: bytes):
frame_size = self.lines_per_frame * self.bytes_per_line frame_size = self.lines_per_frame * self.bytes_per_line
interleave_lines = self.lines_per_frame // self.type_info.lines_per_calibration_data # 2, TODO: algo is quite different when it is 1 interleave_lines = self.lines_per_frame // self.type_info.lines_per_calibration_data # 2, TODO: algo is quite different when it is 1
input_frames = self.calibration_frames input_frames = self.calibration_frames
@ -342,7 +372,7 @@ class Sensor():
return frame return frame
def process_calibration_results(self, cooked_data): def process_calibration_results(self, cooked_data: bytes):
frame = chunks(cooked_data, self.bytes_per_line) frame = chunks(cooked_data, self.bytes_per_line)
# apply scaling factors # apply scaling factors
@ -358,14 +388,18 @@ class Sensor():
rrr = chunks(frame, self.bytes_per_line) rrr = chunks(frame, self.bytes_per_line)
# Don't touch the first 8 bytes of each line, add everything else as signed characters, clipping the values # Don't touch the first 8 bytes of each line, add everything else as signed characters, clipping the values
combined=[ll[:8] + bytes([add(l, r) for l, r in zip(ll[8:],rr[8:])]) for ll, rr in zip(lll, rrr)] combined = [
ll[:8] + bytes([add(l, r) for l, r in zip(ll[8:], rr[8:])])
for ll, rr in zip(lll, rrr)
]
self.calib_data = bytes(b''.join(combined)) self.calib_data = bytes(b''.join(combined))
else: else:
self.calib_data = frame self.calib_data = frame
def get_key_line(self): def get_key_line(self):
if len(self.calib_data) > 0: if len(self.calib_data) > 0:
bytes_per_calibration_line=len(self.calib_data) // self.type_info.lines_per_calibration_data bytes_per_calibration_line = len(
self.calib_data) // self.type_info.lines_per_calibration_data
key_line_offset = 8 + bytes_per_calibration_line * self.key_calibration_line key_line_offset = 8 + bytes_per_calibration_line * self.key_calibration_line
key_line = self.calib_data[key_line_offset:key_line_offset + self.type_info.line_width] key_line = self.calib_data[key_line_offset:key_line_offset + self.type_info.line_width]
key_line = bytes([i - 1 if i == 5 else i for i in key_line]) key_line = bytes([i - 1 if i == 5 else i for i in key_line])
@ -374,7 +408,8 @@ class Sensor():
return key_line return key_line
def line_update_type_1(self, mode, chunks): def line_update_type_1(self, mode: CaptureMode,
chunks: typing.List[typing.List[typing.Union[int, bytes]]]):
for c in chunks: for c in chunks:
# Timeslot Table 2D # Timeslot Table 2D
if c[0] == 0x34: if c[0] == 0x34:
@ -392,19 +427,33 @@ class Sensor():
# It seems to be only used for identification and it looks almost identical to Finger Detect (0x26) # It seems to be only used for identification and it looks almost identical to Finger Detect (0x26)
# Seems to be the same all the time for a given sensor and mostly hardcoded # Seems to be the same all the time for a given sensor and mostly hardcoded
# TODO: analyse construct_wtf_4e @0000000180090BF0 # TODO: analyse construct_wtf_4e @0000000180090BF0
chunks += [[0x4e, unhexlify('fbb20f0000000f00300000008700020067000a00018000000a0200000b1900008813b80b01091000')]] chunks += [[
0x4e,
unhexlify(
'fbb20f0000000f00300000008700020067000a00018000000a0200000b1900008813b80b01091000'
)
]]
# Image Reconstruction. # Image Reconstruction.
# TODO: analyse add_image_reconstruction_cmd_02_buff_list_item @000000018008EA70 # TODO: analyse add_image_reconstruction_cmd_02_buff_list_item @000000018008EA70
chunks += [[0x2e, unhexlify('0200180002000000700070004d010000a0008c003c32321e3c0a0202')]] chunks += [[
0x2e, unhexlify('0200180002000000700070004d010000a0008c003c32321e3c0a0202')
]]
elif mode == CaptureMode.ENROLL: elif mode == CaptureMode.ENROLL:
chunks += [[0x26, unhexlify('fbb20f0000000f00300000008700020067000a00018000000a0200000b19000050c360ea01091000')]] chunks += [[
0x26,
unhexlify(
'fbb20f0000000f00300000008700020067000a00018000000a0200000b19000050c360ea01091000'
)
]]
# Image Reconstruction. There is only one byte difference with the "identify" version. (same is true for 0097) # Image Reconstruction. There is only one byte difference with the "identify" version. (same is true for 0097)
chunks += [[0x2e, unhexlify('0200180023000000700070004d010000a0008c003c32321e3c0a0202')]] chunks += [[
0x2e, unhexlify('0200180023000000700070004d010000a0008c003c32321e3c0a0202')
]]
# ---------------- Interleave --------------- # ---------------- Interleave ---------------
chunks += [[0x44, pack('<L', 1)]] chunks += [[0x44, pack('<L', 1)]]
lines=[] lines: typing.List[Line] = []
cnt = 2 # TODO figure out why 2 cnt = 2 # TODO figure out why 2
l = Line() l = Line()
@ -428,7 +477,8 @@ class Sensor():
cnt += 1 cnt += 1
if len(self.calib_data) > 0: if len(self.calib_data) > 0:
bytes_per_calibration_line=len(self.calib_data) // self.type_info.lines_per_calibration_data bytes_per_calibration_line = len(
self.calib_data) // self.type_info.lines_per_calibration_data
for i in range(0, 112, 4): for i in range(0, 112, 4):
l = Line() l = Line()
@ -446,7 +496,6 @@ class Sensor():
if pad > 0: if pad > 0:
l.data += b'\0' * (4 - pad) l.data += b'\0' * (4 - pad)
# ---------------- Line Update --------------- # ---------------- Line Update ---------------
line_update = pack('<L', len(lines)) line_update = pack('<L', len(lines))
line_update += b''.join([pack('<LL', l.mask, l.flags) for l in lines]) line_update += b''.join([pack('<LL', l.mask, l.flags) for l in lines])
@ -455,12 +504,16 @@ class Sensor():
chunks += [[0x30, line_update]] chunks += [[0x30, line_update]]
# ---------------- Line Update Transform --------------- # ---------------- Line Update Transform ---------------
update_transform = b''.join([pack('<BBH', l.v0, l.v1, l.v2) + l.data for l in lines if ((l.flags & 0x00f00000) >> 0x14) > 1]) update_transform = b''.join([
pack('<BBH', l.v0, l.v1, l.v2) + l.data for l in lines
if ((l.flags & 0x00f00000) >> 0x14) > 1
])
chunks += [[0x43, update_transform]] chunks += [[0x43, update_transform]]
return chunks return chunks
def line_update_type_2(self, mode, chunks): def line_update_type_2(self, mode: CaptureMode,
chunks: typing.List[typing.List[typing.Union[int, bytes]]]):
for c in chunks: for c in chunks:
# patch the 2D params. # patch the 2D params.
# The following is only needed on some rom versions below 6.5 as reported by cmd_01 # The following is only needed on some rom versions below 6.5 as reported by cmd_01
@ -483,14 +536,28 @@ class Sensor():
# It seems to be only used for identification and it looks almost identical to Finger Detect (0x26) # It seems to be only used for identification and it looks almost identical to Finger Detect (0x26)
# Seems to be the same all the time for a given sensor and mostly hardcoded # Seems to be the same all the time for a given sensor and mostly hardcoded
# TODO: analyse construct_wtf_4e @0000000180090BF0 # TODO: analyse construct_wtf_4e @0000000180090BF0
chunks += [[0x4e, unhexlify('fbb20f0000000f00300000006001020040010a00018000000a0200000b1900008813b80b01091000')]] chunks += [[
0x4e,
unhexlify(
'fbb20f0000000f00300000006001020040010a00018000000a0200000b1900008813b80b01091000'
)
]]
# Image Reconstruction. # Image Reconstruction.
# TODO: analyse add_image_reconstruction_cmd_02_buff_list_item @000000018008EA70 # TODO: analyse add_image_reconstruction_cmd_02_buff_list_item @000000018008EA70
chunks += [[0x2e, unhexlify('0200180002000000900090004d01000090017c013c323232640a0201')]] chunks += [[
0x2e, unhexlify('0200180002000000900090004d01000090017c013c323232640a0201')
]]
elif mode == CaptureMode.ENROLL: elif mode == CaptureMode.ENROLL:
chunks += [[0x26, unhexlify('fbb20f0000000f00300000006001020040010a00018000000a0200000b19000050c360ea01091000')]] chunks += [[
0x26,
unhexlify(
'fbb20f0000000f00300000006001020040010a00018000000a0200000b19000050c360ea01091000'
)
]]
# Image Reconstruction. There is only one byte difference with the "identify" version. (same is true for 0097) # Image Reconstruction. There is only one byte difference with the "identify" version. (same is true for 0097)
chunks += [[0x2e, unhexlify('0200180023000000900090004d01000090017c013c323232640a0201')]] chunks += [[
0x2e, unhexlify('0200180023000000900090004d01000090017c013c323232640a0201')
]]
lines = [] lines = []
@ -524,7 +591,6 @@ class Sensor():
if pad > 0: if pad > 0:
l.data += b'\0' * (4 - pad) l.data += b'\0' * (4 - pad)
# ---------------- Line Update --------------- # ---------------- Line Update ---------------
line_update = pack('<L', len(lines)) line_update = pack('<L', len(lines))
line_update += b''.join([pack('<LL', l.mask, l.flags) for l in lines]) line_update += b''.join([pack('<LL', l.mask, l.flags) for l in lines])
@ -534,7 +600,7 @@ class Sensor():
return chunks return chunks
def build_cmd_02(self, mode): def build_cmd_02(self, mode: CaptureMode):
chunks = list(prg.split_chunks(self.hardcoded_prog)) chunks = list(prg.split_chunks(self.hardcoded_prog))
if self.rom_info.product != 0x30: if self.rom_info.product != 0x30:
@ -552,7 +618,7 @@ class Sensor():
return pack('<BHH', 2, self.bytes_per_line, req_lines) + prg.merge_chunks(chunks) return pack('<BHH', 2, self.bytes_per_line, req_lines) + prg.merge_chunks(chunks)
def persist_clean_slate(self, clean_slate): def persist_clean_slate(self, clean_slate: bytes):
start = read_flash(6, 0, 0x44) start = read_flash(6, 0, 0x44)
if start != b'\xff' * 0x44: if start != b'\xff' * 0x44:
@ -586,7 +652,6 @@ class Sensor():
return True return True
def calibrate(self): def calibrate(self):
if os.path.isfile(calib_data_path): if os.path.isfile(calib_data_path):
with open(calib_data_path, 'rb') as f: with open(calib_data_path, 'rb') as f:
@ -616,7 +681,8 @@ class Sensor():
clean_slate = self.average(usb.read_82()) clean_slate = self.average(usb.read_82())
clean_slate = pack('<H', len(clean_slate)) + clean_slate clean_slate = pack('<H', len(clean_slate)) + clean_slate
clean_slate = clean_slate + pack('<H', 0) # TODO: still don't know what this zero is for clean_slate = clean_slate + pack('<H', 0) # TODO: still don't know what this zero is for
clean_slate = pack('<H', len(clean_slate)) + sha256(clean_slate).digest() + b'\0'*0x20 + clean_slate clean_slate = pack(
'<H', len(clean_slate)) + sha256(clean_slate).digest() + b'\0' * 0x20 + clean_slate
clean_slate = pack('<H', 0x5002) + clean_slate clean_slate = pack('<H', 0x5002) + clean_slate
self.persist_clean_slate(clean_slate) self.persist_clean_slate(clean_slate)
@ -625,7 +691,7 @@ class Sensor():
def cancel(self): def cancel(self):
usb.cancel = True usb.cancel = True
def capture(self, mode): def capture(self, mode: CaptureMode) -> typing.Tuple[int, int, int, int]:
try: try:
assert_status(tls.app(self.build_cmd_02(mode))) assert_status(tls.app(self.build_cmd_02(mode)))
@ -638,7 +704,7 @@ class Sensor():
while True: while True:
b = usb.wait_int() b = usb.wait_int()
if b[0] == 2: if b[0] == 2:
break; break
# wait capture complete # wait capture complete
while True: while True:
@ -665,13 +731,12 @@ class Sensor():
if error != 0: if error != 0:
raise Exception('Scanning problem: %04x' % error) raise Exception('Scanning problem: %04x' % error)
return (x, y, w1, w2) return x, y, w1, w2
finally: finally:
tls.app(unhexlify('04')) # capture stop if still running, cleanup tls.app(unhexlify('04')) # capture stop if still running, cleanup
def enrollment_update_start(self, key: int) -> int:
def enrollment_update_start(self, key):
rsp = tls.app(pack('<BLL', 0x68, key, 0)) rsp = tls.app(pack('<BLL', 0x68, key, 0))
assert_status(rsp) assert_status(rsp)
new_key, = unpack('<L', rsp[2:]) new_key, = unpack('<L', rsp[2:])
@ -687,7 +752,7 @@ class Sensor():
assert_status(tls.app(pack('<BL', 0x69, 0))) assert_status(tls.app(pack('<BL', 0x69, 0)))
# Generates interrupt # Generates interrupt
def enrollment_update(self, prev): def enrollment_update(self, prev: bytes):
write_enable() write_enable()
try: try:
rsp = tls.app(b'\x6b' + prev) rsp = tls.app(b'\x6b' + prev)
@ -697,7 +762,7 @@ class Sensor():
return rsp[2:] return rsp[2:]
def append_new_image(self, prev): def append_new_image(self, prev: bytes):
self.enrollment_update(prev) self.enrollment_update(prev)
usb.wait_int() usb.wait_int()
@ -726,10 +791,9 @@ class Sensor():
res = res[magic_len + l:] res = res[magic_len + l:]
return (header, template, tid) return header, template, tid
def make_finger_data(self, subtype: int, template: bytes, tid: bytes):
def make_finger_data(self, subtype, template, tid):
template = pack('<HH', 1, len(template)) + template template = pack('<HH', 1, len(template)) + template
tid = pack('<HH', 2, len(tid)) + tid tid = pack('<HH', 2, len(tid)) + tid
@ -743,11 +807,11 @@ class Sensor():
# TODO: Better typing information needed. # TODO: Better typing information needed.
def enroll(self, identity: SidIdentity, subtype: int, def enroll(self, identity: SidIdentity, subtype: int,
update_cb: typing.Callable[[typing.Any, typing.Optional[Exception]], None]): update_cb: typing.Callable[[typing.Any, typing.Optional[Exception]], None]):
def do_create_finger(final_template, tid): def do_create_finger(final_template: bytes, tid: bytes):
tinfo = self.make_finger_data(subtype, final_template, tid) tinfo = self.make_finger_data(subtype, final_template, tid)
usr = db.lookup_user(identity) usr = db.lookup_user(identity)
if usr == None: if usr is None:
usr = db.new_user(identity) usr = db.new_user(identity)
else: else:
usr = usr.dbid usr = usr.dbid
@ -788,7 +852,7 @@ class Sensor():
self.enrollment_update_end() # done twice for some reason self.enrollment_update_end() # done twice for some reason
return do_create_finger(template, tid) return do_create_finger(template, tid)
def parse_dict(self, x): def parse_dict(self, x: bytes):
rc = {} rc = {}
while len(x) > 0: while len(x) > 0:
@ -824,13 +888,12 @@ class Sensor():
usrid, = unpack('<L', usrid) usrid, = unpack('<L', usrid)
subtype, = unpack('<H', subtype) subtype, = unpack('<H', subtype)
return (usrid, subtype, hsh) return usrid, subtype, hsh
finally: finally:
# cleanup, ignore any errors # cleanup, ignore any errors
tls.app(unhexlify('6200000000')) tls.app(unhexlify('6200000000'))
def identify(self, update_cb: typing.Callable[[Exception], None]):
def identify(self, update_cb):
while True: while True:
try: try:
glow_start_scan() glow_start_scan()
@ -848,7 +911,7 @@ class Sensor():
return self.match_finger() return self.match_finger()
def get_finger_blobs(self, usrid, subtype): def get_finger_blobs(self, usrid: int, subtype: int):
usr = db.get_user(usrid) usr = db.get_user(usrid)
fingerids = [f['dbid'] for f in usr.fingers if f['subtype'] == subtype] fingerids = [f['dbid'] for f in usr.fingers if f['subtype'] == subtype]
@ -860,5 +923,5 @@ class Sensor():
ids = [r['dbid'] for r in finger_record.children if r['type'] == 8] ids = [r['dbid'] for r in finger_record.children if r['type'] == 8]
return [db.get_record_value(id).value for id in ids] return [db.get_record_value(id).value for id in ids]
sensor = Sensor()
sensor = Sensor()

View file

@ -1,8 +1,8 @@
from struct import unpack, pack
import typing import typing
from struct import unpack, pack
class SidIdentity():
class SidIdentity:
def __init__(self, revision: int, auth: int, subauth: typing.Sequence[int]): def __init__(self, revision: int, auth: int, subauth: typing.Sequence[int]):
self.revision = revision self.revision = revision
self.auth = auth self.auth = auth
@ -18,6 +18,7 @@ class SidIdentity():
def __repr__(self): def __repr__(self):
return 'S-%d-%d-%s' % (self.revision, self.auth, '-'.join(map(str, self.subauth))) return 'S-%d-%d-%s' % (self.revision, self.auth, '-'.join(map(str, self.subauth)))
def sid_from_bytes(b: bytes): def sid_from_bytes(b: bytes):
revision = b[0] revision = b[0]
subcnt = b[1] subcnt = b[1]
@ -31,6 +32,7 @@ def sid_from_bytes(b: bytes):
return SidIdentity(revision, auth, subauth) return SidIdentity(revision, auth, subauth)
def sid_from_string(s: str): def sid_from_string(s: str):
parts = s.split('-') parts = s.split('-')

View file

@ -1,17 +1,20 @@
import typing
from binascii import hexlify, unhexlify from binascii import hexlify, unhexlify
class SensorTypeInfo: class SensorTypeInfo:
table=[] table: typing.List["SensorTypeInfo"] = []
@classmethod @classmethod
def get_by_type(cls, sensor_type): def get_by_type(cls, sensor_type: int) -> typing.Optional["SensorTypeInfo"]:
# noinspection PyUnresolvedReferences
from . import generated_tables from . import generated_tables
for i in cls.table: for i in cls.table:
if i.sensor_type == sensor_type: if i.sensor_type == sensor_type:
return i return i
def __init__(self, sensor_type, bytes_per_line, repeat_multiplier, lines_per_calibration_data, line_width, calibration_blob): def __init__(self, sensor_type: int, bytes_per_line: int, repeat_multiplier: int,
lines_per_calibration_data: int, line_width: int, calibration_blob: str):
self.sensor_type = sensor_type self.sensor_type = sensor_type
self.repeat_multiplier = repeat_multiplier self.repeat_multiplier = repeat_multiplier
self.lines_per_calibration_data = lines_per_calibration_data self.lines_per_calibration_data = lines_per_calibration_data
@ -22,7 +25,9 @@ class SensorTypeInfo:
def __repr__(self): def __repr__(self):
calibration_blob = hexlify(self.calibration_blob).decode() calibration_blob = hexlify(self.calibration_blob).decode()
return 'SensorTypeInfo(sensor_type=0x%04x, bytes_per_line=0x%x, repeat_multiplier=%d, lines_per_calibration_data=%d, line_width=%d, calibration_blob=%s)' % ( return 'SensorTypeInfo(sensor_type=0x%04x, bytes_per_line=0x%x, repeat_multiplier=%d, lines_per_calibration_data=%d, line_width=%d, calibration_blob=%s)' % (
self.sensor_type, self.bytes_per_line, self.repeat_multiplier, self.lines_per_calibration_data, self.line_width, repr(calibration_blob)) self.sensor_type, self.bytes_per_line, self.repeat_multiplier,
self.lines_per_calibration_data, self.line_width, repr(calibration_blob))
def fuzzy(expected, actual): def fuzzy(expected, actual):
if expected == actual: if expected == actual:
@ -32,6 +37,7 @@ def fuzzy(expected, actual):
else: else:
return 0 return 0
def metric(i, rominfo): def metric(i, rominfo):
metric = 0 metric = 0
metric |= fuzzy(i.major, rominfo.major) metric |= fuzzy(i.major, rominfo.major)
@ -44,11 +50,13 @@ def metric(i, rominfo):
return metric return metric
class SensorCaptureProg: class SensorCaptureProg:
table=[] table: typing.List["SensorCaptureProg"] = []
@classmethod @classmethod
def get(cls, rominfo, sensor_type, a0, a1): def get(cls, rominfo, sensor_type: int, a0: int, a1: int):
# noinspection PyUnresolvedReferences
from . import generated_tables from . import generated_tables
maximum = 0 maximum = 0
@ -75,7 +83,8 @@ class SensorCaptureProg:
if found is not None: if found is not None:
return b''.join(found.blobs) return b''.join(found.blobs)
def __init__(self, major, minor, build, u1, dev_type, a0, a1, blobs): def __init__(self, major: int, minor: int, build: int, u1: int, dev_type: int, a0: int, a1: int,
blobs: typing.Sequence[str]):
self.major = major self.major = major
self.minor = minor self.minor = minor
self.build = build self.build = build
@ -83,8 +92,7 @@ class SensorCaptureProg:
self.dev_type = dev_type self.dev_type = dev_type
self.a0 = a0 self.a0 = a0
self.a1 = a1 self.a1 = a1
blobs=[unhexlify(b) for b in blobs] self.blobs = [unhexlify(b) for b in blobs]
self.blobs=blobs
def __repr__(self): def __repr__(self):
blobs = [hexlify(b).decode() for b in self.blobs] blobs = [hexlify(b).decode() for b in self.blobs]

View file

@ -1,4 +1,4 @@
import typing
from binascii import hexlify from binascii import hexlify
from struct import unpack, pack from struct import unpack, pack
@ -98,53 +98,57 @@ insn_to_string=[
'Sample Repeat %x, %x, repeat=%x', # 15 'Sample Repeat %x, %x, repeat=%x', # 15
] ]
def decode_insn(b):
def decode_insn(b: bytes):
if b[0] == 0: if b[0] == 0:
return (0, 1) return 0, 1
elif b[0] == 1: elif b[0] == 1:
return (1, 1) return 1, 1
elif b[0] == 2: elif b[0] == 2:
return (2, 1) return 2, 1
elif b[0] == 3: elif b[0] == 3:
return (3, 1) return 3, 1
elif b[0] == 4: elif b[0] == 4:
return (4, 1) return 4, 1
elif b[0] == 5: elif b[0] == 5:
return (5, 2, b[1]) return 5, 2, b[1]
elif b[0] == 6: elif b[0] == 6:
return (6, 2, b[1]) return 6, 2, b[1]
elif b[0] == 7: elif b[0] == 7:
return (7, 2, 0x100 if b[1] == 0 else b[1]) return 7, 2, 0x100 if b[1] == 0 else b[1]
elif b[0] & 0xfe == 8: elif b[0] & 0xfe == 8:
return (8, 2, (b[0] & 1) << 8 | b[1]) return 8, 2, (b[0] & 1) << 8 | b[1]
elif b[0] & 0xfe == 0xa: elif b[0] & 0xfe == 0xa:
return (9, 2, (b[0] & 1) << 8 | b[1]) return 9, 2, (b[0] & 1) << 8 | b[1]
elif b[0] & 0xfc == 0xc: elif b[0] & 0xfc == 0xc:
return (10, 1, b[0] & 3) return 10, 1, b[0] & 3
elif b[0] & 0xf8 == 0x10: elif b[0] & 0xf8 == 0x10:
return (11, 3, b[0] & 7, b[1] << 2, 0x100 if b[2] == 0 else b[2]) return 11, 3, b[0] & 7, b[1] << 2, 0x100 if b[2] == 0 else b[2]
elif b[0] & 0xe0 == 0x20: elif b[0] & 0xe0 == 0x20:
return (12, 1, b[0] & 0x1f) # TODO check how features are converted to op args return 12, 1, b[0] & 0x1f # TODO check how features are converted to op args
elif b[0] & 0xc0 == 0x40: elif b[0] & 0xc0 == 0x40:
return (13, 3, (b[0] & 0x3f)*4+0x80002000, b[1] | (b[2] << 8)) return 13, 3, (b[0] & 0x3f) * 4 + 0x80002000, b[1] | (b[2] << 8)
elif b[0] & 0xc0 == 0x80: elif b[0] & 0xc0 == 0x80:
return (14, 1, (b[0] & 0x38) >> 3, b[0] & 7) return 14, 1, (b[0] & 0x38) >> 3, b[0] & 7
elif b[0] & 0xc0 == 0xc0: elif b[0] & 0xc0 == 0xc0:
return (15, 2, (b[0] & 0x38) >> 3, b[0] & 7, 0x100 if b[1] == 0 else b[1]) return 15, 2, (b[0] & 0x38) >> 3, b[0] & 7, 0x100 if b[1] == 0 else b[1]
else: else:
raise Exception('Unhandled instruction %02x' % b) raise Exception('Unhandled instruction %02x' % b)
def disassm_timeslot_table(b, off):
def disassm_timeslot_table(b: bytes, off: int):
pc = off pc = off
while len(b) > 0: while len(b) > 0:
op, sz, *operands = decode_insn(b) op, sz, *operands = decode_insn(b)
if sz > len(b): if sz > len(b):
raise Exception('Truncated instruction') raise Exception('Truncated instruction')
print(' %04x: %-6s %s' % (pc, hexlify(b[:sz]).decode(), insn_to_string[op] % tuple(operands))) print(' %04x: %-6s %s' %
(pc, hexlify(b[:sz]).decode(), insn_to_string[op] % tuple(operands)))
b = b[sz:] b = b[sz:]
pc += sz pc += sz
def find_nth_insn(b, opcode, n):
def find_nth_insn(b: bytes, opcode: int, n: int):
pc = 0 pc = 0
while len(b) > 0: while len(b) > 0:
op, sz, *_ = decode_insn(b) op, sz, *_ = decode_insn(b)
@ -155,12 +159,13 @@ def find_nth_insn(b, opcode, n):
if op == opcode: if op == opcode:
n -= 1 n -= 1
if n == 0: if n == 0:
return (pc, b[:sz]) return pc, b[:sz]
b = b[sz:] b = b[sz:]
pc += sz pc += sz
def find_nth_regwrite(b, reg_addr, n):
def find_nth_regwrite(b: bytes, reg_addr: int, n: int):
pc = 0 pc = 0
while len(b) > 0: while len(b) > 0:
op, sz, *operands = decode_insn(b) op, sz, *operands = decode_insn(b)
@ -173,22 +178,26 @@ def find_nth_regwrite(b, reg_addr, n):
if addr == reg_addr: if addr == reg_addr:
n -= 1 n -= 1
if n == 0: if n == 0:
return (pc, b[:sz]) return pc, b[:sz]
b = b[sz:] b = b[sz:]
pc += sz pc += sz
def split_chunks(b): def split_chunks(b: bytes) -> typing.Generator[typing.List[typing.Union[int, bytes]], None, None]:
while len(b) > 0: while len(b) > 0:
(typ, sz), b = unpack('<HH', b[:4]), b[4:] (typ, sz), b = unpack('<HH', b[:4]), b[4:]
p, b = b[:sz], b[sz:] p, b = b[:sz], b[sz:]
yield [typ, p] yield [typ, p]
def merge_chunks(cs):
def merge_chunks(cs: typing.List[typing.List[typing.Union[int, bytes]]]):
return b''.join([pack('<HH', key, len(val)) + val for key, val in cs]) return b''.join([pack('<HH', key, len(val)) + val for key, val in cs])
def dump_all(b):
def dump_all(b: bytes):
ts: typing.Optional[bytes] = None
ts_off: typing.Optional[int] = None
while len(b) > 0: while len(b) > 0:
(typ, sz), b = unpack('<HH', b[:4]), b[4:] (typ, sz), b = unpack('<HH', b[:4]), b[4:]
p, b = b[:sz], b[sz:] p, b = b[:sz], b[sz:]
@ -220,4 +229,3 @@ def dump_all(b):
if ts is not None: if ts is not None:
print('Timeslot table, starting at 0x%x:' % ts_off) print('Timeslot table, starting at 0x%x:' % ts_off)
disassm_timeslot_table(ts[ts_off:], ts_off) disassm_timeslot_table(ts[ts_off:], ts_off)

View file

@ -1,20 +1,20 @@
import hmac import hmac
import logging
import os import os
import pickle import pickle
import logging import typing
from binascii import hexlify, unhexlify
from hashlib import sha256
from struct import pack, unpack from struct import pack, unpack
from binascii import *
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import ec from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives.asymmetric.utils import Prehashed from cryptography.hazmat.primitives.asymmetric.utils import Prehashed
from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from hashlib import sha256
from .usb import usb, Usb
from .util import unhex from .util import unhex
from .usb import usb
password_hardcoded = unhexlify('717cd72d0962bc4a2846138dbb2c24192512a76407065f383846139d4bec2033') password_hardcoded = unhexlify('717cd72d0962bc4a2846138dbb2c24192512a76407065f383846139d4bec2033')
gwk_sign_hardcoded = unhexlify('3a4c76b76a97981d1274247e166610e77f4d9c9d07d3c728e532916bdd28b454') gwk_sign_hardcoded = unhexlify('3a4c76b76a97981d1274247e166610e77f4d9c9d07d3c728e532916bdd28b454')
@ -34,7 +34,8 @@ fff000000000000000000000000000000000000000000000000000000000000000000000000
crypto_backend = default_backend() crypto_backend = default_backend()
def prf(secret, seed, length):
def prf(secret: bytes, seed: bytes, length: int):
n = (length + 0x20 - 1) // 0x20 n = (length + 0x20 - 1) // 0x20
res = b'' res = b''
@ -47,21 +48,26 @@ def prf(secret, seed, length):
return res[:length] return res[:length]
def hs_key(): def hs_key():
key = password_hardcoded[:0x10] key = password_hardcoded[:0x10]
seed = password_hardcoded[0x10:] + b'\xaa' * 2 seed = password_hardcoded[0x10:] + b'\xaa' * 2
hs_key = prf(key, b'HS_KEY_PAIR_GEN' + seed, 0x20) hs_key = prf(key, b'HS_KEY_PAIR_GEN' + seed, 0x20)
return int(hs_key[::-1].hex(), 16) return int(hs_key[::-1].hex(), 16)
def with_2bytes_size(chunk):
def with_2bytes_size(chunk: bytes):
return pack('>H', len(chunk)) + chunk return pack('>H', len(chunk)) + chunk
def with_3bytes_size(chunk):
def with_3bytes_size(chunk: bytes):
return pack('>BH', len(chunk) >> 16, len(chunk)) + chunk return pack('>BH', len(chunk) >> 16, len(chunk)) + chunk
def with_1byte_size(chunk):
def with_1byte_size(chunk: bytes):
return pack('>B', len(chunk)) + chunk return pack('>B', len(chunk)) + chunk
def to_bytes(n): def to_bytes(n):
b = b'' b = b''
while n: while n:
@ -70,18 +76,19 @@ def to_bytes(n):
return b return b
def pad(b):
def pad(b: bytes):
l = 16 - (len(b) % 16) l = 16 - (len(b) % 16)
return b + bytes([l - 1]) * l return b + bytes([l - 1]) * l
def unpad(b):
def unpad(b: bytes):
return b[:-1 - b[-1]] return b[:-1 - b[-1]]
# TODO assert the right state transitions # TODO assert the right state transitions
class Tls(): class Tls:
def __init__(self, usb: Usb):
def __init__(self, usb):
self.usb = usb self.usb = usb
self.reset() self.reset()
try: try:
@ -101,16 +108,16 @@ class Tls():
self.secure_tx = False self.secure_tx = False
# Info about the host computer # Info about the host computer
def set_hwkey(self, product_name, serial_number): def set_hwkey(self, product_name: str, serial_number: str):
hw_key = bytes(product_name, 'ascii') + b'\0' + \ hw_key = bytes(product_name, 'ascii') + b'\0' + \
bytes(serial_number, 'ascii') + b'\0' bytes(serial_number, 'ascii') + b'\0'
# pre-TLS keys # pre-TLS keys
self.psk_encryption_key = prf(password_hardcoded, b'GWK' + hw_key, 0x20) self.psk_encryption_key = prf(password_hardcoded, b'GWK' + hw_key, 0x20)
self.psk_validation_key = prf(self.psk_encryption_key, self.psk_validation_key = prf(self.psk_encryption_key, b'GWK_SIGN' + gwk_sign_hardcoded,
b'GWK_SIGN' + gwk_sign_hardcoded, 0x20) 0x20)
def cmd(self, cmd): def cmd(self, cmd: typing.Union[bytes, typing.Callable[[], bytes]]):
if self.secure_rx and self.secure_tx: if self.secure_rx and self.secure_tx:
rsp = self.app(cmd) rsp = self.app(cmd)
else: else:
@ -130,25 +137,21 @@ class Tls():
self.make_keys() self.make_keys()
rsp = self.usb.cmd( rsp = self.usb.cmd(
unhexlify('44000000') + unhexlify('44000000') + self.make_handshake(self.make_certs() + self.make_client_kex() +
self.make_handshake(
self.make_certs() +
self.make_client_kex() +
self.make_cert_verify()) + self.make_cert_verify()) +
self.make_change_cipher_spec() + self.make_change_cipher_spec() + self.make_handshake(self.make_finish()))
self.make_handshake(self.make_finish()))
self.parse_tls_response(rsp) self.parse_tls_response(rsp)
def trace(self, s): def trace(self, s: str):
if self.trace_enabled: if self.trace_enabled:
logging.debug(s) logging.debug(s)
def app(self, b): def app(self, b: typing.Union[bytes, typing.Callable[[], bytes]]):
b = b() if callable(b) else b b = b() if callable(b) else b
return self.parse_tls_response(self.usb.cmd(self.make_app_data(b))) return self.parse_tls_response(self.usb.cmd(self.make_app_data(b)))
def update_neg(self, b): def update_neg(self, b: bytes):
self.handshake_hash.update(b) self.handshake_hash.update(b)
def make_keys(self): def make_keys(self):
@ -165,7 +168,8 @@ class Tls():
def save(self): def save(self):
with open('tls.dict', 'wb') as f: with open('tls.dict', 'wb') as f:
pickle.dump({ pickle.dump(
{
'sign_key': self.sign_key, 'sign_key': self.sign_key,
'validation_key': self.validation_key, 'validation_key': self.validation_key,
'encryption_key': self.encryption_key, 'encryption_key': self.encryption_key,
@ -184,7 +188,7 @@ class Tls():
self.secure_rx = d['secure_rx'] self.secure_rx = d['secure_rx']
self.secure_tx = d['secure_tx'] self.secure_tx = d['secure_tx']
def decrypt(self, c): def decrypt(self, c: bytes):
iv, c = c[:0x10], c[0x10:] iv, c = c[:0x10], c[0x10:]
cipher = Cipher(algorithms.AES(self.decryption_key), modes.CBC(iv), backend=crypto_backend) cipher = Cipher(algorithms.AES(self.decryption_key), modes.CBC(iv), backend=crypto_backend)
decryptor = cipher.decryptor() decryptor = cipher.decryptor()
@ -192,7 +196,7 @@ class Tls():
m = unpad(m) m = unpad(m)
return m return m
def encrypt(self, b): def encrypt(self, b: bytes):
# iv = unhexlify('454849acdd075174d6b9e713a957c2e7') # iv = unhexlify('454849acdd075174d6b9e713a957c2e7')
iv = os.urandom(0x10) iv = os.urandom(0x10)
cipher = Cipher(algorithms.AES(self.encryption_key), modes.CBC(iv), backend=crypto_backend) cipher = Cipher(algorithms.AES(self.encryption_key), modes.CBC(iv), backend=crypto_backend)
@ -201,7 +205,7 @@ class Tls():
c = encryptor.update(b) + encryptor.finalize() c = encryptor.update(b) + encryptor.finalize()
return iv + c return iv + c
def validate(self, t, b): def validate(self, t: int, b: bytes):
b, hs = b[:-0x20], b[-0x20:] b, hs = b[:-0x20], b[-0x20:]
hdr = pack('>BBBH', t, 3, 3, len(b)) hdr = pack('>BBBH', t, 3, 3, len(b))
@ -213,7 +217,7 @@ class Tls():
self.trace('<tls< %02x: %s' % (t, hexlify(b).decode())) self.trace('<tls< %02x: %s' % (t, hexlify(b).decode()))
return b return b
def sign(self, t, b): def sign(self, t: int, b: bytes):
self.trace('>tls> %02x: %s' % (t, hexlify(b).decode())) self.trace('>tls> %02x: %s' % (t, hexlify(b).decode()))
hdr = pack('>BBBH', t, 3, 3, len(b)) hdr = pack('>BBBH', t, 3, 3, len(b))
@ -232,11 +236,12 @@ class Tls():
def make_certs(self): def make_certs(self):
cert = self.tls_cert cert = self.tls_cert
cert = unhexlify('ac16') + cert # what's this? cert = unhexlify('ac16') + cert # what's this?
cert = pack('>BH', 0, len(self.tls_cert)) + cert # this seems to violate the standard (should be len(cert)) cert = pack('>BH', 0, len(
self.tls_cert)) + cert # this seems to violate the standard (should be len(cert))
cert = pack('>BH', 0, len(self.tls_cert)) + cert # same cert = pack('>BH', 0, len(self.tls_cert)) + cert # same
return self.with_neg_hdr(0x0b, cert) return self.with_neg_hdr(0x0b, cert)
def with_neg_hdr(self, t, b): def with_neg_hdr(self, t: int, b: bytes):
b = pack('>B', t) + with_3bytes_size(b) b = pack('>B', t) + with_3bytes_size(b)
self.update_neg(b) self.update_neg(b)
return b return b
@ -250,7 +255,7 @@ class Tls():
b = self.priv_key.sign(buf, ec.ECDSA(Prehashed(hashes.SHA256()))) b = self.priv_key.sign(buf, ec.ECDSA(Prehashed(hashes.SHA256())))
return self.with_neg_hdr(0x0f, b) return self.with_neg_hdr(0x0f, b)
def handle_server_hello(self, p): def handle_server_hello(self, p: bytes):
if p[:2] != unhexlify('0303'): if p[:2] != unhexlify('0303'):
raise Exception('unexpected TLS version %s' % hexlify(p[:2]).decode()) raise Exception('unexpected TLS version %s' % hexlify(p[:2]).decode())
@ -266,17 +271,20 @@ class Tls():
raise Exception('Server accepted unsupported cipher suite %04x' % suite) raise Exception('Server accepted unsupported cipher suite %04x' % suite)
if p[0] != 0: if p[0] != 0:
raise Exception('Server selected to enable compression, which we don''t support %02x' % p[0]) raise Exception('Server selected to enable compression, which we don'
't support %02x' % p[0])
p = p[1:] p = p[1:]
if p != b'': if p != b'':
raise Exception('Not expecting any more data') raise Exception('Not expecting any more data')
def handle_cert_req(self, p): def handle_cert_req(self, p: bytes):
(sign_and_hash_algo, ), p = unpack('>H', p[:2]), p[2:] (sign_and_hash_algo, ), p = unpack('>H', p[:2]), p[2:]
if sign_and_hash_algo != 0x140: if sign_and_hash_algo != 0x140:
raise Exception('Server requested a cert with an unsupported sign and hash algo combination %04x' % sign_and_hash_algo) raise Exception(
'Server requested a cert with an unsupported sign and hash algo combination %04x' %
sign_and_hash_algo)
(l, ), p = unpack('>H', p[:2]), p[2:] (l, ), p = unpack('>H', p[:2]), p[2:]
if l != 0: if l != 0:
@ -285,23 +293,24 @@ class Tls():
if p != b'': if p != b'':
raise Exception('Not expecting any more data') raise Exception('Not expecting any more data')
def handle_server_hello_done(self, p): def handle_server_hello_done(self, p: bytes):
if p != b'': if p != b'':
raise Exception('Not expecting any body for "server hello done" pkt: %s' % hexlify(p).decode()) raise Exception('Not expecting any body for "server hello done" pkt: %s' %
hexlify(p).decode())
def handle_finish(self, b): def handle_finish(self, b: bytes):
hs_hash = self.handshake_hash.copy().digest() hs_hash = self.handshake_hash.copy().digest()
verify_data = prf(self.master_secret, b'server finished' + hs_hash, 0xc) verify_data = prf(self.master_secret, b'server finished' + hs_hash, 0xc)
if verify_data != b: if verify_data != b:
raise Exception('Final handshake check failed') raise Exception('Final handshake check failed')
def handle_app_data(self, b): def handle_app_data(self, b: bytes):
if not self.secure_rx: if not self.secure_rx:
raise Exception('App payload before secure connection established') raise Exception('App payload before secure connection established')
return self.validate(0x17, self.decrypt(b)) return self.validate(0x17, self.decrypt(b))
def handle_handshake(self, handshake): def handle_handshake(self, handshake: bytes) -> None:
if self.secure_rx: if self.secure_rx:
handshake = self.validate(0x16, self.decrypt(handshake)) handshake = self.validate(0x16, self.decrypt(handshake))
@ -327,7 +336,7 @@ class Tls():
self.update_neg(hdr + p) self.update_neg(hdr + p)
def parse_tls_response(self, rsp): def parse_tls_response(self, rsp: bytes):
app_data = b'' app_data = b''
while len(rsp) > 0: while len(rsp) > 0:
@ -358,7 +367,7 @@ class Tls():
return app_data return app_data
def make_app_data(self, b): def make_app_data(self, b: bytes):
if not self.secure_tx: if not self.secure_tx:
raise Exception('App payload before secure connection established') raise Exception('App payload before secure connection established')
@ -366,7 +375,7 @@ class Tls():
return unhexlify('170303') + with_2bytes_size(b) return unhexlify('170303') + with_2bytes_size(b)
def make_handshake(self, b): def make_handshake(self, b: bytes):
if self.secure_tx: if self.secure_tx:
b = self.encrypt(self.sign(0x16, b)) b = self.encrypt(self.sign(0x16, b))
@ -389,16 +398,17 @@ class Tls():
exts = b'' exts = b''
exts += self.make_ext(0x004, pack('>H', 0x0017)) # truncated_hmac = 0x17 exts += self.make_ext(0x004, pack('>H', 0x0017)) # truncated_hmac = 0x17
exts += self.make_ext(0x00b, with_1byte_size(unhexlify('00'))) # EC points format = uncompressed exts += self.make_ext(0x00b,
with_1byte_size(unhexlify('00'))) # EC points format = uncompressed
# h += with_2bytes_size(exts) # h += with_2bytes_size(exts)
h += pack('>H', len(exts) - 2) + exts # -2? WHY?!... h += pack('>H', len(exts) - 2) + exts # -2? WHY?!...
return self.with_neg_hdr(0x01, h) return self.with_neg_hdr(0x01, h)
def make_ext(self, id, b): def make_ext(self, id: int, b: bytes):
return pack('>H', id) + with_2bytes_size(b) return pack('>H', id) + with_2bytes_size(b)
def parseTlsFlash(self, reply): def parse_tls_flash(self, reply: bytes):
while len(reply) > 0: while len(reply) > 0:
hdr, reply = reply[:4], reply[4:] hdr, reply = reply[:4], reply[4:]
hs, reply = reply[:0x20], reply[0x20:] hs, reply = reply[:0x20], reply[0x20:]
@ -431,33 +441,33 @@ class Tls():
else: else:
self.trace('unhandled block id %04x (%d bytes): %s' % (id, sz, hexlify(body))) self.trace('unhandled block id %04x (%d bytes): %s' % (id, sz, hexlify(body)))
def makeTlsFlashBlock(self, id, body): def make_tls_flash_block(self, id: int, body: bytes):
m = sha256() m = sha256()
m.update(body) m.update(body)
hdr = pack('<HH', id, len(body)) hdr = pack('<HH', id, len(body))
return hdr + m.digest() + body return hdr + m.digest() + body
def makeTlsFlash(self): def make_tls_flash(self):
b = self.makeTlsFlashBlock(0, b'\0') b = self.make_tls_flash_block(0, b'\0')
b+= self.makeTlsFlashBlock(4, self.priv_blob) b += self.make_tls_flash_block(4, self.priv_blob)
b+= self.makeTlsFlashBlock(3, self.tls_cert) b += self.make_tls_flash_block(3, self.tls_cert)
b+= self.makeTlsFlashBlock(5, crt_hardcoded) b += self.make_tls_flash_block(5, crt_hardcoded)
b+= self.makeTlsFlashBlock(1, b'\0' * 0x100) b += self.make_tls_flash_block(1, b'\0' * 0x100)
b+= self.makeTlsFlashBlock(2, b'\0' * 0x100) b += self.make_tls_flash_block(2, b'\0' * 0x100)
b+= self.makeTlsFlashBlock(6, self.ecdh_blob) b += self.make_tls_flash_block(6, self.ecdh_blob)
b += b'\xff' * (0x1000 - len(b)) b += b'\xff' * (0x1000 - len(b))
return b return b
def handle_empty(self, body): def handle_empty(self, body: bytes):
if body != b'\0' * len(body): if body != b'\0' * len(body):
raise Exception('Expected empty block') raise Exception('Expected empty block')
def handle_cert(self, body): def handle_cert(self, body: bytes):
# TODO validate cert, check if pub keys match # TODO validate cert, check if pub keys match
self.tls_cert = body self.tls_cert = body
self.trace('TLS cert blob: %s' % hexlify(self.tls_cert)) self.trace('TLS cert blob: %s' % hexlify(self.tls_cert))
def handle_ecdh(self, body): def handle_ecdh(self, body: bytes):
self.ecdh_blob = body self.ecdh_blob = body
key, signature = body[:0x90], body[0x90:] key, signature = body[:0x90], body[0x90:]
x = key[0x8:0x8 + 0x20] x = key[0x8:0x8 + 0x20]
@ -484,13 +494,13 @@ class Tls():
# Corresponding private key should only be known to a genuine Synaptic device. # Corresponding private key should only be known to a genuine Synaptic device.
fwpub = ec.EllipticCurvePublicNumbers( fwpub = ec.EllipticCurvePublicNumbers(
0xf727653b4e16ce0665a6894d7f3a30d7d0a0be310d1292a743671fdf69f6a8d3, 0xf727653b4e16ce0665a6894d7f3a30d7d0a0be310d1292a743671fdf69f6a8d3,
0xa85538f8b6bec50d6eef8bd5f4d07a886243c58b2393948df761a84721a6ca94, ec.SECP256R1()).public_key(crypto_backend) 0xa85538f8b6bec50d6eef8bd5f4d07a886243c58b2393948df761a84721a6ca94,
ec.SECP256R1()).public_key(crypto_backend)
# throws InvalidSignature # throws InvalidSignature
fwpub.verify(signature, key, ec.ECDSA(hashes.SHA256())) fwpub.verify(signature, key, ec.ECDSA(hashes.SHA256()))
def handle_priv(self, body: bytes):
def handle_priv(self, body):
self.priv_blob = body self.priv_blob = body
prefix, body = body[0], body[1:] prefix, body = body[0], body[1:]
if prefix != 2: if prefix != 2:
@ -499,10 +509,14 @@ class Tls():
c, hs = body[:-0x20], body[-0x20:] c, hs = body[:-0x20], body[-0x20:]
sig = hmac.new(self.psk_validation_key, c, sha256).digest() sig = hmac.new(self.psk_validation_key, c, sha256).digest()
if hs != sig: if hs != sig:
raise Exception('Signature verification failed. This device was probably paired with another computer.') raise Exception(
'Signature verification failed. This device was probably paired with another computer.'
)
iv, c = c[:0x10], c[0x10:] iv, c = c[:0x10], c[0x10:]
cipher = Cipher(algorithms.AES(self.psk_encryption_key), modes.CBC(iv), backend=crypto_backend) cipher = Cipher(algorithms.AES(self.psk_encryption_key),
modes.CBC(iv),
backend=crypto_backend)
decryptor = cipher.decryptor() decryptor = cipher.decryptor()
m = decryptor.update(c) + decryptor.finalize() m = decryptor.update(c) + decryptor.finalize()
m = m[:-m[-1]] # unpad (standard this time) m = m[:-m[-1]] # unpad (standard this time)

View file

@ -1,13 +1,15 @@
from time import ctime
import logging import logging
import typing
from os.path import basename from os.path import basename
from time import ctime
from .usb import usb
from .sensor import reboot, write_hw_reg32, read_hw_reg32, identify_sensor
from .flash import write_flash_all, write_fw_signature, get_fw_info from .flash import write_flash_all, write_fw_signature, get_fw_info
from .sensor import reboot, write_hw_reg32, read_hw_reg32, identify_sensor
from .usb import usb
firmware_home = '/usr/share/python-validity' firmware_home = '/usr/share/python-validity'
def default_fwext_name(): def default_fwext_name():
if usb.usb_dev().idVendor == 0x138a: if usb.usb_dev().idVendor == 0x138a:
if usb.usb_dev().idProduct == 0x0090: if usb.usb_dev().idProduct == 0x0090:
@ -19,10 +21,12 @@ def default_fwext_name():
# So, it is important that xpfwext file is matching the blobs contents. # So, it is important that xpfwext file is matching the blobs contents.
return '6_07f_lenovo_mis_qm.xpfwext' return '6_07f_lenovo_mis_qm.xpfwext'
def upload_fwext(fw_path=None):
def upload_fwext(fw_path: typing.Optional[str] = None):
fwi = get_fw_info(2) fwi = get_fw_info(2)
if fwi != None: if fwi is not None:
logging.info('Detected firmware version %d.%d (%s))' % (fwi.major, fwi.minor, ctime(fwi.buildtime))) logging.info('Detected firmware version %d.%d (%s))' %
(fwi.major, fwi.minor, ctime(fwi.buildtime)))
return return
else: else:
logging.info('No firmware detected. Uploading...') logging.info('No firmware detected. Uploading...')
@ -37,13 +41,11 @@ def upload_fwext(fw_path=None):
# ^ TODO -- what is the real reason to detect HW at this stage? # ^ TODO -- what is the real reason to detect HW at this stage?
# just a guess: perhaps it is used to construct fwext filename # just a guess: perhaps it is used to construct fwext filename
default_name = firmware_home + '/' + default_fwext_name() default_name = firmware_home + '/' + default_fwext_name()
if not fw_path: if not fw_path:
fw_path = default_name fw_path = default_name
elif basename(fw_path) != default_name: elif basename(fw_path) != default_name:
logging.warning('WARNING: Your device fw is supposed to be called {}'.format( logging.warning('WARNING: Your device fw is supposed to be called {}'.format(default_name))
default_name))
with open(fw_path, 'rb') as f: with open(fw_path, 'rb') as f:
fwext = f.read() fwext = f.read()
@ -55,10 +57,11 @@ def upload_fwext(fw_path=None):
write_fw_signature(2, signature) write_fw_signature(2, signature)
fwi = get_fw_info(2) fwi = get_fw_info(2)
if fwi == None: if fwi is None:
raise Exception('No firmware detected') raise Exception('No firmware detected')
logging.info('Loaded FWExt version %d.%d (%s), %d modules' % (fwi.major, fwi.minor, ctime(fwi.buildtime), len(fwi.modules))) logging.info('Loaded FWExt version %d.%d (%s), %d modules' %
(fwi.major, fwi.minor, ctime(fwi.buildtime), len(fwi.modules)))
# Reboot # Reboot
reboot() reboot()

View file

@ -1,12 +1,14 @@
import logging
import errno import errno
import usb.core as ucore import logging
from binascii import * import typing
from .util import assert_status from binascii import hexlify, unhexlify
from struct import unpack from struct import unpack
import usb.core as ucore
from usb.core import USBError from usb.core import USBError
from .blobs import init_hardcoded, init_hardcoded_clean_slate from .blobs import init_hardcoded, init_hardcoded_clean_slate
from .util import assert_status
supported_devices = [ supported_devices = [
(0x138a, 0x0090), (0x138a, 0x0090),
@ -14,20 +16,22 @@ supported_devices=[
(0x06cb, 0x009a), (0x06cb, 0x009a),
] ]
class CancelledException(Exception): class CancelledException(Exception):
pass pass
class Usb():
class Usb:
def __init__(self): def __init__(self):
self.interrupt_cb = None
self.trace_enabled = False self.trace_enabled = False
self.dev = None self.dev: typing.Optional[ucore.Device] = None
self.cancel = False self.cancel = False
def open(self, vendor=None, product=None): def open(self, vendor=None, product=None):
if vendor is not None and product is not None: if vendor is not None and product is not None:
dev = ucore.find(idVendor=vendor, idProduct=product) dev = ucore.find(idVendor=vendor, idProduct=product)
else: else:
def match(d): def match(d):
return (d.idVendor, d.idProduct) in supported_devices return (d.idVendor, d.idProduct) in supported_devices
@ -35,7 +39,7 @@ class Usb():
self.open_dev(dev) self.open_dev(dev)
def open_devpath(self, busnum, address): def open_devpath(self, busnum: int, address: int):
def match(d): def match(d):
return d.bus == busnum and d.address == address return d.bus == busnum and d.address == address
@ -43,7 +47,7 @@ class Usb():
self.open_dev(dev) self.open_dev(dev)
def open_dev(self, dev): def open_dev(self, dev: ucore.Device):
if dev is None: if dev is None:
raise Exception('No matching devices found') raise Exception('No matching devices found')
@ -80,7 +84,7 @@ class Usb():
logging.info('Clean slate') logging.info('Clean slate')
self.cmd(init_hardcoded_clean_slate) self.cmd(init_hardcoded_clean_slate)
def cmd(self, out): def cmd(self, out: typing.Union[bytes, typing.Callable[[], bytes]]):
if callable(out): if callable(out):
out = out() out = out()
if not out: if not out:
@ -122,8 +126,9 @@ class Usb():
else: else:
raise e raise e
def trace(self, s): def trace(self, s: str):
if self.trace_enabled: if self.trace_enabled:
logging.debug(s) logging.debug(s)
usb = Usb() usb = Usb()

View file

@ -1,9 +1,9 @@
import re import re
from struct import unpack
from binascii import unhexlify from binascii import unhexlify
from struct import unpack
def assert_status(b):
def assert_status(b: bytes):
s, = unpack('<H', b[:2]) s, = unpack('<H', b[:2])
if s != 0: if s != 0:
if s == 0x44f: if s == 0x44f:
@ -12,6 +12,5 @@ def assert_status(b):
raise Exception('Failed: %04x' % s) raise Exception('Failed: %04x' % s)
def unhex(x): def unhex(x: str):
return unhexlify(re.sub('\W', '', x)) return unhexlify(re.sub(r'\W', '', x))

View file

@ -11,12 +11,10 @@ finger_ids = {
"WINBIO_ANSI_381_POS_LH_MIDDLE_FINGER": 8, "WINBIO_ANSI_381_POS_LH_MIDDLE_FINGER": 8,
"WINBIO_ANSI_381_POS_LH_RING_FINGER": 9, "WINBIO_ANSI_381_POS_LH_RING_FINGER": 9,
"WINBIO_ANSI_381_POS_LH_LITTLE_FINGER": 10, "WINBIO_ANSI_381_POS_LH_LITTLE_FINGER": 10,
"WINBIO_ANSI_381_POS_RH_FOUR_FINGERS": 13, "WINBIO_ANSI_381_POS_RH_FOUR_FINGERS": 13,
"WINBIO_ANSI_381_POS_LH_FOUR_FINGERS": 14, "WINBIO_ANSI_381_POS_LH_FOUR_FINGERS": 14,
"WINBIO_ANSI_381_POS_TWO_THUMBS": 15, "WINBIO_ANSI_381_POS_TWO_THUMBS": 15,
# https://github.com/tpn/winsdk-10/blob/9b69fd26ac0c7d0b83d378dba01080e93349c2ed/Include/10.0.16299.0/shared/winbio_types.h#L920-L929 # https://github.com/tpn/winsdk-10/blob/9b69fd26ac0c7d0b83d378dba01080e93349c2ed/Include/10.0.16299.0/shared/winbio_types.h#L920-L929
"WINBIO_FINGER_UNSPECIFIED_POS_01": 0xf5, "WINBIO_FINGER_UNSPECIFIED_POS_01": 0xf5,
"WINBIO_FINGER_UNSPECIFIED_POS_02": 0xf6, "WINBIO_FINGER_UNSPECIFIED_POS_02": 0xf6,