diff --git a/lib/logitech/unifying_receiver/base.py b/lib/logitech/unifying_receiver/base.py index a9d29b20..2d4b006a 100644 --- a/lib/logitech/unifying_receiver/base.py +++ b/lib/logitech/unifying_receiver/base.py @@ -6,9 +6,17 @@ from __future__ import absolute_import, division, print_function, unicode_literals from time import time as _timestamp -from struct import pack as _pack from random import getrandbits as _random_bits +from struct import pack as _pack +try: + unicode + # if Python2, unicode_literals will mess our first (un)pack() argument + _pack_str = _pack + _pack = lambda x, *args: _pack_str(str(x), *args) +except: + pass + from logging import getLogger, DEBUG as _DEBUG _log = getLogger('LUR.base') del getLogger @@ -145,9 +153,9 @@ def write(handle, devnumber, data): assert isinstance(data, bytes), (repr(data), type(data)) if len(data) > _SHORT_MESSAGE_SIZE - 2 or data[:1] == b'\x82': - wdata = _pack(b'!BB18s', 0x11, devnumber, data) + wdata = _pack('!BB18s', 0x11, devnumber, data) else: - wdata = _pack(b'!BB5s', 0x10, devnumber, data) + wdata = _pack('!BB5s', 0x10, devnumber, data) if _log.isEnabledFor(_DEBUG): _log.debug("(%s) <= w[%02X %02X %s %s]", handle, ord(wdata[:1]), devnumber, _strhex(wdata[2:4]), _strhex(wdata[4:])) @@ -291,10 +299,13 @@ def request(handle, devnumber, request_id, *params): else: timeout = _RECEIVER_REQUEST_TIMEOUT - params = b''.join(_pack(b'B', p) if isinstance(p, int) else p for p in params) + if params: + params = b''.join(_pack('B', p) if isinstance(p, int) else p for p in params) + else: + params = b'' # if _log.isEnabledFor(_DEBUG): # _log.debug("(%s) device %d request_id {%04X} params [%s]", handle, devnumber, request_id, _strhex(params)) - request_data = _pack(b'!H', request_id) + params + request_data = _pack('!H', request_id) + params ihandle = int(handle) notifications_hook = getattr(handle, 'notifications_hook', None) @@ -378,7 +389,7 @@ def ping(handle, devnumber): # reply, and set most significant (0x8) bit in SoftwareId so that the reply # is always distinguishable from notifications request_id = 0x0018 | _random_bits(3) - request_data = _pack(b'!HBBB', request_id, 0, 0, _random_bits(8)) + request_data = _pack('!HBBB', request_id, 0, 0, _random_bits(8)) ihandle = int(handle) notifications_hook = getattr(handle, 'notifications_hook', None) diff --git a/lib/logitech/unifying_receiver/common.py b/lib/logitech/unifying_receiver/common.py index 443787d9..27c52eaf 100644 --- a/lib/logitech/unifying_receiver/common.py +++ b/lib/logitech/unifying_receiver/common.py @@ -6,6 +6,14 @@ from __future__ import absolute_import, division, print_function, unicode_litera from binascii import hexlify as _hexlify from struct import pack as _pack +try: + unicode + # if Python2, unicode_literals will mess our first (un)pack() argument + _pack_str = _pack + _pack = lambda x, *args: _pack_str(str(x), *args) +except: + pass + try: unicode # this is certanly Python 2 @@ -36,7 +44,7 @@ class NamedInt(int): def bytes(self, count=2): if self.bit_length() > count * 8: raise ValueError('cannot fit %X into %d bytes' % (self, count)) - return _pack(b'!L', self)[-count:] + return _pack('!L', self)[-count:] def __eq__(self, other): if isinstance(other, NamedInt): diff --git a/lib/logitech/unifying_receiver/hidpp20.py b/lib/logitech/unifying_receiver/hidpp20.py index 39d479d9..821fdd76 100644 --- a/lib/logitech/unifying_receiver/hidpp20.py +++ b/lib/logitech/unifying_receiver/hidpp20.py @@ -5,6 +5,16 @@ from __future__ import absolute_import, division, print_function, unicode_literals from struct import pack as _pack, unpack as _unpack +try: + unicode + # if Python2, unicode_literals will mess our first (un)pack() argument + _pack_str = _pack + _unpack_str = _unpack + _pack = lambda x, *args: _pack_str(str(x), *args) + _unpack = lambda x, *args: _unpack_str(str(x), *args) +except: + pass + from weakref import proxy as _proxy from logging import getLogger, DEBUG as _DEBUG @@ -156,7 +166,7 @@ class FeaturesArray(object): self.device = None return False - reply = self.device.request(0x0000, _pack(b'!H', FEATURE.FEATURE_SET)) + reply = self.device.request(0x0000, _pack('!H', FEATURE.FEATURE_SET)) if reply is None: self.supported = False else: @@ -190,7 +200,7 @@ class FeaturesArray(object): if self.features[index] is None: feature = self.device.feature_request(FEATURE.FEATURE_SET, 0x10, index) if feature: - feature, = _unpack(b'!H', feature[:2]) + feature, = _unpack('!H', feature[:2]) self.features[index] = FEATURE[feature] return self.features[index] @@ -213,7 +223,7 @@ class FeaturesArray(object): break if may_have: - reply = self.device.request(0x0000, _pack(b'!H', ivalue)) + reply = self.device.request(0x0000, _pack('!H', ivalue)) if reply: index = ord(reply[0:1]) if index: @@ -233,7 +243,7 @@ class FeaturesArray(object): raise ValueError("%s not in list" % repr(value)) if may_have: - reply = self.device.request(0x0000, _pack(b'!H', ivalue)) + reply = self.device.request(0x0000, _pack('!H', ivalue)) if reply: index = ord(reply[0:1]) self.features[index] = FEATURE[ivalue] @@ -274,7 +284,7 @@ class KeysArray(object): if self.keys[index] is None: keydata = feature_request(self.device, FEATURE.REPROGRAMMABLE_KEYS, 0x10, index) if keydata: - key, key_task, flags = _unpack(b'!HHB', keydata[:5]) + key, key_task, flags = _unpack('!HHB', keydata[:5]) self.keys[index] = _ReprogrammableKeyInfo(index, KEY[key], KEY[key_task], flags) return self.keys[index] @@ -327,7 +337,7 @@ def get_firmware(device): if fw_info: level = ord(fw_info[:1]) & 0x0F if level == 0 or level == 1: - name, version_major, version_minor, build = _unpack(b'!3sBBH', fw_info[1:8]) + name, version_major, version_minor, build = _unpack('!3sBBH', fw_info[1:8]) version = '%02X.%02X' % (version_major, version_minor) if build: version += '.B%04X' % build @@ -386,7 +396,7 @@ def get_battery(device): """ battery = feature_request(device, FEATURE.BATTERY) if battery: - discharge, dischargeNext, status = _unpack(b'!BBB', battery[:3]) + discharge, dischargeNext, status = _unpack('!BBB', battery[:3]) if _log.isEnabledFor(_DEBUG): _log.debug("device %d battery %d%% charged, next level %d%% charge, status %d = %s", device.number, discharge, dischargeNext, status, BATTERY_STATUS[status]) @@ -402,7 +412,7 @@ def get_keys(device): def get_mouse_pointer_info(device): pointer_info = feature_request(device, FEATURE.MOUSE_POINTER) if pointer_info: - dpi, flags = _unpack(b'!HB', pointer_info[:3]) + dpi, flags = _unpack('!HB', pointer_info[:3]) acceleration = ['none', 'low', 'med', 'high' ][flags & 0x3] suggest_os_ballistics = (flags & 0x04) != 0 suggest_vertical_orientation = (flags & 0x08) != 0 diff --git a/lib/logitech/unifying_receiver/status.py b/lib/logitech/unifying_receiver/status.py index fe73d105..b9713125 100644 --- a/lib/logitech/unifying_receiver/status.py +++ b/lib/logitech/unifying_receiver/status.py @@ -5,9 +5,17 @@ from __future__ import absolute_import, division, print_function, unicode_literals from time import time as _timestamp -from struct import unpack as _unpack from weakref import proxy as _proxy +from struct import unpack as _unpack +try: + unicode + # if Python2, unicode_literals will mess our first (un)pack() argument + _unpack_str = _unpack + _unpack = lambda x, *args: _unpack_str(str(x), *args) +except: + pass + from logging import getLogger, DEBUG as _DEBUG _log = getLogger('LUR.status') del getLogger @@ -343,7 +351,7 @@ class DeviceStatus(dict): if feature == _hidpp20.FEATURE.SOLAR_CHARGE: if n.data[5:9] == b'GOOD': - charge, lux, adc = _unpack(b'!BHH', n.data[:5]) + charge, lux, adc = _unpack('!BHH', n.data[:5]) self[BATTERY_LEVEL] = charge # guesstimate the battery voltage, emphasis on 'guess' self[BATTERY_STATUS] = '%1.2fV' % (adc * 2.67793237653 / 0x0672)