added a cli tool for scanning the UR devices
This commit is contained in:
parent
3a6e7514fb
commit
0fe3151051
|
@ -1,5 +1,7 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
# Python 2 only for now.
|
||||||
|
|
||||||
import logging
|
|
||||||
from binascii import hexlify, unhexlify
|
from binascii import hexlify, unhexlify
|
||||||
|
|
||||||
|
|
||||||
|
@ -9,19 +11,20 @@ def read_next(handle, timeout=1000, ignore_nodata=False):
|
||||||
print "!! Read failed, aborting"
|
print "!! Read failed, aborting"
|
||||||
raise Exception()
|
raise Exception()
|
||||||
if reply:
|
if reply:
|
||||||
print ">> %s [%s]" % (hexlify(reply), repr(reply))
|
print ">> %s %s" % (hexlify(reply), repr(reply))
|
||||||
return True
|
return True
|
||||||
|
|
||||||
if not ignore_nodata:
|
if not ignore_nodata:
|
||||||
print ">> []"
|
print ">> []"
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def console_cycle(handle):
|
def console_cycle(handle):
|
||||||
while True:
|
while True:
|
||||||
if read_next(handle, timeout=100, ignore_nodata=True):
|
if read_next(handle, timeout=100, ignore_nodata=True):
|
||||||
continue
|
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()
|
line = line.strip()
|
||||||
if not line:
|
if not line:
|
||||||
continue
|
continue
|
||||||
|
@ -33,7 +36,7 @@ def console_cycle(handle):
|
||||||
except:
|
except:
|
||||||
print "!! Invalid input."
|
print "!! Invalid input."
|
||||||
continue
|
continue
|
||||||
print "<< %s [%s]" % (hexlify(data), repr(data))
|
print "<< %s %s" % (hexlify(data), repr(data))
|
||||||
hidapi.write(handle, data)
|
hidapi.write(handle, data)
|
||||||
read_next(handle)
|
read_next(handle)
|
||||||
|
|
||||||
|
@ -41,24 +44,19 @@ def console_cycle(handle):
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
import argparse
|
import argparse
|
||||||
arg_parser = argparse.ArgumentParser()
|
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,
|
arg_parser.add_argument('device', default=None,
|
||||||
help='linux device to connect to')
|
help='linux device to connect to')
|
||||||
args = arg_parser.parse_args()
|
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
|
import hidapi
|
||||||
print "!! Opening device ", args.device
|
print "!! Opening device ", args.device
|
||||||
handle = hidapi.open_path(args.device)
|
handle = hidapi.open_path(args.device)
|
||||||
if handle:
|
if handle:
|
||||||
print "!! Opened %x" % handle
|
print "!! Opened %x" % handle
|
||||||
print "!! vendor=%s product=%s serial=%s" % (
|
print "!! vendor %s product %s serial %s" % (
|
||||||
hidapi.get_manufacturer(handle),
|
repr(hidapi.get_manufacturer(handle)),
|
||||||
hidapi.get_product(handle),
|
repr(hidapi.get_product(handle)),
|
||||||
hidapi.get_serial(handle))
|
repr(hidapi.get_serial(handle)))
|
||||||
try:
|
try:
|
||||||
console_cycle(handle)
|
console_cycle(handle)
|
||||||
except:
|
except:
|
||||||
|
|
|
@ -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)
|
|
@ -1,5 +1,5 @@
|
||||||
#
|
#
|
||||||
# Functions that are specific to the K750 solar keyboard.
|
# Functions specific to the K750 solar keyboard.
|
||||||
#
|
#
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
# Constants used by the rest of the API.
|
# Constants used by the rest of the API.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
from binascii import hexlify
|
||||||
|
|
||||||
"""Possible features available on a Logitech device.
|
"""Possible features available on a Logitech device.
|
||||||
|
|
||||||
A particular device might not support all these features, and may support other
|
A particular device might not support all these features, and may support other
|
||||||
|
@ -42,7 +44,7 @@ def FEATURE_NAME(feature_code):
|
||||||
return None
|
return None
|
||||||
if feature_code in _FEATURE_NAMES:
|
if feature_code in _FEATURE_NAMES:
|
||||||
return _FEATURE_NAMES[feature_code]
|
return _FEATURE_NAMES[feature_code]
|
||||||
return 'UNKNOWN_%s' % feature_code
|
return 'UNKNOWN_%s' % hexlify(feature_code)
|
||||||
|
|
||||||
|
|
||||||
"""Possible types of devices connected to an UR."""
|
"""Possible types of devices connected to an UR."""
|
||||||
|
|
|
@ -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 "$@"
|
Loading…
Reference in New Issue