diff --git a/lib/cli/hidconsole.py b/lib/cli/hidconsole.py index 0ae34e3f..ed9f8fe6 100644 --- a/lib/cli/hidconsole.py +++ b/lib/cli/hidconsole.py @@ -1,5 +1,7 @@ +#!/usr/bin/env python + +# Python 2 only for now. -import logging from binascii import hexlify, unhexlify @@ -9,19 +11,20 @@ def read_next(handle, timeout=1000, ignore_nodata=False): print "!! Read failed, aborting" raise Exception() if reply: - print ">> %s [%s]" % (hexlify(reply), repr(reply)) + print ">> %s %s" % (hexlify(reply), repr(reply)) return True if not ignore_nodata: print ">> []" return False + def console_cycle(handle): while True: if read_next(handle, timeout=100, ignore_nodata=True): continue - line = raw_input('!! Enter packet to send (hex bytes): ') + line = raw_input('!! Enter packet to send (hex bytes) or ^C to abort: ') line = line.strip() if not line: continue @@ -33,7 +36,7 @@ def console_cycle(handle): except: print "!! Invalid input." continue - print "<< %s [%s]" % (hexlify(data), repr(data)) + print "<< %s %s" % (hexlify(data), repr(data)) hidapi.write(handle, data) read_next(handle) @@ -41,24 +44,19 @@ def console_cycle(handle): if __name__ == '__main__': import argparse arg_parser = argparse.ArgumentParser() - arg_parser.add_argument('-v', '--verbose', action='count', default=0, - help='increase the logger verbosity') arg_parser.add_argument('device', default=None, help='linux device to connect to') args = arg_parser.parse_args() - log_level = logging.root.level - 10 * args.verbose - logging.root.setLevel(log_level if log_level > 0 else 1) - import hidapi print "!! Opening device ", args.device handle = hidapi.open_path(args.device) if handle: print "!! Opened %x" % handle - print "!! vendor=%s product=%s serial=%s" % ( - hidapi.get_manufacturer(handle), - hidapi.get_product(handle), - hidapi.get_serial(handle)) + print "!! vendor %s product %s serial %s" % ( + repr(hidapi.get_manufacturer(handle)), + repr(hidapi.get_product(handle)), + repr(hidapi.get_serial(handle))) try: console_cycle(handle) except: diff --git a/lib/cli/ur_scanner.py b/lib/cli/ur_scanner.py new file mode 100644 index 00000000..a9b17b9e --- /dev/null +++ b/lib/cli/ur_scanner.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python + + +import logging +logging.basicConfig(level=logging.DEBUG) + +import struct +from binascii import hexlify + +from logitech.unifying_receiver import api + + +def scan_devices(receiver): + devices = api.list_devices(receiver) + if not devices: + print "!! No attached devices found." + return + + for devinfo in devices: + print "Device [%d] %s (%s)" % (devinfo.number, devinfo.name, devinfo.type) + for fw in devinfo.firmware: + print " %s firmware: %s version %s build %d" % (fw.type, fw.name, fw.version, fw.build) + + for index in range(0, len(devinfo.features_array)): + feature = devinfo.features_array[index] + if feature: + print " Feature %s (%s) available at index %d" % (api.FEATURE_NAME(feature), hexlify(feature), index) + + if api.FEATURE.REPROGRAMMABLE_KEYS in devinfo.features_array: + keys_count = api.request(receiver, devinfo.number, api.FEATURE.REPROGRAMMABLE_KEYS, features_array=devinfo.features_array) + if keys_count: + keys_count = ord(keys_count[:1]) + print " %d reprogrammable keys available" % keys_count + for index in range(0, keys_count): + key_info = api.request(receiver, devinfo.number, api.FEATURE.REPROGRAMMABLE_KEYS, + function=b'\x10', params=struct.pack('!B', index), + features_array=devinfo.features_array) + ctrl_id_indexes, ctrl_task_indexes, flags = struct.unpack('!HHB', key_info[:5]) + + flag = '' + if flags & 0x10: + flag += ' reprogrammable' + if flags & 0x08: + flag += ' fn-sensitive' + if flags & 0x04: + flag += ' nonstandard' + if flags & 0x02: + flag += ' is-fn' + if flags & 0x01: + flag += ' mse' + + print " key %d : %04x %04x %s" % (index, ctrl_id_indexes, ctrl_task_indexes, flag) + + + + print "--------" + + + +if __name__ == '__main__': + import argparse + arg_parser = argparse.ArgumentParser() + arg_parser.add_argument('-v', '--verbose', action='count', default=0, + help='increase the logger verbosity') + args = arg_parser.parse_args() + + log_level = logging.root.level - 10 * args.verbose + logging.root.setLevel(log_level if log_level > 0 else 1) + + receiver = api.open() + if receiver: + print "!! Logitech Unifying Receiver found." + scan_devices(receiver) + else: + print "!! Logitech Unifying Receiver not found." + + api.close(receiver) diff --git a/lib/logitech/devices/k750.py b/lib/logitech/devices/k750.py index a9d9c7bd..8c757125 100644 --- a/lib/logitech/devices/k750.py +++ b/lib/logitech/devices/k750.py @@ -1,5 +1,5 @@ # -# Functions that are specific to the K750 solar keyboard. +# Functions specific to the K750 solar keyboard. # import logging diff --git a/lib/logitech/unifying_receiver/constants.py b/lib/logitech/unifying_receiver/constants.py index 539740f4..45c8716f 100644 --- a/lib/logitech/unifying_receiver/constants.py +++ b/lib/logitech/unifying_receiver/constants.py @@ -2,6 +2,8 @@ # Constants used by the rest of the API. # +from binascii import hexlify + """Possible features available on a Logitech device. A particular device might not support all these features, and may support other @@ -42,7 +44,7 @@ def FEATURE_NAME(feature_code): return None if feature_code in _FEATURE_NAMES: return _FEATURE_NAMES[feature_code] - return 'UNKNOWN_%s' % feature_code + return 'UNKNOWN_%s' % hexlify(feature_code) """Possible types of devices connected to an UR.""" diff --git a/hidconsole b/tools/hidconsole similarity index 100% rename from hidconsole rename to tools/hidconsole diff --git a/tools/ur_scanner b/tools/ur_scanner new file mode 100755 index 00000000..8b96df51 --- /dev/null +++ b/tools/ur_scanner @@ -0,0 +1,8 @@ +#!/bin/sh + +cd `dirname "$0"` + +export LD_LIBRARY_PATH=$PWD/lib +export PYTHONPATH=$PWD/lib + +exec python -OO -m cli.ur_scanner "$@"