From 33521558ed7007c24b24127f1448c2c23ecbfb35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filipe=20La=C3=ADns?= Date: Thu, 2 Jul 2020 14:24:08 +0100 Subject: [PATCH] pre-commit: initial fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Filipe LaĆ­ns --- ChangeLog | 2 +- docs/.gitignore | 2 +- docs/README.md | 2 +- docs/capabilities.md | 6 +- docs/devices.md | 6 +- docs/devices/M510_HIDppV4.5.txt | 34 +++--- docs/devices/anywhere-mx-2.txt | 28 ++--- docs/devices/craft.txt | 1 - docs/devices/k270-unifying.txt | 19 ++-- docs/devices/k360.txt | 20 ++-- docs/devices/k750.txt | 20 ++-- docs/devices/k780.txt | 38 +++---- docs/devices/k800-new.txt | 108 ++++++++++---------- docs/devices/k830.txt | 30 +++--- docs/devices/m185_new.txt | 25 +++-- docs/devices/m185_old.txt | 27 +++-- docs/devices/m325.txt | 20 ++-- docs/devices/m345.txt | 20 ++-- docs/devices/m525.txt | 20 ++-- docs/devices/m560.txt | 22 ++-- docs/devices/m570.txt | 1 - docs/devices/m585.txt | 1 - docs/devices/mk220-new.txt | 43 ++++---- docs/devices/mk220.txt | 41 ++++---- docs/devices/mk240-nano.md | 50 ++++----- docs/devices/mk270.txt | 43 ++++---- docs/devices/mk520.txt | 19 ++-- docs/devices/mx-master-3.txt | 53 +++++----- docs/devices/mx-master.txt | 34 +++--- docs/devices/performance-mx.txt | 2 +- docs/devices/t400.txt | 30 +++--- docs/devices/t650.txt | 30 +++--- docs/features.md | 6 +- docs/index.md | 10 +- docs/installation.md | 8 +- docs/logitech/hid10.txt | 1 - docs/usage.md | 1 - lib/hidapi/hidconsole.py | 44 ++++---- lib/logitech_receiver/base.py | 24 ++--- lib/logitech_receiver/common.py | 2 +- lib/logitech_receiver/hidpp10.py | 2 +- lib/logitech_receiver/hidpp20.py | 10 +- lib/logitech_receiver/i18n.py | 40 ++++---- lib/logitech_receiver/listener.py | 10 +- lib/logitech_receiver/notifications.py | 80 +++++++-------- lib/logitech_receiver/receiver.py | 40 ++++---- lib/logitech_receiver/settings.py | 58 +++++------ lib/logitech_receiver/settings_templates.py | 72 ++++++------- lib/logitech_receiver/special_keys.py | 4 +- lib/logitech_receiver/status.py | 20 ++-- lib/solaar/cli/__init__.py | 4 +- lib/solaar/cli/config.py | 2 +- lib/solaar/cli/pair.py | 2 +- lib/solaar/cli/probe.py | 24 ++--- lib/solaar/cli/show.py | 60 +++++------ lib/solaar/configuration.py | 10 +- lib/solaar/gtk.py | 4 +- lib/solaar/listener.py | 30 +++--- lib/solaar/tasks.py | 6 +- lib/solaar/ui/__init__.py | 22 ++-- lib/solaar/ui/about.py | 12 +-- lib/solaar/ui/action.py | 6 +- lib/solaar/ui/config_panel.py | 8 +- lib/solaar/ui/icons.py | 16 +-- lib/solaar/ui/notify.py | 20 ++-- lib/solaar/ui/pair_window.py | 32 +++--- lib/solaar/ui/tray.py | 22 ++-- lib/solaar/ui/window.py | 100 +++++++++--------- lib/solaar/upower.py | 8 +- setup.py | 1 + tools/monitor.py | 2 +- 71 files changed, 804 insertions(+), 816 deletions(-) diff --git a/ChangeLog b/ChangeLog index ff6dfdd6..8e260cc5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -7,7 +7,7 @@ * Update French translation * Update installation documentation -1.0.2rc2: +1.0.2rc2: * Remove packaging directory tree as it is not maintained * Pip installs udev rule and solaar autostart when doing install without --user flag * Use Solaar icon instead of a missing battery icon diff --git a/docs/.gitignore b/docs/.gitignore index 32411353..5ef23a42 100644 --- a/docs/.gitignore +++ b/docs/.gitignore @@ -3,4 +3,4 @@ .jekyll-metadata Gemfile Gemfile.lock -_site/ \ No newline at end of file +_site/ diff --git a/docs/README.md b/docs/README.md index 79b3b4e9..708a6911 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,4 +1,4 @@ # Documentation Readme This project's documentation is hosted using GitHub pages, which serves static pages using Jeykll. -[Please refer to the official documentation for instructions for how to build the site locally.](https://help.github.com/articles/setting-up-your-github-pages-site-locally-with-jekyll/) \ No newline at end of file +[Please refer to the official documentation for instructions for how to build the site locally.](https://help.github.com/articles/setting-up-your-github-pages-site-locally-with-jekyll/) diff --git a/docs/capabilities.md b/docs/capabilities.md index 8f74f68d..fe7fdd40 100644 --- a/docs/capabilities.md +++ b/docs/capabilities.md @@ -104,11 +104,11 @@ several heuristics to determine which icon names to use for this purpose, but as more and more battery icon schemes have been developed this has become impossible to do well. Solaar now uses the eleven standard battery icon names `battery-{full,good,low,critical,empty}[-charging]` and -`battery-missing`. +`battery-missing`. Solaar will use the symbolic versions of these icons if started with the -option `--battery-icons=symbolic`. Because of bugs external to Solaar -these symbolic icons may be nearly invisible in dark themes. +option `--battery-icons=symbolic`. Because of bugs external to Solaar +these symbolic icons may be nearly invisible in dark themes. [solaar]: https://github.com/pwr-Solaar/Solaar [logitech]: https://www.logitech.com diff --git a/docs/devices.md b/docs/devices.md index 183f1605..85edf158 100644 --- a/docs/devices.md +++ b/docs/devices.md @@ -10,8 +10,8 @@ features are supported by Solaar. The information in these tables is incomplete, based on what devices users have been able to test Solaar with. The HID++ column specifies the device's HID++ version. Some devices report -version 4.5, but that is the same as version 2.0 as listed here. -For devices what support HID++ 2.0 or greater, Solaar is able to discover +version 4.5, but that is the same as version 2.0 as listed here. +For devices what support HID++ 2.0 or greater, Solaar is able to discover the features the device supports. The Battery column specifies if Solaar is able to read the device's battery @@ -21,7 +21,7 @@ For mice, the DPI column specifies if the mouse's sensitivity is fixed (`-`), can only be read (`R`), or can be read and changed by Solaar (`R/W`). The reprog(rammable) keys feature is currently not fully supported by Solaar. -You are able to read this feature using command-line interface of Solaar, +You are able to read this feature using command-line interface of Solaar, but it is not possible to assign different keys. diff --git a/docs/devices/M510_HIDppV4.5.txt b/docs/devices/M510_HIDppV4.5.txt index 89b3c8eb..ba827d29 100644 --- a/docs/devices/M510_HIDppV4.5.txt +++ b/docs/devices/M510_HIDppV4.5.txt @@ -8,12 +8,12 @@ Firmware: RQM 62.00.B0013 The power switch is located on the base. Supports 22 HID++ 2.0 features: - 0: ROOT {0000} - 1: FEATURE SET {0001} - 2: DEVICE FW VERSION {0003} - 3: DEVICE NAME {0005} - 4: RESET {0020} - 5: BATTERY STATUS {1000} + 0: ROOT {0000} + 1: FEATURE SET {0001} + 2: DEVICE FW VERSION {0003} + 3: DEVICE NAME {0005} + 4: RESET {0020} + 5: BATTERY STATUS {1000} 6: unknown:1802 {1802} internal, hidden 7: unknown:1810 {1810} internal, hidden 8: unknown:1830 {1830} internal, hidden @@ -21,28 +21,28 @@ 10: unknown:1890 {1890} internal, hidden 11: unknown:18A0 {18A0} internal, hidden 12: unknown:18B1 {18B1} internal, hidden - 13: REPROG CONTROLS V4 {1B04} - 14: WIRELESS DEVICE STATUS {1D4B} + 13: REPROG CONTROLS V4 {1B04} + 14: WIRELESS DEVICE STATUS {1D4B} 15: unknown:1DF0 {1DF0} hidden 16: unknown:1DF3 {1DF3} internal, hidden 17: unknown:1E00 {1E00} hidden 18: unknown:1EB0 {1EB0} internal, hidden 19: unknown:1F03 {1F03} internal, hidden - 20: LOWRES WHEEL {2130} - 21: POINTER SPEED {2205} + 20: LOWRES WHEEL {2130} + 21: POINTER SPEED {2205} Has 7 reprogrammable keys: - 0: LEFT CLICK , default: LeftClick => LEFT CLICK + 0: LEFT CLICK , default: LeftClick => LEFT CLICK divertable, mse, pos:0, group:1, gmask:1 - 1: RIGHT CLICK , default: RightClick => RIGHT CLICK + 1: RIGHT CLICK , default: RightClick => RIGHT CLICK divertable, mse, pos:0, group:1, gmask:1 - 2: MIDDLE BUTTON , default: MiddleMouseButton => MIDDLE BUTTON + 2: MIDDLE BUTTON , default: MiddleMouseButton => MIDDLE BUTTON divertable, mse, reprogrammable, pos:0, group:2, gmask:3 - 3: LEFT SCROLL AS AC PAN , default: HorzScrollLeftSet => LEFT SCROLL AS AC PAN + 3: LEFT SCROLL AS AC PAN , default: HorzScrollLeftSet => LEFT SCROLL AS AC PAN divertable, mse, reprogrammable, pos:0, group:2, gmask:3 - 4: RIGHT SCROLL AS AC PAN , default: HorzScrollRightSet => RIGHT SCROLL AS AC PAN + 4: RIGHT SCROLL AS AC PAN , default: HorzScrollRightSet => RIGHT SCROLL AS AC PAN divertable, mse, reprogrammable, pos:0, group:2, gmask:3 - 5: BACK AS BUTTON 4 , default: BackEx => BACK AS BUTTON 4 + 5: BACK AS BUTTON 4 , default: BackEx => BACK AS BUTTON 4 divertable, mse, reprogrammable, pos:0, group:2, gmask:3 - 6: FORWARD AS BUTTON 5 , default: BrowserForwardEx => FORWARD AS BUTTON 5 + 6: FORWARD AS BUTTON 5 , default: BrowserForwardEx => FORWARD AS BUTTON 5 divertable, mse, reprogrammable, pos:0, group:2, gmask:3 Battery: 70%, discharging. diff --git a/docs/devices/anywhere-mx-2.txt b/docs/devices/anywhere-mx-2.txt index eeb91036..5330e5ce 100644 --- a/docs/devices/anywhere-mx-2.txt +++ b/docs/devices/anywhere-mx-2.txt @@ -19,22 +19,22 @@ Unifying Receiver Bootloader: BOT 23.00.B0007 Firmware: MPM 02.00.B0007 Firmware: MPM 02.00.B0007 - Other: + Other: The power switch is located on the base. Supports 26 HID++ 2.0 features: - 0: ROOT {0000} - 1: FEATURE SET {0001} - 2: DEVICE FW VERSION {0003} - 3: DEVICE NAME {0005} - 4: WIRELESS DEVICE STATUS {1D4B} - 5: RESET {0020} - 6: BATTERY STATUS {1000} - 7: CHANGE HOST {1814} - 8: REPROG CONTROLS V4 {1B04} - 9: ADJUSTABLE DPI {2201} - 10: VERTICAL SCROLLING {2100} - 11: HIRES WHEEL {2121} - 12: DFUCONTROL 2 {00C1} + 0: ROOT {0000} + 1: FEATURE SET {0001} + 2: DEVICE FW VERSION {0003} + 3: DEVICE NAME {0005} + 4: WIRELESS DEVICE STATUS {1D4B} + 5: RESET {0020} + 6: BATTERY STATUS {1000} + 7: CHANGE HOST {1814} + 8: REPROG CONTROLS V4 {1B04} + 9: ADJUSTABLE DPI {2201} + 10: VERTICAL SCROLLING {2100} + 11: HIRES WHEEL {2121} + 12: DFUCONTROL 2 {00C1} 13: unknown:1813 {1813} internal, hidden 14: unknown:1830 {1830} internal, hidden 15: unknown:1890 {1890} internal, hidden diff --git a/docs/devices/craft.txt b/docs/devices/craft.txt index 77977c3d..4a68437c 100644 --- a/docs/devices/craft.txt +++ b/docs/devices/craft.txt @@ -111,4 +111,3 @@ Unifying Receiver 23: unknown:0034 , default: Do Nothing One => unknown:0034 nonstandard, pos:0, group:0, gmask:0 Battery: 0%, full. - diff --git a/docs/devices/k270-unifying.txt b/docs/devices/k270-unifying.txt index 4b6e054e..37bf0890 100644 --- a/docs/devices/k270-unifying.txt +++ b/docs/devices/k270-unifying.txt @@ -18,18 +18,18 @@ Unifying Receiver Firmware: RQK 35.00.B0017 The power switch is located on the top case. Supports 12 HID++ 2.0 features: - 0: ROOT {0000} - 1: FEATURE SET {0001} - 2: DEVICE FW VERSION {0003} - 3: DEVICE NAME {0005} - 4: BATTERY STATUS {1000} + 0: ROOT {0000} + 1: FEATURE SET {0001} + 2: DEVICE FW VERSION {0003} + 3: DEVICE NAME {0005} + 4: BATTERY STATUS {1000} 5: unknown:1820 {1820} hidden - 6: REPROG CONTROLS {1B00} - 7: WIRELESS DEVICE STATUS {1D4B} + 6: REPROG CONTROLS {1B00} + 7: WIRELESS DEVICE STATUS {1D4B} 8: unknown:1DF0 {1DF0} hidden 9: unknown:1DF3 {1DF3} hidden - 10: ENCRYPTION {4100} - 11: KEYBOARD LAYOUT {4520} + 10: ENCRYPTION {4100} + 11: KEYBOARD LAYOUT {4520} Has 8 reprogrammable keys: 0: Play/Pause => Play/Pause nonstandard 1: Mute => Mute nonstandard @@ -40,4 +40,3 @@ Unifying Receiver 6: SLEEP => Sleep nonstandard, reprogrammable 7: Calculator => Calculator nonstandard, reprogrammable Battery: 90%, discharging. - diff --git a/docs/devices/k360.txt b/docs/devices/k360.txt index 3162ee51..511ca57f 100644 --- a/docs/devices/k360.txt +++ b/docs/devices/k360.txt @@ -58,19 +58,19 @@ Total number of HID++ 2.0 features: 12 Firmware : RQK 36.00.B0007 The power switch is located on the top case Supports 13 HID++ 2.0 features: - 0: ROOT {0000} - 1: FEATURE SET {0001} - 2: DEVICE FW VERSION {0003} - 3: DEVICE NAME {0005} - 4: BATTERY STATUS {1000} + 0: ROOT {0000} + 1: FEATURE SET {0001} + 2: DEVICE FW VERSION {0003} + 3: DEVICE NAME {0005} + 4: BATTERY STATUS {1000} 5: unknown:1820 {1820} hidden - 6: REPROG CONTROLS {1B00} - 7: WIRELESS DEVICE STATUS {1D4B} + 6: REPROG CONTROLS {1B00} + 7: WIRELESS DEVICE STATUS {1D4B} 8: unknown:1DF0 {1DF0} hidden 9: unknown:1DF3 {1DF3} hidden - 10: FN INVERSION {40A0} - 11: ENCRYPTION {4100} - 12: KEYBOARD LAYOUT {4520} + 10: FN INVERSION {40A0} + 11: ENCRYPTION {4100} + 12: KEYBOARD LAYOUT {4520} Has 18 reprogrammable keys: 0: MY HOME => HomePage FN sensitive, is FN, reprogrammable 1: Mail => Mail FN sensitive, is FN, reprogrammable diff --git a/docs/devices/k750.txt b/docs/devices/k750.txt index 8e7720bf..82f118d8 100644 --- a/docs/devices/k750.txt +++ b/docs/devices/k750.txt @@ -12,17 +12,17 @@ Bootloader: DFU 00.02.B0003 The power switch is located on the edge of top right corner. Supports 11 HID++ 2.0 features: - 0: ROOT {0000} - 1: FEATURE SET {0001} - 2: DEVICE FW VERSION {0003} - 3: DEVICE NAME {0005} - 4: REPROG CONTROLS {1B00} - 5: WIRELESS DEVICE STATUS {1D4B} + 0: ROOT {0000} + 1: FEATURE SET {0001} + 2: DEVICE FW VERSION {0003} + 3: DEVICE NAME {0005} + 4: REPROG CONTROLS {1B00} + 5: WIRELESS DEVICE STATUS {1D4B} 6: unknown:1DF3 {1DF3} hidden - 7: FN INVERSION {40A0} - 8: ENCRYPTION {4100} - 9: SOLAR DASHBOARD {4301} - 10: KEYBOARD LAYOUT {4520} + 7: FN INVERSION {40A0} + 8: ENCRYPTION {4100} + 9: SOLAR DASHBOARD {4301} + 10: KEYBOARD LAYOUT {4520} Has 12 reprogrammable keys: 0: MY HOME => HomePage FN sensitive, is FN, reprogrammable 1: Mail => Email FN sensitive, is FN, reprogrammable diff --git a/docs/devices/k780.txt b/docs/devices/k780.txt index ef600fee..41444e23 100644 --- a/docs/devices/k780.txt +++ b/docs/devices/k780.txt @@ -7,27 +7,27 @@ Serial number: 4D71FEE1 Bootloader: BOT 25.00.B0005 Firmware: MPK 01.00.B0018 - Other: + Other: The power switch is located on the edge of top right corner. Supports 31 HID++ 2.0 features: - 0: ROOT {0000} - 1: FEATURE SET {0001} - 2: DEVICE FW VERSION {0003} - 3: DEVICE NAME {0005} - 4: WIRELESS DEVICE STATUS {1D4B} - 5: RESET {0020} - 6: unknown:0007 {0007} - 7: BATTERY STATUS {1000} - 8: CHANGE HOST {1814} - 9: unknown:1815 {1815} - 10: REPROG CONTROLS V4 {1B04} - 11: unknown:1C00 {1C00} - 12: NEW FN INVERSION {40A2} - 13: ENCRYPTION {4100} - 14: KEYBOARD DISABLE {4521} - 15: unknown:4531 {4531} - 16: LOCK KEY STATE {4220} - 17: unknown:00C2 {00C2} + 0: ROOT {0000} + 1: FEATURE SET {0001} + 2: DEVICE FW VERSION {0003} + 3: DEVICE NAME {0005} + 4: WIRELESS DEVICE STATUS {1D4B} + 5: RESET {0020} + 6: unknown:0007 {0007} + 7: BATTERY STATUS {1000} + 8: CHANGE HOST {1814} + 9: unknown:1815 {1815} + 10: REPROG CONTROLS V4 {1B04} + 11: unknown:1C00 {1C00} + 12: NEW FN INVERSION {40A2} + 13: ENCRYPTION {4100} + 14: KEYBOARD DISABLE {4521} + 15: unknown:4531 {4531} + 16: LOCK KEY STATE {4220} + 17: unknown:00C2 {00C2} 18: unknown:1803 {1803} internal, hidden 19: unknown:1806 {1806} internal, hidden 20: unknown:1805 {1805} internal, hidden diff --git a/docs/devices/k800-new.txt b/docs/devices/k800-new.txt index 29642f74..353669ca 100644 --- a/docs/devices/k800-new.txt +++ b/docs/devices/k800-new.txt @@ -77,43 +77,43 @@ Unifying Receiver Bootloader: BOT 56.10.B0005 Firmware: MPM 12.10.B0005 Firmware: MPM 12.10.B0005 - Other: + Other: The power switch is located on the base. Supports 32 HID++ 2.0 features: 16:01:47,214 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 000B 000000] 16:01:47,311 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 000B 00000100000000000000000000000000] - 0: ROOT {0000} + 0: ROOT {0000} 16:01:47,312 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 000C 000100] 16:01:47,333 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 000C 01000100000000000000000000000000] - 1: FEATURE SET {0001} + 1: FEATURE SET {0001} 16:01:47,334 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 000F 000300] 16:01:47,431 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 000F 02000200000000000000000000000000] - 2: DEVICE FW VERSION {0003} + 2: DEVICE FW VERSION {0003} 16:01:47,431 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 011C 030000] 16:01:47,453 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 011C 00050000000000000000000000000000] 16:01:47,454 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 000F 000500] 16:01:47,475 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 000F 03000000000000000000000000000000] - 3: DEVICE NAME {0005} + 3: DEVICE NAME {0005} 16:01:47,475 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 0119 040000] 16:01:47,575 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 0119 1D4B0000000000000000000000000000] 16:01:47,575 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 000A 1D4B00] 16:01:47,593 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 000A 04000000000000000000000000000000] - 4: WIRELESS DEVICE STATUS {1D4B} + 4: WIRELESS DEVICE STATUS {1D4B} 16:01:47,593 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 011A 050000] 16:01:47,617 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 011A 00200000000000000000000000000000] 16:01:47,617 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 0009 002000] 16:01:47,715 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 0009 05000000000000000000000000000000] - 5: RESET {0020} + 5: RESET {0020} 16:01:47,715 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 011E 060000] 16:01:47,735 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 011E 00210000000000000000000000000000] 16:01:47,735 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 000B 002100] 16:01:47,755 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 000B 06000000000000000000000000000000] - 6: unknown:0021 {0021} + 6: unknown:0021 {0021} 16:01:47,755 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 011C 070000] 16:01:47,775 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 011C 10000000000000000000000000000000] 16:01:47,775 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 000C 100000] 16:01:47,795 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 000C 07000000000000000000000000000000] - 7: BATTERY STATUS {1000} + 7: BATTERY STATUS {1000} 16:01:47,795 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 011F 080000] 16:01:47,815 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 011F 18066000000000000000000000000000] 16:01:47,815 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 000C 180600] @@ -123,22 +123,22 @@ Unifying Receiver 16:01:47,855 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 0119 18140001000000000000000000000000] 16:01:47,855 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 000A 181400] 16:01:47,875 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 000A 09000100000000000000000000000000] - 9: CHANGE HOST {1814} + 9: CHANGE HOST {1814} 16:01:47,875 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 011A 0A0000] 16:01:47,895 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 011A 1B040003000000000000000000000000] 16:01:47,895 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 000A 1B0400] 16:01:47,915 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 000A 0A000300000000000000000000000000] - 10: REPROG CONTROLS V4 {1B04} + 10: REPROG CONTROLS V4 {1B04} 16:01:47,915 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 011E 0B0000] 16:01:47,935 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 011E 22010001000000000000000000000000] 16:01:47,935 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 000E 220100] 16:01:47,957 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 000E 0B000100000000000000000000000000] - 11: ADJUSTABLE DPI {2201} + 11: ADJUSTABLE DPI {2201} 16:01:47,957 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 011A 0C0000] 16:01:47,977 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 011A 21000000000000000000000000000000] 16:01:47,977 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 0009 210000] 16:01:47,997 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 0009 0C000000000000000000000000000000] - 12: VERTICAL SCROLLING {2100} + 12: VERTICAL SCROLLING {2100} 16:01:47,998 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 0C0C 000000] 16:01:48,017 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 0C0C 03180000000000000000000000000000] Roller type: 3G @@ -148,12 +148,12 @@ Unifying Receiver 16:01:48,037 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 011A 21100000000000000000000000000000] 16:01:48,037 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 0008 211000] 16:01:48,057 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 0008 0D000000000000000000000000000000] - 13: SMART SHIFT {2110} + 13: SMART SHIFT {2110} 16:01:48,057 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 011C 0E0000] 16:01:48,077 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 011C 21210000000000000000000000000000] 16:01:48,077 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 000C 212100] 16:01:48,097 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 000C 0E000000000000000000000000000000] - 14: HIRES WHEEL {2121} + 14: HIRES WHEEL {2121} 16:01:48,097 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 0E09 000000] 16:01:48,117 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 0E09 080C0000000000000000000000000000] 16:01:48,117 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 0E1D 000000] @@ -171,12 +171,12 @@ Unifying Receiver 16:01:48,179 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 011F 65010000000000000000000000000000] 16:01:48,179 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 000A 650100] 16:01:48,199 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 000A 0F000000000000000000000000000000] - 15: GESTURE 2 {6501} + 15: GESTURE 2 {6501} 16:01:48,199 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 0119 100000] 16:01:48,219 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 0119 00C20000000000000000000000000000] 16:01:48,219 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 0009 00C200] 16:01:48,239 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 0009 10000000000000000000000000000000] - 16: unknown:00C2 {00C2} + 16: unknown:00C2 {00C2} 16:01:48,240 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 011B 110000] 16:01:48,259 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 011B 18136000000000000000000000000000] 16:01:48,259 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 0009 181300] @@ -259,49 +259,49 @@ Unifying Receiver 16:01:48,885 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 0A1C 00500038010001010000000000000000] 16:01:48,885 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 0A2B 005000] 16:01:48,905 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 0A2B 00500000000000000000000000000000] - 0: LEFT CLICK , default: LeftClick => LEFT CLICK + 0: LEFT CLICK , default: LeftClick => LEFT CLICK mse, pos:0, group:1, gmask:1 16:01:48,905 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 0A1D 010000] 16:01:48,925 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 0A1D 00510039010001010000000000000000] 16:01:48,925 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 0A28 005100] 16:01:48,945 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 0A28 00510000000000000000000000000000] - 1: RIGHT CLICK , default: RightClick => RIGHT CLICK + 1: RIGHT CLICK , default: RightClick => RIGHT CLICK mse, pos:0, group:1, gmask:1 16:01:48,945 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 0A1B 020000] 16:01:48,965 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 0A1B 0052003A310003070100000000000000] 16:01:48,965 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 0A2B 005200] 16:01:48,985 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 0A2B 00520000000000000000000000000000] - 2: MIDDLE BUTTON , default: MiddleMouseButton => MIDDLE BUTTON + 2: MIDDLE BUTTON , default: MiddleMouseButton => MIDDLE BUTTON mse, reprogrammable, divertable, pos:0, group:3, gmask:7 16:01:48,985 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 0A1E 030000] 16:01:49,005 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 0A1E 0053003C310002030100000000000000] 16:01:49,006 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 0A28 005300] 16:01:49,027 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 0A28 00530000000000000000000000000000] - 3: BACK AS BUTTON 4 , default: BackEx => BACK AS BUTTON 4 + 3: BACK AS BUTTON 4 , default: BackEx => BACK AS BUTTON 4 mse, reprogrammable, divertable, pos:0, group:2, gmask:3 16:01:49,027 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 0A1B 040000] 16:01:49,047 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 0A1B 0056003E310002030100000000000000] 16:01:49,047 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 0A2F 005600] 16:01:49,067 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 0A2F 00560000000000000000000000000000] - 4: FORWARD AS BUTTON 5 , default: BrowserForwardEx => FORWARD AS BUTTON 5 + 4: FORWARD AS BUTTON 5 , default: BrowserForwardEx => FORWARD AS BUTTON 5 mse, reprogrammable, divertable, pos:0, group:2, gmask:3 16:01:49,067 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 0A1C 050000] 16:01:49,087 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 0A1C 00C300A9310003070100000000000000] 16:01:49,087 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 0A2A 00C300] 16:01:49,107 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 0A2A 00C30000000000000000000000000000] - 5: unknown:00C3 , default: unknown:00A9 => unknown:00C3 + 5: unknown:00C3 , default: unknown:00A9 => unknown:00C3 mse, reprogrammable, divertable, pos:0, group:3, gmask:7 16:01:49,107 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 0A1A 060000] 16:01:49,127 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 0A1A 00C4009D310003070100000000000000] 16:01:49,127 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 0A2C 00C400] 16:01:49,147 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 0A2C 00C40000000000000000000000000000] - 6: unknown:00C4 , default: unknown:009D => unknown:00C4 + 6: unknown:00C4 , default: unknown:009D => unknown:00C4 mse, reprogrammable, divertable, pos:0, group:3, gmask:7 16:01:49,147 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 0A1C 070000] 16:01:49,167 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 0A1C 00D700B4A00004000300000000000000] 16:01:49,167 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 0A2C 00D700] 16:01:49,187 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 0A2C 00D70000000000000000000000000000] - 7: unknown:00D7 , default: unknown:00B4 => unknown:00D7 + 7: unknown:00D7 , default: unknown:00B4 => unknown:00D7 divertable, virtual, pos:0, group:4, gmask:0 16:01:49,187 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 070B 000000] 16:01:49,207 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 070B 32140000000000000000000000000000] @@ -341,63 +341,63 @@ Unifying Receiver Supports 25 HID++ 2.0 features: 16:01:49,487 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 000F 000000] 16:01:49,527 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 000F 00000100000000000000000000000000] - 0: ROOT {0000} + 0: ROOT {0000} 16:01:49,527 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 000F 000100] 16:01:49,567 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 000F 01000100000000000000000000000000] - 1: FEATURE SET {0001} + 1: FEATURE SET {0001} 16:01:49,568 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 000C 000300] 16:01:49,607 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 000C 02000200000000000000000000000000] - 2: DEVICE FW VERSION {0003} + 2: DEVICE FW VERSION {0003} 16:01:49,607 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 011A 030000] 16:01:49,647 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 011A 00050000000000000000000000000000] 16:01:49,647 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 000D 000500] 16:01:49,687 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 000D 03000000000000000000000000000000] - 3: DEVICE NAME {0005} + 3: DEVICE NAME {0005} 16:01:49,687 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 011C 040000] 16:01:49,729 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 011C 1D4B0000000000000000000000000000] 16:01:49,729 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 000D 1D4B00] 16:01:49,770 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 000D 04000000000000000000000000000000] - 4: WIRELESS DEVICE STATUS {1D4B} + 4: WIRELESS DEVICE STATUS {1D4B} 16:01:49,770 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 0119 050000] 16:01:49,809 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 0119 00200000000000000000000000000000] 16:01:49,809 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 000D 002000] 16:01:49,849 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 000D 05000000000000000000000000000000] - 5: RESET {0020} + 5: RESET {0020} 16:01:49,849 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 0118 060000] 16:01:49,889 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 0118 10000000000000000000000000000000] 16:01:49,889 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 0009 100000] 16:01:49,929 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 0009 06000000000000000000000000000000] - 6: BATTERY STATUS {1000} + 6: BATTERY STATUS {1000} 16:01:49,929 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 011D 070000] 16:01:49,969 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 011D 19830000000000000000000000000000] 16:01:49,969 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 000B 198300] 16:01:50,009 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 000B 07000000000000000000000000000000] - 7: unknown:1983 {1983} + 7: unknown:1983 {1983} 16:01:50,010 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 011F 080000] 16:01:50,051 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 011F 1B040003000000000000000000000000] 16:01:50,051 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 000E 1B0400] 16:01:50,091 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 000E 08000300000000000000000000000000] - 8: REPROG CONTROLS V4 {1B04} + 8: REPROG CONTROLS V4 {1B04} 16:01:50,091 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 0119 090000] 16:01:50,131 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 0119 40A00000000000000000000000000000] 16:01:50,131 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 0009 40A000] 16:01:50,171 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 0009 09000000000000000000000000000000] - 9: FN INVERSION {40A0} + 9: FN INVERSION {40A0} 16:01:50,171 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 011C 0A0000] 16:01:50,211 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 011C 41000000000000000000000000000000] 16:01:50,211 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 000A 410000] 16:01:50,251 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 000A 0A000000000000000000000000000000] - 10: ENCRYPTION {4100} + 10: ENCRYPTION {4100} 16:01:50,251 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 0118 0B0000] 16:01:50,293 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 0118 45210000000000000000000000000000] 16:01:50,293 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 000F 452100] 16:01:50,333 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 000F 0B000000000000000000000000000000] - 11: KEYBOARD DISABLE {4521} + 11: KEYBOARD DISABLE {4521} 16:01:50,334 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 011E 0C0000] 16:01:50,373 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 011E 00C20000000000000000000000000000] 16:01:50,373 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 000F 00C200] 16:01:50,413 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 000F 0C000000000000000000000000000000] - 12: unknown:00C2 {00C2} + 12: unknown:00C2 {00C2} 16:01:50,414 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 0118 0D0000] 16:01:50,453 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 0118 18036000000000000000000000000000] 16:01:50,454 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 0008 180300] @@ -465,93 +465,93 @@ Unifying Receiver 16:01:51,461 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 081C 0022001A3A0100000000000000000000] 16:01:51,462 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 082F 002200] 16:01:51,501 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 082F 00220000000000000000000000000000] - 0: MY HOME , default: HomePage => MY HOME + 0: MY HOME , default: HomePage => MY HOME is FN, FN sensitive, reprogrammable, divertable, pos:1, group:0, gmask:0 16:01:51,502 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 0819 010000] 16:01:51,541 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 0819 000E000E3A0200000000000000000000] 16:01:51,542 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 0829 000E00] 16:01:51,581 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 0829 000E0000000000000000000000000000] - 1: Mail , default: Email => Mail + 1: Mail , default: Email => Mail is FN, FN sensitive, reprogrammable, divertable, pos:2, group:0, gmask:0 16:01:51,582 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 0818 020000] 16:01:51,621 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 0818 003E002D3A0300000000000000000000] 16:01:51,622 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 0828 003E00] 16:01:51,661 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 0828 003E0000000000000000000000000000] - 2: SEARCH , default: SearchForFiles => SEARCH + 2: SEARCH , default: SearchForFiles => SEARCH is FN, FN sensitive, reprogrammable, divertable, pos:3, group:0, gmask:0 16:01:51,662 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 081B 030000] 16:01:51,701 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 081B 000800083A0400000000000000000000] 16:01:51,702 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 082E 000800] 16:01:51,743 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 082E 00080000000000000000000000000000] - 3: Application Switcher , default: Application Switcher => Application Switcher + 3: Application Switcher , default: Application Switcher => Application Switcher is FN, FN sensitive, reprogrammable, divertable, pos:4, group:0, gmask:0 16:01:51,744 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 081D 040000] 16:01:51,784 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 081D 00E200C12A0500000000000000000000] 16:01:51,784 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 082E 00E200] 16:01:51,824 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 082E 00E20000000000000000000000000000] - 4: unknown:00E2 , default: unknown:00C1 => unknown:00E2 + 4: unknown:00E2 , default: unknown:00C1 => unknown:00E2 is FN, FN sensitive, divertable, pos:5, group:0, gmask:0 16:01:51,824 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 081A 050000] 16:01:51,864 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 081A 00E300C22A0600000000000000000000] 16:01:51,864 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 082B 00E300] 16:01:51,904 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 082B 00E30000000000000000000000000000] - 5: unknown:00E3 , default: unknown:00C2 => unknown:00E3 + 5: unknown:00E3 , default: unknown:00C2 => unknown:00E3 is FN, FN sensitive, divertable, pos:6, group:0, gmask:0 16:01:51,904 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 0818 060000] 16:01:51,943 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 0818 0040002F3A0800000000000000000000] 16:01:51,944 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 082E 004000] 16:01:51,984 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 082E 00400000000000000000000000000000] - 6: SLEEP , default: Sleep => SLEEP + 6: SLEEP , default: Sleep => SLEEP is FN, FN sensitive, reprogrammable, divertable, pos:8, group:0, gmask:0 16:01:51,984 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 081D 070000] 16:01:52,025 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 081D 0028001D3A0900000000000000000000] 16:01:52,026 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 0828 002800] 16:01:52,065 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 0828 00280000000000000000000000000000] - 7: MEDIA PLAYER , default: Music => MEDIA PLAYER + 7: MEDIA PLAYER , default: Music => MEDIA PLAYER is FN, FN sensitive, reprogrammable, divertable, pos:9, group:0, gmask:0 16:01:52,066 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 081F 080000] 16:01:52,106 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 081F 000600062A0A00000000000000000000] 16:01:52,106 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 0828 000600] 16:01:52,145 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 0828 00060000000000000000000000000000] - 8: Previous , default: Previous => Previous + 8: Previous , default: Previous => Previous is FN, FN sensitive, divertable, pos:10, group:0, gmask:0 16:01:52,146 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 081F 090000] 16:01:52,186 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 081F 000400042A0B00000000000000000000] 16:01:52,186 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 082B 000400] 16:01:52,225 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 082B 00040000000000000000000000000000] - 9: Play/Pause , default: Play/Pause => Play/Pause + 9: Play/Pause , default: Play/Pause => Play/Pause is FN, FN sensitive, divertable, pos:11, group:0, gmask:0 16:01:52,226 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 081B 0A0000] 16:01:52,265 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 081B 000500052A0C00000000000000000000] 16:01:52,266 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 0829 000500] 16:01:52,308 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 0829 00050000000000000000000000000000] - 10: Next , default: Next => Next + 10: Next , default: Next => Next is FN, FN sensitive, divertable, pos:12, group:0, gmask:0 16:01:52,308 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 0818 0B0000] 16:01:52,348 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 0818 00010001240000000000000000000000] 16:01:52,348 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 082C 000100] 16:01:52,387 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 082C 00010000000000000000000000000000] - 11: Volume Up , default: Volume Up => Volume Up + 11: Volume Up , default: Volume Up => Volume Up nonstandard, divertable, pos:0, group:0, gmask:0 16:01:52,388 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 081C 0C0000] 16:01:52,427 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 081C 00020002240000000000000000000000] 16:01:52,428 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 082C 000200] 16:01:52,468 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 082C 00020000000000000000000000000000] - 12: Volume Down , default: Volume Down => Volume Down + 12: Volume Down , default: Volume Down => Volume Down nonstandard, divertable, pos:0, group:0, gmask:0 16:01:52,468 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 0819 0D0000] 16:01:52,507 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 0819 00030003240000000000000000000000] 16:01:52,508 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 082D 000300] 16:01:52,547 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 082D 00030000000000000000000000000000] - 13: Mute , default: Mute => Mute + 13: Mute , default: Mute => Mute nonstandard, divertable, pos:0, group:0, gmask:0 16:01:52,548 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 081B 0E0000] 16:01:52,589 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 081B 000A000A340000000000000000000000] 16:01:52,590 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 082F 000A00] 16:01:52,630 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 082F 000A0000000000000000000000000000] - 14: Calculator , default: Calculator => Calculator + 14: Calculator , default: Calculator => Calculator nonstandard, reprogrammable, divertable, pos:0, group:0, gmask:0 16:01:52,630 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 060C 000000] 16:01:52,670 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 060C 32140000000000000000000000000000] 16:01:52,670 DEBUG [MainThread] logitech_receiver.hidpp20: device 2 battery 50% charged, next level 20% charge, status 0 = discharging - Battery: 50%, discharging. \ No newline at end of file + Battery: 50%, discharging. diff --git a/docs/devices/k830.txt b/docs/devices/k830.txt index be60a63a..17f8a7cb 100644 --- a/docs/devices/k830.txt +++ b/docs/devices/k830.txt @@ -11,22 +11,22 @@ Firmware: RQK 56.00.B0020 The power switch is located on the edge of top right corner. Supports 27 HID++ 2.0 features: - 0: ROOT {0000} - 1: FEATURE SET {0001} - 2: DEVICE FW VERSION {0003} - 3: DEVICE NAME {0005} - 4: WIRELESS DEVICE STATUS {1D4B} - 5: unknown:0020 {0020} - 6: BATTERY STATUS {1000} - 7: BACKLIGHT {1981} - 8: unknown:1B04 {1B04} - 9: unknown:2005 {2005} - 10: NEW FN INVERSION {40A2} - 11: ENCRYPTION {4100} - 12: unknown:4521 {4521} + 0: ROOT {0000} + 1: FEATURE SET {0001} + 2: DEVICE FW VERSION {0003} + 3: DEVICE NAME {0005} + 4: WIRELESS DEVICE STATUS {1D4B} + 5: unknown:0020 {0020} + 6: BATTERY STATUS {1000} + 7: BACKLIGHT {1981} + 8: unknown:1B04 {1B04} + 9: unknown:2005 {2005} + 10: NEW FN INVERSION {40A2} + 11: ENCRYPTION {4100} + 12: unknown:4521 {4521} 13: TOUCHPAD RAW XY {6100} hidden - 14: unknown:6501 {6501} - 15: unknown:00C1 {00C1} + 14: unknown:6501 {6501} + 15: unknown:00C1 {00C1} 16: unknown:1811 {1811} internal, hidden 17: unknown:1830 {1830} internal, hidden 18: unknown:1890 {1890} internal, hidden diff --git a/docs/devices/m185_new.txt b/docs/devices/m185_new.txt index f90d71a9..64490314 100644 --- a/docs/devices/m185_new.txt +++ b/docs/devices/m185_new.txt @@ -18,15 +18,15 @@ Device path : /dev/hidraw3 Firmware: RQM 64.00.B0008 The power switch is located on the base. Supports 20 HID++ 2.0 features: - 0: ROOT {0000} - 1: FEATURE SET {0001} - 2: DEVICE FW VERSION {0003} - 3: DEVICE NAME {0005} - 4: RESET {0020} - 5: REPROG CONTROLS V4 {1B04} - 6: WIRELESS DEVICE STATUS {1D4B} - 7: LOWRES WHEEL {2130} - 8: POINTER SPEED {2205} + 0: ROOT {0000} + 1: FEATURE SET {0001} + 2: DEVICE FW VERSION {0003} + 3: DEVICE NAME {0005} + 4: RESET {0020} + 5: REPROG CONTROLS V4 {1B04} + 6: WIRELESS DEVICE STATUS {1D4B} + 7: LOWRES WHEEL {2130} + 8: POINTER SPEED {2205} 9: unknown:1802 {1802} internal, hidden 10: unknown:1810 {1810} internal, hidden 11: unknown:1830 {1830} internal, hidden @@ -39,11 +39,10 @@ Device path : /dev/hidraw3 18: unknown:1F03 {1F03} internal, hidden 19: unknown:1E80 {1E80} internal, hidden Has 3 reprogrammable keys: - 0: LEFT CLICK , default: LeftClick => LEFT CLICK + 0: LEFT CLICK , default: LeftClick => LEFT CLICK mse, reprogrammable, pos:0, group:1, gmask:1 - 1: RIGHT CLICK , default: RightClick => RIGHT CLICK + 1: RIGHT CLICK , default: RightClick => RIGHT CLICK mse, reprogrammable, pos:0, group:1, gmask:1 - 2: MIDDLE BUTTON , default: MiddleMouseButton => MIDDLE BUTTON + 2: MIDDLE BUTTON , default: MiddleMouseButton => MIDDLE BUTTON divertable, mse, reprogrammable, pos:0, group:2, gmask:3 Battery status unavailable. - diff --git a/docs/devices/m185_old.txt b/docs/devices/m185_old.txt index 59470cd7..78e79541 100644 --- a/docs/devices/m185_old.txt +++ b/docs/devices/m185_old.txt @@ -18,12 +18,12 @@ Unifying Receiver Firmware: RQM 65.00.B0003 The power switch is located on the base. Supports 22 HID++ 2.0 features: - 0: ROOT {0000} - 1: FEATURE SET {0001} - 2: DEVICE FW VERSION {0003} - 3: DEVICE NAME {0005} - 4: RESET {0020} - 5: BATTERY STATUS {1000} + 0: ROOT {0000} + 1: FEATURE SET {0001} + 2: DEVICE FW VERSION {0003} + 3: DEVICE NAME {0005} + 4: RESET {0020} + 5: BATTERY STATUS {1000} 6: unknown:1810 {1810} internal, hidden 7: unknown:1830 {1830} internal, hidden 8: unknown:1802 {1802} internal, hidden @@ -31,21 +31,20 @@ Unifying Receiver 10: unknown:1890 {1890} internal, hidden 11: unknown:18A0 {18A0} internal, hidden 12: unknown:18B1 {18B1} internal, hidden - 13: REPROG CONTROLS V4 {1B04} - 14: WIRELESS DEVICE STATUS {1D4B} + 13: REPROG CONTROLS V4 {1B04} + 14: WIRELESS DEVICE STATUS {1D4B} 15: unknown:1DF0 {1DF0} hidden 16: unknown:1DF3 {1DF3} internal, hidden 17: unknown:1E00 {1E00} hidden 18: unknown:1EB0 {1EB0} internal, hidden 19: unknown:1F03 {1F03} internal, hidden - 20: LOWRES WHEEL {2130} - 21: POINTER SPEED {2205} + 20: LOWRES WHEEL {2130} + 21: POINTER SPEED {2205} Has 3 reprogrammable keys: - 0: LEFT CLICK , default: LeftClick => LEFT CLICK + 0: LEFT CLICK , default: LeftClick => LEFT CLICK mse, reprogrammable, pos:0, group:1, gmask:1 - 1: RIGHT CLICK , default: RightClick => RIGHT CLICK + 1: RIGHT CLICK , default: RightClick => RIGHT CLICK mse, reprogrammable, pos:0, group:1, gmask:1 - 2: MIDDLE BUTTON , default: MiddleMouseButton => MIDDLE BUTTON + 2: MIDDLE BUTTON , default: MiddleMouseButton => MIDDLE BUTTON divertable, mse, reprogrammable, pos:0, group:2, gmask:3 Battery: 5%, discharging. - diff --git a/docs/devices/m325.txt b/docs/devices/m325.txt index babea08e..ca4b1cad 100644 --- a/docs/devices/m325.txt +++ b/docs/devices/m325.txt @@ -8,19 +8,19 @@ Serial number: ABB05E01 Firmware: RQM 27.02.B0028 The power switch is located on the base. Supports 13 HID++ 2.0 features: - 0: ROOT {0000} - 1: FEATURE SET {0001} - 2: DEVICE FW VERSION {0003} - 3: DEVICE NAME {0005} - 4: BATTERY STATUS {1000} - 5: WIRELESS DEVICE STATUS {1D4B} + 0: ROOT {0000} + 1: FEATURE SET {0001} + 2: DEVICE FW VERSION {0003} + 3: DEVICE NAME {0005} + 4: BATTERY STATUS {1000} + 5: WIRELESS DEVICE STATUS {1D4B} 6: unknown:1DF3 {1DF3} hidden - 7: REPROG CONTROLS {1B00} + 7: REPROG CONTROLS {1B00} 8: unknown:1DF0 {1DF0} hidden 9: unknown:1F03 {1F03} hidden - 10: VERTICAL SCROLLING {2100} - 11: HI RES SCROLLING {2120} - 12: MOUSE POINTER {2200} + 10: VERTICAL SCROLLING {2100} + 11: HI RES SCROLLING {2120} + 12: MOUSE POINTER {2200} Has 5 reprogrammable keys: 0: LEFT CLICK => LeftClick mse, reprogrammable 1: RIGHT CLICK => RightClick mse, reprogrammable diff --git a/docs/devices/m345.txt b/docs/devices/m345.txt index d9f6fe98..ee2ec162 100644 --- a/docs/devices/m345.txt +++ b/docs/devices/m345.txt @@ -40,17 +40,17 @@ Total number of HID++ 2.0 features: 12 Firmware: RQM 27.02.B0028 The power switch is located on the base. Supports 13 HID++ 2.0 features: - 0: ROOT {0000} - 1: FEATURE SET {0001} - 2: DEVICE FW VERSION {0003} - 3: DEVICE NAME {0005} - 4: BATTERY STATUS {1000} - 5: WIRELESS DEVICE STATUS {1D4B} + 0: ROOT {0000} + 1: FEATURE SET {0001} + 2: DEVICE FW VERSION {0003} + 3: DEVICE NAME {0005} + 4: BATTERY STATUS {1000} + 5: WIRELESS DEVICE STATUS {1D4B} 6: unknown:1DF3 {1DF3} hidden - 7: REPROG CONTROLS {1B00} + 7: REPROG CONTROLS {1B00} 8: unknown:1DF0 {1DF0} hidden 9: unknown:1F03 {1F03} hidden - 10: VERTICAL SCROLLING {2100} - 11: HI RES SCROLLING {2120} - 12: MOUSE POINTER {2200} + 10: VERTICAL SCROLLING {2100} + 11: HI RES SCROLLING {2120} + 12: MOUSE POINTER {2200} Battery: 90%, discharging, diff --git a/docs/devices/m525.txt b/docs/devices/m525.txt index 43648f23..da1823ca 100644 --- a/docs/devices/m525.txt +++ b/docs/devices/m525.txt @@ -34,19 +34,19 @@ Total number of HID++ 2.0 features: 12 Firmware: RQM 27.02.B0028 The power switch is located on the base. Supports 13 HID++ 2.0 features: - 0: ROOT {0000} - 1: FEATURE SET {0001} - 2: DEVICE FW VERSION {0003} - 3: DEVICE NAME {0005} - 4: BATTERY STATUS {1000} - 5: WIRELESS DEVICE STATUS {1D4B} + 0: ROOT {0000} + 1: FEATURE SET {0001} + 2: DEVICE FW VERSION {0003} + 3: DEVICE NAME {0005} + 4: BATTERY STATUS {1000} + 5: WIRELESS DEVICE STATUS {1D4B} 6: unknown:1DF3 {1DF3} hidden - 7: REPROG CONTROLS {1B00} + 7: REPROG CONTROLS {1B00} 8: unknown:1DF0 {1DF0} hidden 9: unknown:1F03 {1F03} hidden - 10: VERTICAL SCROLLING {2100} - 11: HI RES SCROLLING {2120} - 12: MOUSE POINTER {2200} + 10: VERTICAL SCROLLING {2100} + 11: HI RES SCROLLING {2120} + 12: MOUSE POINTER {2200} Has 5 reprogrammable keys: 0: LEFT CLICK => LeftClick mse, reprogrammable 1: RIGHT CLICK => RightClick mse, reprogrammable diff --git a/docs/devices/m560.txt b/docs/devices/m560.txt index 8e6801bb..3f347a02 100644 --- a/docs/devices/m560.txt +++ b/docs/devices/m560.txt @@ -8,28 +8,28 @@ Firmware: RQM 48.00.B0015 The power switch is located on the base. Supports 22 HID++ 2.0 features: - 0: ROOT {0000} - 1: FEATURE SET {0001} - 2: DEVICE FW VERSION {0003} - 3: DEVICE NAME {0005} - 4: BATTERY STATUS {1000} + 0: ROOT {0000} + 1: FEATURE SET {0001} + 2: DEVICE FW VERSION {0003} + 3: DEVICE NAME {0005} + 4: BATTERY STATUS {1000} 5: unknown:1830 {1830} internal, hidden 6: unknown:1850 {1850} internal, hidden 7: unknown:1860 {1860} internal, hidden 8: unknown:1890 {1890} internal, hidden 9: unknown:18A0 {18A0} internal, hidden - 10: REPROG CONTROLS V3 {1B03} - 11: WIRELESS DEVICE STATUS {1D4B} + 10: REPROG CONTROLS V3 {1B03} + 11: WIRELESS DEVICE STATUS {1D4B} 12: unknown:1DF3 {1DF3} internal, hidden - 13: REPROG CONTROLS {1B00} + 13: REPROG CONTROLS {1B00} 14: unknown:1DF0 {1DF0} hidden 15: unknown:1E00 {1E00} hidden 16: unknown:18B0 {18B0} internal, hidden 17: unknown:1E90 {1E90} internal, hidden 18: unknown:1F03 {1F03} internal, hidden - 19: VERTICAL SCROLLING {2100} - 20: HI RES SCROLLING {2120} - 21: MOUSE POINTER {2200} + 19: VERTICAL SCROLLING {2100} + 20: HI RES SCROLLING {2120} + 21: MOUSE POINTER {2200} Has 7 reprogrammable keys: 0: LEFT CLICK => LeftClick mse, reprogrammable 1: RIGHT CLICK => RightClick mse, reprogrammable diff --git a/docs/devices/m570.txt b/docs/devices/m570.txt index 7fb833da..105c3617 100644 --- a/docs/devices/m570.txt +++ b/docs/devices/m570.txt @@ -22,4 +22,3 @@ Unifying Receiver The power switch is located on the base. Notifications: battery status (0x100000). Battery: 100%, discharging. - diff --git a/docs/devices/m585.txt b/docs/devices/m585.txt index c158120a..053bb56e 100644 --- a/docs/devices/m585.txt +++ b/docs/devices/m585.txt @@ -80,4 +80,3 @@ Unifying Receiver 7: unknown:00D7 , default: unknown:00B4 => unknown:00D7 divertable, virtual, pos:0, group:3, gmask:0 Battery: 50%, discharging. - diff --git a/docs/devices/mk220-new.txt b/docs/devices/mk220-new.txt index d8712b3b..e5f9b1c7 100644 --- a/docs/devices/mk220-new.txt +++ b/docs/devices/mk220-new.txt @@ -15,16 +15,16 @@ Unifying Receiver Serial number: 00000000 Firmware: RQK 49.00.B0029 Supports 18 HID++ 2.0 features: - 0: ROOT {0000} - 1: FEATURE SET {0001} - 2: DEVICE FW VERSION {0003} - 3: DEVICE NAME {0005} - 4: BATTERY STATUS {1000} - 5: REPROG CONTROLS {1B00} - 6: WIRELESS DEVICE STATUS {1D4B} - 7: FN INVERSION {40A0} - 8: ENCRYPTION {4100} - 9: KEYBOARD LAYOUT {4520} + 0: ROOT {0000} + 1: FEATURE SET {0001} + 2: DEVICE FW VERSION {0003} + 3: DEVICE NAME {0005} + 4: BATTERY STATUS {1000} + 5: REPROG CONTROLS {1B00} + 6: WIRELESS DEVICE STATUS {1D4B} + 7: FN INVERSION {40A0} + 8: ENCRYPTION {4100} + 9: KEYBOARD LAYOUT {4520} 10: unknown:1810 {1810} internal, hidden 11: unknown:1830 {1830} internal, hidden 12: unknown:1890 {1890} internal, hidden @@ -47,8 +47,8 @@ Unifying Receiver 10: Volume Up => Volume Up is FN, FN sensitive Battery: 30%, discharging. - 2: Wireless Mouse - Codename : + 2: Wireless Mouse + Codename : Kind : mouse Wireless PID : 4022 Protocol : HID++ 2.0 @@ -56,15 +56,15 @@ Unifying Receiver Serial number: 00000000 Firmware: RQM 38.00.B0044 Supports 18 HID++ 2.0 features: - 0: ROOT {0000} - 1: FEATURE SET {0001} - 2: DEVICE FW VERSION {0003} - 3: DEVICE NAME {0005} - 4: BATTERY STATUS {1000} - 5: REPROG CONTROLS {1B00} - 6: WIRELESS DEVICE STATUS {1D4B} - 7: VERTICAL SCROLLING {2100} - 8: MOUSE POINTER {2200} + 0: ROOT {0000} + 1: FEATURE SET {0001} + 2: DEVICE FW VERSION {0003} + 3: DEVICE NAME {0005} + 4: BATTERY STATUS {1000} + 5: REPROG CONTROLS {1B00} + 6: WIRELESS DEVICE STATUS {1D4B} + 7: VERTICAL SCROLLING {2100} + 8: MOUSE POINTER {2200} 9: unknown:1810 {1810} internal, hidden 10: unknown:1830 {1830} internal, hidden 11: unknown:1850 {1850} internal, hidden @@ -79,4 +79,3 @@ Unifying Receiver 1: RIGHT CLICK => RightClick mse, reprogrammable 2: MIDDLE BUTTON => MiddleMouseButton mse, reprogrammable Battery: 30%, discharging. - diff --git a/docs/devices/mk220.txt b/docs/devices/mk220.txt index 9096d13a..94c5df2a 100644 --- a/docs/devices/mk220.txt +++ b/docs/devices/mk220.txt @@ -16,22 +16,22 @@ Unifying Receiver Firmware: RQM 29.00.B0010 The power switch is located on the base. Supports 16 HID++ 2.0 features: - 0: ROOT {0000} - 1: FEATURE SET {0001} - 2: DEVICE FW VERSION {0003} - 3: DEVICE NAME {0005} + 0: ROOT {0000} + 1: FEATURE SET {0001} + 2: DEVICE FW VERSION {0003} + 3: DEVICE NAME {0005} 4: unknown:1850 {1850} hidden 5: unknown:1860 {1860} hidden - 6: BATTERY STATUS {1000} - 7: WIRELESS DEVICE STATUS {1D4B} + 6: BATTERY STATUS {1000} + 7: WIRELESS DEVICE STATUS {1D4B} 8: unknown:1DF3 {1DF3} hidden - 9: REPROG CONTROLS {1B00} + 9: REPROG CONTROLS {1B00} 10: unknown:1DF0 {1DF0} hidden 11: unknown:1E00 {1E00} hidden 12: unknown:1E80 {1E80} hidden 13: unknown:1F03 {1F03} hidden - 14: VERTICAL SCROLLING {2100} - 15: MOUSE POINTER {2200} + 14: VERTICAL SCROLLING {2100} + 15: MOUSE POINTER {2200} Has 3 reprogrammable keys: 0: LEFT CLICK => LeftClick mse, reprogrammable 1: RIGHT CLICK => RightClick mse, reprogrammable @@ -47,20 +47,20 @@ Unifying Receiver Serial number: 5BB1D72E Firmware: RQK 37.00.B0011 Supports 14 HID++ 2.0 features: - 0: ROOT {0000} - 1: FEATURE SET {0001} - 2: FEATURE INFO {0002} - 3: DEVICE FW VERSION {0003} - 4: DEVICE NAME {0005} - 5: BATTERY STATUS {1000} + 0: ROOT {0000} + 1: FEATURE SET {0001} + 2: FEATURE INFO {0002} + 3: DEVICE FW VERSION {0003} + 4: DEVICE NAME {0005} + 5: BATTERY STATUS {1000} 6: unknown:1820 {1820} hidden - 7: REPROG CONTROLS {1B00} - 8: REPROG CONTROLS V2 {1B01} - 9: WIRELESS DEVICE STATUS {1D4B} + 7: REPROG CONTROLS {1B00} + 8: REPROG CONTROLS V2 {1B01} + 9: WIRELESS DEVICE STATUS {1D4B} 10: unknown:1DF0 {1DF0} hidden 11: unknown:1DF3 {1DF3} hidden - 12: ENCRYPTION {4100} - 13: KEYBOARD LAYOUT {4520} + 12: ENCRYPTION {4100} + 13: KEYBOARD LAYOUT {4520} Has 12 reprogrammable keys: 0: FN F1 => Do Nothing One is FN, reprogrammable 1: FN F2 => Do Nothing One is FN, reprogrammable @@ -75,4 +75,3 @@ Unifying Receiver 10: Volume Down => Volume Down is FN 11: Volume Up => Volume Up is FN Battery: 90%, discharging. - diff --git a/docs/devices/mk240-nano.md b/docs/devices/mk240-nano.md index feea7f94..733e6b8c 100644 --- a/docs/devices/mk240-nano.md +++ b/docs/devices/mk240-nano.md @@ -18,16 +18,16 @@ Unifying Receiver (NOTE: NOT claimed to be supporting Unifying from the package Serial number: 4BBBBA4A Firmware: RQK 49.00.B0029 Supports 18 HID++ 2.0 features: - 0: ROOT {0000} - 1: FEATURE SET {0001} - 2: DEVICE FW VERSION {0003} - 3: DEVICE NAME {0005} - 4: BATTERY STATUS {1000} - 5: REPROG CONTROLS {1B00} - 6: WIRELESS DEVICE STATUS {1D4B} - 7: FN INVERSION {40A0} - 8: ENCRYPTION {4100} - 9: KEYBOARD LAYOUT {4520} + 0: ROOT {0000} + 1: FEATURE SET {0001} + 2: DEVICE FW VERSION {0003} + 3: DEVICE NAME {0005} + 4: BATTERY STATUS {1000} + 5: REPROG CONTROLS {1B00} + 6: WIRELESS DEVICE STATUS {1D4B} + 7: FN INVERSION {40A0} + 8: ENCRYPTION {4100} + 9: KEYBOARD LAYOUT {4520} 10: unknown:1810 {1810} internal, hidden 11: unknown:1830 {1830} internal, hidden 12: unknown:1890 {1890} internal, hidden @@ -59,15 +59,15 @@ Unifying Receiver (NOTE: NOT claimed to be supporting Unifying from the package Serial number: 00000000 Firmware: RQM 38.00.B0044 Supports 18 HID++ 2.0 features: - 0: ROOT {0000} - 1: FEATURE SET {0001} - 2: DEVICE FW VERSION {0003} - 3: DEVICE NAME {0005} - 4: BATTERY STATUS {1000} - 5: REPROG CONTROLS {1B00} - 6: WIRELESS DEVICE STATUS {1D4B} - 7: VERTICAL SCROLLING {2100} - 8: MOUSE POINTER {2200} + 0: ROOT {0000} + 1: FEATURE SET {0001} + 2: DEVICE FW VERSION {0003} + 3: DEVICE NAME {0005} + 4: BATTERY STATUS {1000} + 5: REPROG CONTROLS {1B00} + 6: WIRELESS DEVICE STATUS {1D4B} + 7: VERTICAL SCROLLING {2100} + 8: MOUSE POINTER {2200} 9: unknown:1810 {1810} internal, hidden 10: unknown:1830 {1830} internal, hidden 11: unknown:1850 {1850} internal, hidden @@ -92,36 +92,36 @@ Dj Api Version : 2, 50, 25 ęŽ„ę”¶å™Ø(Receiver) Name : ē„”ē·šęŽ„ę”¶å™Ø(Wireless Receiver) ModelId : 0x46dc534 -Serial Number : +Serial Number : Handle : 0xff000001 Wireless Status : 0x3 Firmware version : 029.001.00016 -Bootloader version : +Bootloader version : Dfu Status : 0x1 Is Dfu Cancellable : Yes Max Device Capacity : 6 滑鼠(Mouse) - Name : + Name : ModelId : 0x0 Serial Number : 4022-00-00-00-00 Handle : 0x2000003 Wireless Status : 0x0 Firmware version : 038.000.00044 - Bootloader version : + Bootloader version : Dfu Status : 0x1 Is Dfu Cancellable : No Battery Status : 0x2 Parent Handle : 0xff000001 éµē›¤(Keyboard) - Name : + Name : ModelId : 0x0 Serial Number : 4023-4B-BB-BA-4A Handle : 0x1000002 Wireless Status : 0x0 Firmware version : 049.000.00029 - Bootloader version : + Bootloader version : Dfu Status : 0x1 Is Dfu Cancellable : No Battery Status : 0x2 diff --git a/docs/devices/mk270.txt b/docs/devices/mk270.txt index eea12d48..332d8af3 100644 --- a/docs/devices/mk270.txt +++ b/docs/devices/mk270.txt @@ -6,7 +6,7 @@ Unifying Receiver Has 2 paired device(s) out of a maximum of 6. Notifications: (none) - 1: Wireless Keyboard + 1: Wireless Keyboard Codename : MK270 Kind : keyboard Wireless PID : 4023 @@ -15,16 +15,16 @@ Unifying Receiver Serial number: 00000000 Firmware: RQK 49.00.B0029 Supports 18 HID++ 2.0 features: - 0: ROOT {0000} - 1: FEATURE SET {0001} - 2: DEVICE FW VERSION {0003} - 3: DEVICE NAME {0005} - 4: BATTERY STATUS {1000} - 5: REPROG CONTROLS {1B00} - 6: WIRELESS DEVICE STATUS {1D4B} - 7: FN INVERSION {40A0} - 8: ENCRYPTION {4100} - 9: KEYBOARD LAYOUT {4520} + 0: ROOT {0000} + 1: FEATURE SET {0001} + 2: DEVICE FW VERSION {0003} + 3: DEVICE NAME {0005} + 4: BATTERY STATUS {1000} + 5: REPROG CONTROLS {1B00} + 6: WIRELESS DEVICE STATUS {1D4B} + 7: FN INVERSION {40A0} + 8: ENCRYPTION {4100} + 9: KEYBOARD LAYOUT {4520} 10: unknown:1810 {1810} internal, hidden 11: unknown:1830 {1830} internal, hidden 12: unknown:1890 {1890} internal, hidden @@ -47,7 +47,7 @@ Unifying Receiver 10: Volume Up => Volume Up FN sensitive, is FN Battery: 30%, discharging. - 2: Wireless Mouse + 2: Wireless Mouse Codename : M185 Kind : mouse Wireless PID : 4038 @@ -56,31 +56,30 @@ Unifying Receiver Serial number: 00000000 Firmware: RQM 54.00.B0004 Supports 22 HID++ 2.0 features: - 0: ROOT {0000} - 1: FEATURE SET {0001} - 2: DEVICE FW VERSION {0003} - 3: DEVICE NAME {0005} - 4: BATTERY STATUS {1000} + 0: ROOT {0000} + 1: FEATURE SET {0001} + 2: DEVICE FW VERSION {0003} + 3: DEVICE NAME {0005} + 4: BATTERY STATUS {1000} 5: unknown:1830 {1830} internal, hidden 6: unknown:1850 {1850} internal, hidden 7: unknown:1860 {1860} internal, hidden 8: unknown:1890 {1890} internal, hidden 9: unknown:18A0 {18A0} internal, hidden 10: unknown:18C0 {18C0} internal, hidden - 11: WIRELESS DEVICE STATUS {1D4B} + 11: WIRELESS DEVICE STATUS {1D4B} 12: unknown:1DF3 {1DF3} internal, hidden - 13: REPROG CONTROLS {1B00} + 13: REPROG CONTROLS {1B00} 14: unknown:1DF0 {1DF0} hidden 15: unknown:1E00 {1E00} hidden 16: unknown:1E80 {1E80} internal, hidden 17: unknown:1E90 {1E90} internal, hidden 18: unknown:1F03 {1F03} internal, hidden - 19: VERTICAL SCROLLING {2100} - 20: MOUSE POINTER {2200} + 19: VERTICAL SCROLLING {2100} + 20: MOUSE POINTER {2200} 21: unknown:18B0 {18B0} internal, hidden Has 3 reprogrammable keys: 0: LEFT CLICK => LeftClick mse, reprogrammable 1: RIGHT CLICK => RightClick mse, reprogrammable 2: MIDDLE BUTTON => MiddleMouseButton mse, reprogrammable Battery: 70%, discharging. - diff --git a/docs/devices/mk520.txt b/docs/devices/mk520.txt index 86f81ad4..fa71c3fe 100644 --- a/docs/devices/mk520.txt +++ b/docs/devices/mk520.txt @@ -19,27 +19,27 @@ Unifying Receiver Firmware: RQM 40.01.B0017 The power switch is located on the base. Supports 21 HID++ 2.0 features: - 0: ROOT {0000} - 1: FEATURE SET {0001} - 2: DEVICE FW VERSION {0003} - 3: DEVICE NAME {0005} - 4: BATTERY STATUS {1000} + 0: ROOT {0000} + 1: FEATURE SET {0001} + 2: DEVICE FW VERSION {0003} + 3: DEVICE NAME {0005} + 4: BATTERY STATUS {1000} 5: unknown:1830 {1830} internal, hidden 6: unknown:1850 {1850} internal, hidden 7: unknown:1860 {1860} internal, hidden 8: unknown:1890 {1890} internal, hidden 9: unknown:18A0 {18A0} internal, hidden 10: unknown:18C0 {18C0} internal, hidden - 11: WIRELESS DEVICE STATUS {1D4B} + 11: WIRELESS DEVICE STATUS {1D4B} 12: unknown:1DF3 {1DF3} internal, hidden - 13: REPROG CONTROLS {1B00} + 13: REPROG CONTROLS {1B00} 14: unknown:1DF0 {1DF0} hidden 15: unknown:1E00 {1E00} hidden 16: unknown:1E80 {1E80} internal, hidden 17: unknown:1E90 {1E90} internal, hidden 18: unknown:1F03 {1F03} internal, hidden - 19: VERTICAL SCROLLING {2100} - 20: MOUSE POINTER {2200} + 19: VERTICAL SCROLLING {2100} + 20: MOUSE POINTER {2200} Has 3 reprogrammable keys: 0: LEFT CLICK => LeftClick mse, reprogrammable 1: RIGHT CLICK => RightClick mse, reprogrammable @@ -58,4 +58,3 @@ Unifying Receiver The power switch is located on the top case. Notifications: (none). Battery: full, discharging. - diff --git a/docs/devices/mx-master-3.txt b/docs/devices/mx-master-3.txt index d584874a..1aaf2c33 100644 --- a/docs/devices/mx-master-3.txt +++ b/docs/devices/mx-master-3.txt @@ -18,23 +18,23 @@ Unifying Receiver Serial number: B0C9EC6E Bootloader: BOT 95.00.B0013 Firmware: MPM 19.00.B0013 - Other: + Other: The power switch is located on the base. Supports 34 HID++ 2.0 features: - 0: ROOT {0000} - 1: FEATURE SET {0001} - 2: DEVICE FW VERSION {0003} - 3: DEVICE NAME {0005} - 4: WIRELESS DEVICE STATUS {1D4B} - 5: RESET {0020} - 6: unknown:0021 {0021} - 7: BATTERY STATUS {1000} - 8: REPROG CONTROLS V4 {1B04} - 9: CHANGE HOST {1814} - 10: unknown:2250 {2250} - 11: ADJUSTABLE DPI {2201} - 12: SMART SHIFT {2110} - 13: HIRES WHEEL {2121} + 0: ROOT {0000} + 1: FEATURE SET {0001} + 2: DEVICE FW VERSION {0003} + 3: DEVICE NAME {0005} + 4: WIRELESS DEVICE STATUS {1D4B} + 5: RESET {0020} + 6: unknown:0021 {0021} + 7: BATTERY STATUS {1000} + 8: REPROG CONTROLS V4 {1B04} + 9: CHANGE HOST {1814} + 10: unknown:2250 {2250} + 11: ADJUSTABLE DPI {2201} + 12: SMART SHIFT {2110} + 13: HIRES WHEEL {2121} Multiplier: 15 Has invert Normal wheel motion @@ -42,9 +42,9 @@ Unifying Receiver Normal wheel mode Low resolution mode HID notification - 14: unknown:2150 {2150} - 15: unknown:2251 {2251} - 16: unknown:00C2 {00C2} + 14: unknown:2150 {2150} + 15: unknown:2251 {2251} + 16: unknown:00C2 {00C2} 17: unknown:1802 {1802} internal, hidden 18: unknown:1803 {1803} internal, hidden 19: unknown:1806 {1806} internal, hidden @@ -63,21 +63,20 @@ Unifying Receiver 32: unknown:9205 {9205} internal, hidden 33: unknown:9300 {9300} internal, hidden Has 8 reprogrammable keys: - 0: LEFT CLICK , default: LeftClick => LEFT CLICK + 0: LEFT CLICK , default: LeftClick => LEFT CLICK mse, pos:0, group:1, gmask:1 - 1: RIGHT CLICK , default: RightClick => RIGHT CLICK + 1: RIGHT CLICK , default: RightClick => RIGHT CLICK mse, pos:0, group:1, gmask:1 - 2: MIDDLE BUTTON , default: MiddleMouseButton => MIDDLE BUTTON + 2: MIDDLE BUTTON , default: MiddleMouseButton => MIDDLE BUTTON divertable, mse, reprogrammable, pos:0, group:3, gmask:7 - 3: BACK AS BUTTON 4 , default: BackEx => BACK AS BUTTON 4 + 3: BACK AS BUTTON 4 , default: BackEx => BACK AS BUTTON 4 divertable, mse, reprogrammable, pos:0, group:2, gmask:3 - 4: FORWARD AS BUTTON 5 , default: BrowserForwardEx => FORWARD AS BUTTON 5 + 4: FORWARD AS BUTTON 5 , default: BrowserForwardEx => FORWARD AS BUTTON 5 divertable, mse, reprogrammable, pos:0, group:2, gmask:3 - 5: unknown:00C3 , default: unknown:00A9 => unknown:00C3 + 5: unknown:00C3 , default: unknown:00A9 => unknown:00C3 divertable, mse, reprogrammable, pos:0, group:3, gmask:7 - 6: unknown:00C4 , default: unknown:009D => unknown:00C4 + 6: unknown:00C4 , default: unknown:009D => unknown:00C4 divertable, mse, reprogrammable, pos:0, group:3, gmask:7 - 7: unknown:00D7 , default: unknown:00B4 => unknown:00D7 + 7: unknown:00D7 , default: unknown:00B4 => unknown:00D7 divertable, virtual, pos:0, group:4, gmask:0 Battery: 100%, discharging. - diff --git a/docs/devices/mx-master.txt b/docs/devices/mx-master.txt index 557bae60..becaac9e 100644 --- a/docs/devices/mx-master.txt +++ b/docs/devices/mx-master.txt @@ -19,24 +19,24 @@ Unifying Receiver Bootloader: BOT 18.00.B0012 Firmware: MPM 11.00.B0012 Firmware: MPM 11.00.B0012 - Other: + Other: The power switch is located on the base. Supports 29 HID++ 2.0 features: - 0: ROOT {0000} - 1: FEATURE SET {0001} - 2: DEVICE FW VERSION {0003} - 3: DEVICE NAME {0005} - 4: WIRELESS DEVICE STATUS {1D4B} - 5: RESET {0020} - 6: BATTERY STATUS {1000} - 7: CHANGE HOST {1814} - 8: REPROG CONTROLS V4 {1B04} - 9: ADJUSTABLE DPI {2201} - 10: VERTICAL SCROLLING {2100} - 11: SMART SHIFT {2110} - 12: HIRES WHEEL {2121} - 13: GESTURE 2 {6501} - 14: DFUCONTROL 2 {00C1} + 0: ROOT {0000} + 1: FEATURE SET {0001} + 2: DEVICE FW VERSION {0003} + 3: DEVICE NAME {0005} + 4: WIRELESS DEVICE STATUS {1D4B} + 5: RESET {0020} + 6: BATTERY STATUS {1000} + 7: CHANGE HOST {1814} + 8: REPROG CONTROLS V4 {1B04} + 9: ADJUSTABLE DPI {2201} + 10: VERTICAL SCROLLING {2100} + 11: SMART SHIFT {2110} + 12: HIRES WHEEL {2121} + 13: GESTURE 2 {6501} + 14: DFUCONTROL 2 {00C1} 15: unknown:1813 {1813} internal, hidden 16: unknown:1830 {1830} internal, hidden 17: unknown:1890 {1890} internal, hidden @@ -51,4 +51,4 @@ Unifying Receiver 26: unknown:9200 {9200} internal, hidden 27: unknown:9240 {9240} internal, hidden 28: unknown:1805 {1805} internal, hidden - Battery: 50%, discharging. \ No newline at end of file + Battery: 50%, discharging. diff --git a/docs/devices/performance-mx.txt b/docs/devices/performance-mx.txt index 928f7dae..09e408fb 100644 --- a/docs/devices/performance-mx.txt +++ b/docs/devices/performance-mx.txt @@ -7,7 +7,7 @@ >> ( 1.097) [10 01 8101 020000] '\x10\x01\x81\x01\x02\x00\x00' # battery (07 means full) -<< ( 7.335) [10 01 8107 000000] '\x10\x01\x81\x07\x00\x00\x00' +<< ( 7.335) [10 01 8107 000000] '\x10\x01\x81\x07\x00\x00\x00' >> ( 7.382) [10 01 8107 070000] '\x10\x01\x81\x07\x07\x00\x00' # Set LEDS - ab cd 00, where a/b/c/d values are 1=off, 2=on, 3=flash diff --git a/docs/devices/t400.txt b/docs/devices/t400.txt index 76752b24..ea09bb97 100644 --- a/docs/devices/t400.txt +++ b/docs/devices/t400.txt @@ -67,16 +67,16 @@ Unifying Receiver Firmware: RQM 39.00.B0029 Bootloader: BL 03.00 Hardware: 72 - Other: + Other: The power switch is located on the base. Supports 28 HID++ 2.0 features: - 0: ROOT {0000} - 1: FEATURE SET {0001} - 2: FEATURE INFO {0002} - 3: DEVICE FW VERSION {0003} - 4: DEVICE NAME {0005} - 5: DFUCONTROL {00C0} - 6: BATTERY STATUS {1000} + 0: ROOT {0000} + 1: FEATURE SET {0001} + 2: FEATURE INFO {0002} + 3: DEVICE FW VERSION {0003} + 4: DEVICE NAME {0005} + 5: DFUCONTROL {00C0} + 6: BATTERY STATUS {1000} 7: unknown:1802 {1802} internal, hidden 8: unknown:1810 {1810} internal, hidden 9: unknown:1830 {1830} internal, hidden @@ -85,19 +85,19 @@ Unifying Receiver 12: unknown:1890 {1890} internal, hidden 13: unknown:18A0 {18A0} internal, hidden 14: unknown:18E3 {18E3} internal, hidden - 15: REPROG CONTROLS {1B00} - 16: WIRELESS DEVICE STATUS {1D4B} + 15: REPROG CONTROLS {1B00} + 16: WIRELESS DEVICE STATUS {1D4B} 17: unknown:1DF3 {1DF3} internal, hidden 18: unknown:1E00 {1E00} hidden 19: unknown:1E80 {1E80} internal, hidden 20: unknown:1F03 {1F03} internal, hidden 21: unknown:1F04 {1F04} internal, hidden - 22: VERTICAL SCROLLING {2100} + 22: VERTICAL SCROLLING {2100} 23: unknown:2101 {2101} hidden - 24: HI RES SCROLLING {2120} - 25: MOUSE POINTER {2200} + 24: HI RES SCROLLING {2120} + 25: MOUSE POINTER {2200} 26: TOUCHMOUSE RAW POINTS {6110} hidden - 27: REPROG CONTROLS V3 {1B03} + 27: REPROG CONTROLS V3 {1B03} Has 7 reprogrammable keys: 0: LEFT CLICK => LeftClick mse, reprogrammable 1: RIGHT CLICK => RightClick mse, reprogrammable @@ -105,5 +105,5 @@ Unifying Receiver 3: METRO START SCREEN => MetroStartScreen mse, reprogrammable 4: ZOOMIN => Do Nothing mse, reprogrammable 5: ZOOMOUT => Do Nothing mse, reprogrammable - 6: BACK HSCROLL => TouchBackForwardHorzScroll + 6: BACK HSCROLL => TouchBackForwardHorzScroll Battery: 100%, discharging. diff --git a/docs/devices/t650.txt b/docs/devices/t650.txt index 98ade9e5..0061b571 100644 --- a/docs/devices/t650.txt +++ b/docs/devices/t650.txt @@ -62,28 +62,28 @@ Unifying Receiver Firmware: RQM 41.01.B0037 Bootloader: BL 03.00 Hardware: 72 - Other: + Other: The power switch is located on the base. Supports 23 HID++ 2.0 features: - 0: ROOT {0000} - 1: FEATURE SET {0001} - 2: FEATURE INFO {0002} - 3: DEVICE FW VERSION {0003} - 4: DEVICE NAME {0005} - 5: BATTERY STATUS {1000} - 6: WIRELESS DEVICE STATUS {1D4B} + 0: ROOT {0000} + 1: FEATURE SET {0001} + 2: FEATURE INFO {0002} + 3: DEVICE FW VERSION {0003} + 4: DEVICE NAME {0005} + 5: BATTERY STATUS {1000} + 6: WIRELESS DEVICE STATUS {1D4B} 7: unknown:1DF3 {1DF3} internal, hidden - 8: REPROG CONTROLS {1B00} + 8: REPROG CONTROLS {1B00} 9: unknown:1F03 {1F03} internal, hidden - 10: VERTICAL SCROLLING {2100} - 11: HI RES SCROLLING {2120} - 12: MOUSE POINTER {2200} - 13: DFUCONTROL {00C0} + 10: VERTICAL SCROLLING {2100} + 11: HI RES SCROLLING {2120} + 12: MOUSE POINTER {2200} + 13: DFUCONTROL {00C0} 14: unknown:1E80 {1E80} internal, hidden - 15: TOUCHPAD RAW XY {6100} + 15: TOUCHPAD RAW XY {6100} 16: unknown:1860 {1860} internal, hidden 17: unknown:1E00 {1E00} hidden - 18: REPROG CONTROLS V2 {1B01} + 18: REPROG CONTROLS V2 {1B01} 19: unknown:1890 {1890} internal, hidden 20: unknown:18E5 {18E5} internal, hidden 21: unknown:18A0 {18A0} internal, hidden diff --git a/docs/features.md b/docs/features.md index 7186bf1d..7977b564 100644 --- a/docs/features.md +++ b/docs/features.md @@ -121,7 +121,7 @@ lib/logitech_receiver/hidpp20.py In most cases it should suffice to only implement the settable feature interface for each setting in the feature. That will add one or more -widgets in the Solaar main window to show and change the setting, +widgets in the Solaar main window to show and change the setting, will permit storing and restoring changed settings, and will output the feature settings in `solaar show`. @@ -183,11 +183,11 @@ the setting name (from the common strings), the feature ID (if any), the feature implementation (if any), the register implementation (if any). -and +and the identifier for the setting implementation if different from the setting name. The identifier is used in descriptors.py to say that a device has the register or feature implementation. The identifier can be the same as the setting name if there is only one implementation for the setting. -This table is used to generate the data structures for describing devices in descriptors.py +This table is used to generate the data structures for describing devices in descriptors.py and is also used to auto-discover feature implementations. ``` _S( _POINTER_SPEED[0], _F.POINTER_SPEED, _feature_pointer_speed ), diff --git a/docs/index.md b/docs/index.md index fda920fa..cbe7014e 100644 --- a/docs/index.md +++ b/docs/index.md @@ -3,8 +3,8 @@ title: Solaar layout: default --- -**Solaar** is a Linux manager for Logitech's devices that connect via a USB -[Unifying][unifying], Lightspeed, or Nano receiver. +**Solaar** is a Linux manager for Logitech's devices that connect via a USB +[Unifying][unifying], Lightspeed, or Nano receiver. Solaar does not work with Logitech peripherals that use Bluetooth or peripherals from other companies. @@ -19,10 +19,10 @@ system tray and also starts with its main window showing. For more information on Solaar's command-line interface use the help option, as in `solaar --help`. -Solaar is able to pair and unpair devices with +Solaar is able to pair and unpair devices with receivers as supported by the receiver. Solaar can also control some of the changeable features of devices, such as smooth scrolling or -function key behavior. +function key behavior. For more information on how to use Solaar see [docs/usage.md](https://pwr-solaar.github.io/Solaar/usage). For more information on the capabilities of Solaar see @@ -39,7 +39,7 @@ Some of the capabilities of Solaar have been developed by observing the behavior Logitech receivers and devices and generalizing from these observations. If your Logitech receiver or device behaves in a strange way this may be caused by an incorrect behavior generalization. -Please report such experiences by creating an issue in +Please report such experiences by creating an issue in [the Solaar repository](https://github.com/pwr-Solaar/Solaar/issues). [unifying]: https://en.wikipedia.org/wiki/Logitech_Unifying_receiver diff --git a/docs/installation.md b/docs/installation.md index cab2ff1b..e952642a 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -22,7 +22,7 @@ and its daemon running. If you have a recent Linux distribution, you are most likely good to go. Solaar requires Python 3.2+ -and the `python3-pyudev` package. +and the `python3-pyudev` package. To run the GUI, solaar also requires Gtk3, and its GObject introspection bindings. The Debian/Ubuntu packages that need to be installed are @@ -47,7 +47,7 @@ Solaar needs to write to the receiver's HID device. To be able to do this without running as root requires udev rule that gives seated users write access to the HID devices for Logitech receivers. -You can install this rule by copying, as root, +You can install this rule by copying, as root, `rules.d/42-logitech-unify-permissions.rules` from Solaar to `/etc/udev/rules.d`. The udev daemon will automatically pick up this file using inotify. @@ -100,7 +100,7 @@ If you install Solaar yourself you may need to create or modify this file. ## Using PyPI -As an alternative to downloading and installing you can install the most recent release -(but not the current github version) of Solaar from PyPI. +As an alternative to downloading and installing you can install the most recent release +(but not the current github version) of Solaar from PyPI. Just run `pip install --user solaar` or `sudo pip install solaar`. The `--user` flag will not install the Solaar udev rule or the Solaar autostart file. diff --git a/docs/logitech/hid10.txt b/docs/logitech/hid10.txt index 9472dd21..4a91992e 100644 --- a/docs/logitech/hid10.txt +++ b/docs/logitech/hid10.txt @@ -275,4 +275,3 @@ Index (same as command) zz (don't care, recommended to return 0) - diff --git a/docs/usage.md b/docs/usage.md index 81624220..c8fe6c28 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -113,4 +113,3 @@ Solaar also has a command line interface that can do most of what can be done using the Solaar main window. For more information on the Solaar command line interface, run `solaar --help` to see the Solaar commands and then `solaar --help` to see the arguments to any of the commands. - diff --git a/lib/hidapi/hidconsole.py b/lib/hidapi/hidconsole.py index b70d4eaa..e8d070c8 100644 --- a/lib/hidapi/hidconsole.py +++ b/lib/hidapi/hidconsole.py @@ -108,7 +108,7 @@ def _continuous_read(handle, timeout=2000): try: reply = _hid.read(handle, 128, timeout) except OSError as e: - _error("Read failed, aborting: " + str(e), True) + _error('Read failed, aborting: ' + str(e), True) break assert reply is not None if reply: @@ -119,25 +119,25 @@ def _validate_input(line, hidpp=False): try: data = unhexlify(line.encode('ascii')) except Exception as e: - _error("Invalid input: " + str(e)) + _error('Invalid input: ' + str(e)) return None if hidpp: if len(data) < 4: - _error("Invalid HID++ request: need at least 4 bytes") + _error('Invalid HID++ request: need at least 4 bytes') return None if data[:1] not in b'\x10\x11': - _error("Invalid HID++ request: first byte must be 0x10 or 0x11") + _error('Invalid HID++ request: first byte must be 0x10 or 0x11') return None if data[1:2] not in b'\xFF\x01\x02\x03\x04\x05\x06': _error( - "Invalid HID++ request: second byte must be 0xFF or one of 0x01..0x06" + 'Invalid HID++ request: second byte must be 0xFF or one of 0x01..0x06' ) return None if data[:1] == b'\x10': if len(data) > 7: _error( - "Invalid HID++ request: maximum length of a 0x10 request is 7 bytes" + 'Invalid HID++ request: maximum length of a 0x10 request is 7 bytes' ) return None while len(data) < 7: @@ -145,7 +145,7 @@ def _validate_input(line, hidpp=False): elif data[:1] == b'\x11': if len(data) > 20: _error( - "Invalid HID++ request: maximum length of a 0x11 request is 20 bytes" + 'Invalid HID++ request: maximum length of a 0x11 request is 20 bytes' ) return None while len(data) < 20: @@ -162,27 +162,27 @@ def _open(args): device = d.path break if not device: - sys.exit("!! No HID++ receiver found.") + sys.exit('!! No HID++ receiver found.') if not device: - sys.exit("!! Device path required.") + sys.exit('!! Device path required.') - print(".. Opening device", device) + print('.. Opening device', device) handle = _hid.open_path(device) if not handle: - sys.exit("!! Failed to open %s, aborting." % device) + sys.exit('!! Failed to open %s, aborting.' % device) - print(".. Opened handle %r, vendor %r product %r serial %r." % + print('.. Opened handle %r, vendor %r product %r serial %r.' % (handle, _hid.get_manufacturer(handle), _hid.get_product(handle), _hid.get_serial(handle))) if args.hidpp: if _hid.get_manufacturer(handle) != b'Logitech': - sys.exit("!! Only Logitech devices support the HID++ protocol.") - print(".. HID++ validation enabled.") + sys.exit('!! Only Logitech devices support the HID++ protocol.') + print('.. HID++ validation enabled.') else: if (_hid.get_manufacturer(handle) == b'Logitech' and b'Receiver' in _hid.get_product(handle)): args.hidpp = True - print(".. Logitech receiver detected, HID++ validation enabled.") + print('.. Logitech receiver detected, HID++ validation enabled.') return handle @@ -196,15 +196,15 @@ def _parse_arguments(): import argparse arg_parser = argparse.ArgumentParser() arg_parser.add_argument( - '--history', help="history file (default ~/.hidconsole-history)") + '--history', help='history file (default ~/.hidconsole-history)') arg_parser.add_argument('--hidpp', action='store_true', - help="ensure input data is a valid HID++ request") + help='ensure input data is a valid HID++ request') arg_parser.add_argument( 'device', nargs='?', - help="linux device to connect to (/dev/hidrawX); " - "may be omitted if --hidpp is given, in which case it looks for the first Logitech receiver" + help='linux device to connect to (/dev/hidrawX); ' + 'may be omitted if --hidpp is given, in which case it looks for the first Logitech receiver' ) return arg_parser.parse_args() @@ -215,7 +215,7 @@ def main(): if interactive: print( - ".. Press ^C/^D to exit, or type hex bytes to write to the device." + '.. Press ^C/^D to exit, or type hex bytes to write to the device.' ) import readline @@ -264,12 +264,12 @@ def main(): time.sleep(0.700) except EOFError: if interactive: - print("") + print('') else: time.sleep(1) finally: - print(".. Closing handle %r" % handle) + print('.. Closing handle %r' % handle) _hid.close(handle) if interactive: readline.write_history_file(args.history) diff --git a/lib/logitech_receiver/base.py b/lib/logitech_receiver/base.py index 374d4adc..328c797e 100644 --- a/lib/logitech_receiver/base.py +++ b/lib/logitech_receiver/base.py @@ -176,13 +176,13 @@ def write(handle, devnumber, data): else: wdata = _pack('!BB5s', 0x10, devnumber, data) if _log.isEnabledFor(_DEBUG): - _log.debug("(%s) <= w[%02X %02X %s %s]", handle, ord(wdata[:1]), + _log.debug('(%s) <= w[%02X %02X %s %s]', handle, ord(wdata[:1]), devnumber, _strhex(wdata[2:4]), _strhex(wdata[4:])) try: _hid.write(int(handle), wdata) except Exception as reason: - _log.error("write failed, assuming handle %r no longer available", + _log.error('write failed, assuming handle %r no longer available', handle) close(handle) raise NoReceiver(reason=reason) @@ -214,7 +214,7 @@ def check_message(data): if report_lengths.get(report_id) == len(data): return True else: - _log.warn("unexpected message size: report_id %02X message %s" % + _log.warn('unexpected message size: report_id %02X message %s' % (report_id, _strhex(data))) return False @@ -233,7 +233,7 @@ def _read(handle, timeout): timeout = int(timeout * 1000) data = _hid.read(int(handle), _MAX_READ_SIZE, timeout) except Exception as reason: - _log.error("read failed, assuming handle %r no longer available", + _log.error('read failed, assuming handle %r no longer available', handle) close(handle) raise NoReceiver(reason=reason) @@ -243,7 +243,7 @@ def _read(handle, timeout): devnumber = ord(data[1:2]) if _log.isEnabledFor(_DEBUG): - _log.debug("(%s) => r[%02X %02X %s %s]", handle, report_id, + _log.debug('(%s) => r[%02X %02X %s %s]', handle, report_id, devnumber, _strhex(data[2:4]), _strhex(data[4:])) return report_id, devnumber, data[2:] @@ -265,7 +265,7 @@ def _skip_incoming(handle, ihandle, notifications_hook): # read whatever is already in the buffer, if any data = _hid.read(ihandle, _MAX_READ_SIZE, 0) except Exception as reason: - _log.error("read failed, assuming receiver %s no longer available", + _log.error('read failed, assuming receiver %s no longer available', handle) close(handle) raise NoReceiver(reason=reason) @@ -389,7 +389,7 @@ def request(handle, devnumber, request_id, *params): if _log.isEnabledFor(_DEBUG): _log.debug( - "(%s) device 0x%02X error on request {%04X}: %d = %s", + '(%s) device 0x%02X error on request {%04X}: %d = %s', handle, devnumber, request_id, error, _hidpp10.ERROR[error]) return @@ -399,7 +399,7 @@ def request(handle, devnumber, request_id, *params): # a HID++ 2.0 feature call returned with an error error = ord(reply_data[3:4]) _log.error( - "(%s) device %d error on feature request {%04X}: %d = %s", + '(%s) device %d error on feature request {%04X}: %d = %s', handle, devnumber, request_id, error, _hidpp20.ERROR[error]) raise _hidpp20.FeatureCallError(number=devnumber, @@ -445,7 +445,7 @@ def request(handle, devnumber, request_id, *params): # if _log.isEnabledFor(_DEBUG): # _log.debug("(%s) still waiting for reply, delta %f", handle, delta) - _log.warn("timeout (%0.2f/%0.2f) on device %d request {%04X} params [%s]", + _log.warn('timeout (%0.2f/%0.2f) on device %d request {%04X} params [%s]', delta, timeout, devnumber, request_id, _strhex(params)) # raise DeviceUnreachable(number=devnumber, request=request_id) @@ -456,7 +456,7 @@ def ping(handle, devnumber): :returns: The HID protocol supported by the device, as a floating point number, if the device is active. """ if _log.isEnabledFor(_DEBUG): - _log.debug("(%s) pinging device %d", handle, devnumber) + _log.debug('(%s) pinging device %d', handle, devnumber) # import inspect as _inspect # print ('\n '.join(str(s) for s in _inspect.stack())) @@ -504,7 +504,7 @@ def ping(handle, devnumber): if error == _hidpp10.ERROR.unknown_device: # no paired device with that number _log.error( - "(%s) device %d error on ping request: unknown device", + '(%s) device %d error on ping request: unknown device', handle, devnumber) raise NoSuchDevice(number=devnumber, request=request_id) @@ -518,6 +518,6 @@ def ping(handle, devnumber): delta = _timestamp() - request_started - _log.warn("(%s) timeout (%0.2f/%0.2f) on device %d ping", handle, delta, + _log.warn('(%s) timeout (%0.2f/%0.2f) on device %d ping', handle, delta, _PING_TIMEOUT, devnumber) # raise DeviceUnreachable(number=devnumber, request=request_id) diff --git a/lib/logitech_receiver/common.py b/lib/logitech_receiver/common.py index b1030a50..cde4b58b 100644 --- a/lib/logitech_receiver/common.py +++ b/lib/logitech_receiver/common.py @@ -107,7 +107,7 @@ class NamedInts(object): def __init__(self, **kwargs): def _readable_name(n): if not is_string(n): - raise TypeError("expected (unicode) string, got " + + raise TypeError('expected (unicode) string, got ' + str(type(n))) return n.replace('__', '/').replace('_', ' ') diff --git a/lib/logitech_receiver/hidpp10.py b/lib/logitech_receiver/hidpp10.py index fe7f9385..727eb601 100644 --- a/lib/logitech_receiver/hidpp10.py +++ b/lib/logitech_receiver/hidpp10.py @@ -202,7 +202,7 @@ def parse_battery_status(register, reply): elif charging_byte & 0x22 == 0x22: status_text = BATTERY_STATUS.full else: - _log.warn("could not parse 0x07 battery status: %02X (level %02X)", + _log.warn('could not parse 0x07 battery status: %02X (level %02X)', charging_byte, status_byte) status_text = None diff --git a/lib/logitech_receiver/hidpp20.py b/lib/logitech_receiver/hidpp20.py index 0ee3f1ed..3b880118 100644 --- a/lib/logitech_receiver/hidpp20.py +++ b/lib/logitech_receiver/hidpp20.py @@ -268,7 +268,7 @@ class FeaturesArray(object): count = self.device.request(fs_index << 8) if count is None: _log.warn( - "FEATURE_SET found, but failed to read features count" + 'FEATURE_SET found, but failed to read features count' ) # most likely the device is unavailable return False @@ -348,7 +348,7 @@ class FeaturesArray(object): self.features[index] = FEATURE[ivalue] return index - raise ValueError("%r not in list" % featureId) + raise ValueError('%r not in list' % featureId) def __iter__(self): if self._check(): @@ -530,7 +530,7 @@ def get_name(device): name += fragment[:name_length - len(name)] else: _log.error( - "failed to read whole name of %s (expected %d chars)", + 'failed to read whole name of %s (expected %d chars)', device, name_length) return None @@ -545,7 +545,7 @@ def get_battery(device): discharge = None if discharge == 0 else discharge if _log.isEnabledFor(_DEBUG): _log.debug( - "device %d battery %d%% charged, next level %d%% charge, status %d = %s", + 'device %d battery %d%% charged, next level %d%% charge, status %d = %s', device.number, discharge, dischargeNext, status, BATTERY_STATUS[status]) return discharge, BATTERY_STATUS[status], dischargeNext @@ -583,7 +583,7 @@ def decipher_voltage(voltage_report): if _log.isEnabledFor(_DEBUG): _log.debug( - "device %d, battery voltage %d mV, charging = %s, charge status %d = %s, charge level %s, charge type %s", + 'device %d, battery voltage %d mV, charging = %s, charge status %d = %s, charge level %s, charge type %s', device.number, voltage, status, (flags & 0x03), charge_sts, charge_lvl, charge_type) diff --git a/lib/logitech_receiver/i18n.py b/lib/logitech_receiver/i18n.py index 721d1908..4c6bcaae 100644 --- a/lib/logitech_receiver/i18n.py +++ b/lib/logitech_receiver/i18n.py @@ -35,30 +35,30 @@ except: _DUMMY = ( # approximative battery levels - _("empty"), - _("critical"), - _("low"), - _("good"), - _("full"), + _('empty'), + _('critical'), + _('low'), + _('good'), + _('full'), # battery charging statuses - _("discharging"), - _("recharging"), - _("almost full"), - _("charged"), - _("slow recharge"), - _("invalid battery"), - _("thermal error"), + _('discharging'), + _('recharging'), + _('almost full'), + _('charged'), + _('slow recharge'), + _('invalid battery'), + _('thermal error'), # pairing errors - _("device timeout"), - _("device not supported"), - _("too many devices"), - _("sequence timeout"), + _('device timeout'), + _('device not supported'), + _('too many devices'), + _('sequence timeout'), # firmware kinds - _("Firmware"), - _("Bootloader"), - _("Hardware"), - _("Other"), + _('Firmware'), + _('Bootloader'), + _('Hardware'), + _('Other'), ) diff --git a/lib/logitech_receiver/listener.py b/lib/logitech_receiver/listener.py index 3bb75549..cab3ac75 100644 --- a/lib/logitech_receiver/listener.py +++ b/lib/logitech_receiver/listener.py @@ -67,7 +67,7 @@ class _ThreadedHandle(object): def _open(self): handle = _base.open_path(self.path) if handle is None: - _log.error("%r failed to open new handle", self) + _log.error('%r failed to open new handle', self) else: # if _log.isEnabledFor(_DEBUG): # _log.debug("%r opened new handle %d", self, handle) @@ -80,7 +80,7 @@ class _ThreadedHandle(object): self._local = None handles, self._handles = self._handles, [] if _log.isEnabledFor(_DEBUG): - _log.debug("%r closing %s", self, handles) + _log.debug('%r closing %s', self, handles) for h in handles: _base.close(h) @@ -163,7 +163,7 @@ class EventsListener(_threading.Thread): # get the right low-level handle for this thread ihandle = int(self.receiver.handle) if _log.isEnabledFor(_INFO): - _log.info("started with %s (%d)", self.receiver, ihandle) + _log.info('started with %s (%d)', self.receiver, ihandle) self.has_started() @@ -178,7 +178,7 @@ class EventsListener(_threading.Thread): # _log.debug("read next notification") n = _base.read(ihandle, _EVENT_READ_TIMEOUT) except _base.NoReceiver: - _log.warning("receiver disconnected") + _log.warning('receiver disconnected') self.receiver.close() break @@ -194,7 +194,7 @@ class EventsListener(_threading.Thread): try: self._notifications_callback(n) except: - _log.exception("processing %s", n) + _log.exception('processing %s', n) # elif self.tick_period: # idle_reads -= 1 diff --git a/lib/logitech_receiver/notifications.py b/lib/logitech_receiver/notifications.py index 7d299604..0c0c526f 100644 --- a/lib/logitech_receiver/notifications.py +++ b/lib/logitech_receiver/notifications.py @@ -72,10 +72,10 @@ def _process_receiver_notification(receiver, status, n): # pairing lock notification if n.sub_id == 0x4A: status.lock_open = bool(n.address & 0x01) - reason = (_("pairing lock is open") - if status.lock_open else _("pairing lock is closed")) + reason = (_('pairing lock is open') + if status.lock_open else _('pairing lock is closed')) if _log.isEnabledFor(_INFO): - _log.info("%s: %s", receiver, reason) + _log.info('%s: %s', receiver, reason) status[_K.ERROR] = None if status.lock_open: @@ -86,12 +86,12 @@ def _process_receiver_notification(receiver, status, n): status[ _K.ERROR] = error_string = _hidpp10.PAIRING_ERRORS[pair_error] status.new_device = None - _log.warn("pairing error %d: %s", pair_error, error_string) + _log.warn('pairing error %d: %s', pair_error, error_string) status.changed(reason=reason) return True - _log.warn("%s: unhandled notification %s", receiver, n) + _log.warn('%s: unhandled notification %s', receiver, n) # @@ -124,7 +124,7 @@ def _process_device_notification(device, status, n): try: feature = device.features[n.sub_id] except IndexError: - _log.warn("%s: notification from invalid feature index %02X: %s", + _log.warn('%s: notification from invalid feature index %02X: %s', device, n.sub_id, n) return False @@ -133,31 +133,31 @@ def _process_device_notification(device, status, n): def _process_dj_notification(device, status, n): if _log.isEnabledFor(_DEBUG): - _log.debug("%s (%s) DJ notification %s", device, device.protocol, n) + _log.debug('%s (%s) DJ notification %s', device, device.protocol, n) if n.sub_id == 0x40: # do all DJ paired notifications also show up as HID++ 1.0 notifications? if _log.isEnabledFor(_INFO): - _log.info("%s: ignoring DJ unpaired: %s", device, n) + _log.info('%s: ignoring DJ unpaired: %s', device, n) return True if n.sub_id == 0x41: # do all DJ paired notifications also show up as HID++ 1.0 notifications? if _log.isEnabledFor(_INFO): - _log.info("%s: ignoring DJ paired: %s", device, n) + _log.info('%s: ignoring DJ paired: %s', device, n) return True if n.sub_id == 0x42: if _log.isEnabledFor(_INFO): - _log.info("%s: ignoring DJ connection: %s", device, n) + _log.info('%s: ignoring DJ connection: %s', device, n) return True - _log.warn("%s: unrecognized DJ %s", device, n) + _log.warn('%s: unrecognized DJ %s', device, n) def _process_hidpp10_custom_notification(device, status, n): if _log.isEnabledFor(_DEBUG): - _log.debug("%s (%s) custom notification %s", device, device.protocol, + _log.debug('%s (%s) custom notification %s', device, device.protocol, n) if n.sub_id in (_R.battery_status, _R.battery_charge): @@ -172,10 +172,10 @@ def _process_hidpp10_custom_notification(device, status, n): # message layout: 10 ix 17("address") # TODO anything we can do with this? if _log.isEnabledFor(_INFO): - _log.info("illumination event: %s", n) + _log.info('illumination event: %s', n) return True - _log.warn("%s: unrecognized %s", device, n) + _log.warn('%s: unrecognized %s', device, n) def _process_hidpp10_notification(device, status, n): @@ -190,9 +190,9 @@ def _process_hidpp10_notification(device, status, n): del device.receiver[device.number] status.changed(active=False, alert=_ALERT.ALL, - reason=_("unpaired")) + reason=_('unpaired')) else: - _log.warn("%s: disconnection with unknown type %02X: %s", device, + _log.warn('%s: disconnection with unknown type %02X: %s', device, n.address, n) return True @@ -211,7 +211,7 @@ def _process_hidpp10_notification(device, status, n): if protocol_name: if _log.isEnabledFor(_DEBUG): wpid = _strhex(n.data[2:3] + n.data[1:2]) - assert wpid == device.wpid, "%s wpid mismatch, got %s" % ( + assert wpid == device.wpid, '%s wpid mismatch, got %s' % ( device, wpid) flags = ord(n.data[:1]) & 0xF0 @@ -221,14 +221,14 @@ def _process_hidpp10_notification(device, status, n): sw_present = bool(flags & 0x10) has_payload = bool(flags & 0x80) _log.debug( - "%s: %s connection notification: software=%s, encrypted=%s, link=%s, payload=%s", + '%s: %s connection notification: software=%s, encrypted=%s, link=%s, payload=%s', device, protocol_name, sw_present, link_encrypted, link_established, has_payload) status[_K.LINK_ENCRYPTED] = link_encrypted status.changed(active=link_established) else: _log.warn( - "%s: connection notification with unknown protocol %02X: %s", + '%s: connection notification with unknown protocol %02X: %s', device.number, n.address, n) return True @@ -244,16 +244,16 @@ def _process_hidpp10_notification(device, status, n): if n.sub_id == 0x4B: if n.address == 0x01: if _log.isEnabledFor(_DEBUG): - _log.debug("%s: device powered on", device) - reason = status.to_string() or _("powered on") + _log.debug('%s: device powered on', device) + reason = status.to_string() or _('powered on') status.changed(active=True, alert=_ALERT.NOTIFICATION, reason=reason) else: - _log.warn("%s: unknown %s", device, n) + _log.warn('%s: unknown %s', device, n) return True - _log.warn("%s: unrecognized %s", device, n) + _log.warn('%s: unrecognized %s', device, n) def _process_feature_notification(device, status, n, feature): @@ -267,7 +267,7 @@ def _process_feature_notification(device, status, n, feature): _hidpp20.BATTERY_STATUS[battery_status], discharge_next_level) else: - _log.warn("%s: unknown BATTERY %s", device, n) + _log.warn('%s: unknown BATTERY %s', device, n) return True if feature == _F.BATTERY_VOLTAGE: @@ -276,30 +276,30 @@ def _process_feature_notification(device, status, n, feature): n.data) status.set_battery_info(level, status, None, voltage) else: - _log.warn("%s: unknown VOLTAGE %s", device, n) + _log.warn('%s: unknown VOLTAGE %s', device, n) return True # TODO: what are REPROG_CONTROLS_V{2,3}? if feature == _F.REPROG_CONTROLS: if n.address == 0x00: if _log.isEnabledFor(_INFO): - _log.info("%s: reprogrammable key: %s", device, n) + _log.info('%s: reprogrammable key: %s', device, n) else: - _log.warn("%s: unknown REPROGRAMMABLE KEYS %s", device, n) + _log.warn('%s: unknown REPROGRAMMABLE KEYS %s', device, n) return True if feature == _F.WIRELESS_DEVICE_STATUS: if n.address == 0x00: if _log.isEnabledFor(_DEBUG): - _log.debug("wireless status: %s", n) + _log.debug('wireless status: %s', n) if n.data[0:3] == b'\x01\x01\x01': status.changed(active=True, alert=_ALERT.NOTIFICATION, reason='powered on') else: - _log.warn("%s: unknown WIRELESS %s", device, n) + _log.warn('%s: unknown WIRELESS %s', device, n) else: - _log.warn("%s: unknown WIRELESS %s", device, n) + _log.warn('%s: unknown WIRELESS %s', device, n) return True if feature == _F.SOLAR_DASHBOARD: @@ -319,7 +319,7 @@ def _process_feature_notification(device, status, n, feature): status.set_battery_info(charge, status_text, None) elif n.address == 0x20: if _log.isEnabledFor(_DEBUG): - _log.debug("%s: Light Check button pressed", device) + _log.debug('%s: Light Check button pressed', device) status.changed(alert=_ALERT.SHOW_WINDOW) # first cancel any reporting # device.feature_request(_F.SOLAR_DASHBOARD) @@ -329,25 +329,25 @@ def _process_feature_notification(device, status, n, feature): device.feature_request(_F.SOLAR_DASHBOARD, 0x00, reports_count, reports_period) else: - _log.warn("%s: unknown SOLAR CHARGE %s", device, n) + _log.warn('%s: unknown SOLAR CHARGE %s', device, n) else: - _log.warn("%s: SOLAR CHARGE not GOOD? %s", device, n) + _log.warn('%s: SOLAR CHARGE not GOOD? %s', device, n) return True if feature == _F.TOUCHMOUSE_RAW_POINTS: if n.address == 0x00: if _log.isEnabledFor(_INFO): - _log.info("%s: TOUCH MOUSE points %s", device, n) + _log.info('%s: TOUCH MOUSE points %s', device, n) elif n.address == 0x10: touch = ord(n.data[:1]) button_down = bool(touch & 0x02) mouse_lifted = bool(touch & 0x01) if _log.isEnabledFor(_INFO): _log.info( - "%s: TOUCH MOUSE status: button_down=%s mouse_lifted=%s", + '%s: TOUCH MOUSE status: button_down=%s mouse_lifted=%s', device, button_down, mouse_lifted) else: - _log.warn("%s: unknown TOUCH MOUSE %s", device, n) + _log.warn('%s: unknown TOUCH MOUSE %s', device, n) return True if feature == _F.HIRES_WHEEL: @@ -356,18 +356,18 @@ def _process_feature_notification(device, status, n, feature): flags, delta_v = _unpack('>bh', n.data[:3]) high_res = (flags & 0x10) != 0 periods = flags & 0x0f - _log.info("%s: WHEEL: res: %d periods: %d delta V:%-3d", + _log.info('%s: WHEEL: res: %d periods: %d delta V:%-3d', device, high_res, periods, delta_v) return True elif (n.address == 0x10): if _log.isEnabledFor(_INFO): flags = ord(n.data[:1]) ratchet = flags & 0x01 - _log.info("%s: WHEEL: ratchet: %d", device, ratchet) + _log.info('%s: WHEEL: ratchet: %d', device, ratchet) return True else: - _log.warn("%s: unknown WHEEL %s", device, n) + _log.warn('%s: unknown WHEEL %s', device, n) return True - _log.warn("%s: unrecognized %s for feature %s (index %02X)", device, n, + _log.warn('%s: unrecognized %s for feature %s (index %02X)', device, n, feature, n.sub_id) diff --git a/lib/logitech_receiver/receiver.py b/lib/logitech_receiver/receiver.py index 9647be57..a0bfddbb 100644 --- a/lib/logitech_receiver/receiver.py +++ b/lib/logitech_receiver/receiver.py @@ -106,19 +106,19 @@ class PairedDevice(object): device_info = self.receiver.read_register( _R.receiver_info, 0x04) if device_info is None: - _log.error("failed to read Nano wpid for device %d of %s", + _log.error('failed to read Nano wpid for device %d of %s', number, receiver) raise _base.NoSuchDevice(number=number, receiver=receiver, - error="read Nano wpid") + error='read Nano wpid') self.wpid = _strhex(device_info[3:5]) self._polling_rate = 0 - self._power_switch = '(' + _("unknown") + ')' + self._power_switch = '(' + _('unknown') + ')' # the wpid is necessary to properly identify wireless link on/off notifications # also it gets set to None on this object when the device is unpaired - assert self.wpid is not None, "failed to read wpid: device %d of %s" % ( + assert self.wpid is not None, 'failed to read wpid: device %d of %s' % ( number, receiver) self.descriptor = _DESCRIPTORS.get(self.wpid) @@ -289,14 +289,14 @@ class PairedDevice(object): set_flag_bits = 0 ok = _hidpp10.set_notification_flags(self, set_flag_bits) if ok is None: - _log.warn("%s: failed to %s device notifications", self, + _log.warn('%s: failed to %s device notifications', self, 'enable' if enable else 'disable') flag_bits = _hidpp10.get_notification_flags(self) flag_names = None if flag_bits is None else tuple( _hidpp10.NOTIFICATION_FLAG.flag_names(flag_bits)) if _log.isEnabledFor(_INFO): - _log.info("%s: device notifications %s %s", self, + _log.info('%s: device notifications %s %s', self, 'enabled' if enable else 'disabled', flag_names) return flag_bits if ok else None @@ -364,7 +364,7 @@ class Receiver(object): self.product_id = device_info.product_id product_info = _product_information(self.product_id) if not product_info: - raise Exception("Unknown receiver type", self.product_id) + raise Exception('Unknown receiver type', self.product_id) # read the serial immediately, so we can find out max_devices serial_reply = self.read_register(_R.receiver_info, 0x03) @@ -426,7 +426,7 @@ class Receiver(object): set_flag_bits = 0 ok = _hidpp10.set_notification_flags(self, set_flag_bits) if ok is None: - _log.warn("%s: failed to %s receiver notifications", self, + _log.warn('%s: failed to %s receiver notifications', self, 'enable' if enable else 'disable') return None @@ -434,7 +434,7 @@ class Receiver(object): flag_names = None if flag_bits is None else tuple( _hidpp10.NOTIFICATION_FLAG.flag_names(flag_bits)) if _log.isEnabledFor(_INFO): - _log.info("%s: receiver notifications %s => %s", self, + _log.info('%s: receiver notifications %s => %s', self, 'enabled' if enable else 'disabled', flag_names) return flag_bits @@ -442,12 +442,12 @@ class Receiver(object): """Scan all devices.""" if self.handle: if not self.write_register(_R.receiver_connection, 0x02): - _log.warn("%s: failed to trigger device link notifications", + _log.warn('%s: failed to trigger device link notifications', self) def register_new_device(self, number, notification=None): if self._devices.get(number) is not None: - raise IndexError("%s: device number %d already registered" % + raise IndexError('%s: device number %d already registered' % (self, number)) assert notification is None or notification.devnumber == number @@ -457,14 +457,14 @@ class Receiver(object): dev = PairedDevice(self, number, notification) assert dev.wpid if _log.isEnabledFor(_INFO): - _log.info("%s: found new device %d (%s)", self, number, + _log.info('%s: found new device %d (%s)', self, number, dev.wpid) self._devices[number] = dev return dev except _base.NoSuchDevice: - _log.exception("register_new_device") + _log.exception('register_new_device') - _log.warning("%s: looked for device %d, not found", self, number) + _log.warning('%s: looked for device %d, not found', self, number) self._devices[number] = None def set_lock(self, lock_closed=True, device=0, timeout=0): @@ -474,7 +474,7 @@ class Receiver(object): timeout) if reply: return True - _log.warn("%s: failed to %s the receiver lock", self, + _log.warn('%s: failed to %s the receiver lock', self, 'close' if lock_closed else 'open') def count(self): @@ -536,7 +536,7 @@ class Receiver(object): dev.wpid = None if key in self._devices: del self._devices[key] - _log.warn("%s removed device %s", self, dev) + _log.warn('%s removed device %s', self, dev) else: reply = self.write_register(_R.receiver_pairing, 0x03, key) if reply: @@ -545,9 +545,9 @@ class Receiver(object): dev.wpid = None if key in self._devices: del self._devices[key] - _log.warn("%s unpaired device %s", self, dev) + _log.warn('%s unpaired device %s', self, dev) else: - _log.error("%s failed to unpair device %s", self, dev) + _log.error('%s failed to unpair device %s', self, dev) raise IndexError(key) def __len__(self): @@ -586,8 +586,8 @@ class Receiver(object): if handle: return Receiver(handle, device_info) except OSError as e: - _log.exception("open %s", device_info) + _log.exception('open %s', device_info) if e.errno == _errno.EACCES: raise except: - _log.exception("open %s", device_info) + _log.exception('open %s', device_info) diff --git a/lib/logitech_receiver/settings.py b/lib/logitech_receiver/settings.py index 6d9ce398..173c182c 100644 --- a/lib/logitech_receiver/settings.py +++ b/lib/logitech_receiver/settings.py @@ -110,7 +110,7 @@ class Setting(object): assert hasattr(self, '_device') if _log.isEnabledFor(_DEBUG): - _log.debug("%s: settings read %r from %s", self.name, self._value, + _log.debug('%s: settings read %r from %s', self.name, self._value, self._device) if self._value is None and self._device.persister: @@ -141,7 +141,7 @@ class Setting(object): assert value is not None if _log.isEnabledFor(_DEBUG): - _log.debug("%s: settings write %r to %s", self.name, value, + _log.debug('%s: settings write %r to %s', self.name, value, self._device) if self._device.online: @@ -160,7 +160,7 @@ class Setting(object): data_bytes = self._validator.prepare_write(value, current_value) if data_bytes is not None: if _log.isEnabledFor(_DEBUG): - _log.debug("%s: settings prepare write(%s) => %r", + _log.debug('%s: settings prepare write(%s) => %r', self.name, value, data_bytes) reply = self._rw.write(self._device, data_bytes) @@ -175,7 +175,7 @@ class Setting(object): assert hasattr(self, '_device') if _log.isEnabledFor(_DEBUG): - _log.debug("%s: apply %s (%s)", self.name, self._value, + _log.debug('%s: apply %s (%s)', self.name, self._value, self._device) value = self.read() @@ -202,7 +202,7 @@ class Settings(Setting): assert hasattr(self, '_device') if _log.isEnabledFor(_DEBUG): - _log.debug("%s: settings read %r from %s", self.name, self._value, + _log.debug('%s: settings read %r from %s', self.name, self._value, self._device) if self._value is None and getattr(self._device, 'persister', None): @@ -219,7 +219,7 @@ class Settings(Setting): return self._value if self._device.online: - reply_map = dict() + reply_map = {} for key, value in self._validator.choices.items(): reply = self._rw.read(self._device, key) if reply: @@ -241,7 +241,7 @@ class Settings(Setting): assert key is not None if _log.isEnabledFor(_DEBUG): - _log.debug("%s: settings read %r key %r from %s", self.name, + _log.debug('%s: settings read %r key %r from %s', self.name, self._value, key, self._device) if self._value is None and getattr(self._device, 'persister', None): @@ -269,7 +269,7 @@ class Settings(Setting): assert map is not None if _log.isEnabledFor(_DEBUG): - _log.debug("%s: settings write %r to %s", self.name, map, + _log.debug('%s: settings write %r to %s', self.name, map, self._device) if self._device.online: @@ -285,7 +285,7 @@ class Settings(Setting): if data_bytes is not None: if _log.isEnabledFor(_DEBUG): _log.debug( - "%s: settings prepare map write(%s,%s) => %r", + '%s: settings prepare map write(%s,%s) => %r', self.name, key, value, data_bytes) reply = self._rw.write(self._device, int(key), data_bytes) if not reply: @@ -300,7 +300,7 @@ class Settings(Setting): assert value is not None if _log.isEnabledFor(_DEBUG): - _log.debug("%s: settings write key %r value %r to %s", self.name, + _log.debug('%s: settings write key %r value %r to %s', self.name, key, value, self._device) if self._device.online: @@ -315,7 +315,7 @@ class Settings(Setting): if data_bytes is not None: if _log.isEnabledFor(_DEBUG): _log.debug( - "%s: settings prepare key value write(%s,%s) => %r", + '%s: settings prepare key value write(%s,%s) => %r', self.name, key, value, data_bytes) reply = self._rw.write(self._device, int(key), data_bytes) if not reply: @@ -333,7 +333,7 @@ class BitFieldSetting(Setting): assert hasattr(self, '_device') if _log.isEnabledFor(_DEBUG): - _log.debug("%s: settings read %r from %s", self.name, self._value, + _log.debug('%s: settings read %r from %s', self.name, self._value, self._device) if self._value is None and getattr(self._device, 'persister', None): @@ -350,7 +350,7 @@ class BitFieldSetting(Setting): return self._value if self._device.online: - reply_map = dict() + reply_map = {} reply = self._rw.read(self._device) if reply: # keys are ints, because that is what the device uses, @@ -370,7 +370,7 @@ class BitFieldSetting(Setting): assert key is not None if _log.isEnabledFor(_DEBUG): - _log.debug("%s: settings read %r key %r from %s", self.name, + _log.debug('%s: settings read %r key %r from %s', self.name, self._value, key, self._device) if self._value is None and getattr(self._device, 'persister', None): @@ -397,7 +397,7 @@ class BitFieldSetting(Setting): assert map is not None if _log.isEnabledFor(_DEBUG): - _log.debug("%s: settings write %r to %s", self.name, map, + _log.debug('%s: settings write %r to %s', self.name, map, self._device) if self._device.online: @@ -410,7 +410,7 @@ class BitFieldSetting(Setting): data_bytes = self._validator.prepare_write(self._value) if data_bytes is not None: if _log.isEnabledFor(_DEBUG): - _log.debug("%s: settings prepare map write(%s) => %r", + _log.debug('%s: settings prepare map write(%s) => %r', self.name, self._value, data_bytes) reply = self._rw.write(self._device, data_bytes) if not reply: @@ -424,7 +424,7 @@ class BitFieldSetting(Setting): assert value is not None if _log.isEnabledFor(_DEBUG): - _log.debug("%s: settings write key %r value %r to %s", self.name, + _log.debug('%s: settings write key %r value %r to %s', self.name, key, value, self._device) if self._device.online: @@ -440,7 +440,7 @@ class BitFieldSetting(Setting): if data_bytes is not None: if _log.isEnabledFor(_DEBUG): _log.debug( - "%s: settings prepare key value write(%s,%s) => %r", + '%s: settings prepare key value write(%s,%s) => %r', self.name, key, str(value), data_bytes) reply = self._rw.write(self._device, data_bytes) if not reply: @@ -583,13 +583,13 @@ class BooleanValidator(object): if isinstance(self.mask, int): reply_value = ord(reply_bytes[:1]) & self.mask if _log.isEnabledFor(_DEBUG): - _log.debug("BooleanValidator: validate read %r => %02X", + _log.debug('BooleanValidator: validate read %r => %02X', reply_bytes, reply_value) if reply_value == self.true_value: return True if reply_value == self.false_value: return False - _log.warn("BooleanValidator: reply %02X mismatched %02X/%02X/%02X", + _log.warn('BooleanValidator: reply %02X mismatched %02X/%02X/%02X', reply_value, self.true_value, self.false_value, self.mask) return False @@ -606,7 +606,7 @@ class BooleanValidator(object): if reply_value == false_value: return False - _log.warn("BooleanValidator: reply %r mismatched %r/%r/%r", + _log.warn('BooleanValidator: reply %r mismatched %r/%r/%r', reply_bytes, self.true_value, self.false_value, self.mask) return False @@ -642,7 +642,7 @@ class BooleanValidator(object): return None if _log.isEnabledFor(_DEBUG): - _log.debug("BooleanValidator: prepare_write(%s, %s) => %r", + _log.debug('BooleanValidator: prepare_write(%s, %s) => %r', new_value, current_value, to_write) return to_write @@ -706,7 +706,7 @@ class ChoicesValidator(object): def validate_read(self, reply_bytes): reply_value = _bytes2int(reply_bytes[:self._bytes_count]) valid_value = self.choices[reply_value] - assert valid_value is not None, "%s: failed to validate read value %02X" % ( + assert valid_value is not None, '%s: failed to validate read value %02X' % ( self.__class__.__name__, reply_value) return valid_value @@ -724,7 +724,7 @@ class ChoicesValidator(object): raise ValueError(new_value) if choice is None: - raise ValueError("invalid choice %r" % new_value) + raise ValueError('invalid choice %r' % new_value) assert isinstance(choice, _NamedInt) return choice.bytes(self._bytes_count) @@ -772,14 +772,14 @@ class ChoicesMapValidator(ChoicesValidator): if self.extra_default is not None and self.extra_default == reply_value: return int(self.choices[key][0]) assert reply_value in self.choices[ - key], "%s: failed to validate read value %02X" % ( + key], '%s: failed to validate read value %02X' % ( self.__class__.__name__, reply_value) return reply_value def prepare_write(self, key, new_value): choices = self.choices[key] if new_value not in choices and new_value != self.extra_default: - raise ValueError("invalid choice %r" % new_value) + raise ValueError('invalid choice %r' % new_value) return _int2bytes(new_value, self._skip_bytes_count + self._value_bytes_count) @@ -808,13 +808,13 @@ class RangeValidator(object): def validate_read(self, reply_bytes): reply_value = _bytes2int(reply_bytes[:self._bytes_count]) - assert reply_value >= self.min_value, "%s: failed to validate read value %02X" % ( + assert reply_value >= self.min_value, '%s: failed to validate read value %02X' % ( self.__class__.__name__, reply_value) - assert reply_value <= self.max_value, "%s: failed to validate read value %02X" % ( + assert reply_value <= self.max_value, '%s: failed to validate read value %02X' % ( self.__class__.__name__, reply_value) return reply_value def prepare_write(self, new_value, current_value=None): if new_value < self.min_value or new_value > self.max_value: - raise ValueError("invalid choice %r" % new_value) + raise ValueError('invalid choice %r' % new_value) return _int2bytes(new_value, self._bytes_count) diff --git a/lib/logitech_receiver/settings_templates.py b/lib/logitech_receiver/settings_templates.py index 9c00cc78..216c5a6e 100644 --- a/lib/logitech_receiver/settings_templates.py +++ b/lib/logitech_receiver/settings_templates.py @@ -314,48 +314,48 @@ def feature_range(name, # _HAND_DETECTION = ( - 'hand-detection', _("Hand Detection"), - _("Turn on illumination when the hands hover over the keyboard.")) + 'hand-detection', _('Hand Detection'), + _('Turn on illumination when the hands hover over the keyboard.')) _SMOOTH_SCROLL = ( - 'smooth-scroll', _("Smooth Scrolling"), - _("High-sensitivity mode for vertical scroll with the wheel.")) + 'smooth-scroll', _('Smooth Scrolling'), + _('High-sensitivity mode for vertical scroll with the wheel.')) _SIDE_SCROLL = ( - 'side-scroll', _("Side Scrolling"), - _("When disabled, pushing the wheel sideways sends custom button events\n" - "instead of the standard side-scrolling events.")) + 'side-scroll', _('Side Scrolling'), + _('When disabled, pushing the wheel sideways sends custom button events\n' + 'instead of the standard side-scrolling events.')) _HI_RES_SCROLL = ( - 'hi-res-scroll', _("High Resolution Scrolling"), - _("High-sensitivity mode for vertical scroll with the wheel.")) -_LOW_RES_SCROLL = ('lowres-smooth-scroll', _("HID++ Scrolling"), - _("HID++ mode for vertical scroll with the wheel.") + '\n' + - _("Effectively turns off wheel scrolling in Linux.")) -_HIRES_INV = ('hires-smooth-invert', _("High Resolution Wheel Invert"), - _("High-sensitivity wheel invert mode for vertical scroll.")) -_HIRES_RES = ('hires-smooth-resolution', _("Wheel Resolution"), - _("High-sensitivity mode for vertical scroll with the wheel.")) + 'hi-res-scroll', _('High Resolution Scrolling'), + _('High-sensitivity mode for vertical scroll with the wheel.')) +_LOW_RES_SCROLL = ('lowres-smooth-scroll', _('HID++ Scrolling'), + _('HID++ mode for vertical scroll with the wheel.') + '\n' + + _('Effectively turns off wheel scrolling in Linux.')) +_HIRES_INV = ('hires-smooth-invert', _('High Resolution Wheel Invert'), + _('High-sensitivity wheel invert mode for vertical scroll.')) +_HIRES_RES = ('hires-smooth-resolution', _('Wheel Resolution'), + _('High-sensitivity mode for vertical scroll with the wheel.')) _FN_SWAP = ( - 'fn-swap', _("Swap Fx function"), - _("When set, the F1..F12 keys will activate their special function,\n" - "and you must hold the FN key to activate their standard function.") + + 'fn-swap', _('Swap Fx function'), + _('When set, the F1..F12 keys will activate their special function,\n' + 'and you must hold the FN key to activate their standard function.') + '\n\n' + - _("When unset, the F1..F12 keys will activate their standard function,\n" - "and you must hold the FN key to activate their special function.")) -_DPI = ('dpi', _("Sensitivity (DPI)"), None) -_POINTER_SPEED = ('pointer_speed', _("Sensitivity (Pointer Speed)"), - _("Speed multiplier for mouse (256 is normal multiplier).")) + _('When unset, the F1..F12 keys will activate their standard function,\n' + 'and you must hold the FN key to activate their special function.')) +_DPI = ('dpi', _('Sensitivity (DPI)'), None) +_POINTER_SPEED = ('pointer_speed', _('Sensitivity (Pointer Speed)'), + _('Speed multiplier for mouse (256 is normal multiplier).')) _SMART_SHIFT = ( - 'smart-shift', _("Smart Shift"), - _("Automatically switch the mouse wheel between ratchet and freespin mode.\n" - "The mouse wheel is always free at 0, and always locked at 50")) -_BACKLIGHT = ('backlight', _("Backlight"), - _("Turn illumination on or off on keyboard.")) + 'smart-shift', _('Smart Shift'), + _('Automatically switch the mouse wheel between ratchet and freespin mode.\n' + 'The mouse wheel is always free at 0, and always locked at 50')) +_BACKLIGHT = ('backlight', _('Backlight'), + _('Turn illumination on or off on keyboard.')) _REPROGRAMMABLE_KEYS = ('reprogrammable-keys', _( - "Actions" -), _("Change the action for the key or button.") + "\n" + _( - "Changing important actions (such as for the left mouse button) can result in an unusable system." + 'Actions' +), _('Change the action for the key or button.') + '\n' + _( + 'Changing important actions (such as for the left mouse button) can result in an unusable system.' )) -_DISABLE_KEYS = ('disable-keyboard-keys', _("Disable keys"), - _("Disable specific keyboard keys.")) +_DISABLE_KEYS = ('disable-keyboard-keys', _('Disable keys'), + _('Disable specific keyboard keys.')) # # @@ -741,12 +741,12 @@ def check_feature_settings(device, already_known): try: detected = featureFn()(device) if _log.isEnabledFor(_DEBUG): - _log.debug("check_feature[%s] detected %s", featureId, + _log.debug('check_feature[%s] detected %s', featureId, detected) if detected: already_known.append(detected) except Exception as reason: - _log.error("check_feature[%s] inconsistent feature %s", featureId, + _log.error('check_feature[%s] inconsistent feature %s', featureId, reason) for name, featureId, featureFn, _, _ in _SETTINGS_TABLE: diff --git a/lib/logitech_receiver/special_keys.py b/lib/logitech_receiver/special_keys.py index 95140342..bbb3688e 100644 --- a/lib/logitech_receiver/special_keys.py +++ b/lib/logitech_receiver/special_keys.py @@ -271,7 +271,7 @@ CONTROL = _NamedInts( MultiPlatform_App_Switch_2=0x0100, # MultiPlatform_App_Switch Fn_Inversion__Hot_Key=0x0101, LeftAndRightClick=0x0102, - LED_TOGGLE=0x013B, # + LED_TOGGLE=0x013B, # ) CONTROL._fallback = lambda x: 'unknown:%04X' % x @@ -486,7 +486,7 @@ TASK = _NamedInts( App_Switch=0x00D5, Fn_Inversion=0x00D6, LeftAndRightClick=0x00D7, - LedToggle=0x00DD, # + LedToggle=0x00DD, # ) TASK._fallback = lambda x: 'unknown:%04X' % x # hidpp 4.5 info from https://lekensteyn.nl/files/logitech/x1b04_specialkeysmsebuttons.html diff --git a/lib/logitech_receiver/status.py b/lib/logitech_receiver/status.py index 17f46248..144aec44 100644 --- a/lib/logitech_receiver/status.py +++ b/lib/logitech_receiver/status.py @@ -106,8 +106,8 @@ class ReceiverStatus(dict): def __str__(self): count = len(self._receiver) - return (_("No paired devices.") if count == 0 else ngettext( - "%(count)s paired device.", "%(count)s paired devices.", count) % { + return (_('No paired devices.') if count == 0 else ngettext( + '%(count)s paired device.', '%(count)s paired devices.', count) % { 'count': count }) @@ -161,11 +161,11 @@ class DeviceStatus(dict): battery_level = self.get(KEYS.BATTERY_LEVEL) if battery_level is not None: if isinstance(battery_level, _NamedInt): - yield _("Battery: %(level)s") % { + yield _('Battery: %(level)s') % { 'level': _(str(battery_level)) } else: - yield _("Battery: %(percent)d%%") % { + yield _('Battery: %(percent)d%%') % { 'percent': battery_level } @@ -178,7 +178,7 @@ class DeviceStatus(dict): light_level = self.get(KEYS.LIGHT_LEVEL) if light_level is not None: if comma: yield ', ' - yield _("Lighting: %(level)s lux") % {'level': light_level} + yield _('Lighting: %(level)s lux') % {'level': light_level} return ''.join(i for i in _items()) @@ -198,7 +198,7 @@ class DeviceStatus(dict): voltage=None, timestamp=None): if _log.isEnabledFor(_DEBUG): - _log.debug("%s: battery %s, %s", self._device, level, status) + _log.debug('%s: battery %s, %s', self._device, level, status) if level is None: # Some notifications may come with no battery level info, just @@ -239,19 +239,19 @@ class DeviceStatus(dict): level > _BATTERY_ATTENTION_LEVEL): self[KEYS.ERROR] = None else: - _log.warn("%s: battery %d%%, ALERT %s", self._device, level, + _log.warn('%s: battery %d%%, ALERT %s', self._device, level, status) if self.get(KEYS.ERROR) != status: self[KEYS.ERROR] = status # only show the notification once alert = ALERT.NOTIFICATION | ALERT.ATTENTION if isinstance(level, _NamedInt): - reason = _("Battery: %(level)s (%(status)s)") % { + reason = _('Battery: %(level)s (%(status)s)') % { 'level': _(level), 'status': _(status) } else: - reason = _("Battery: %(percent)d%% (%(status)s)") % { + reason = _('Battery: %(percent)d%% (%(status)s)') % { 'percent': level, 'status': status.name } @@ -336,7 +336,7 @@ class DeviceStatus(dict): # Devices lose configuration when they are turned off, # make sure they're up-to-date. if _log.isEnabledFor(_DEBUG): - _log.debug("%s pushing device settings %s", d, + _log.debug('%s pushing device settings %s', d, d.settings) for s in d.settings: s.apply() diff --git a/lib/solaar/cli/__init__.py b/lib/solaar/cli/__init__.py index 3698e25b..d5008a90 100644 --- a/lib/solaar/cli/__init__.py +++ b/lib/solaar/cli/__init__.py @@ -113,12 +113,12 @@ def _receivers(dev_path=None): try: r = Receiver.open(dev_info) if _log.isEnabledFor(_DEBUG): - _log.debug("[%s] => %s", dev_info.path, r) + _log.debug('[%s] => %s', dev_info.path, r) if r: yield r except Exception as e: _log.exception('opening ' + str(dev_info)) - _sys.exit("%s: error: %s" % (NAME, str(e))) + _sys.exit('%s: error: %s' % (NAME, str(e))) def _find_receiver(receivers, name): diff --git a/lib/solaar/cli/config.py b/lib/solaar/cli/config.py index 688dca38..0904cff5 100644 --- a/lib/solaar/cli/config.py +++ b/lib/solaar/cli/config.py @@ -127,7 +127,7 @@ def run(receivers, args, find_receiver, find_device): raise Exception("can't interpret '%s' as integer" % args.value) else: - raise Exception("NotImplemented") + raise Exception('NotImplemented') result = setting.write(value) if result is None: diff --git a/lib/solaar/cli/pair.py b/lib/solaar/cli/pair.py index 3224a398..69ca7285 100644 --- a/lib/solaar/cli/pair.py +++ b/lib/solaar/cli/pair.py @@ -96,6 +96,6 @@ def run(receivers, args, find_receiver, _ignore): else: error = receiver.status.get(_status.KEYS.ERROR) if error: - raise Exception("pairing failed: %s" % error) + raise Exception('pairing failed: %s' % error) else: print('Paired a device') # this is better than an error diff --git a/lib/solaar/cli/probe.py b/lib/solaar/cli/probe.py index ce3531f3..d5995670 100644 --- a/lib/solaar/cli/probe.py +++ b/lib/solaar/cli/probe.py @@ -48,32 +48,32 @@ def run(receivers, args, find_receiver, _ignore): print(' Register Dump') register = receiver.read_register(_R.notifications) - print(" Notification Register %#04x: %s" % + print(' Notification Register %#04x: %s' % (_R.notifications % 0x100, - '0x' + _strhex(register) if register else "None")) + '0x' + _strhex(register) if register else 'None')) register = receiver.read_register(_R.receiver_connection) - print(" Connection State %#04x: %s" % + print(' Connection State %#04x: %s' % (_R.receiver_connection % 0x100, - '0x' + _strhex(register) if register else "None")) + '0x' + _strhex(register) if register else 'None')) register = receiver.read_register(_R.devices_activity) - print(" Device Activity %#04x: %s" % + print(' Device Activity %#04x: %s' % (_R.devices_activity % 0x100, - '0x' + _strhex(register) if register else "None")) + '0x' + _strhex(register) if register else 'None')) for device in range(0, 6): for sub_reg in [0x0, 0x10, 0x20, 0x30]: register = receiver.read_register(_R.receiver_info, sub_reg + device) - print(" Pairing Register %#04x %#04x: %s" % + print(' Pairing Register %#04x %#04x: %s' % (_R.receiver_info % 0x100, sub_reg + device, - '0x' + _strhex(register) if register else "None")) + '0x' + _strhex(register) if register else 'None')) register = receiver.read_register(_R.receiver_info, 0x40 + device) - print(" Pairing Name %#04x %#02x: %s" % + print(' Pairing Name %#04x %#02x: %s' % (_R.receiver_info % 0x100, 0x40 + device, - register[2:2 + ord(register[1:2])] if register else "None")) + register[2:2 + ord(register[1:2])] if register else 'None')) for sub_reg in range(0, 5): register = receiver.read_register(_R.firmware, sub_reg) - print(" Firmware %#04x %#04x: %s" % + print(' Firmware %#04x %#04x: %s' % (_R.firmware % 0x100, sub_reg, - '0x' + _strhex(register) if register else "None")) + '0x' + _strhex(register) if register else 'None')) diff --git a/lib/solaar/cli/show.py b/lib/solaar/cli/show.py index 08e75584..2151d58b 100644 --- a/lib/solaar/cli/show.py +++ b/lib/solaar/cli/show.py @@ -124,79 +124,79 @@ def _print_device(dev): wheel = _hidpp20.get_hires_wheel(dev) if wheel: multi, has_invert, has_switch, inv, res, target, ratchet = wheel - print(" Multiplier: %s" % multi) + print(' Multiplier: %s' % multi) if has_invert: - print(" Has invert") + print(' Has invert') if inv: - print(" Inverse wheel motion") + print(' Inverse wheel motion') else: - print(" Normal wheel motion") + print(' Normal wheel motion') if has_switch: - print(" Has ratchet switch") + print(' Has ratchet switch') if ratchet: - print(" Normal wheel mode") + print(' Normal wheel mode') else: - print(" Free wheel mode") + print(' Free wheel mode') if res: - print(" High resolution mode") + print(' High resolution mode') else: - print(" Low resolution mode") + print(' Low resolution mode') if target: - print(" HID++ notification") + print(' HID++ notification') else: - print(" HID notification") + print(' HID notification') elif feature == _hidpp20.FEATURE.MOUSE_POINTER: mouse_pointer = _hidpp20.get_mouse_pointer_info(dev) if mouse_pointer: - print(" DPI: %s" % mouse_pointer['dpi']) - print(" Acceleration: %s" % + print(' DPI: %s' % mouse_pointer['dpi']) + print(' Acceleration: %s' % mouse_pointer['acceleration']) if mouse_pointer['suggest_os_ballistics']: - print(" Use OS ballistics") + print(' Use OS ballistics') else: - print(" Override OS ballistics") + print(' Override OS ballistics') if mouse_pointer['suggest_vertical_orientation']: - print(" Provide vertical tuning, trackball") + print(' Provide vertical tuning, trackball') else: - print(" No vertical tuning, standard mice") + print(' No vertical tuning, standard mice') if feature == _hidpp20.FEATURE.VERTICAL_SCROLLING: vertical_scrolling_info = _hidpp20.get_vertical_scrolling_info( dev) if vertical_scrolling_info: - print(" Roller type: %s" % + print(' Roller type: %s' % vertical_scrolling_info['roller']) - print(" Ratchet per turn: %s" % + print(' Ratchet per turn: %s' % vertical_scrolling_info['ratchet']) - print(" Scroll lines: %s" % + print(' Scroll lines: %s' % vertical_scrolling_info['lines']) elif feature == _hidpp20.FEATURE.HI_RES_SCROLLING: scrolling_mode, scrolling_resolution = _hidpp20.get_hi_res_scrolling_info( dev) if scrolling_mode: - print(" Hi-res scrolling enabled") + print(' Hi-res scrolling enabled') else: - print(" Hi-res scrolling disabled") + print(' Hi-res scrolling disabled') if scrolling_resolution: - print(" Hi-res scrolling multiplier: %s" % + print(' Hi-res scrolling multiplier: %s' % scrolling_resolution) elif feature == _hidpp20.FEATURE.POINTER_SPEED: pointer_speed = _hidpp20.get_pointer_speed_info(dev) if pointer_speed: - print(" Pointer Speed: %s" % pointer_speed) + print(' Pointer Speed: %s' % pointer_speed) elif feature == _hidpp20.FEATURE.LOWRES_WHEEL: wheel_status = _hidpp20.get_lowres_wheel_status(dev) if wheel_status: - print(" Wheel Reports: %s" % wheel_status) + print(' Wheel Reports: %s' % wheel_status) elif feature == _hidpp20.FEATURE.NEW_FN_INVERSION: inverted, default_inverted = _hidpp20.get_new_fn_inversion(dev) - print(" Fn-swap:", - "enabled" if inverted else "disabled") - print(" Fn-swap default:", - "enabled" if default_inverted else "disabled") + print(' Fn-swap:', + 'enabled' if inverted else 'disabled') + print(' Fn-swap default:', + 'enabled' if default_inverted else 'disabled') for setting in dev_settings: if setting.feature == feature: v = setting.read(False) - print(" %s: %s" % (setting.label, v)) + print(' %s: %s' % (setting.label, v)) if dev.online and dev.keys: print(' Has %d reprogrammable keys:' % len(dev.keys)) diff --git a/lib/solaar/configuration.py b/lib/solaar/configuration.py index 2a59ca7c..e35431a4 100644 --- a/lib/solaar/configuration.py +++ b/lib/solaar/configuration.py @@ -47,14 +47,14 @@ def _load(): with open(_file_path, 'r') as config_file: loaded_configuration = _json_load(config_file) except: - _log.error("failed to load from %s", _file_path) + _log.error('failed to load from %s', _file_path) # loaded_configuration.update(_configuration) _configuration.clear() _configuration.update(loaded_configuration) if _log.isEnabledFor(_DEBUG): - _log.debug("load => %s", _configuration) + _log.debug('load => %s', _configuration) _cleanup(_configuration) _configuration[_KEY_VERSION] = __version__ @@ -71,7 +71,7 @@ def save(): try: _os.makedirs(dirname) except: - _log.error("failed to create %s", dirname) + _log.error('failed to create %s', dirname) return False _cleanup(_configuration) @@ -85,10 +85,10 @@ def save(): sort_keys=True) if _log.isEnabledFor(_INFO): - _log.info("saved %s to %s", _configuration, _file_path) + _log.info('saved %s to %s', _configuration, _file_path) return True except: - _log.error("failed to save to %s", _file_path) + _log.error('failed to save to %s', _file_path) def _cleanup(d): diff --git a/lib/solaar/gtk.py b/lib/solaar/gtk.py index 7b0d95ff..cd7990bb 100755 --- a/lib/solaar/gtk.py +++ b/lib/solaar/gtk.py @@ -39,7 +39,7 @@ def _require(module, os_package, gi=None, gi_package=None, gi_version=None): return importlib.import_module(module) except (ImportError, ValueError): import sys - sys.exit("%s: missing required system package %s" % (NAME, os_package)) + sys.exit('%s: missing required system package %s' % (NAME, os_package)) prefer_symbolic_battery_icons = False @@ -115,7 +115,7 @@ def _parse_arguments(): if not args.action: if logging.root.isEnabledFor(logging.INFO): - logging.info("language %s (%s), translations path %s", + logging.info('language %s (%s), translations path %s', _i18n.language, _i18n.encoding, _i18n.path) return args diff --git a/lib/solaar/listener.py b/lib/solaar/listener.py index 61df92ec..da151a51 100644 --- a/lib/solaar/listener.py +++ b/lib/solaar/listener.py @@ -84,7 +84,7 @@ class ReceiverListener(_listener.EventsListener): def has_started(self): if _log.isEnabledFor(_INFO): - _log.info("%s: notifications listener has started (%s)", + _log.info('%s: notifications listener has started (%s)', self.receiver, self.receiver.handle) notification_flags = self.receiver.enable_notifications() self.receiver.status[ @@ -96,18 +96,18 @@ class ReceiverListener(_listener.EventsListener): r, self.receiver = self.receiver, None assert r is not None if _log.isEnabledFor(_INFO): - _log.info("%s: notifications listener has stopped", r) + _log.info('%s: notifications listener has stopped', r) # because udev is not notifying us about device removal, # make sure to clean up in _all_listeners _all_listeners.pop(r.path, None) - r.status = _("The receiver was unplugged.") + r.status = _('The receiver was unplugged.') if r: try: r.close() except: - _log.exception("closing receiver %s" % r.path) + _log.exception('closing receiver %s' % r.path) self.status_changed_callback(r) #, _status.ALERT.NOTIFICATION) # def tick(self, timestamp): @@ -151,11 +151,11 @@ class ReceiverListener(_listener.EventsListener): assert device is not None if _log.isEnabledFor(_INFO): if device.kind is None: - _log.info("status_changed %s: %s, %s (%X) %s", device, + _log.info('status_changed %s: %s, %s (%X) %s', device, 'present' if bool(device) else 'removed', device.status, alert, reason or '') else: - _log.info("status_changed %s: %s %s, %s (%X) %s", device, + _log.info('status_changed %s: %s %s, %s (%X) %s', device, 'paired' if bool(device) else 'unpaired', 'online' if device.online else 'offline', device.status, alert, reason or '') @@ -171,7 +171,7 @@ class ReceiverListener(_listener.EventsListener): # Device was unpaired, and isn't valid anymore. # We replace it with a ghost so that the UI has something to work # with while cleaning up. - _log.warn("device %s was unpaired, ghosting", device) + _log.warn('device %s was unpaired, ghosting', device) device = _ghost(device) self.status_changed_callback(device, alert, reason) @@ -194,7 +194,7 @@ class ReceiverListener(_listener.EventsListener): if not (0 < n.devnumber <= self.receiver.max_devices): if _log.isEnabledFor(_WARNING): _log.warning( - _("Unexpected device number (%s) in notification %s." % + _('Unexpected device number (%s) in notification %s.' % (n.devnumber, n))) return already_known = n.devnumber in self.receiver @@ -231,14 +231,14 @@ class ReceiverListener(_listener.EventsListener): dev = self.receiver[n.devnumber] if not dev: - _log.warn("%s: received %s for invalid device %d: %r", + _log.warn('%s: received %s for invalid device %d: %r', self.receiver, n, n.devnumber, dev) return # Apply settings every time the device connects if n.sub_id == 0x41: if _log.isEnabledFor(_INFO): - _log.info("%s triggered new device %s (%s)", n, dev, dev.kind) + _log.info('%s triggered new device %s (%s)', n, dev, dev.kind) # If there are saved configs, bring the device's settings up-to-date. # They will be applied when the device is marked as online. configuration.attach_to(dev) @@ -253,7 +253,7 @@ class ReceiverListener(_listener.EventsListener): # this should be the first notification after a device was paired assert n.sub_id == 0x41 and n.address == 0x04 if _log.isEnabledFor(_INFO): - _log.info("%s: pairing detected new device", self.receiver) + _log.info('%s: pairing detected new device', self.receiver) self.receiver.status.new_device = dev elif dev.online is None: dev.ping() @@ -283,7 +283,7 @@ def _start(device_info): _all_listeners[device_info.path] = rl return rl - _log.warn("failed to open %s", device_info) + _log.warn('failed to open %s', device_info) def start_all(): @@ -291,7 +291,7 @@ def start_all(): stop_all() if _log.isEnabledFor(_INFO): - _log.info("starting receiver listening threads") + _log.info('starting receiver listening threads') for device_info in _base.receivers(): _process_receiver_event('add', device_info) @@ -302,7 +302,7 @@ def stop_all(): if listeners: if _log.isEnabledFor(_INFO): - _log.info("stopping receiver listening threads %s", listeners) + _log.info('stopping receiver listening threads %s', listeners) for l in listeners: l.stop() @@ -352,7 +352,7 @@ def _process_receiver_event(action, device_info): assert _error_callback if _log.isEnabledFor(_INFO): - _log.info("receiver event %s %s", action, device_info) + _log.info('receiver event %s %s', action, device_info) # whatever the action, stop any previous receivers at this path l = _all_listeners.pop(device_info.path, None) diff --git a/lib/solaar/tasks.py b/lib/solaar/tasks.py index dd11e322..a01a3842 100644 --- a/lib/solaar/tasks.py +++ b/lib/solaar/tasks.py @@ -56,7 +56,7 @@ class TaskRunner(_Thread): self.alive = True if _log.isEnabledFor(_DEBUG): - _log.debug("started") + _log.debug('started') while self.alive: task = self.queue.get() @@ -66,7 +66,7 @@ class TaskRunner(_Thread): try: function(*args, **kwargs) except: - _log.exception("calling %s", function) + _log.exception('calling %s', function) if _log.isEnabledFor(_DEBUG): - _log.debug("stopped") + _log.debug('stopped') diff --git a/lib/solaar/ui/__init__.py b/lib/solaar/ui/__init__.py index b1b5a872..11594afd 100644 --- a/lib/solaar/ui/__init__.py +++ b/lib/solaar/ui/__init__.py @@ -43,18 +43,18 @@ GLib.threads_init() def _error_dialog(reason, object): - _log.error("error: %s %s", reason, object) + _log.error('error: %s %s', reason, object) if reason == 'permissions': - title = _("Permissions error") - text = _("Found a Logitech Receiver (%s), but did not have permission to open it.") % object + \ + title = _('Permissions error') + text = _('Found a Logitech Receiver (%s), but did not have permission to open it.') % object + \ '\n\n' + \ _("If you've just installed Solaar, try removing the receiver and plugging it back in.") elif reason == 'unpair': - title = _("Unpairing failed") - text = _("Failed to unpair %{device} from %{receiver}.").format(device=object.name, receiver=object.receiver.name) + \ + title = _('Unpairing failed') + text = _('Failed to unpair %{device} from %{receiver}.').format(device=object.name, receiver=object.receiver.name) + \ '\n\n' + \ - _("The receiver returned an error, with no further details.") + _('The receiver returned an error, with no further details.') else: raise Exception("ui.error_dialog: don't know how to handle (%s, %s)", reason, object) @@ -95,7 +95,7 @@ from . import notify, tray, window # isort:skip # noqa: E402 def _startup(app, startup_hook, use_tray, show_window): if _log.isEnabledFor(_DEBUG): - _log.debug("startup registered=%s, remote=%s", app.get_is_registered(), + _log.debug('startup registered=%s, remote=%s', app.get_is_registered(), app.get_is_remote()) from solaar.tasks import TaskRunner as _TaskRunner @@ -113,7 +113,7 @@ def _startup(app, startup_hook, use_tray, show_window): def _activate(app): if _log.isEnabledFor(_DEBUG): - _log.debug("activate") + _log.debug('activate') if app.get_windows(): window.popup() else: @@ -122,14 +122,14 @@ def _activate(app): def _command_line(app, command_line): if _log.isEnabledFor(_DEBUG): - _log.debug("command_line %s", command_line.get_arguments()) + _log.debug('command_line %s', command_line.get_arguments()) return 0 def _shutdown(app, shutdown_hook): if _log.isEnabledFor(_DEBUG): - _log.debug("shutdown") + _log.debug('shutdown') shutdown_hook() @@ -167,7 +167,7 @@ def run_loop(startup_hook, shutdown_hook, use_tray, show_window, args=None): def _status_changed(device, alert, reason): assert device is not None if _log.isEnabledFor(_DEBUG): - _log.debug("status changed: %s (%s) %s", device, alert, reason) + _log.debug('status changed: %s (%s) %s', device, alert, reason) tray.update(device) if alert & ALERT.ATTENTION: diff --git a/lib/solaar/ui/about.py b/lib/solaar/ui/about.py index 8c572755..b38d3f21 100644 --- a/lib/solaar/ui/about.py +++ b/lib/solaar/ui/about.py @@ -36,7 +36,7 @@ def _create(): about.set_program_name(NAME) about.set_version(__version__) about.set_comments( - _("Shows status of devices connected\nthrough wireless Logitech receivers." + _('Shows status of devices connected\nthrough wireless Logitech receivers.' )) about.set_logo_icon_name(NAME.lower()) @@ -46,25 +46,25 @@ def _create(): about.set_authors(('Daniel Pavel http://github.com/pwr', )) try: - about.add_credit_section(_("GUI design"), + about.add_credit_section(_('GUI design'), ('Julien Gascard', 'Daniel Pavel')) - about.add_credit_section(_("Testing"), ( + about.add_credit_section(_('Testing'), ( 'Douglas Wagner', 'Julien Gascard', 'Peter Wu http://www.lekensteyn.nl/logitech-unifying.html', )) - about.add_credit_section(_("Logitech documentation"), ( + about.add_credit_section(_('Logitech documentation'), ( 'Julien Danjou http://julien.danjou.info/blog/2012/logitech-unifying-upower', 'Nestor Lopez Casado http://drive.google.com/folderview?id=0BxbRzx7vEV7eWmgwazJ3NUFfQ28', )) except TypeError: # gtk3 < ~3.6.4 has incorrect gi bindings import logging - logging.exception("failed to fully create the about dialog") + logging.exception('failed to fully create the about dialog') except: # the Gtk3 version may be too old, and the function does not exist import logging - logging.exception("failed to fully create the about dialog") + logging.exception('failed to fully create the about dialog') about.set_translator_credits('\n'.join(( 'gogo (croatian)', diff --git a/lib/solaar/ui/action.py b/lib/solaar/ui/action.py index b3a3c059..ad22e9aa 100644 --- a/lib/solaar/ui/action.py +++ b/lib/solaar/ui/action.py @@ -68,7 +68,7 @@ def make_toggle(name, label, function, stock_id=None, *args): # toggle_notifications = make_toggle('notifications', 'Notifications', _toggle_notifications) about = make('help-about', - _("About") + ' ' + NAME, + _('About') + ' ' + NAME, _show_about_window, stock_id=Gtk.STOCK_ABOUT) @@ -96,10 +96,10 @@ def unpair(window, device): qdialog = Gtk.MessageDialog(window, 0, Gtk.MessageType.QUESTION, Gtk.ButtonsType.NONE, - _("Unpair") + ' ' + device.name + ' ?') + _('Unpair') + ' ' + device.name + ' ?') qdialog.set_icon_name('remove') qdialog.add_button(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL) - qdialog.add_button(_("Unpair"), Gtk.ResponseType.ACCEPT) + qdialog.add_button(_('Unpair'), Gtk.ResponseType.ACCEPT) choice = qdialog.run() qdialog.destroy() if choice == Gtk.ResponseType.ACCEPT: diff --git a/lib/solaar/ui/config_panel.py b/lib/solaar/ui/config_panel.py index 39afbefe..ff65efcf 100644 --- a/lib/solaar/ui/config_panel.py +++ b/lib/solaar/ui/config_panel.py @@ -184,11 +184,11 @@ def _create_sbox(s): sbox.pack_start(Gtk.Label(s.label), False, False, 0) spinner = Gtk.Spinner() - spinner.set_tooltip_text(_("Working") + '...') + spinner.set_tooltip_text(_('Working') + '...') failed = Gtk.Image.new_from_icon_name('dialog-warning', Gtk.IconSize.SMALL_TOOLBAR) - failed.set_tooltip_text(_("Read/write operation failed.")) + failed.set_tooltip_text(_('Read/write operation failed.')) if s.kind == _SETTING_KIND.toggle: control = _create_toggle_control(s) @@ -220,7 +220,7 @@ def _create_sbox(s): control = _create_map_choice_control(X(s, {'choices': choices})) sbox.pack_end(control, True, True, 0) else: - raise Exception("NotImplemented") + raise Exception('NotImplemented') control.set_sensitive(False) # the first read will enable it sbox.pack_end(spinner, False, False, 0) @@ -259,7 +259,7 @@ def _update_setting_item(sbox, value, is_online=True): if value.get(kbox.get_active_id()): vbox.set_active_id(str(value.get(kbox.get_active_id()))) else: - raise Exception("NotImplemented") + raise Exception('NotImplemented') control.set_sensitive(True) diff --git a/lib/solaar/ui/icons.py b/lib/solaar/ui/icons.py index 767be4c5..2a3ca305 100644 --- a/lib/solaar/ui/icons.py +++ b/lib/solaar/ui/icons.py @@ -54,7 +54,7 @@ def _look_for_application_icons(): import sys as _sys if _log.isEnabledFor(_DEBUG): - _log.debug("sys.path[0] = %s", _sys.path[0]) + _log.debug('sys.path[0] = %s', _sys.path[0]) prefix_share = _path.normpath( _path.join(_path.realpath(_sys.path[0]), '..')) src_share = _path.normpath( @@ -75,7 +75,7 @@ def _look_for_application_icons(): for location in share_solaar: location = _path.join(location, 'icons') if _log.isEnabledFor(_DEBUG): - _log.debug("looking for icons in %s", location) + _log.debug('looking for icons in %s', location) if _path.exists(_path.join(location, TRAY_ATTENTION + '.svg')): yield location @@ -97,7 +97,7 @@ def _init_icon_paths(): for p in _look_for_application_icons(): _default_theme.prepend_search_path(p) if _log.isEnabledFor(_DEBUG): - _log.debug("icon theme paths: %s", _default_theme.get_search_path()) + _log.debug('icon theme paths: %s', _default_theme.get_search_path()) if gtk.prefer_symbolic_battery_icons: if _default_theme.has_icon('battery-good-symbolic'): @@ -105,9 +105,9 @@ def _init_icon_paths(): _use_symbolic_icons = True return else: - _log.warning("failed to detect symbolic icons") + _log.warning('failed to detect symbolic icons') if not _default_theme.has_icon('battery-good'): - _log.warning("failed to detect icons") + _log.warning('failed to detect icons') # @@ -118,10 +118,10 @@ def _init_icon_paths(): def battery(level=None, charging=False): icon_name = _battery_icon_name(level, charging) if not _default_theme.has_icon(icon_name): - _log.warning("icon %s not found in current theme", icon_name) + _log.warning('icon %s not found in current theme', icon_name) return TRAY_OKAY # use Solaar icon if battery icon not available elif _log.isEnabledFor(_DEBUG): - _log.debug("battery icon for %s:%s = %s", level, charging, icon_name) + _log.debug('battery icon for %s:%s = %s', level, charging, icon_name) return icon_name @@ -222,4 +222,4 @@ def icon_file(name, size=_LARGE_SIZE): # _log.debug("icon %s(%d) => %s", name, size, file_name) return file_name - _log.warn("icon %s(%d) not found in current theme", name, size) + _log.warn('icon %s(%d) not found in current theme', name, size) diff --git a/lib/solaar/ui/notify.py b/lib/solaar/ui/notify.py index 14c411cd..53f812ef 100644 --- a/lib/solaar/ui/notify.py +++ b/lib/solaar/ui/notify.py @@ -57,18 +57,18 @@ if available: if available: if not Notify.is_initted(): if _log.isEnabledFor(_INFO): - _log.info("starting desktop notifications") + _log.info('starting desktop notifications') try: return Notify.init(NAME) except: - _log.exception("initializing desktop notifications") + _log.exception('initializing desktop notifications') available = False return available and Notify.is_initted() def uninit(): if available and Notify.is_initted(): if _log.isEnabledFor(_INFO): - _log.info("stopping desktop notifications") + _log.info('stopping desktop notifications') _notifications.clear() Notify.uninit() @@ -95,14 +95,14 @@ if available: n.update(NAME, reason, icon_file) n.set_urgency(Notify.Urgency.NORMAL) - n.set_hint("desktop-entry", GLib.Variant('s', NAME.lower())) + n.set_hint('desktop-entry', GLib.Variant('s', NAME.lower())) try: # if _log.isEnabledFor(_DEBUG): # _log.debug("showing %s", n) n.show() except Exception: - _log.exception("showing %s", n) + _log.exception('showing %s', n) def show(dev, reason=None, icon=None): """Show a notification with title and text.""" @@ -117,11 +117,11 @@ if available: if reason: message = reason elif dev.status is None: - message = _("unpaired") + message = _('unpaired') elif bool(dev.status): - message = dev.status.to_string() or _("connected") + message = dev.status.to_string() or _('connected') else: - message = _("offline") + message = _('offline') # we need to use the filename here because the notifications daemon # is an external application that does not know about our icon sets @@ -131,14 +131,14 @@ if available: n.update(summary, message, icon_file) urgency = Notify.Urgency.LOW if dev.status else Notify.Urgency.NORMAL n.set_urgency(urgency) - n.set_hint("desktop-entry", GLib.Variant('s', NAME.lower())) + n.set_hint('desktop-entry', GLib.Variant('s', NAME.lower())) try: # if _log.isEnabledFor(_DEBUG): # _log.debug("showing %s", n) n.show() except Exception: - _log.exception("showing %s", n) + _log.exception('showing %s', n) else: init = lambda: False diff --git a/lib/solaar/ui/pair_window.py b/lib/solaar/ui/pair_window.py index 38337797..2419f5e7 100644 --- a/lib/solaar/ui/pair_window.py +++ b/lib/solaar/ui/pair_window.py @@ -70,7 +70,7 @@ def _create_page(assistant, kind, header=None, icon_name=None, text=None): def _check_lock_state(assistant, receiver, count=2): if not assistant.is_drawable(): if _log.isEnabledFor(_DEBUG): - _log.debug("assistant %s destroyed, bailing out", assistant) + _log.debug('assistant %s destroyed, bailing out', assistant) return False if receiver.status.get(_K.ERROR): @@ -99,7 +99,7 @@ def _check_lock_state(assistant, receiver, count=2): def _prepare(assistant, page, receiver): index = assistant.get_current_page() if _log.isEnabledFor(_DEBUG): - _log.debug("prepare %s %d %s", assistant, index, page) + _log.debug('prepare %s %d %s', assistant, index, page) if index == 0: if receiver.set_lock(False, timeout=_PAIRING_TIMEOUT): @@ -119,7 +119,7 @@ def _prepare(assistant, page, receiver): def _finish(assistant, receiver): if _log.isEnabledFor(_DEBUG): - _log.debug("finish %s", assistant) + _log.debug('finish %s', assistant) assistant.destroy() receiver.status.new_device = None if receiver.status.lock_open: @@ -130,23 +130,23 @@ def _finish(assistant, receiver): def _pairing_failed(assistant, receiver, error): if _log.isEnabledFor(_DEBUG): - _log.debug("%s fail: %s", receiver, error) + _log.debug('%s fail: %s', receiver, error) assistant.commit() - header = _("Pairing failed") + ': ' + _(str(error)) + '.' + header = _('Pairing failed') + ': ' + _(str(error)) + '.' if 'timeout' in str(error): text = _( - "Make sure your device is within range, and has a decent battery charge." + 'Make sure your device is within range, and has a decent battery charge.' ) elif str(error) == 'device not supported': text = _( - "A new device was detected, but it is not compatible with this receiver." + 'A new device was detected, but it is not compatible with this receiver.' ) elif 'many' in str(error): - text = _("The receiver only supports %d paired device(s).") + text = _('The receiver only supports %d paired device(s).') else: - text = _("No further details are available about the error.") + text = _('No further details are available about the error.') _create_page(assistant, Gtk.AssistantPageType.SUMMARY, header, 'dialog-error', text) @@ -157,11 +157,11 @@ def _pairing_failed(assistant, receiver, error): def _pairing_succeeded(assistant, receiver, device): assert device if _log.isEnabledFor(_DEBUG): - _log.debug("%s success: %s", receiver, device) + _log.debug('%s success: %s', receiver, device) page = _create_page(assistant, Gtk.AssistantPageType.SUMMARY) - header = Gtk.Label(_("Found a new device:")) + header = Gtk.Label(_('Found a new device:')) header.set_alignment(0.5, 0) page.pack_start(header, False, False, 0) @@ -190,7 +190,7 @@ def _pairing_succeeded(assistant, receiver, device): Gtk.IconSize.MENU), False, False, 0) hbox.pack_start( - Gtk.Label(_("The wireless link is not encrypted") + '!'), + Gtk.Label(_('The wireless link is not encrypted') + '!'), False, False, 0) hbox.show_all() else: @@ -219,14 +219,14 @@ def create(receiver): assistant.set_role('pair-device') page_text = _( - "If the device is already turned on, turn if off and on again.") + 'If the device is already turned on, turn if off and on again.') if receiver.remaining_pairings() and receiver.remaining_pairings() >= 0: - page_text += _("\n\nThis receiver has %d pairing(s) remaining." + page_text += _('\n\nThis receiver has %d pairing(s) remaining.' ) % receiver.remaining_pairings() - page_text += _("\nCancelling at this point will not use up a pairing.") + page_text += _('\nCancelling at this point will not use up a pairing.') page_intro = _create_page(assistant, Gtk.AssistantPageType.PROGRESS, - _("Turn on the device you want to pair."), + _('Turn on the device you want to pair.'), 'preferences-desktop-peripherals', page_text) spinner = Gtk.Spinner() spinner.set_visible(True) diff --git a/lib/solaar/ui/tray.py b/lib/solaar/ui/tray.py index 59b99ad2..39c6a910 100644 --- a/lib/solaar/ui/tray.py +++ b/lib/solaar/ui/tray.py @@ -56,7 +56,7 @@ def _create_menu(quit_handler): # per-device menu entries will be generated as-needed - no_receiver = Gtk.MenuItem.new_with_label(_("No Logitech receiver found")) + no_receiver = Gtk.MenuItem.new_with_label(_('No Logitech receiver found')) no_receiver.set_sensitive(False) menu.append(no_receiver) menu.append(Gtk.SeparatorMenuItem.new()) @@ -65,7 +65,7 @@ def _create_menu(quit_handler): menu.append(about.create_menu_item()) menu.append( make('application-exit', - _("Quit"), + _('Quit'), quit_handler, stock_id=Gtk.STOCK_QUIT).create_menu_item()) del about, make @@ -149,7 +149,7 @@ def _scroll(tray_icon, event, direction=None): _picked_device = candidate or _picked_device if _log.isEnabledFor(_DEBUG): - _log.debug("scroll: picked %s", _picked_device) + _log.debug('scroll: picked %s', _picked_device) _update_tray_icon() @@ -172,7 +172,7 @@ try: from gi.repository import AppIndicator3 if _log.isEnabledFor(_DEBUG): - _log.debug("using %sAppIndicator3" % + _log.debug('using %sAppIndicator3' % ('Ayatana ' if ayatana_appindicator_found else '')) # Defense against AppIndicator3 bug that treats files in current directory as icon files @@ -238,7 +238,7 @@ try: except ImportError: if _log.isEnabledFor(_DEBUG): - _log.debug("using StatusIcon") + _log.debug('using StatusIcon') def _create(menu): icon = Gtk.StatusIcon.new_from_icon_name(_icons.TRAY_INIT) @@ -302,7 +302,7 @@ except ImportError: def _generate_tooltip_lines(): if not _devices_info: - yield '%s: ' % NAME + _("no receiver") + yield '%s: ' % NAME + _('no receiver') return yield from _generate_description_lines() @@ -310,7 +310,7 @@ def _generate_tooltip_lines(): def _generate_description_lines(): if not _devices_info: - yield _("no receiver") + yield _('no receiver') return for _ignore, number, name, status in _devices_info: @@ -323,13 +323,13 @@ def _generate_description_lines(): if status: yield '\t%s' % p else: - yield '\t%s (' % p + _("offline") + ')' + yield '\t%s (' % p + _('offline') + ')' else: if status: yield '%s (' % name + _( - "no status") + ')' + 'no status') + ')' else: - yield '%s (' % name + _("offline") + ')' + yield '%s (' % name + _('offline') + ')' yield '' @@ -350,7 +350,7 @@ def _pick_device_with_lowest_battery(): picked_level = level or 0 if _log.isEnabledFor(_DEBUG): - _log.debug("picked device with lowest battery: %s", picked) + _log.debug('picked device with lowest battery: %s', picked) return picked diff --git a/lib/solaar/ui/window.py b/lib/solaar/ui/window.py index 2081e225..dfc6989f 100644 --- a/lib/solaar/ui/window.py +++ b/lib/solaar/ui/window.py @@ -52,7 +52,7 @@ _INFO_ICON_SIZE = Gtk.IconSize.LARGE_TOOLBAR _DEVICE_ICON_SIZE = Gtk.IconSize.DND try: import gi - gi.check_version("3.7.4") + gi.check_version('3.7.4') _CAN_SET_ROW_NONE = None except (ValueError, AttributeError): _CAN_SET_ROW_NONE = '' @@ -112,7 +112,7 @@ def _create_receiver_panel(): p._count.set_alignment(0, 0.5) p.pack_start(p._count, True, True, 0) - p._scanning = Gtk.Label(_("Scanning") + '...') + p._scanning = Gtk.Label(_('Scanning') + '...') p._spinner = Gtk.Spinner() bp = Gtk.Box.new(Gtk.Orientation.HORIZONTAL, 8) @@ -145,14 +145,14 @@ def _create_device_panel(): return b - p._battery = _status_line(_("Battery")) + p._battery = _status_line(_('Battery')) p.pack_start(p._battery, False, False, 0) - p._secure = _status_line(_("Wireless Link")) + p._secure = _status_line(_('Wireless Link')) p._secure._icon.set_from_icon_name('dialog-warning', _INFO_ICON_SIZE) p.pack_start(p._secure, False, False, 0) - p._lux = _status_line(_("Lighting")) + p._lux = _status_line(_('Lighting')) p.pack_start(p._lux, False, False, 0) p._config = _config_panel.create() @@ -183,7 +183,7 @@ def _create_buttons_box(): bb._details = _new_button(None, 'dialog-information', _SMALL_BUTTON_ICON_SIZE, - tooltip=_("Show Technical Details"), + tooltip=_('Show Technical Details'), toggle=True, clicked=_update_details) bb.add(bb._details) @@ -198,7 +198,7 @@ def _create_buttons_box(): assert receiver.kind is None _action.pair(_window, receiver) - bb._pair = _new_button(_("Pair new device"), + bb._pair = _new_button(_('Pair new device'), 'list-add', clicked=_pair_new_device) bb.add(bb._pair) @@ -211,7 +211,7 @@ def _create_buttons_box(): assert device.kind is not None _action.unpair(_window, device) - bb._unpair = _new_button(_("Unpair"), + bb._unpair = _new_button(_('Unpair'), 'edit-delete', clicked=_unpair_current_device) bb.add(bb._unpair) @@ -221,7 +221,7 @@ def _create_buttons_box(): def _create_empty_panel(): p = Gtk.Label() - p.set_markup('' + _("Select a device") + '') + p.set_markup('' + _('Select a device') + '') p.set_sensitive(False) return p @@ -339,12 +339,12 @@ def _create_window_layout(): bottom_buttons_box = Gtk.ButtonBox(Gtk.Orientation.HORIZONTAL) bottom_buttons_box.set_layout(Gtk.ButtonBoxStyle.START) bottom_buttons_box.set_spacing(20) - quit_button = _new_button(_("Quit") + ' ' + NAME, + quit_button = _new_button(_('Quit') + ' ' + NAME, 'application-exit', icon_size=_SMALL_BUTTON_ICON_SIZE, clicked=destroy) bottom_buttons_box.add(quit_button) - about_button = _new_button(_("About") + ' ' + NAME, + about_button = _new_button(_('About') + ' ' + NAME, 'help-about', icon_size=_SMALL_BUTTON_ICON_SIZE, clicked=_show_about_window) @@ -444,7 +444,7 @@ def _receiver_row(receiver_path, receiver=None): status_text, status_icon, receiver) assert len(row_data) == len(_TREE_SEPATATOR) if _log.isEnabledFor(_DEBUG): - _log.debug("new receiver row %s", row_data) + _log.debug('new receiver row %s', row_data) item = _model.append(None, row_data) if _TREE_SEPATATOR: _model.append(None, _TREE_SEPATATOR) @@ -480,7 +480,7 @@ def _device_row(receiver_path, device_number, device=None): device) assert len(row_data) == len(_TREE_SEPATATOR) if _log.isEnabledFor(_DEBUG): - _log.debug("new device row %s at index %d", row_data, + _log.debug('new device row %s at index %d', row_data, new_child_index) item = _model.insert(receiver_row, new_child_index, row_data) @@ -503,7 +503,7 @@ def select(receiver_path, device_number=None): selection = _tree.get_selection() selection.select_iter(item) else: - _log.warn("select(%s, %s) failed to find an item", receiver_path, + _log.warn('select(%s, %s) failed to find an item', receiver_path, device_number) @@ -548,33 +548,33 @@ def _update_details(button): # cached, and involves no HID++ calls. if device.kind is None: - yield (_("Path"), device.path) + yield (_('Path'), device.path) # 046d is the Logitech vendor id - yield (_("USB id"), '046d:' + device.product_id) + yield (_('USB id'), '046d:' + device.product_id) if read_all: - yield (_("Serial"), device.serial) + yield (_('Serial'), device.serial) else: - yield (_("Serial"), '...') + yield (_('Serial'), '...') else: # yield ('Codename', device.codename) - yield (_("Index"), device.number) - yield (_("Wireless PID"), device.wpid) + yield (_('Index'), device.number) + yield (_('Wireless PID'), device.wpid) hid_version = device.protocol - yield (_("Protocol"), 'HID++ %1.1f' % + yield (_('Protocol'), 'HID++ %1.1f' % hid_version if hid_version else _('Unknown')) if read_all and device.polling_rate: - yield (_("Polling rate"), + yield (_('Polling rate'), _('%(rate)d ms (%(rate_hz)dHz)') % { 'rate': device.polling_rate, 'rate_hz': 1000 // device.polling_rate }) if read_all or not device.online: - yield (_("Serial"), device.serial) + yield (_('Serial'), device.serial) else: - yield (_("Serial"), '...') + yield (_('Serial'), '...') if read_all: if device.firmware: @@ -582,15 +582,15 @@ def _update_details(button): yield (' ' + _(str(fw.kind)), (fw.name + ' ' + fw.version).strip()) elif device.kind is None or device.online: - yield (' %s' % _("Firmware"), '...') + yield (' %s' % _('Firmware'), '...') flag_bits = device.status.get(_K.NOTIFICATION_FLAGS) if flag_bits is not None: flag_names = ( - '(%s)' % _("none"), + '(%s)' % _('none'), ) if flag_bits == 0 else _hidpp10.NOTIFICATION_FLAG.flag_names( flag_bits) - yield (_("Notifications"), ('\n%15s' % ' ').join(flag_names)) + yield (_('Notifications'), ('\n%15s' % ' ').join(flag_names)) def _set_details(text): _details._text.set_markup(text) @@ -696,7 +696,7 @@ def _update_device_panel(device, panel, buttons, full=False): panel._battery._icon.set_sensitive(False) panel._battery._icon.set_from_icon_name(icon_name, _INFO_ICON_SIZE) panel._battery._text.set_sensitive(True) - panel._battery._text.set_markup('%s' % _("unknown")) + panel._battery._text.set_markup('%s' % _('unknown')) else: charging = device.status.get(_K.BATTERY_CHARGING) icon_name = _icons.battery(battery_level, charging) @@ -704,52 +704,52 @@ def _update_device_panel(device, panel, buttons, full=False): panel._battery._icon.set_sensitive(True) if battery_voltage is not None: - text = "%(battery_voltage)dmV" % { + text = '%(battery_voltage)dmV' % { 'battery_voltage': battery_voltage } elif isinstance(battery_level, _NamedInt): text = _(str(battery_level)) else: - text = "%(battery_percent)d%%" % {'battery_percent': battery_level} + text = '%(battery_percent)d%%' % {'battery_percent': battery_level} if battery_next_level is not None: if isinstance(battery_next_level, _NamedInt): - text += " (" + _("next ") + _( - str(battery_next_level)) + ")" + text += ' (' + _('next ') + _( + str(battery_next_level)) + ')' else: - text += " (" + _("next ") + ( - "%d%%" % battery_next_level) + ")" + text += ' (' + _('next ') + ( + '%d%%' % battery_next_level) + ')' if is_online: if charging: - text += ' (%s)' % _("charging") + text += ' (%s)' % _('charging') else: - text += ' (%s)' % _("last known") + text += ' (%s)' % _('last known') panel._battery._text.set_sensitive(is_online) panel._battery._text.set_markup(text) if is_online: not_secure = device.status.get(_K.LINK_ENCRYPTED) == False if not_secure: - panel._secure._text.set_text(_("not encrypted")) + panel._secure._text.set_text(_('not encrypted')) panel._secure._icon.set_from_icon_name('security-low', _INFO_ICON_SIZE) panel._secure.set_tooltip_text( - _("The wireless link between this device and its receiver is not encrypted.\n" - "\n" - "For pointing devices (mice, trackballs, trackpads), this is a minor security issue.\n" - "\n" - "It is, however, a major security issue for text-input devices (keyboards, numpads),\n" - "because typed text can be sniffed inconspicuously by 3rd parties within range." + _('The wireless link between this device and its receiver is not encrypted.\n' + '\n' + 'For pointing devices (mice, trackballs, trackpads), this is a minor security issue.\n' + '\n' + 'It is, however, a major security issue for text-input devices (keyboards, numpads),\n' + 'because typed text can be sniffed inconspicuously by 3rd parties within range.' )) else: - panel._secure._text.set_text(_("encrypted")) + panel._secure._text.set_text(_('encrypted')) panel._secure._icon.set_from_icon_name('security-high', _INFO_ICON_SIZE) panel._secure.set_tooltip_text( - _("The wireless link between this device and its receiver is encrypted." + _('The wireless link between this device and its receiver is encrypted.' )) panel._secure._icon.set_visible(True) else: - panel._secure._text.set_markup('%s' % _("offline")) + panel._secure._text.set_markup('%s' % _('offline')) panel._secure._icon.set_visible(False) panel._secure.set_tooltip_text('') @@ -761,7 +761,7 @@ def _update_device_panel(device, panel, buttons, full=False): panel._lux._icon.set_from_icon_name(_icons.lux(light_level), _INFO_ICON_SIZE) panel._lux._text.set_text( - _("%(light_level)d lux") % {'light_level': light_level}) + _('%(light_level)d lux') % {'light_level': light_level}) panel._lux.set_visible(True) else: panel._lux.set_visible(False) @@ -898,7 +898,7 @@ def update(device, need_popup=False): # peripheral is_paired = bool(device) assert device.receiver - assert device.number is not None and device.number > 0, "invalid device number" + str( + assert device.number is not None and device.number > 0, 'invalid device number' + str( device.number) item = _device_row(device.receiver.path, device.number, device if is_paired else None) @@ -915,13 +915,13 @@ def update(device, need_popup=False): _model.set_value(item, _COLUMN.STATUS_ICON, _CAN_SET_ROW_NONE) else: if battery_voltage is not None: - status_text = "%(battery_voltage)dmV" % { + status_text = '%(battery_voltage)dmV' % { 'battery_voltage': battery_voltage } elif isinstance(battery_level, _NamedInt): status_text = _(str(battery_level)) else: - status_text = "%(battery_percent)d%%" % { + status_text = '%(battery_percent)d%%' % { 'battery_percent': battery_level } _model.set_value(item, _COLUMN.STATUS_TEXT, status_text) diff --git a/lib/solaar/upower.py b/lib/solaar/upower.py index 9cd1ee21..72ecba1d 100644 --- a/lib/solaar/upower.py +++ b/lib/solaar/upower.py @@ -35,7 +35,7 @@ _suspend_callback = None def _suspend(): if _suspend_callback: if _log.isEnabledFor(_INFO): - _log.info("received suspend event") + _log.info('received suspend event') _suspend_callback() @@ -45,7 +45,7 @@ _resume_callback = None def _resume(): if _resume_callback: if _log.isEnabledFor(_INFO): - _log.info("received resume event") + _log.info('received resume event') _resume_callback() @@ -93,11 +93,11 @@ try: if _log.isEnabledFor(_INFO): _log.info( - "connected to system dbus, watching for suspend/resume events") + 'connected to system dbus, watching for suspend/resume events') except: # Either: # - the dbus library is not available # - the system dbus is not running - _log.warn("failed to register suspend/resume callbacks") + _log.warn('failed to register suspend/resume callbacks') pass diff --git a/setup.py b/setup.py index 52c8c689..f7266beb 100755 --- a/setup.py +++ b/setup.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 from glob import glob as _glob + try: from setuptools import setup except ImportError: diff --git a/tools/monitor.py b/tools/monitor.py index aa6c5319..d336426d 100644 --- a/tools/monitor.py +++ b/tools/monitor.py @@ -13,7 +13,7 @@ sys.path += (sys.path[0] + '/../lib', ) def print_event(action, device): - print("~~~~ device [%s] %s" % (action, device)) + print('~~~~ device [%s] %s' % (action, device)) hidapi.monitor(print_event, DEVICE_UNIFYING_RECEIVER,