From 764ad45ca2c0c549443baed1270cb32b8490c3e2 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 19 Jul 2019 13:49:36 +1000 Subject: [PATCH 01/17] wacom: normalize the pressure to the advertised [0, 0xffff] range This requires adjusting the svg conversion in kete as well, afaict the 1000 range there was chosen because it's (almost) the midpoint of the Bamboo series with 2048 pressure grades. So let's use half of 0x10000 instead, which is approximately 0x8000 as the crow flies. Fixes #142 --- tools/kete.py | 3 ++- tuhi/wacom.py | 6 +++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/tools/kete.py b/tools/kete.py index 9810c7d..751493a 100755 --- a/tools/kete.py +++ b/tools/kete.py @@ -629,7 +629,8 @@ class Fetcher(Worker): elif self.orientation == 'Reverse-Landscape': x, y = width - x, height - y - delta = (p['pressure'] - 1000.0) / 1000.0 + # Pressure normalized range is [0, 0xffff] + delta = (p['pressure'] - 0x8000) / 0x8000 stroke_width = 0.4 + 0.20 * delta points_with_sk_width.append((x, y, stroke_width)) diff --git a/tuhi/wacom.py b/tuhi/wacom.py index 67eaf24..9ca68f9 100644 --- a/tuhi/wacom.py +++ b/tuhi/wacom.py @@ -963,7 +963,11 @@ class WacomProtocolBase(WacomProtocolLowLevelComm): if packet.bitmask & 0b00111100 == 0: continue - stroke.new_abs((x, y), p) + def normalize(p): + NORMALIZED_RANGE = 0x10000 + return NORMALIZED_RANGE * p / self.pressure + + stroke.new_abs((x, y), normalize(p)) drawing.seal() return drawing From 5b73c8ea2d2fb276e82f8091c9ed71fa95086f63 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 15 Jul 2019 21:05:32 +1000 Subject: [PATCH 02/17] Add a few more comments to the codebase --- tuhi/base.py | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/tuhi/base.py b/tuhi/base.py index 242666a..276fc50 100644 --- a/tuhi/base.py +++ b/tuhi/base.py @@ -241,6 +241,7 @@ class TuhiDevice(GObject.Object): self.mode = DeviceMode.LISTEN def _on_listening_updated(self, dbus_device, pspec): + # Callback when a DBus client calls Start/Stop listening self.notify('listening') def _on_live_updated(self, dbus_device, pspec): @@ -274,6 +275,10 @@ class TuhiDevice(GObject.Object): class Tuhi(GObject.Object): + ''' + The Tuhi object is the main entry point and glue object between the + backend and the DBus server. + ''' __gsignals__ = { 'device-added': (GObject.SignalFlags.RUN_FIRST, None, (GObject.TYPE_PYOBJECT,)), @@ -331,6 +336,9 @@ class Tuhi(GObject.Object): if bluez_device.vendor_id not in WACOM_COMPANY_IDS: return False + # When the device is in register mode (blue light blinking), the + # manufacturer is merely 4 bytes. This will reset to 7 bytes even + # when the device simply times out and does not register fully. manufacturer_data = bluez_device.manufacturer_data return manufacturer_data is not None and len(manufacturer_data) == 4 @@ -348,13 +356,21 @@ class Tuhi(GObject.Object): self._on_listening_updated(None, None) def _add_device(self, manager, bluez_device, hotplugged=False): - # Note: this function gets called every time the bluez device - # changes a property too (like signal strength). IOW, it gets called - # every second or so. + ''' + Process a new BlueZ device that may be one of our devices. + + This function is called once during intial setup to enumerate the + BlueZ devices and for every BlueZ device property change. Including + RSSI which will give you a value every second or so. + + .. :param hotplugged: True if this function was called from a BlueZ + device property update. False when called during the initial setup + stage. + ''' uuid = None - # check if the device is already known by us + # check if the device is already known to us try: config = self.config.devices[bluez_device.address] uuid = config['uuid'] From deb2c3ad2f4f83f810e889b7a3cad0fd8e435306 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 15 Jul 2019 21:24:11 +1000 Subject: [PATCH 03/17] base: rename the hotplugged argument This one is a bit confusing, because most of the time it's not a hotplug event, it's just the RSSI property updating. --- tuhi/base.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tuhi/base.py b/tuhi/base.py index 276fc50..548bb5d 100644 --- a/tuhi/base.py +++ b/tuhi/base.py @@ -355,7 +355,7 @@ class Tuhi(GObject.Object): # restart discovery if some users are already in the listening mode self._on_listening_updated(None, None) - def _add_device(self, manager, bluez_device, hotplugged=False): + def _add_device(self, manager, bluez_device, from_live_update=False): ''' Process a new BlueZ device that may be one of our devices. @@ -363,7 +363,7 @@ class Tuhi(GObject.Object): BlueZ devices and for every BlueZ device property change. Including RSSI which will give you a value every second or so. - .. :param hotplugged: True if this function was called from a BlueZ + .. :param from_live_update: True if this function was called from a BlueZ device property update. False when called during the initial setup stage. ''' @@ -380,10 +380,10 @@ class Tuhi(GObject.Object): if uuid is None and bluez_device.vendor_id not in WACOM_COMPANY_IDS: return - # if the device has been 'hotplugged' in the bluez stack, + # if we got here from a currently live BlueZ device, # ManufacturerData is reliable. Else, consider the device not in # register mode - if hotplugged and Tuhi._device_in_register_mode(bluez_device): + if from_live_update and Tuhi._device_in_register_mode(bluez_device): mode = DeviceMode.REGISTER else: mode = DeviceMode.LISTEN From e1a3675439116c00a5bd5e14b5b539b0193db59e Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 17 Jul 2019 10:07:11 +1000 Subject: [PATCH 04/17] base: ignore anything not from the known vendor IDs We don't want to accidentally start talking to a device and brick it. --- tuhi/base.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/tuhi/base.py b/tuhi/base.py index 548bb5d..b0934d2 100644 --- a/tuhi/base.py +++ b/tuhi/base.py @@ -333,9 +333,6 @@ class Tuhi(GObject.Object): @classmethod def _device_in_register_mode(cls, bluez_device): - if bluez_device.vendor_id not in WACOM_COMPANY_IDS: - return False - # When the device is in register mode (blue light blinking), the # manufacturer is merely 4 bytes. This will reset to 7 bytes even # when the device simply times out and does not register fully. @@ -368,16 +365,17 @@ class Tuhi(GObject.Object): stage. ''' - uuid = None + # We have a reverse-engineered protocol. Let's not talk to anyone + # who doesn't look like we know them to avoid potentially bricking a + # device. + if bluez_device.vendor_id not in WACOM_COMPANY_IDS: + return # check if the device is already known to us try: config = self.config.devices[bluez_device.address] uuid = config['uuid'] except KeyError: - pass - - if uuid is None and bluez_device.vendor_id not in WACOM_COMPANY_IDS: return # if we got here from a currently live BlueZ device, From 37b9b2eefa44f7b0e89c93e5da3d43fc45c43a56 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 17 Jul 2019 10:03:57 +1000 Subject: [PATCH 05/17] base: simplify check for in register mode With a "or []" we can force this to be at least a 0-length list, obsoleting the None check. --- tuhi/base.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tuhi/base.py b/tuhi/base.py index b0934d2..ba21654 100644 --- a/tuhi/base.py +++ b/tuhi/base.py @@ -336,8 +336,7 @@ class Tuhi(GObject.Object): # When the device is in register mode (blue light blinking), the # manufacturer is merely 4 bytes. This will reset to 7 bytes even # when the device simply times out and does not register fully. - manufacturer_data = bluez_device.manufacturer_data - return manufacturer_data is not None and len(manufacturer_data) == 4 + return len(bluez_device.manufacturer_data or []) == 4 def _on_bluez_discovery_started(self, manager): # Something else may turn discovery mode on, we don't care about From 08e3ec532e98729388526ec07ca091c88829a25d Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 17 Jul 2019 10:06:37 +1000 Subject: [PATCH 06/17] base: drop the extra function for checking if the device is in register mode Now that it's just a one-liner, we don't need an extra function --- tuhi/base.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/tuhi/base.py b/tuhi/base.py index ba21654..23f5aca 100644 --- a/tuhi/base.py +++ b/tuhi/base.py @@ -331,13 +331,6 @@ class Tuhi(GObject.Object): for addr in unregistered: del self.devices[addr] - @classmethod - def _device_in_register_mode(cls, bluez_device): - # When the device is in register mode (blue light blinking), the - # manufacturer is merely 4 bytes. This will reset to 7 bytes even - # when the device simply times out and does not register fully. - return len(bluez_device.manufacturer_data or []) == 4 - def _on_bluez_discovery_started(self, manager): # Something else may turn discovery mode on, we don't care about # it then @@ -380,7 +373,11 @@ class Tuhi(GObject.Object): # if we got here from a currently live BlueZ device, # ManufacturerData is reliable. Else, consider the device not in # register mode - if from_live_update and Tuhi._device_in_register_mode(bluez_device): + # + # When the device is in register mode (blue light blinking), the + # manufacturer is merely 4 bytes. This will reset to 7 bytes even + # when the device simply times out and does not register fully. + if from_live_update and len(bluez_device.manufacturer_data or []) == 4: mode = DeviceMode.REGISTER else: mode = DeviceMode.LISTEN From 92a9628adfe189602c6d4086f771c454dc03605d Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 17 Jul 2019 10:13:14 +1000 Subject: [PATCH 07/17] base: drop the separate function for bluez updates A lambda does the job here without increasing the class profile --- tuhi/base.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/tuhi/base.py b/tuhi/base.py index 23f5aca..c83fda6 100644 --- a/tuhi/base.py +++ b/tuhi/base.py @@ -309,8 +309,10 @@ class Tuhi(GObject.Object): for dev in self.bluez.devices: self._add_device(self.bluez, dev) - self.bluez.connect('device-added', self._on_bluez_device_updated) - self.bluez.connect('device-updated', self._on_bluez_device_updated) + self.bluez.connect('device-added', + lambda mgr, dev: self._add_device(mgr, dev, True)) + self.bluez.connect('device-updated', + lambda mgr, dev: self._add_device(mgr, dev, True)) def _on_tuhi_bus_name_lost(self, dbus_server): self.mainloop.quit() @@ -401,9 +403,6 @@ class Tuhi(GObject.Object): elif d.listening: d.listen() - def _on_bluez_device_updated(self, manager, bluez_device): - self._add_device(manager, bluez_device, True) - def _on_listening_updated(self, tuhi_dbus_device, pspec): listen = self._search_stop_handler is not None for dev in self.devices.values(): From cda4300388d58def76998d147b982a55ccd50d94 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 31 Jul 2019 11:13:58 +1000 Subject: [PATCH 08/17] wacom: visually align the UUIDs And add # NOQA to shut up flake8 Signed-off-by: Peter Hutterer --- tuhi/wacom.py | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/tuhi/wacom.py b/tuhi/wacom.py index 9ca68f9..b21a4e1 100644 --- a/tuhi/wacom.py +++ b/tuhi/wacom.py @@ -28,18 +28,15 @@ from .uhid import UHIDDevice logger = logging.getLogger('tuhi.wacom') -NORDIC_UART_SERVICE_UUID = '6e400001-b5a3-f393-e0a9-e50e24dcca9e' -NORDIC_UART_CHRC_TX_UUID = '6e400002-b5a3-f393-e0a9-e50e24dcca9e' -NORDIC_UART_CHRC_RX_UUID = '6e400003-b5a3-f393-e0a9-e50e24dcca9e' - -WACOM_LIVE_SERVICE_UUID = '00001523-1212-efde-1523-785feabcd123' -WACOM_CHRC_LIVE_PEN_DATA_UUID = '00001524-1212-efde-1523-785feabcd123' - -WACOM_OFFLINE_SERVICE_UUID = 'ffee0001-bbaa-9988-7766-554433221100' -WACOM_OFFLINE_CHRC_PEN_DATA_UUID = 'ffee0003-bbaa-9988-7766-554433221100' - -MYSTERIOUS_NOTIFICATION_SERVICE_UUID = '3a340720-c572-11e5-86c5-0002a5d5c51b' -MYSTERIOUS_NOTIFICATION_CHRC_UUID = '3a340721-c572-11e5-86c5-0002a5d5c51b' +NORDIC_UART_SERVICE_UUID = '6e400001-b5a3-f393-e0a9-e50e24dcca9e' # NOQA +NORDIC_UART_CHRC_TX_UUID = '6e400002-b5a3-f393-e0a9-e50e24dcca9e' # NOQA +NORDIC_UART_CHRC_RX_UUID = '6e400003-b5a3-f393-e0a9-e50e24dcca9e' # NOQA +WACOM_LIVE_SERVICE_UUID = '00001523-1212-efde-1523-785feabcd123' # NOQA +WACOM_CHRC_LIVE_PEN_DATA_UUID = '00001524-1212-efde-1523-785feabcd123' # NOQA +WACOM_OFFLINE_SERVICE_UUID = 'ffee0001-bbaa-9988-7766-554433221100' # NOQA +WACOM_OFFLINE_CHRC_PEN_DATA_UUID = 'ffee0003-bbaa-9988-7766-554433221100' # NOQA +MYSTERIOUS_NOTIFICATION_SERVICE_UUID = '3a340720-c572-11e5-86c5-0002a5d5c51b' # NOQA +MYSTERIOUS_NOTIFICATION_CHRC_UUID = '3a340721-c572-11e5-86c5-0002a5d5c51b' # NOQA @enum.unique From b009ea3c96da5a04d2dbd99e09c276a932926769 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 31 Jul 2019 14:12:36 +1000 Subject: [PATCH 09/17] wacom: rename the mysterious bits to sysevent These bits are used for system notifications Signed-off-by: Peter Hutterer --- tuhi/wacom.py | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/tuhi/wacom.py b/tuhi/wacom.py index b21a4e1..e96d8f2 100644 --- a/tuhi/wacom.py +++ b/tuhi/wacom.py @@ -28,15 +28,15 @@ from .uhid import UHIDDevice logger = logging.getLogger('tuhi.wacom') -NORDIC_UART_SERVICE_UUID = '6e400001-b5a3-f393-e0a9-e50e24dcca9e' # NOQA -NORDIC_UART_CHRC_TX_UUID = '6e400002-b5a3-f393-e0a9-e50e24dcca9e' # NOQA -NORDIC_UART_CHRC_RX_UUID = '6e400003-b5a3-f393-e0a9-e50e24dcca9e' # NOQA -WACOM_LIVE_SERVICE_UUID = '00001523-1212-efde-1523-785feabcd123' # NOQA -WACOM_CHRC_LIVE_PEN_DATA_UUID = '00001524-1212-efde-1523-785feabcd123' # NOQA -WACOM_OFFLINE_SERVICE_UUID = 'ffee0001-bbaa-9988-7766-554433221100' # NOQA -WACOM_OFFLINE_CHRC_PEN_DATA_UUID = 'ffee0003-bbaa-9988-7766-554433221100' # NOQA -MYSTERIOUS_NOTIFICATION_SERVICE_UUID = '3a340720-c572-11e5-86c5-0002a5d5c51b' # NOQA -MYSTERIOUS_NOTIFICATION_CHRC_UUID = '3a340721-c572-11e5-86c5-0002a5d5c51b' # NOQA +NORDIC_UART_SERVICE_UUID = '6e400001-b5a3-f393-e0a9-e50e24dcca9e' # NOQA +NORDIC_UART_CHRC_TX_UUID = '6e400002-b5a3-f393-e0a9-e50e24dcca9e' # NOQA +NORDIC_UART_CHRC_RX_UUID = '6e400003-b5a3-f393-e0a9-e50e24dcca9e' # NOQA +WACOM_LIVE_SERVICE_UUID = '00001523-1212-efde-1523-785feabcd123' # NOQA +WACOM_CHRC_LIVE_PEN_DATA_UUID = '00001524-1212-efde-1523-785feabcd123' # NOQA +WACOM_OFFLINE_SERVICE_UUID = 'ffee0001-bbaa-9988-7766-554433221100' # NOQA +WACOM_OFFLINE_CHRC_PEN_DATA_UUID = 'ffee0003-bbaa-9988-7766-554433221100' # NOQA +SYSEVENT_NOTIFICATION_SERVICE_UUID = '3a340720-c572-11e5-86c5-0002a5d5c51b' # NOQA +SYSEVENT_NOTIFICATION_CHRC_UUID = '3a340721-c572-11e5-86c5-0002a5d5c51b' # NOQA @enum.unique @@ -160,8 +160,8 @@ class DataLogger(object): def recv(self, data): return self.parent._recv(self.source, data) - class _Mysterious(object): - source = 'MYSTERIOUS' + class _SysEvent(object): + source = 'SYSEVENT' def __init__(self, parent): self.parent = parent @@ -201,7 +201,7 @@ class DataLogger(object): self.nordic = DataLogger._Nordic(self) self.pen = DataLogger._Pen(self) - self.mysterious = DataLogger._Mysterious(self) + self.sysevent = DataLogger._SysEvent(self) self.logfile = None def _on_bluez_connected(self, bluez_device): @@ -557,7 +557,7 @@ class WacomRegisterHelper(WacomProtocolLowLevelComm): @classmethod def is_spark(cls, device): - return MYSTERIOUS_NOTIFICATION_CHRC_UUID not in device.characteristics + return SYSEVENT_NOTIFICATION_CHRC_UUID not in device.characteristics def register_device(self, uuid): protocol = Protocol.UNKNOWN @@ -1058,8 +1058,8 @@ class WacomProtocolSlate(WacomProtocolSpark): def __init__(self, device, uuid): super().__init__(device, uuid) - device.connect_gatt_value(MYSTERIOUS_NOTIFICATION_CHRC_UUID, - self._on_mysterious_data_received) + device.connect_gatt_value(SYSEVENT_NOTIFICATION_CHRC_UUID, + self._on_sysevent_data_received) def live_mode(self, mode, uhid): # Slate tablet has two models A5 and A4 @@ -1072,8 +1072,8 @@ class WacomProtocolSlate(WacomProtocolSpark): return super().live_mode(mode, uhid) - def _on_mysterious_data_received(self, name, value): - self.fw_logger.mysterious.recv(value) + def _on_sysevent_data_received(self, name, value): + self.fw_logger.sysevent.recv(value) def ack_transaction(self): self.send_nordic_command_sync(command=0xca) From d3726420cf98dcf676e0c170eab36da32c05c7f7 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 31 Jul 2019 14:15:38 +1000 Subject: [PATCH 10/17] wacom: add a comment describing where to we store stuff Signed-off-by: Peter Hutterer --- tuhi/wacom.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tuhi/wacom.py b/tuhi/wacom.py index e96d8f2..5a52515 100644 --- a/tuhi/wacom.py +++ b/tuhi/wacom.py @@ -138,6 +138,8 @@ class DataLogger(object): This uses a logger for stdout, but it also writes the log files to disk for future re-use. + Targets for log are $HOME/.share/tuhi/12:AB:23:CD:.../.yml + ''' class _Nordic(object): source = 'NORDIC' @@ -450,8 +452,8 @@ class WacomPacketHandlerUnknownFixedStrokeDataIntuosPro(WacomPacketHandler): class WacomProtocolLowLevelComm(GObject.Object): ''' Internal class to handle the communication with the Wacom device. - No-one should directly instanciate this. - + No-one should directly instanciate this, use the device-specific + subclass instead (e.g. WacomProtocolIntuosPro). :param device: the BlueZDevice object that is this wacom device ''' From c84f3f8c635fb42bd573be350986f16bfd8a8fcb Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 31 Jul 2019 14:24:23 +1000 Subject: [PATCH 11/17] wacom: error code 0x05 is an unrecognized command Signed-off-by: Peter Hutterer --- tuhi/wacom.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tuhi/wacom.py b/tuhi/wacom.py index 5a52515..360d2ea 100644 --- a/tuhi/wacom.py +++ b/tuhi/wacom.py @@ -287,6 +287,10 @@ class WacomEEAGAINException(WacomException): errno = errno.EAGAIN +class WacomUnsupportedCommandException(WacomException): + errno = errno.ENOMSG + + class WacomWrongModeException(WacomException): errno = errno.EBADE @@ -515,7 +519,7 @@ class WacomProtocolLowLevelComm(GObject.Object): elif data[0] == 0x02: raise WacomEEAGAINException(f'unexpected answer: {data[0]:02x}') elif data[0] == 0x05: - raise WacomCorruptDataException(f'invalid opcode') + raise WacomUnsupportedCommandException(f'invalid opcode') elif data[0] == 0x07: raise WacomNotRegisteredException(f'wrong device, please re-register') elif data[0] != 0x00: From 6e27d70517bcdfd17d97eea2e820ac47924e8df9 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 31 Jul 2019 15:54:45 +1000 Subject: [PATCH 12/17] wacom: de-duplicate an opcode check we don't need the same-ish check twice, we can just pop our non-list into a list an go from there. Signed-off-by: Peter Hutterer --- tuhi/wacom.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/tuhi/wacom.py b/tuhi/wacom.py index 360d2ea..084fcc9 100644 --- a/tuhi/wacom.py +++ b/tuhi/wacom.py @@ -501,12 +501,11 @@ class WacomProtocolLowLevelComm(GObject.Object): # logger.debug(f'received {data.opcode:02x} / {data.length:02x} / {b2hex(bytes(data))}') - if isinstance(expected_opcode, list): - if data.opcode not in expected_opcode: - raise WacomException(f'unexpected opcode: {data.opcode:02x}') - else: - if data.opcode != expected_opcode: - raise WacomException(f'unexpected opcode: {data.opcode:02x}') + if not isinstance(expected_opcode, list): + expected_opcode = [expected_opcode] + + if data.opcode not in expected_opcode: + raise WacomException(f'unexpected opcode: {data.opcode:02x}') return data From 075fae13f92422d3f2204de1a5898cc875a76669 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 2 Aug 2019 10:57:21 +1000 Subject: [PATCH 13/17] flake 8 fixes Signed-off-by: Peter Hutterer --- tools/kete.py | 1 - tuhi/wacom.py | 48 +++++++++++++++++++++++++----------------------- 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/tools/kete.py b/tools/kete.py index 751493a..c112a39 100755 --- a/tools/kete.py +++ b/tools/kete.py @@ -292,7 +292,6 @@ class TuhiKeteDevice(_DBusObject): else: logger.debug(f'{self}: Download done') - def _on_properties_changed(self, proxy, changed_props, invalidated_props): if changed_props is None: return diff --git a/tuhi/wacom.py b/tuhi/wacom.py index 084fcc9..112c08d 100644 --- a/tuhi/wacom.py +++ b/tuhi/wacom.py @@ -172,21 +172,21 @@ class DataLogger(object): return self.parent._recv(self.source, data) commands = { - 0xb1: 'start/stop live', - 0xb6: 'set time', - 0xb7: 'get firmware', - 0xb9: 'read battery info', - 0xbb: 'get/set name', - 0xc1: 'check for data', - 0xc3: 'start reading', - 0xc5: 'fetch data', - 0xc8: 'end of data', - 0xca: 'ack transaction', - 0xcc: 'fetch data', - 0xea: 'get dimensions', - 0xe5: 'finish registering', - 0xe6: 'check connection', - 0xdb: 'get name', + 0xb1: 'start/stop live', + 0xb6: 'set time', + 0xb7: 'get firmware', + 0xb9: 'read battery info', + 0xbb: 'get/set name', + 0xc1: 'check for data', + 0xc3: 'start reading', + 0xc5: 'fetch data', + 0xc8: 'end of data', + 0xca: 'ack transaction', + 0xcc: 'fetch data', + 0xea: 'get dimensions', + 0xe5: 'finish registering', + 0xe6: 'check connection', + 0xdb: 'get name', } def __init__(self, bluez_device): @@ -236,10 +236,12 @@ class DataLogger(object): def _recv(self, source, data): if source in ['NORDIC', 'PEN']: - def _convert(values): return list2hex(values) + def _convert(values): + return list2hex(values) convert = _convert else: - def _convert(values): return binascii.hexlify(bytes(values)) + def _convert(values): + return binascii.hexlify(bytes(values)) convert = _convert self.logger.debug(f'{self.btaddr}: RX {source} <-- {convert(data)}') @@ -1004,7 +1006,7 @@ class WacomProtocolBase(WacomProtocolLowLevelComm): arguments=None) self.set_time() self.read_time() - name = self.get_name() + self.get_name() self.get_firmware_version() def live_mode(self, mode, uhid): @@ -1102,7 +1104,7 @@ class WacomProtocolSlate(WacomProtocolSpark): self.set_time() self.read_time() self.ec_command() - name = self.get_name() + self.get_name() w, h = self.get_dimensions() if self.width != w or self.height != h: @@ -1124,7 +1126,7 @@ class WacomProtocolSlate(WacomProtocolSpark): self.height = h self.notify('dimensions') - fw = self.get_firmware_version() + self.get_firmware_version() self.ec_command() if self.read_offline_data() == 0: logger.info('no data to retrieve') @@ -1310,9 +1312,9 @@ class WacomDevice(GObject.Object): def _init_protocol(self, protocol): protocols = { - Protocol.SPARK: WacomProtocolSpark, - Protocol.SLATE: WacomProtocolSlate, - Protocol.INTUOS_PRO: WacomProtocolIntuosPro, + Protocol.SPARK: WacomProtocolSpark, + Protocol.SLATE: WacomProtocolSlate, + Protocol.INTUOS_PRO: WacomProtocolIntuosPro, } if protocol not in protocols: From eacc03b6ea4174b92473ea400352354c23b705b1 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 31 Jul 2019 15:58:14 +1000 Subject: [PATCH 14/17] wacom: rename a function to make it more obvious We're not checking for data here, we're taking the next message. Signed-off-by: Peter Hutterer --- tuhi/wacom.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tuhi/wacom.py b/tuhi/wacom.py index 112c08d..168d906 100644 --- a/tuhi/wacom.py +++ b/tuhi/wacom.py @@ -485,12 +485,12 @@ class WacomProtocolLowLevelComm(GObject.Object): self.fw_logger.nordic.send(data) chrc.write_value(data) - def check_nordic_incoming(self): + def pop_next_message(self): answer = self.nordic_answer length = answer[1] args = answer[2:] if length > len(args): - raise WacomException(f'error while processing answer, should get an answer of size {length} instead of {len(args)}') + raise WacomException(f'Invalid answer message length: expected {length}, got {len(args)}') self.nordic_answer = self.nordic_answer[length + 2:] # opcode + len return NordicData(answer) @@ -499,7 +499,7 @@ class WacomProtocolLowLevelComm(GObject.Object): # timeout raise WacomTimeoutException(f'{self.device.name}: Timeout while reading data') - data = self.check_nordic_incoming() + data = self.pop_next_message() # logger.debug(f'received {data.opcode:02x} / {data.length:02x} / {b2hex(bytes(data))}') From 96df9fc41697851f08f0e86f47e610a4938e0125 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 2 Aug 2019 11:09:02 +1000 Subject: [PATCH 15/17] wacom: make sure we only return the data packet size we want If we have more data than our packet [1], let's not return the whole data array. Slice it to size instead. [1] this never happens with the current code, we don't work asynchronously Signed-off-by: Peter Hutterer --- tuhi/wacom.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tuhi/wacom.py b/tuhi/wacom.py index 168d906..f12d82d 100644 --- a/tuhi/wacom.py +++ b/tuhi/wacom.py @@ -492,7 +492,7 @@ class WacomProtocolLowLevelComm(GObject.Object): if length > len(args): raise WacomException(f'Invalid answer message length: expected {length}, got {len(args)}') self.nordic_answer = self.nordic_answer[length + 2:] # opcode + len - return NordicData(answer) + return NordicData(answer[:length + 2]) def wait_nordic_data(self, expected_opcode, timeout=None): if not self.nordic_event.acquire(timeout=timeout): From 341b91349ef4156758128083b29743190d2c084a Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 1 Aug 2019 15:54:06 +1000 Subject: [PATCH 16/17] wacom: fix the data logger being off by one Signed-off-by: Peter Hutterer --- tuhi/wacom.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tuhi/wacom.py b/tuhi/wacom.py index f12d82d..7de5629 100644 --- a/tuhi/wacom.py +++ b/tuhi/wacom.py @@ -254,7 +254,7 @@ class DataLogger(object): def _send(self, source, data): command = data[0] - arguments = data[1:] + arguments = data[2:] if data[0] in self.commands: self.logger.debug(f'command: {self.commands[data[0]]}') From 28cb94bc89624e152e4efdf7f7fdbf2de5602b2b Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 9 Aug 2019 12:59:00 +1000 Subject: [PATCH 17/17] base: fix failing registration of new devices Regression introduced in e1a3675439116c00a5bd5e14b5b539b0193db59e Where a device has no config entry, the e1a367 change would return early. This is fine for devices previously seen and still lingering in the config but for completely new devices, we'll never get past that KeyError. Return to the old behaviour: where we don't have a stored UUID we continue with the None UUID. Fixes #148 Signed-off-by: Peter Hutterer --- tuhi/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tuhi/base.py b/tuhi/base.py index c83fda6..1b36470 100644 --- a/tuhi/base.py +++ b/tuhi/base.py @@ -370,7 +370,7 @@ class Tuhi(GObject.Object): config = self.config.devices[bluez_device.address] uuid = config['uuid'] except KeyError: - return + uuid = None # if we got here from a currently live BlueZ device, # ManufacturerData is reliable. Else, consider the device not in