added a cli tool for scanning the UR devices

This commit is contained in:
Daniel Pavel 2012-09-28 10:33:55 +03:00
parent 3a6e7514fb
commit 0fe3151051
6 changed files with 100 additions and 15 deletions

View File

@ -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:

77
lib/cli/ur_scanner.py Normal file
View File

@ -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)

View File

@ -1,5 +1,5 @@
# #
# Functions that are specific to the K750 solar keyboard. # Functions specific to the K750 solar keyboard.
# #
import logging import logging

View File

@ -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."""

8
tools/ur_scanner Executable file
View File

@ -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 "$@"