Compare commits

..

874 Commits
0.9.2 ... 1.0.7

Author SHA1 Message Date
Peter F. Patel-Schneider
0fbeebf121 release 1.0.7 2021-10-01 07:06:28 -04:00
Peter F. Patel-Schneider
79565cb31e i18n: update po files 2021-10-01 07:06:28 -04:00
Peter F. Patel-Schneider
9fca203372 release 1.0.7rc3 2021-09-25 13:54:45 -04:00
Peter F. Patel-Schneider
64d48a19a7 docs: upgrade pairing/unpairing documentation 2021-09-25 13:47:47 -04:00
Peter F. Patel-Schneider
1d73217ad2 receiver: mark Nano receiver C52F as not unpairing 2021-09-25 13:47:47 -04:00
Peter F. Patel-Schneider
585a3b901a receiver: lock on actual handle, not just on handle number 2021-09-24 21:55:15 -04:00
Peter F. Patel-Schneider
0d9fe48b0c listener: handle fake Nano connection notifications 2021-09-24 21:55:15 -04:00
Peter F. Patel-Schneider
a9adc06b7a ui: correctly determine setting box in change_click method 2021-09-24 10:17:59 -04:00
Ryunosuke Toda
64062a456f Update Japanese translation 2021-09-23 16:03:49 -04:00
Peter F. Patel-Schneider
27f6d6c76b settings: don't use time_ns so as not to require Python 3.7 2021-09-23 13:13:18 -04:00
Peter F. Patel-Schneider
e82457f284 release 1.0.7rc2 2021-09-14 15:50:34 -04:00
Peter F. Patel-Schneider
6d56dd538e release 1.0.7rc1 2021-09-14 15:44:36 -04:00
Peter F. Patel-Schneider
5488593caa doc: update installation instructions to mention Python versions 2021-09-14 11:51:48 -04:00
Peter F. Patel-Schneider
338a2687d3 device: don't signal status change when battery changes from None to None 2021-09-14 11:51:48 -04:00
Peter F. Patel-Schneider
83f79c55f1 doc: add paragraph on old versions to index.md 2021-09-06 16:38:37 -04:00
toda-ryunosuke
2daef846e3 Add Japanese translation 2021-09-04 18:25:36 -04:00
Peter F. Patel-Schneider
c5ef207961 device: use first word of name for code name if friendly name not available 2021-08-31 19:05:57 -04:00
Peter F. Patel-Schneider
c02a1b820b device: pass protocol to base request so that SW ID can be done right 2021-08-31 19:05:57 -04:00
Peter F. Patel-Schneider
a7ddb3efdd cli: allow for new_fn_inversion call to fail 2021-08-31 19:05:57 -04:00
Peter F. Patel-Schneider
2f870fe0f7 device: allow for None reponse from kind request 2021-08-31 19:05:57 -04:00
kkrentz
3ef5e63cd4 Fix "'int' object is not subscriptable" on G613 2021-08-30 20:23:10 -04:00
Peter F. Patel-Schneider
b94ae51ac8 rules: consistent naming for HID++ Diversion settings 2021-08-27 06:18:13 -04:00
Jose Riha
3f33d0633a Add Slovak translation 2021-08-24 05:17:22 -04:00
ifurther
dcafaf18e2 po/i18n: update zh_TW translation 2021-08-22 14:56:43 -04:00
Peter F. Patel-Schneider
67e40b35e8 device: add G102 mouse 2021-08-22 11:16:41 -04:00
Peter F. Patel-Schneider
30f56a1c0f device: use 0xFF instead of 0 for direct-connected devices 2021-08-22 11:16:41 -04:00
Vinícius
4b97ebd649 po/i18n: update pt_BR translation 2021-08-20 18:44:04 -04:00
Peter F. Patel-Schneider
c2de1b59ef ui: use logging for signalling unfound udev rule 2021-08-18 10:01:22 -04:00
Peter F. Patel-Schneider
4e76c99e0f hid: add debug message when potential device found 2021-08-18 09:40:23 -04:00
Matthaiks
42b83ecce8 po: update Polish translation (#1222)
* po: update Polish translation

* po: update Polish translation

* po: update Polish translation

Co-authored-by: Peter F. Patel-Schneider <pfpschneider@gmail.com>
2021-08-06 21:09:38 -04:00
Peter F. Patel-Schneider
14c2ac6959 po: make common button names translatable and show translations 2021-08-06 18:30:52 -04:00
Peter F. Patel-Schneider
a1874c572b i18n: mark more strings as translatable 2021-08-06 13:41:22 -04:00
Peter F. Patel-Schneider
ee4275f45c gtk: add new possible locations for udev rule 2021-08-06 13:41:22 -04:00
Peter F. Patel-Schneider
70a0fcd906 cli: show battery information under unified battery feature 2021-08-05 16:37:28 -04:00
Peter F. Patel-Schneider
18d79f8dd4 docs: mention that Solaar is available in Fedorals 2021-08-05 16:37:28 -04:00
Peter F. Patel-Schneider
cdc7a27c9e rules: add rule condition for process under mouse 2021-07-22 10:46:31 -04:00
Peter F. Patel-Schneider
39a5350f30 settings: add binary read prefix to handle fancy fn-swap setting 2021-07-20 09:59:37 -04:00
Peter F. Patel-Schneider
538ab9c947 receiver: serialize requests per handle so that threads do not receive response for a different request 2021-07-17 13:58:20 -04:00
Peter F. Patel-Schneider
d898edc4a3 notifications: downgrade unknown notifications warnings to info messages 2021-07-15 10:31:38 -04:00
Peter F. Patel-Schneider
ed0b730e74 device: fix bug with timeout when setting reprog keys 2021-07-15 10:21:03 -04:00
Peter F. Patel-Schneider
50392da360 rules: add checks for empty process name and class 2021-07-15 10:16:16 -04:00
Karthik Nishanth
85a86ec3c5 diversion: implement pressed and released action on Key condition (#1189)
- Track `key_up` key in addition to `key_down`
- Support `pressed` or `released` action in `Key` condition
- Add radio button to KeyUI to represent `pressed` or `released`
2021-07-12 15:51:57 -04:00
Peter F. Patel-Schneider
6290c84efd rules: upgrade rule execution debug message to info message 2021-07-04 22:10:45 -04:00
Peter F. Patel-Schneider
dbdbbf7fb3 docs: fix pointer to Solaar logo 2021-07-04 10:13:44 -04:00
Peter F. Patel-Schneider
3d65a77515 misc: better error message for missing gi package 2021-07-04 10:13:44 -04:00
Peter F. Patel-Schneider
e15ce68498 rules: process old mouse movement tests as MouseGesture conditions 2021-07-04 09:38:29 -04:00
ApeironTsuka
011f3f556b rules: allow sequence of mouse moves as mouse gestures
* Add more robust mouse gesture support
- Remove existing mouse-* Test types
- Add new 'Mouse Gesture' Condition
- Implement Rule Editor UI for it
- Add support for diverted buttons
- Added diagonal mouse gesture directions

Allows you to chain multiple movements/buttons (for instance, moving the mouse up and then left) together into a single mappable gesture.

* Update docs

* Cleanup
Fix inconsistent indenting
Fix possible overwriting of built-in
Fix 'Mouse Gesture' Condition rule not starting with an initial Action field

* Make flake8 happy

* yapf

* Document no-op and make it more apparent

* Make changes to Mouse Gesture UI suggested/submitted by viniciusbm.

Co-authored-by: Apeiron <apeiron@none>
Co-authored-by: Peter F. Patel-Schneider <pfpschneider@gmail.com>
2021-07-04 08:52:38 -04:00
Peter F. Patel-Schneider
8854ca6f23 docs: update advice on kernel versions 2021-06-15 19:03:43 -04:00
Peter F. Patel-Schneider
4690ca77c4 settings: fix fake divert gkeys read to return byte string 2021-06-15 19:03:43 -04:00
Robert Birkelbach
d172d27408 Support logitech g pro x superlight
The title speaks for itself: Add support for the g pro x superlight.
2021-06-08 12:09:30 -04:00
Peter F. Patel-Schneider
67dbe5f4c8 device: convert HID++ 2.0 device kinds to enhanced HID++ 1.0 kinds 2021-06-04 08:59:39 -04:00
Peter F. Patel-Schneider
5aedbad692 docs: update Solaar version in bug report template 2021-05-29 20:33:27 -04:00
Peter F. Patel-Schneider
9495cc03c2 misc: update about window 2021-04-25 14:48:28 -04:00
Peter F. Patel-Schneider
9deb7d66aa misc: update about window 2021-04-25 09:14:59 -04:00
Peter F. Patel-Schneider
c67bd32522 release 1.0.6 2021-04-25 09:07:58 -04:00
Peter F. Patel-Schneider
ce98e89427 release 1.0.6rc2 2021-04-25 09:03:36 -04:00
Peter F. Patel-Schneider
72b37deb52 release 1.0.6rc2 2021-04-25 08:59:59 -04:00
Peter F. Patel-Schneider
0cfb9b8896 misc: tell issue reporters to look in known issues first 2021-04-23 13:21:04 -04:00
Peter F. Patel-Schneider
51c6b6f2de misc: update long description to add pointer to installation instructions 2021-04-21 14:26:31 -04:00
Peter F. Patel-Schneider
1c1be84e59 device: downgrade warning about removing missing notification handler to info message 2021-04-21 13:55:58 -04:00
Peter F. Patel-Schneider
4edbf51f17 ui: better message for missing udev file 2021-04-21 08:53:41 -04:00
Peter F. Patel-Schneider
98b5804a21 rules: turn several log messages from INFO to DEBUG 2021-04-20 07:58:41 -04:00
Peter F. Patel-Schneider
d3799dcf41 docs: minor updates and cleanup 2021-04-18 11:13:50 -04:00
Peter F. Patel-Schneider
44b1b5b6d0 misc: update release.sh 2021-04-18 08:06:25 -04:00
Peter F. Patel-Schneider
f5fac6f713 release 1.0.6rc1 2021-04-18 07:46:03 -04:00
Peter F. Patel-Schneider
be143992ff po: update German translation 2021-04-18 07:36:29 -04:00
Peter F. Patel-Schneider
086a8252d2 docs: add new settings and rule example 2021-04-18 07:36:29 -04:00
Peter F. Patel-Schneider
39beaf8b3a docs: document new version of sliding DPI 2021-04-18 07:36:29 -04:00
Peter F. Patel-Schneider
3969472dd3 settings: dpi sliding looks for suitable key 2021-04-18 07:36:29 -04:00
Peter F. Patel-Schneider
90bae7db84 settings: only produce warning if can't turn off DPI sliding 2021-04-18 07:36:29 -04:00
Peter F. Patel-Schneider
a734a35b7e rules: add a mouse-noop test for mouse gesture with little movement 2021-04-17 10:32:24 -04:00
Peter F. Patel-Schneider
64915b09f7 docs: update description of mouse gestures setting 2021-04-17 10:32:24 -04:00
Peter F. Patel-Schneider
7add22e861 settings: don't halt when trying to write invalid map choice 2021-04-17 10:32:24 -04:00
Peter F. Patel-Schneider
75fec689a0 settings: change name of App Switch Button 2021-04-17 10:32:24 -04:00
Peter F. Patel-Schneider
5d885f76e7 settings: show potential triggering keys for mouse gesture setting 2021-04-17 10:32:24 -04:00
Peter F. Patel-Schneider
42624c7102 ui: write persisted value when changing from ignoring a setting 2021-04-17 10:32:24 -04:00
Peter F. Patel-Schneider
087b99a2de settings: use keys interface in divert_keys setting 2021-04-17 10:32:24 -04:00
Peter F. Patel-Schneider
b3a6dc5b2e ui: update map all settings that are not None 2021-04-17 10:32:24 -04:00
Peter F. Patel-Schneider
95dafbe3aa settings: fix return value for mouse gesture callback 2021-04-15 17:00:29 -04:00
Peter F. Patel-Schneider
a1dc69d203 ui: make ignore settings not sensitive at startup 2021-04-13 13:27:59 -04:00
Peter F. Patel-Schneider
e32cf61fa8 docs: document sliding dpi and mouse gestures 2021-04-13 09:26:24 -04:00
Peter F. Patel-Schneider
f7488f67c1 settings: add mouse gesture handling 2021-04-13 09:26:24 -04:00
Peter F. Patel-Schneider
6c62f975d0 ui: directly connected devices don't need to support connection notifications 2021-04-12 23:21:22 -04:00
Peter F. Patel-Schneider
62034758f0 ui: check that receivers support connection nofications 2021-04-12 22:32:11 -04:00
Peter F. Patel-Schneider
e66a83aa36 docs: sudo should not be used to run Solaar 2021-04-12 19:05:11 -04:00
Peter F. Patel-Schneider
a288caa7ee settings: fix typo 2021-04-12 08:08:31 -04:00
Peter F. Patel-Schneider
5be7541875 settings: for polling rate setting only change profiles mode when actually writing 2021-04-12 08:04:41 -04:00
Peter F. Patel-Schneider
33a4bf8bf5 ui: read current value of setting when switching away from ignore 2021-04-12 07:39:35 -04:00
Peter F. Patel-Schneider
b2970186df docs: describe setting ignoring and add note about drivers and scroll wheel resolution 2021-04-12 07:39:35 -04:00
Peter F. Patel-Schneider
52fcbe3b48 settings: restore _feature_hires_smooth_resolution 2021-04-12 07:39:35 -04:00
Peter F. Patel-Schneider
b34061c766 ui: add ability to ignore a Solaar setting 2021-04-12 07:39:35 -04:00
Peter F. Patel-Schneider
2ce8a3b249 docs: describe how to install a system tray for Gnome 2021-04-09 09:39:30 -04:00
Peter F. Patel-Schneider
8c5800e536 receiver: use symbolic identifiers for sub-registers 2021-04-09 07:46:10 -04:00
gogogogi
804ba267f6 device: add G700 wired support 2021-04-09 07:43:54 -04:00
Peter F. Patel-Schneider
6099df1b42 ui: do not set attention icon - gets around bug in XFCE 16 2021-04-09 07:28:23 -04:00
Peter F. Patel-Schneider
fc1e38d196 docs: add note that some system tray implementations might not set up icons correctly 2021-04-09 07:28:23 -04:00
Peter F. Patel-Schneider
55ed173c39 ui: replace deprecated GTK stock values 2021-04-09 07:28:23 -04:00
Peter F. Patel-Schneider
593d27770d ui: only use first element of theme path for appindicator extra path 2021-04-09 07:28:23 -04:00
Peter F. Patel-Schneider
0dbb93e6a5 ui: only prepend one icon path to theme search paths 2021-04-09 07:28:23 -04:00
Peter F. Patel-Schneider
68049efc41 ui: better handling of tray icons 2021-04-09 07:28:23 -04:00
Peter F. Patel-Schneider
1d18e4d8f7 receiver: receiver c52e does not unpair 2021-04-09 07:24:11 -04:00
SiDevesh
d3a18bb85f rules: match WM_CLASS also for process matching in rules 2021-04-08 15:01:50 -04:00
Peter F. Patel-Schneider
1cb8f0c874 ui: correctly set icon theme value when regular battery icons are missiong 2021-04-07 19:59:25 -04:00
Peter F. Patel-Schneider
7e360e4416 settings: remove _feature_hires_smooth_resolution as recent Linux input drivers depend on it not changing 2021-04-04 22:36:54 -04:00
Peter F. Patel-Schneider
9842972d8b receiver: handle exception when device is not available while being added 2021-04-04 22:33:38 -04:00
Peter F. Patel-Schneider
a4b54df433 device: fix debug message error 2021-04-02 10:25:01 -04:00
Peter F. Patel-Schneider
6ed09d0643 listener: perform initial activation of devices in listener threads
listener: perform initial activation of devices in listener threads
2021-03-30 08:36:37 -04:00
Peter F. Patel-Schneider
1bd68177ab configure: keep track of serial numbers in configuration file 2021-03-30 08:36:37 -04:00
Peter F. Patel-Schneider
985ebd46cd device: check device is active before performing request and don't replace empty settings 2021-03-30 08:36:37 -04:00
Peter F. Patel-Schneider
3fb197b78c device: set host names longer than 14 bytes 2021-03-29 11:43:30 -04:00
Peter F. Patel-Schneider
cb67897d15 device: set current host name if not current host 2021-03-29 11:43:30 -04:00
Peter F. Patel-Schneider
533cd54b92 settings: add setting for SMART SHIFT ENHANCED feature 2021-03-26 15:55:59 -04:00
Peter F. Patel-Schneider
a658f2e2b0 device: add names for 2250 and 2251 features 2021-03-26 15:55:59 -04:00
Peter F. Patel-Schneider
5aa45a78c3 docs: update package dependencies 2021-03-23 22:31:04 -04:00
Peter F. Patel-Schneider
689d57d097 device: don't always use long messages for protocol 1.0 2021-03-22 08:35:34 -04:00
Peter F. Patel-Schneider
dc3f70ff86 cli: use 1-origin addressing when selecting from choices in config 2021-03-18 09:57:03 -04:00
Peter F. Patel-Schneider
58f1a142ec cli: fix config check against choices 2021-03-18 09:57:03 -04:00
Peter F. Patel-Schneider
10233dac30 settings: add quirk to not set up host mode on G915 TKL keyboard 2021-03-07 22:02:49 -05:00
Peter F. Patel-Schneider
ec9ac9c920 docs: put show output in a details block in issue templates 2021-03-06 07:39:04 -05:00
Peter F. Patel-Schneider
5642a658ab cli: print settings saved in config file in show command 2021-03-06 07:39:04 -05:00
Peter F. Patel-Schneider
08d571aea9 docs: add notes about different settings on different computers 2021-03-05 07:31:13 -05:00
Peter F. Patel-Schneider
3cd76aa191 tools: fix up call to udev matching in hidconsole 2021-03-02 19:02:08 -05:00
daviddavid
3d3d0d4ccc Update French translation for 1.0.5 release
- by David Geiger <david.david@mageialinux-online.org>
2021-02-27 10:25:45 -05:00
Peter F. Patel-Schneider
83f45218de release 1.0.5 2021-02-27 09:03:29 -05:00
Peter F. Patel-Schneider
69df28c155 docs: update docs - remembering settings, point to github docs 2021-02-21 14:02:48 -05:00
Peter F. Patel-Schneider
babdb44b4f cli: fix up help messages for selecting devices and receivers for CLI commands 2021-02-21 13:23:33 -05:00
Peter F. Patel-Schneider
daee35de4a cli: fix bug in finding receiver to pair 2021-02-21 06:30:32 -05:00
Peter F. Patel-Schneider
8d01e28138 release 1.0.5rc2 2021-02-18 15:04:18 -05:00
Peter F. Patel-Schneider
04d79810d4 cli: set keyed settings with config 2021-02-18 11:02:57 -05:00
Matthaiks
6fa1bfd044 po: Update translation for Polish 2021-02-17 16:16:52 -05:00
Leonardo Gates
c1a79a49f8 settings: implement polling rate 2021-02-17 07:58:30 -05:00
Peter F. Patel-Schneider
04775a3719 device: use long messages for all 2.0 requests 2021-02-16 20:20:33 -05:00
Peter F. Patel-Schneider
20f16e8e10 i18n: update german and italian translations 2021-02-16 20:14:37 -05:00
Peter F. Patel-Schneider
eb0d939d1a cli: don't select unpaired device for config command 2021-02-16 08:25:46 -05:00
Peter F. Patel-Schneider
4b52b77348 cli: add device name to output when changing settings using config command 2021-02-16 08:25:46 -05:00
Equidamoid
8fccd84345 Log real exception when can't use Xorg API (#1066)
* fix: log real exception when can't use Xorg API

* chore: make linter happy
2021-02-08 18:55:10 -05:00
Alexander Huck
2ea92db3ca remove trailing whitespace 2021-02-01 12:54:32 -05:00
Alexander Huck
205047e278 Update about.py 2021-02-01 12:54:32 -05:00
Alexander Huck
c268ff7a45 Update about.py to bump copyright years
Update Copyright Timeframe
2021-02-01 12:54:32 -05:00
Peter F. Patel-Schneider
7dbf92955e doc: remove packages that no longer exist 2021-01-27 11:43:33 -05:00
Peter F. Patel-Schneider
82a41bf46b device: show remaining pairings in show 2021-01-27 11:35:11 -05:00
daviddavid
1de3b2e472 Update French translation for 1.0.4 release
- by David Geiger <david.david@mageialinux-online.org>
2021-01-23 11:44:50 -05:00
Heimen Stoffels
f6b76900d9 Updated Dutch translation 2021-01-15 17:40:13 -05:00
Peter F. Patel-Schneider
1c6f289d91 ui: add option to not use battery icons for tray icon 2021-01-04 09:53:46 -05:00
Matthaiks
ca0e2a0a3f po: Update translation for Polish
Version 1.0.4
2021-01-04 09:53:09 -05:00
Peter F. Patel-Schneider
111f2be5c8 device: defense against missing devices 2021-01-03 16:01:59 -05:00
Marián Kyral
f68a831c81 Add Czech translation 2020-12-30 12:22:09 -05:00
Marián Kyral
b722eccf04 Fix typo 2020-12-30 12:22:09 -05:00
Peter F. Patel-Schneider
53b7c63680 docs: remove pointer to SUSE package as it is very old 2020-12-27 07:08:39 -05:00
Vinícius
aa4456e9dc receiver: changing duplicate label of GESTURE 2 options 2020-12-17 12:18:22 -05:00
Ricardo Mones
8d657f891a Update es.po
Hi, I'm using 1.0.4 in Debian testing and Spanish translation lacks a lot of strings, here it is an updated file.
2020-12-15 06:39:33 -05:00
Peter F. Patel-Schneider
a688bfd9ec settings: add setting to divert G keys and handle in rules 2020-12-13 22:24:08 -05:00
Dominik 'Rathann' Mierzejewski
a47f3fa5d1 fix metainfo file location
Rename the file to match the <id> tag inside the file.

Install the file in correct location.

This fixes #1025 .
2020-12-04 10:07:38 -05:00
Peter F. Patel-Schneider
69f889e33f rules: only activate rules if X11 is running 2020-12-02 10:10:47 -05:00
Peter F. Patel-Schneider
52049af8e1 receiver: add remote device type 2020-11-30 08:18:09 -05:00
Peter F. Patel-Schneider
7d0402a97f rules: only use X11 code when X11 is available 2020-11-28 09:41:59 -05:00
Peter F. Patel-Schneider
0427e5607e settings: correctly handle diversions when key has other flags set 2020-11-27 17:38:38 -05:00
Peter F. Patel-Schneider
419a7722ad rules: make rule processing conditional on X11 being available 2020-11-27 10:48:16 -05:00
Peter F. Patel-Schneider
60afd53257 device: fix short name for MX Keys keyboard 2020-11-27 10:48:16 -05:00
Peter F. Patel-Schneider
a99a5a544e rules: fix syntax in MouseClick 2020-11-27 10:12:21 -05:00
Peter F. Patel-Schneider
244d48d245 rules: remove use of pynput 2020-11-27 10:12:21 -05:00
Peter F. Patel-Schneider
808a719823 device: push device settings when device is active after suspend 2020-11-27 10:02:46 -05:00
Bruno Mello
56db8fbdf9 Update installation.md
Fix spelling of python psutil package
2020-11-23 18:12:18 -05:00
Peter F. Patel-Schneider
0af12fbf2e docs: mention GUI editor for notification rules 2020-11-21 12:44:50 -05:00
Peter F. Patel-Schneider
646151ae61 receiver: reduce unnecessary writes of config file 2020-11-21 12:34:13 -05:00
Peter F. Patel-Schneider
66138ad7c0 docs: add instructions on Python development package 2020-11-21 12:32:33 -05:00
Peter F. Patel-Schneider
d81a971455 cli: don't show devices as receivers 2020-11-21 12:32:33 -05:00
Peter F. Patel-Schneider
66f3d5d02b receiver: gracefully handle more receiver and device disconnects 2020-11-21 12:32:33 -05:00
Peter F. Patel-Schneider
6b8e7a2d9c ui: only emit warning on path mismatch between device and recevier in main window 2020-11-21 12:32:33 -05:00
Peter F. Patel-Schneider
504d23fab7 ui: only emit warning when updating tray for inactive device 2020-11-21 12:32:33 -05:00
Vinícius
52109ade91 ui: ignore Ctrl+Delete shortcut if root is selected 2020-11-21 12:23:41 -05:00
Vinícius
daafe5ebca ui: don't offer to delete/cut root element and don't offer to paste non-Rule at the top level 2020-11-21 12:23:41 -05:00
Vinícius
8be0e21ac7 ui: delete method that is no longer used 2020-11-21 12:23:41 -05:00
Vinícius
9c04bfad92 ui: fixed unnecessary dialogue when window is closed after discarding changes 2020-11-21 12:23:41 -05:00
Vinícius
4025b83dfd ui: add icons to rule editor buttons and implement Ctrl+S shortcut 2020-11-21 12:23:41 -05:00
Vinícius
bc51117f59 ui: use readable names on the left column of rule editor 2020-11-21 12:23:41 -05:00
Vinícius
a8819b06c8 ui: make KeyPress entry larger (relative to window size) 2020-11-21 12:23:41 -05:00
Vinícius
6f973cdc27 ui: fix bug that prevented copying from a built-in rule for the first time 2020-11-21 12:23:41 -05:00
Vinícius
b548d05cad ui: change diversion editor window title and button label 2020-11-21 12:23:41 -05:00
Vinícius
ef3d3e5290 ui: fix feature entry bug when feature is not on the list 2020-11-21 12:23:41 -05:00
Vinícius
487e1a3ded ui: show Feature completion matches for all features 2020-11-21 12:23:41 -05:00
Vinícius
4206d370f1 ui: add delete button for every Execute argument 2020-11-21 12:23:41 -05:00
Vinícius
29ccd55210 ui: improve validation of FeatureUI and KeyUI diversion rule components 2020-11-21 12:23:41 -05:00
Vinícius
b399380445 ui: diversion rule editor - move save and discard buttons to the top 2020-11-21 12:23:41 -05:00
Vinícius
1d68ef858e ui: make rule editing buttons larger and add delete buttons for KeyPress. 2020-11-21 12:23:41 -05:00
Vinícius
717213c506 ui: move diversion button to the right 2020-11-21 12:23:41 -05:00
Vinícius
0b5c263799 receiver: fix and improve diversion load/save functions 2020-11-21 12:23:41 -05:00
Vinícius
1379da70a8 ui: add GUI for diversion rules (draft) 2020-11-21 12:23:41 -05:00
Peter F. Patel-Schneider
f42ff35f24 doc: add app metainfo file 2020-11-17 17:24:47 -05:00
Peter F. Patel-Schneider
3d8c9272fb install: update and document new dependencies 2020-11-17 17:07:32 -05:00
Vinícius
381371c899 receiver: add MouseClick diversion rule 2020-11-14 10:38:01 -05:00
Peter F. Patel-Schneider
be590c154a docs: add documentation for rules processing and change name of rules file 2020-11-13 08:46:04 -05:00
Peter F. Patel-Schneider
30e4324906 receiver: associate source file with top-level rules 2020-11-13 08:46:04 -05:00
Peter F. Patel-Schneider
545db1f641 receiver: add named tests for hires and lowres wheels 2020-11-13 08:46:04 -05:00
Peter F. Patel-Schneider
5e2b2b6647 device: add quirk for WPID 4055 in button diversion 2020-11-13 08:46:04 -05:00
Peter F. Patel-Schneider
f3a276d7a3 receiver: add rule-based processing of diverted features 2020-11-13 08:46:04 -05:00
Peter F. Patel-Schneider
02a7d8cadd util: allow accessing NamedInts by readable name 2020-11-13 08:46:04 -05:00
Peter F. Patel-Schneider
4da7feec3b receiver: regularize capitalization of Logitech CONTROL key names 2020-11-13 08:46:04 -05:00
Peter F. Patel-Schneider
f75c9845d2 settings: add setting for diverting keys 2020-11-13 08:46:04 -05:00
Peter F. Patel-Schneider
b947dd4896 settings: add crown diversion setting 2020-11-13 08:46:04 -05:00
Peter F. Patel-Schneider
ade9c816c7 receiver: add report_id to notifications and use where appropriate 2020-11-13 08:46:04 -05:00
Vinícius
8141fafb4b ui: create attributes to access children in settings with multiple items 2020-11-02 09:28:12 -05:00
Peter F. Patel-Schneider
79b18d07c9 cli: fix bug in probe 2020-11-02 09:15:43 -05:00
Peter F. Patel-Schneider
d92939135f device: warn when feature notifiation comes in before device fully set up 2020-11-02 08:27:08 -05:00
Peter F. Patel-Schneider
733bf913e6 device: implement UNIFIED_BATTERY feature
device: implement UNIFIED_BATTERY feature
2020-11-02 08:27:08 -05:00
Peter F. Patel-Schneider
1162ccb897 device: be defensive when getting device id 2020-11-01 15:14:18 -05:00
Peter F. Patel-Schneider
73ddb12d8e docs: fix typos in devices.md 2020-10-28 12:41:04 -04:00
Peter F. Patel-Schneider
93b5a0008b ui: add lock icon to control whether setting can be changed 2020-10-25 14:13:58 -04:00
Wojciech Nawrocki
847205eb06 settings_templates: typo
Oops!
2020-10-25 14:03:05 -04:00
Antony Kellermann
98b4aff33d Fix warning 2020-10-25 14:02:25 -04:00
Peter F. Patel-Schneider
a4e4c160c1 release 1.0.4 2020-10-22 10:02:24 -04:00
Peter F. Patel-Schneider
b97c83be97 po: update pt_BR translation 2020-10-22 10:02:24 -04:00
Peter F. Patel-Schneider
2e4e0a0676 release: fix ChangeLog 2020-10-12 08:35:02 -04:00
Peter F. Patel-Schneider
93fe73214c release 1.0.4rc1 2020-10-12 08:25:35 -04:00
Peter F. Patel-Schneider
4ca2496a6f docs: update devices.md for USB and BT devices 2020-10-12 08:05:13 -04:00
Peter F. Patel-Schneider
b19006104f device: support unknown USB-connected and Bluetooth devices 2020-10-12 08:05:13 -04:00
Peter F. Patel-Schneider
dba9d472a8 hidapi: fix bug in processing of serial numbers 2020-10-07 15:18:28 -04:00
Peter F. Patel-Schneider
7a7aad8977 device: use FRIENDLY NAME for codename if needed and available 2020-10-07 05:30:34 -04:00
Olivier Dormond
254e2cb77e device: add BT information for MX Keys 2020-10-03 09:10:59 -04:00
Peter F. Patel-Schneider
fdb1b43373 device: add USB information for G700s 2020-10-01 17:45:49 -04:00
Peter F. Patel-Schneider
a9d6b4c319 listener: make sure device has a status before processing notifications 2020-10-01 17:45:49 -04:00
Peter F. Patel-Schneider
7908a4f5a4 ui: ensure that Gtk 3.0 is the version loaded 2020-10-01 17:45:49 -04:00
Peter F. Patel-Schneider
757c731610 device: show DPI values, not slider, in sliding notification 2020-10-01 12:48:11 -04:00
Peter F. Patel-Schneider
612e8fb4f7 device: store sliding DPI value in persister and respect changes in regular DPI setting 2020-10-01 12:48:11 -04:00
Peter F. Patel-Schneider
3effccf390 docs: update for USB and Bluetooth 2020-09-29 11:26:34 -04:00
Peter F. Patel-Schneider
84e0e74709 device: add BT IDs for MX Master and MX Master 2S 2020-09-29 11:26:34 -04:00
Peter F. Patel-Schneider
ec8a51d353 udev: get manufacturer and product from HID_ID 2020-09-29 11:26:34 -04:00
Peter F. Patel-Schneider
3b6a4ed0ed receiver: put USB and BT identifiers in descriptors.py 2020-09-29 11:26:34 -04:00
Peter F. Patel-Schneider
815c9755b5 receiver: handle bluetooth-connected devices 2020-09-29 11:26:34 -04:00
Peter F. Patel-Schneider
1e7050595e receiver: add model and node ID and use in configurations 2020-09-29 11:26:34 -04:00
Peter F. Patel-Schneider
fc59c0fbf6 device: only look up feature notifications in SLIDING DPI setting 2020-09-28 14:47:43 -04:00
Peter F. Patel-Schneider
4874d72c16 receiver: fix bug in debug message 2020-09-28 14:47:43 -04:00
Peter F. Patel-Schneider
e6cfd0a0c1 device: increase speed for DPI sliding 2020-09-28 12:59:04 -04:00
Peter F. Patel-Schneider
ebf7984ad0 device: determine SLIDING DPI suitability based on device features 2020-09-28 12:59:04 -04:00
Peter F. Patel-Schneider
2654b6bbe0 ui: add forced-refresh argument to window update 2020-09-28 12:59:04 -04:00
Wojciech Nawrocki
9f7c7209fe device: support DPI sliding with two slots on MX Vertical mouse
Reimplements the entire behaviour of Logitech's software for this
mouse on Windows.
2020-09-28 12:59:04 -04:00
Wojciech Nawrocki
41fb08c059 notify: allow displaying progress 2020-09-28 12:59:04 -04:00
Wojciech Nawrocki
362d43a7a1 backend: allow device objects to handle notifications 2020-09-28 12:59:04 -04:00
Peter F. Patel-Schneider
0259e44c31 cli: ignore DJ pairing notifications in CLI pair command 2020-09-24 18:22:35 -04:00
Peter F. Patel-Schneider
df8b6b488c receiver: add USB information for MX Vertical when wired 2020-09-23 18:03:47 -04:00
Peter F. Patel-Schneider
825b7b6f34 udev: add permissions for any Logitech device 2020-09-23 18:03:47 -04:00
Peter F. Patel-Schneider
b1d4b2f3cd receiver: add model and node ID and use in configurations 2020-09-23 18:03:47 -04:00
Peter F. Patel-Schneider
58823763ea ui: handle wired devices 2020-09-23 18:03:47 -04:00
Peter F. Patel-Schneider
aeb8588e06 cli: make probe and config work for wired devices 2020-09-23 18:03:47 -04:00
Peter F. Patel-Schneider
ebfd26b3d0 receiver: add USB information for G502 Hero when wired 2020-09-23 18:03:47 -04:00
Peter F. Patel-Schneider
95a30a8089 cli: add extra information about features to show command output 2020-09-23 18:03:47 -04:00
Peter F. Patel-Schneider
dca6b4ba38 ui: show all host choices 2020-09-21 08:57:47 -04:00
Peter F. Patel-Schneider
b1706fa9e2 ui: don't show unpaired host choices 2020-09-21 07:44:55 -04:00
Peter F. Patel-Schneider
ff5d744183 ui: improve display strings and ordering for settings 2020-09-21 07:44:55 -04:00
Peter F. Patel-Schneider
377e44c624 ui: add separator before device settings 2020-09-21 07:44:55 -04:00
Peter F. Patel-Schneider
6e986ddf8c docs: add missing word in index.md 2020-09-18 05:49:43 -04:00
Peter F. Patel-Schneider
714f8782b3 cli: reduce chance of connect notifications clashing when pairing 2020-09-18 05:49:43 -04:00
Peter F. Patel-Schneider
ad57db4a39 receiver: permit connection notifications that are not unifying 2020-09-18 05:49:43 -04:00
Peter F. Patel-Schneider
8b5d56feb4 device: if hidraw node is not available wait and try a second time 2020-09-18 05:49:43 -04:00
Peter F. Patel-Schneider
2153035c30 ui: add device path to information panel for non-receivers 2020-09-18 05:49:43 -04:00
Peter F. Patel-Schneider
dbf6226f77 receiver: update strings for several settings 2020-09-18 05:49:43 -04:00
Alex Cherkayev
7a82b93aaf udev: add function to get wpid from udev
base: make workaround flag name more generic
descriptors: fix wpid's for 27Mhz devices
device: Improve wpid and kind processing for 27Mhz devices
notifications: Improve wpid generation for 27Mhz devices
docs: fix wpid's for EX100
2020-09-07 11:43:25 -04:00
Ali Sabzevari
9de4d392d4 Fix broken link to about website 2020-09-04 14:39:25 -04:00
Peter F. Patel-Schneider
b0297694d1 receiver: remove spurious part of special handling for ex100 receiver 2020-09-01 23:13:49 -04:00
Vinícius
7fdba7fe75 ui: disabled ListBoxRow background colour on hover 2020-09-01 18:38:00 -04:00
Vinícius
9f330479c1 docs: filled information about GESTURE2 and some supported devices 2020-09-01 18:38:00 -04:00
Vinícius
36e8dcb396 descriptors: added GESTURE2 to known supported devices 2020-09-01 18:38:00 -04:00
Vinícius
708edbc444 ui: make collapsible sections start collapsed 2020-09-01 18:38:00 -04:00
Vinícius
d87bc594f4 ui: fixed vertical alignment of panel after collapsing widgets 2020-09-01 18:38:00 -04:00
Vinícius
7a65c40312 ui: removed GESTURE2 specs from the panel 2020-09-01 18:38:00 -04:00
Vinícius
6994e1e41c receiver/ui: added labels and tooltips to some settings 2020-09-01 18:38:00 -04:00
Vinícius
1ce67954cb receiver: fixed number of spec "field widths" 2020-09-01 18:38:00 -04:00
Vinícius
1e8956ff96 ui: fixed horizontal alignment and size of multiple toggle/range widgets 2020-09-01 18:38:00 -04:00
Vinícius
c8fe87ee2d receiver: implementation of GESTURE 2 params; improved UI for multiple toggle 2020-09-01 18:38:00 -04:00
Vinícius
aa067b2774 receiver: show GESTURE2 specs on the panel 2020-09-01 18:38:00 -04:00
Vinícius
b3751913b2 receiver: read GESTURE2 param defaults 2020-09-01 18:38:00 -04:00
Vinícius
09394cfbf5 receiver: support GESTURE2 specs 2020-09-01 18:38:00 -04:00
Vinícius
7498febc3a receiver: GESTURE 2 also applies to mice 2020-09-01 18:38:00 -04:00
Vinícius
4a5c0ea523 receiver: initial implementation of boolean GESTURE 2 settings 2020-09-01 18:38:00 -04:00
Peter F. Patel-Schneider
633760e261 receiver: add initial support for GESTURE_2 2020-09-01 18:38:00 -04:00
Peter F. Patel-Schneider
68aebc8c1b cli: slight improvement to probe 2020-09-01 18:35:31 -04:00
Peter F. Patel-Schneider
831287ead6 cli: add full register dump for probe 2020-09-01 18:04:24 -04:00
Peter F. Patel-Schneider
1bba8b26de cli: fix bug in probe.py 2020-08-29 13:38:11 -04:00
Peter F. Patel-Schneider
718c2d4039 receiver: simplify settings interface 2020-08-28 08:41:14 -04:00
Peter F. Patel-Schneider
1516daa6d0 listener: fix misleading connection log message 2020-08-27 08:27:58 -04:00
Peter F. Patel-Schneider
4df84107e1 receiver: don't emit warning for battery status notifications 2020-08-27 05:22:03 -04:00
Peter F. Patel-Schneider
3e4c09380a receiver: be extra cautious when writing key-value pairs for settings 2020-08-27 05:22:03 -04:00
Peter F. Patel-Schneider
e6947d95d8 receiver: use DJ connection notifications to set device active status 2020-08-27 05:22:03 -04:00
Peter F. Patel-Schneider
f5c00a5f2a docs: mention that Solaar udev rule is needed for access to device hidraw nodes 2020-08-25 07:28:09 -04:00
effective-light
246c6cc1b2 udev: add a timeout to find_paired_node because the device might not be instantly ready (e.g. after pairing) 2020-08-25 06:47:07 -04:00
effective-light
2d29db4609 udev: simplify find_paired_node 2020-08-25 06:47:07 -04:00
effective-light
374388daf0 udev: add new rules for the wired devices and have the udev rules apply to paired peripherals 2020-08-25 06:47:07 -04:00
effective-light
fe55e39560 udev: use HID_PHYS instead of HID_UNIQ to look for relevant child nodes 2020-08-25 06:47:07 -04:00
effective-light
535b1f02ce device: report a wired device's serial number 2020-08-25 06:47:07 -04:00
effective-light
eec5df5d56 device: read the serial number properly from the device hidraw nodes 2020-08-25 06:47:07 -04:00
effective-light
c4d2ec4008 device: ensure that the serial ids match since wpids aren't distinct between devices and fallback to the receiver's handle when a match can't be found 2020-08-25 06:47:07 -04:00
effective-light
00ea128775 Prevent the precommit hooks from complaining 2020-08-25 06:47:07 -04:00
effective-light
b98033d558 base: add a number of relevant device ids and print them when the "show" command is executed 2020-08-25 06:47:07 -04:00
effective-light
16823092bc device: add preliminary support for wired devices 2020-08-25 06:47:07 -04:00
effective-light
9a13eb0229 receiver: talk directly to the device where possible 2020-08-25 06:47:07 -04:00
effective-light
35114490d3 cli: print each device's direct path 2020-08-25 06:47:07 -04:00
effective-light
bf3aeff7d8 receiver: open and store each paired device's direct hidraw node 2020-08-25 06:47:07 -04:00
Peter F. Patel-Schneider
d027c66198 receiver: add WPID 0612 for VX Revolution mouse 2020-08-24 08:28:48 -04:00
Peter F. Patel-Schneider
04e8281738 receiver: handle devices with serial numbers that don't provide number of pairings 2020-08-24 08:28:48 -04:00
Peter F. Patel-Schneider
f5c63ccc39 ui: better display of battery information in main window 2020-08-22 10:43:10 -04:00
Peter F. Patel-Schneider
9b8f96e824 receiver: fix bug when setting causes exception 2020-08-17 18:04:11 -04:00
Peter F. Patel-Schneider
5117028c52 misc: ignore exceptions when trying to set locale 2020-08-17 11:03:03 -04:00
Peter F. Patel-Schneider
eda0a95585 receiver: correctly handle settings that share a name in config 2020-08-15 14:41:56 -04:00
Peter F. Patel-Schneider
5041530952 receiver: don't produce pop-up notifications at startup and power on 2020-08-14 10:10:39 -04:00
Peter F. Patel-Schneider
9d0fcea02e receiver: simpler interface for settings 2020-08-13 16:38:11 -04:00
Peter F. Patel-Schneider
1400473877 receiver: make unpairing log messages be INFO, not warning 2020-08-12 19:12:41 -04:00
Peter F. Patel-Schneider
330fadfbce receiver: check that device can retrieve host names before trying that 2020-08-12 19:12:41 -04:00
Kudlaty
b3cc4361e8 receiver: add lightspeed receiver c541 2020-08-12 14:35:05 -04:00
Peter F. Patel-Schneider
2e1e8dc9b5 receiver: fix bug in logging DJ notifications 2020-08-10 05:34:33 -04:00
Peter F. Patel-Schneider
44f85d5dee receiver: change notification before status setup from assertion to warning 2020-08-09 18:20:18 -04:00
Peter F. Patel-Schneider
78a6ae9208 receiver: keep better track of battery voltage status for GUI 2020-08-09 18:20:18 -04:00
Américo Monteiro
4c31adb907 po: Add Portuguese translation 2020-08-09 15:46:06 -04:00
Peter F. Patel-Schneider
15b1965582 receiver: add lightspeed receiver c545 2020-08-09 11:21:28 -04:00
Peter F. Patel-Schneider
6918353a29 cli: improve messages for unpairing errors 2020-08-08 07:58:01 -04:00
Wojciech Nawrocki
1973693cc8 hidpp20: support version 4 of REPROG_CONTROLS_V4 2020-08-07 13:40:36 -04:00
Wojciech Nawrocki
1361af5501 special_keys: uppercase for DPI switch control 2020-08-07 13:40:36 -04:00
Wojciech Nawrocki
6e5d36e59f settings: use KeysArray for key reprogramming 2020-08-07 13:40:36 -04:00
Wojciech Nawrocki
95dc973748 hidpp20: add full support for version 2 of REPROG_CONTROLS_V4 2020-08-07 13:40:36 -04:00
muzena
e7047f4606 Update Croatian translation 2020-08-04 16:31:04 -04:00
John Erling Blad
d1908694c4 linted release page 2020-08-04 07:53:44 -04:00
John Erling Blad
b5bb04b8a2 po: update pot-file 2020-08-04 07:52:43 -04:00
John Erling Blad
14725e42ee po: update translation for Norwegian Bokmal 2020-08-04 07:52:23 -04:00
John erling Blad
5b796bae7d po: update translation for Norwegian Nynorsk 2020-08-04 07:51:38 -04:00
John erling Blad
e4f5d75095 po: update translation for Danish 2020-08-04 07:51:07 -04:00
John erling Blad
409065ed29 po: update translation for Swedish 2020-08-04 07:50:31 -04:00
Peter F. Patel-Schneider
56c6a52941 docs: put absolute links back in index.md 2020-08-04 07:49:47 -04:00
Peter F. Patel-Schneider
fd02b33971 ui: use ngettext for translatable strings with number dependencies 2020-08-02 11:56:56 -04:00
Peter F. Patel-Schneider
e763aeadb4 release 1.0.3 2020-08-02 11:46:13 -04:00
John Erling Blad
aaee650caf cleanup and lint the docs 2020-08-02 11:25:00 -04:00
John Erling Blad
6645b5b04c po: update translation for Swedish 2020-08-02 11:24:24 -04:00
John Erling Blad
e8f169f6f5 po: add translation for Danish 2020-08-02 11:23:45 -04:00
John Erling Blad
19a5fa3911 po: add translation for Norwegian Nynorsk 2020-08-01 15:46:59 -04:00
John Erling Blad
64e20533a0 po: update translation for Norwegian Bokmål 2020-08-01 15:41:28 -04:00
daviddavid
86a49128b4 Update French translation for 1.0.3rc2 release
- by David Geiger <david.david@mageialinux-online.org>
2020-08-01 07:51:52 -04:00
John Erling Blad
a579eb4ded po: update translation for Swedish 2020-07-31 06:23:44 -04:00
Peter F. Patel-Schneider
59296f41ca docs: add instructions on translations to docs/installation.md 2020-07-31 06:21:48 -04:00
Peter F. Patel-Schneider
0b0cf63240 release 1.0.3rc2 2020-07-30 02:58:23 -04:00
Peter F. Patel-Schneider
5dbf691403 receiver: ignore DJ pairing notifications 2020-07-30 02:44:56 -04:00
John Erling Blad
c1b6bf92c7 po: update pot file 2020-07-29 11:20:43 -04:00
John Erling Blad
3909a79149 po: add translation for Norwegian Bokmal 2020-07-29 11:20:43 -04:00
Peter F. Patel-Schneider
97caca023f docs: update devices.md with M720 2020-07-27 17:01:15 -04:00
Peter F. Patel-Schneider
11bc5bde37 docs: add warning about running Solaar as root 2020-07-27 10:21:55 -04:00
Peter F. Patel-Schneider
fb328b3993 release 1.0.3rc1 2020-07-25 21:25:16 -04:00
Peter F. Patel-Schneider
4fbf5aa531 dist: update ChangeLog for release 1.0.3rc1 2020-07-25 21:25:16 -04:00
Peter F. Patel-Schneider
07b42e2b34 dist: require Python 3.6 2020-07-25 21:25:16 -04:00
Peter F. Patel-Schneider
95893f3aac docs: minor documentation cleanup 2020-07-25 21:25:16 -04:00
Peter F. Patel-Schneider
46e6c98523 dist: remove deprecated solaar-cli appliation 2020-07-25 21:25:16 -04:00
Peter F. Patel-Schneider
e4d3f5e61e dist: don't install files in /etc from setup.py 2020-07-25 21:25:16 -04:00
Peter F. Patel-Schneider
a2ac8b46c1 misc: check for udev rule file presence at startup 2020-07-25 21:25:16 -04:00
Vinícius
d2eabe4258 receiver: prevent errors after clicking the name of an idle device 2020-07-25 16:47:05 -04:00
Peter F. Patel-Schneider
204bc6e810 hidapi: fix infinite loop on some write errors 2020-07-20 20:37:15 +01:00
Alex Cherkayev
e436b1bd1d receiver: add support for EX100 keyboard/mouse and receiver (046d:c517)
docs: add EX100 keyboard/mouse combo
device: add EX100 keyboard and mouse
hidpp10: fix notification parsing, add device features flags, fix documentation links
notifications: fix wpid processing for 27 MHz protocol
cli: add display of device features flags for HID++ 1.0 devices
2020-07-20 11:55:59 -04:00
Peter F. Patel-Schneider
4dfa55c96c receiver: add mode and inversion settings for feature THUMB_WHEEL 2020-07-19 08:35:46 -04:00
Lukas Michel
7f70039284 update german translation (#857)
* update german translation

* update german translation: apply suggestions from code review

Co-authored-by: Marcel Schilling <marcel.schilling@uni-luebeck.de>

Co-authored-by: Marcel Schilling <marcel.schilling@uni-luebeck.de>
2020-07-19 07:55:35 -04:00
Peter F. Patel-Schneider
2d2e71daa3 receiver: restore feature number to feature choice settings 2020-07-16 15:06:08 -04:00
Peter F. Patel-Schneider
4ce2abca0a ui: turn off write-backs for values obtained from device 2020-07-16 15:06:08 -04:00
Peter F. Patel-Schneider
bc6b1de472 gui: correctly show initial value for choice settings 2020-07-16 15:06:08 -04:00
Peter F. Patel-Schneider
90cc629f26 receiver: don't write non-persisted settings when applying them 2020-07-16 15:06:08 -04:00
Peter F. Patel-Schneider
de0894bc34 receiver: adjust CHANGE_HOST numbers to user-visible ones 2020-07-13 19:15:44 -04:00
Peter F. Patel-Schneider
e86a50cfa9 receiver: use report rate feature if available to determine polling rate 2020-07-13 13:34:21 -04:00
Peter F. Patel-Schneider
b6615d5abe cli: in config don't apply setting unnecessarily and don't print setting after writing 2020-07-12 18:12:18 -04:00
Peter F. Patel-Schneider
323fb13161 cli: check range values for validity in config 2020-07-12 18:12:18 -04:00
Peter F. Patel-Schneider
fef22de021 cli: don't lower-case choice values and allow numeric selection of choices 2020-07-12 18:12:18 -04:00
Peter F. Patel-Schneider
5a4205d002 receiver: add CHANGE_HOST setting 2020-07-12 18:04:04 -04:00
Peter F. Patel-Schneider
1c2b347512 receiver: allow for settings that do not persist 2020-07-12 18:04:04 -04:00
Peter F. Patel-Schneider
63872b9146 receiver: add settings option to not wait for reply when writing to device 2020-07-12 18:04:04 -04:00
Peter F. Patel-Schneider
c6506b3508 receiver: add option to not wait for a reply when requesting to device 2020-07-12 18:04:04 -04:00
Peter F. Patel-Schneider
c9c472e391 receiver: add setting for MULTIPLATFORM and DUALPLATFORM feature 2020-07-12 17:38:00 -04:00
Peter F. Patel-Schneider
1dc59fd374 docs: update issue templates 2020-07-11 15:36:49 -04:00
Peter F. Patel-Schneider
24798ee310 docs: remove logitech files and outdated information; update supported features 2020-07-11 15:36:49 -04:00
Peter F. Patel-Schneider
e05c1aa90c cli: make config faster 2020-07-10 14:16:41 -04:00
Peter F. Patel-Schneider
fe0ab16cc8 misc: dump threads on SIGINT 2020-07-09 12:51:38 -04:00
Peter F. Patel-Schneider
c38d10a654 receiver: gather host names from HOSTS_INFO feature and show them 2020-07-09 12:44:27 -04:00
Filipe Laíns
d386f4369b git-blame-ignore-revs: add pre-commit bulk change
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2020-07-07 16:10:37 +01:00
Filipe Laíns
ae4a0eba70 git-blame-ignore-revs: fix commit ids due to rebase
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2020-07-07 16:10:37 +01:00
Peter F. Patel-Schneider
72fd2f255e device: mouse m510v1 doesn't have a working smooth scroll so remove from its descriptor 2020-07-07 10:20:00 -04:00
Filipe Laíns
a8d067035d git-blame-ignore-revs: add yapf, isort and flake8 bulk changes
A clean blame can be accessed with:
git blame --ignore-revs-file .git-blame-ignore-revs <file>

Signed-off-by: Filipe Laíns <lains@archlinux.org>
2020-07-07 15:11:15 +01:00
Filipe Laíns
27c90fa736 yapf: adjust style to not indent closing brackets
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2020-07-07 15:11:15 +01:00
Filipe Laíns
bbaa144397 ci: add pre-commit
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2020-07-07 15:11:15 +01:00
Filipe Laíns
e751f741f7 setup.py: set minimum python version to 3.5
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2020-07-07 15:11:15 +01:00
Filipe Laíns
8e89aa0038 yapf: set max line lenght to 127
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2020-07-07 15:11:15 +01:00
Filipe Laíns
627185079f flake8: initial fix
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2020-07-07 15:11:15 +01:00
Filipe Laíns
de5514aa23 pre-commit: add flake8
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2020-07-07 15:11:15 +01:00
Filipe Laíns
0bc58d5653 flake8: add config
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2020-07-07 15:11:15 +01:00
Filipe Laíns
33521558ed pre-commit: initial fix
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2020-07-07 15:11:15 +01:00
Filipe Laíns
63fa581d13 pre-commit: add initial config
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2020-07-07 15:11:15 +01:00
Filipe Laíns
e6369e0c3c isort: intial import fix
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2020-07-07 15:11:15 +01:00
Filipe Laíns
be4e88dc1a isort: add config
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2020-07-07 15:11:15 +01:00
Filipe Laíns
72a8d311bc yapf: change code style to yapf
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2020-07-07 15:11:15 +01:00
Peter F. Patel-Schneider
cab523e122 receiver: add direct implementation of NEW FN INVERSION feature
receiver: fix bug in NEW FN INVERSION

receiver: fix bug in NEW FN INVERSION

receiver: fix bug in NEW FN INVERSION
2020-06-30 16:20:38 -04:00
Peter F. Patel-Schneider
070a2bf837 receiver: add new set of special keys from logitech documentation
receiver: descriptor and key for MX Vertical mouse
2020-06-28 02:45:20 +01:00
Peter F. Patel-Schneider
0836766bfb receiver: fix k375s Fn inversion 2020-06-26 05:07:47 -04:00
Peter F. Patel-Schneider
4379bd0613 receiver: update tooltips for several settings 2020-06-23 06:26:21 -04:00
Peter F. Patel-Schneider
ad2660a1bd receiver: minor updates to key remapping 2020-06-23 06:26:21 -04:00
Vinícius
6d16462988 receiver: simpler way to create setting information for device descriptors 2020-06-21 20:19:30 -04:00
Peter F. Patel-Schneider
e69c4c6b4f receiver: don't abort on unexpected device number, just warn 2020-06-21 12:16:04 -04:00
Vinícius
5e4c792a64 receiver: fix error when settings listed on descriptor.py return None
e.g. REPROG_CONTROLS_V4 when no keys can be reprogrammed by Solaar
2020-06-20 20:33:29 -04:00
Peter F. Patel-Schneider
c5ca2c2818 receiver: remove testing line from settings_template.py 2020-06-20 14:01:38 -04:00
Peter F. Patel-Schneider
f631f0f551 receiver: keep track of non-features to not continually try to find them 2020-06-20 13:38:09 -04:00
Vinícius
ef54a750dc receiver: implement KEYBOARD_DISABLE_KEYS feature
(the UI needs some improvement)
2020-06-20 13:30:32 -04:00
Peter F. Patel-Schneider
c99f470dd5 receiver: don't consider group 0 in reprogramming keys 2020-06-20 05:56:00 -04:00
Peter F. Patel-Schneider
1dfc4f22df receiver: add more special keys 2020-06-20 05:56:00 -04:00
Peter F. Patel-Schneider
68b4ca7abf receiver: make key settings structure uniform 2020-06-20 05:56:00 -04:00
Peter F. Patel-Schneider
09125bce2d receiver: filter out DJ reports that are not notifications 2020-06-20 05:31:45 -04:00
Peter F. Patel-Schneider
aeb03df3f7 receiver: fix bug reporting hid++ 1.0 batteries 2020-06-17 09:53:16 -04:00
Peter F. Patel-Schneider
f191d95990 misc: better reporting of errors 2020-06-17 09:53:16 -04:00
Peter F. Patel-Schneider
5926596298 receiver: add special keys and actions from Craft Keyboard 2020-06-16 17:42:34 -04:00
Peter F. Patel-Schneider
97fdcbf3ff receiver: modify and add a few names for special keys and actions 2020-06-16 15:21:10 -04:00
Peter F. Patel-Schneider
66c8621cab receiver: handle gmask 0 and group 0 in reprogrammable keys 2020-06-16 15:21:10 -04:00
Peter F. Patel-Schneider
a4bf1da6f9 docs: add information on key reprogramming 2020-06-16 15:21:10 -04:00
Peter F. Patel-Schneider
922414ae04 ui: add map choice control to ui 2020-06-16 15:21:10 -04:00
Peter F. Patel-Schneider
9beb13a305 receiver: add key reprogramming setting 2020-06-16 15:21:10 -04:00
Peter F. Patel-Schneider
89995656cd receiver: only check for device features once per device 2020-06-08 17:01:32 +01:00
Peter F. Patel-Schneider
f198b2706b cli: use Setting name and value to show feature status if not handled directly 2020-06-08 16:59:38 +01:00
Peter F. Patel-Schneider
bd0f9ca7d7 receiver: add feature to Setting class 2020-06-08 16:59:38 +01:00
Peter F. Patel-Schneider
784661bbc0 ui: remove maximum window size 2020-06-07 13:33:42 +01:00
Peter F. Patel-Schneider
579b09619b receiver: process battery voltage notifications 2020-06-06 12:59:26 -04:00
Peter F. Patel-Schneider
013f383bc8 ui: display battery voltage in ui if available 2020-06-06 12:59:26 -04:00
Peter F. Patel-Schneider
7936d2dd48 receiver: use battery voltage in read_battery if available 2020-06-06 12:59:26 -04:00
Peter F. Patel-Schneider
cb84d3b797 ui: remove translation for several strings that should not be translated in window.py 2020-06-06 12:59:26 -04:00
Peter F. Patel-Schneider
79947dca6c receiver: gather and show battery next level where available 2020-06-06 12:59:26 -04:00
Peter F. Patel-Schneider
d41c35b1c6 docs: minor update to usage.md 2020-06-05 12:18:25 -04:00
Peter F. Patel-Schneider
093169fb23 docs: update features.md with current status and add implementation section 2020-06-05 12:18:25 -04:00
Peter F. Patel-Schneider
6c77aa3b61 receiver: add c53d as a Lightspeed receiver 2020-05-25 20:51:17 -04:00
Peter F. Patel-Schneider
4a108b3ab7 release 1.0.2 2020-05-22 01:43:53 +01:00
Peter F. Patel-Schneider
fac6cd6840 po: minor fix to es translation file 2020-05-22 01:19:20 +01:00
Peter F. Patel-Schneider
edf610d235 doc: add usage document 2020-05-22 01:18:44 +01:00
Peter F. Patel-Schneider
dac9c1bd8e doc: minor improvements to index.md 2020-05-22 01:18:44 +01:00
Peter F. Patel-Schneider
352375aa9a doc: minor improvements to installation.md 2020-05-22 01:18:44 +01:00
Peter F. Patel-Schneider
44722560d2 release 1.0.2rc3 2020-05-17 18:39:31 +01:00
daviddavid
101e24c7bf Update again French translation
- by David Geiger <david.david@mageialinux-online.org>
2020-05-17 11:57:11 -04:00
Peter F. Patel-Schneider
b7e8e646b5 ui: don't complain for receivers in other seats 2020-05-17 11:55:01 -04:00
Peter F. Patel-Schneider
97fa7de28a devices: pass arguments through in feature_choices_dynamic 2020-05-17 11:51:38 -04:00
Peter F. Patel-Schneider
302720b0db ui: add --battery-icons=symbolic option to prefer symbolic icons 2020-05-17 16:29:14 +01:00
daviddavid
813c238704 Update French translation
- by David Geiger <david.david@mageialinux-online.org>
2020-05-14 09:36:32 -04:00
Peter F. Patel-Schneider
354c914bd2 docs: improve installation document 2020-05-13 11:48:06 -04:00
daviddavid
574aee0cc7 po formatting updates (for release 1.0.2rc2) 2020-05-13 15:37:57 +01:00
Peter F. Patel-Schneider
a3cdcf4cd1 git: add lib/solaar.egg-info/ to .gitignore 2020-05-13 15:35:35 +01:00
Peter F. Patel-Schneider
592ced0a53 release 1.0.2rc2 2020-05-10 23:11:37 +01:00
Peter F. Patel-Schneider
3a2593798e release: fix up RELEASE.md 2020-05-10 03:49:32 +01:00
Peter F. Patel-Schneider
67b7d46844 docs: update ChangeLog 2020-05-07 19:33:57 +01:00
Peter F. Patel-Schneider
5411e43b77 ui: use Solaar icon instead of missing battery icons 2020-05-07 19:33:57 +01:00
Peter F. Patel-Schneider
66dc0bd285 release: remove packaging directory as it is not maintained 2020-05-02 18:44:34 +01:00
Peter F. Patel-Schneider
f641554ed5 release: release candidates do not have hyphen before rc 2020-05-02 17:42:13 +01:00
Peter F. Patel-Schneider
beec4c2130 release: change version from 1.0.2-rc1 to 1.0.2rc2 2020-05-02 17:42:13 +01:00
Peter F. Patel-Schneider
f5bf488ffc docs: update ChangeLog for 1.0.2rc2 2020-05-02 17:42:13 +01:00
Steven Lilley
1deaa09142 devices: Add Pebble M350 mouse 2020-05-02 17:25:29 +01:00
Peter F. Patel-Schneider
88a0dfff6f ui: add environment variable to switch to symbolic battery icons in tray 2020-05-02 10:28:51 -04:00
Peter F. Patel-Schneider
f28da6e7c4 docs: add a short discussion of how battery icons work 2020-05-02 10:28:51 -04:00
Peter F. Patel-Schneider
5290980ac8 ui: only use standard battery icons 2020-05-02 10:28:51 -04:00
Peter F. Patel-Schneider
4d23d3abac device: heuristic inference of battery level when charging and no discharging information available 2020-05-02 09:58:24 -04:00
Peter F. Patel-Schneider
0c4e757cf9 docs: add K600 TV, M350 WPID 4080, and MX Keys to devices.md and improve wording in it 2020-05-02 09:26:01 -04:00
Peter F. Patel-Schneider
d487a0d889 ui: remove assert that updated receiver is still in window 2020-05-02 14:07:42 +01:00
Roshan Shariff
65824a4c08 ui: add 'desktop-entry' hint to indicate notification source.
GNOME requires that notifications have a 'desktop-entry' hint to be
able to filter notifications by application. See
https://wiki.gnome.org/Initiatives/GnomeGoals/NotificationSource.

Fixes pwr-Solaar/Solaar#734
2020-05-01 13:56:22 -04:00
tarxf
58a1c7ffb0 docs: dixed name typo for MX Master 2S 2020-04-25 02:38:02 +01:00
Peter F. Patel-Schneider
1f896d2b9e docs: add changing device features to long description of Solaar 2020-04-22 21:37:25 +01:00
Peter F. Patel-Schneider
377c954933 install: remove Daniels email from setup.py 2020-04-20 12:01:57 -04:00
Peter F. Patel-Schneider
4744ce47b2 install: update installation directions and remove outdated rules/install.sh 2020-04-20 12:01:57 -04:00
Peter F. Patel-Schneider
b01b74f2a8 install: install udev rule with pip 2020-04-20 12:01:57 -04:00
Peter F. Patel-Schneider
6282ae05e8 install: remove incorrect code for determining autostart directory from setup.py 2020-04-20 12:01:57 -04:00
Peter F. Patel-Schneider
b5e1f47c50 ui: add setuptools global install share directory to icon directories 2020-04-20 10:32:40 -04:00
Peter F. Patel-Schneider
8ffaeb112f devices: add four older devices 2020-04-20 15:26:37 +01:00
Peter F. Patel-Schneider
2189d4a35b receiver: add new macro for old receivers and use it to set max devices to 6 for C517 2020-04-20 15:26:37 +01:00
Jan Szenborn
706ee2990f Improve polish translations 2020-04-20 15:25:47 +01:00
Peter F. Patel-Schneider
06875fb9ab release: update remaining version 1.0.1 to 1.0.2-rc1 where needed 2020-04-20 15:22:30 +01:00
Peter F. Patel-Schneider
f6b0cc59ed ui: only use file path for tray icon if icon name is file in current directory 2020-04-20 15:21:19 +01:00
Peter F. Patel-Schneider
e3aacdbf05 receiver: don't check that device kind matches feature kind 2020-04-20 15:20:03 +01:00
Peter F. Patel-Schneider
45dc81b4c4 docs: update information on pre-built packages 2020-04-20 15:19:22 +01:00
Peter F. Patel-Schneider
0324fd9a1e ui: more flexible way to determine icon from battery level 2020-04-18 14:27:42 +01:00
Thomas Uhle
ca9f9b3447 ui: add support for Ayatana AppIndicator 2020-04-07 18:58:18 -04:00
Peter F. Patel-Schneider
624247d378 install: fix up errors when required packages not installed 2020-04-05 20:55:32 +01:00
Thomas Uhle
5f8dbdeb6d ui: fix tooltip description
The program's name is printed twice if AppIndicator is used and no receiver
is found because AppIndicator always adds the program's name as a title to
the tooltip.
2020-04-01 11:10:54 -04:00
Thomas Uhle
2bdb844557 ui: fix end of iterative calls to _blink()
Prepare _icon_before_attention for the next iteration by reinitializing it
at the end of the current iteration.
2020-04-01 11:10:54 -04:00
Thomas Uhle
422f336d70 ui: add missing parentheses to function call
Compare function's return value to AppIndicator3.IndicatorStatus.ATTENTION
instead of the function object reference.
2020-04-01 11:10:54 -04:00
Peter F. Patel-Schneider
563ef0d8ef receiver: remove extra argument in call when unpairing 2020-03-22 17:23:28 +00:00
Peter F. Patel-Schneider
3a85c4f64b UI: lookup attention icon filename directly to get around bug in libappindicator 2020-03-17 23:17:59 +00:00
Filipe Laíns
4056f5b9d3 release.sh: simplify script
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2020-03-16 21:59:41 +00:00
Filipe Laíns
442a7d18a5 release.sh: document release process
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2020-03-16 21:59:41 +00:00
Filipe Laíns
79be4b20d7 release.sh: don't throw github release creation error on dry run
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2020-03-16 21:59:41 +00:00
Filipe Laíns
b2f3b56c31 release 1.0.2-rc1
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2020-03-16 20:57:35 +00:00
Peter F. Patel-Schneider
072f932206 ui: handle devices and receivers with no firmware information 2020-03-16 20:55:18 +00:00
Filipe Laíns
d5a3a4fe7e release.sh: initial script
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2020-03-16 16:58:41 +00:00
Peter F. Patel-Schneider
a49b7938e0 receiver: Receiver C517 can have two paired devices 2020-03-16 16:04:16 +00:00
Peter F. Patel-Schneider
1eef88eb44 cli: handle receivers with no firmware information 2020-03-16 16:04:16 +00:00
Peter F. Patel-Schneider
eda1399330 cli: force unpairing attempt when using cli 2020-03-15 23:34:51 +00:00
Peter F. Patel-Schneider
8dbc4b5707 docs: Update ChangeLog 2020-03-15 23:33:47 +00:00
Peter F. Patel-Schneider
687a28d2c2 UI: lookup icon filenames directly to get around bug in libappindicator 2020-03-15 22:00:56 +00:00
Peter F. Patel-Schneider
f733390bd1 install: autostart .desktop file has --window=hide 2020-03-15 22:00:21 +00:00
Peter F. Patel-Schneider
ac6fa9643f UI: change default for --window to show 2020-03-15 22:00:21 +00:00
Peter F. Patel-Schneider
f28053a09a docs: improve documentation on required packages 2020-03-15 21:59:42 +00:00
gogogogi
49145ae272 translations: Update Croatian language translation
* Update Croatian language

* Update version
2020-03-15 16:30:00 -04:00
Peter F. Patel-Schneider
af26870e83 docs: use correct name of udev rules file in installation directions 2020-03-08 15:15:17 +00:00
Peter F. Patel-Schneider
007163a563 docs: update ChangeLog 2020-03-08 15:15:17 +00:00
Peter F. Patel-Schneider
a9acdbe47a receiver: add c537 nano receiver 2020-03-06 18:00:37 -05:00
Peter F. Patel-Schneider
955df30c7f upower: properly add signal receiver 2020-02-22 08:46:56 -05:00
Peter F. Patel-Schneider
23c0397764 listener: mark device as inactive after resume so that settings are correctly pushed 2020-02-22 08:46:56 -05:00
Peter F. Patel-Schneider
789f5f05c3 receiver: don't check features when device is not online 2020-02-22 08:46:56 -05:00
Peter F. Patel-Schneider
ea2c22c015 receiver: fix seldom-encountered bug for devices that have no features set up yet 2020-02-21 16:52:28 +00:00
Peter F. Patel-Schneider
1c09b9c45d upower: add in logind signals for suspend/resume 2020-02-21 16:52:28 +00:00
Peter F. Patel-Schneider
dd9626f7a4 docs: ask for git describe output if running a cloned version 2020-02-21 16:48:05 +00:00
Rijnhard Hessel
35909afb0d packaging: remove solaar-gnome3 package 2020-02-21 09:50:30 -05:00
Rijnhard Hessel
8e67bbbc11 receiver: add safety for non-compliant mouse features
receiver: safely handle errors with check_feature to allow device to be detected even if some features are inconsistent
2020-02-21 09:33:14 -05:00
Peter F. Patel-Schneider
a5813e4e23 packaging: remove last vestiges of python2 2020-02-20 19:49:38 +00:00
Peter F. Patel-Schneider
d439d43be6 docs: replace dummy URL for Solaar with real URL 2020-02-20 12:27:41 +00:00
Peter F. Patel-Schneider
11465f2b2a cli: add probe command to show receiver register information 2020-02-18 23:21:59 +00:00
Peter F. Patel-Schneider
079f2dacd4 docs: add information on --windows flag and rewrite other bits of index.md 2020-02-18 08:32:02 -05:00
Peter F. Patel-Schneider
7c6bd4202d receiver: use dictionary for expected message length checking; ignore messages with unknown report ids 2020-02-18 08:14:22 -05:00
Peter F. Patel-Schneider
1740a9a8c4 receiver: segregate and standardly handle DJ notifications separately - just ignore them all for now 2020-02-18 08:14:22 -05:00
Peter F. Patel-Schneider
0cadc3247e receiver: don't create notifications for movement and key reports 2020-02-18 08:14:22 -05:00
Peter F. Patel-Schneider
e23de2ee9f ui: add quit button to main window 2020-02-18 13:14:10 +00:00
Peter F. Patel-Schneider
8fb52a3f37 ui: don't show warning in pairing window for receivers with unlimited pairing 2020-02-18 12:19:45 +00:00
Peter F. Patel-Schneider
3edac85b90 ui: turn on window manager notifications again 2020-02-18 12:17:49 +00:00
Peter F. Patel-Schneider
64c76e51ef receiver,cli,ui: minor code cleanup 2020-02-17 11:53:39 +00:00
Peter F. Patel-Schneider
02cac598a0 receiver: all nano receivers re-pair but don't unpair 2020-02-17 11:53:39 +00:00
Peter F. Patel-Schneider
02a47b4003 install: adjust autostart desktop installation to use usual desktop file 2020-02-17 08:35:47 +00:00
Peter F. Patel-Schneider
4afe8c893b ui: add option to show the main window or run solaar without tray 2020-02-17 08:35:47 +00:00
Peter F. Patel-Schneider
5afa094175 ui: Add message about remaining pairings to pairing window when receiver has limited pairings 2020-02-17 08:34:53 +00:00
Peter F. Patel-Schneider
196705ba1f docs: fix information about receiver c534 2020-02-17 08:34:53 +00:00
Peter F. Patel-Schneider
4c46a999f7 gui: treat nano protocol disconnections correctly when pairing 2020-02-17 08:34:53 +00:00
Peter F. Patel-Schneider
7bd31c0d95 cli: complain when trying to unpair from a receiver that does not unpair 2020-02-17 08:34:53 +00:00
Peter F. Patel-Schneider
dc2a1adf26 ui: handle re-pairing receivers correctly when pairing 2020-02-17 08:34:53 +00:00
Peter F. Patel-Schneider
e89b50cdf2 cli: correct reporting for pairing with receivers that re-pair (i.e., c534) 2020-02-17 08:34:53 +00:00
Peter F. Patel-Schneider
d08e0a9574 cli: Show a positive response instead of an error when receiver pairs on already-used slot in CLI 2020-02-17 08:34:53 +00:00
Peter F. Patel-Schneider
22d37c4c1c ui: Better determination in GUI of when receiver may pair (still might be conservative) 2020-02-17 08:34:53 +00:00
Peter F. Patel-Schneider
546ccb7ac2 receiver: determine remaining pairings (if receiver has this) and display in solaar show and main window 2020-02-17 08:34:53 +00:00
Peter F. Patel-Schneider
1ab03d4c9f receiver: add check for bad results from getting the usb device 2020-02-16 22:16:37 +00:00
Peter F. Patel-Schneider
a6fcb75aa8 receiver: get receiver name from receiver information list 2020-02-16 22:16:37 +00:00
Peter F. Patel-Schneider
907c5ab075 receiver: change usb identification of receivers to dictionary to allow adding other fields, add receiver name to dictionary 2020-02-16 22:16:37 +00:00
Peter F. Patel-Schneider
515f994ab8 receiver: ignore disconnects of disconnected devices 2020-02-16 22:16:37 +00:00
Peter F. Patel-Schneider
25905c5d77 receiver: Show type of receiver in CLI show command 2020-02-16 22:16:37 +00:00
Peter F. Patel-Schneider
babf0f4ded receiver: Show serial number in stringify of receivers 2020-02-16 22:16:37 +00:00
Peter F. Patel-Schneider
41664b8e21 docs: update changelog to 11 February 2020 commits 2020-02-16 22:07:45 +00:00
svntjng
5c080a7831 docs: add supported feature for M330 2020-02-16 22:06:12 +00:00
Peter F. Patel-Schneider
5aa4fa0239 update version in docs/_config.yml to 1.0.1 2020-02-11 15:55:15 +00:00
Peter F. Patel-Schneider
4f4e610635 receiver: battery level 0 is unknown level 2020-02-10 18:44:28 +00:00
Peter F. Patel-Schneider
39791be440 doc: fix typos and improve some wording 2020-02-06 19:09:00 +01:00
Peter F. Patel-Schneider
2814350f9f doc: fix wording about supported Nano receivers 2020-02-06 19:09:00 +01:00
Peter F. Patel-Schneider
4a28b48275 doc: add paragraph on firmware 2020-02-06 19:09:00 +01:00
Peter F. Patel-Schneider
97474a21de doc: fix formatting, add receivers, change version 4.5 to 2.0 2020-02-06 19:09:00 +01:00
Peter F. Patel-Schneider
719106bf0f doc: solaar does keep track of device status 2020-02-06 19:09:00 +01:00
Peter F. Patel-Schneider
0a735a32ed doc: better documentation: devices and capabilities 2020-02-06 19:09:00 +01:00
Dmitriusan
bd26b9340d scripts/debian: switch to python3 2020-02-06 19:06:47 +01:00
Peter F. Patel-Schneider
f45ae5ffad solaar: use python3, not generic python 2020-02-06 17:37:10 +01:00
Peter F. Patel-Schneider
0520dde990 receiver: use None for serial number of c534 2020-02-04 22:04:43 +01:00
Peter F. Patel-Schneider
e53781ec6e install: autostart desktop file starts with tray only 2020-01-22 22:22:14 +00:00
Peter F. Patel-Schneider
1bc189e2fe ui: add --tray option to start without window visible 2020-01-22 22:22:14 +00:00
Peter F. Patel-Schneider
91bcfa28ea docs: minor changes to installation.md to eliminate python2 support 2020-01-21 21:51:35 +00:00
Filipe Laíns
64c1de32da setup.py: drop python 2 support
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2020-01-21 21:51:25 +00:00
Peter F. Patel-Schneider
56762b5494 device: move persister from Setting to _DeviceDescriptor to get around problem with settings discovered after startup 2020-01-21 03:23:25 +00:00
Peter F. Patel-Schneider
77e21a0b63 ui: fix crash when styles add padding by not setting 1-pixel columns; slightly better window layout; add style class to window 2020-01-21 03:11:35 +00:00
Peter F. Patel-Schneider
d6fa5269c5 ui: don't ignore offline devices when determining whether pairing is possible 2020-01-21 03:08:49 +00:00
Peter F. Patel-Schneider
0198d58dc7 hidpp20: fix error when showing battery
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2020-01-19 18:18:33 +00:00
Filipe Laíns
c30f0a79bd docs: features: add partly working and unsupported status
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2020-01-19 18:18:30 +00:00
Filipe Laíns
89ee83b906 docs: features: change checkmark style
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2020-01-19 18:18:11 +00:00
Filipe Laíns
0bef7b84f8 docs: features: make the table easier to maintain
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2020-01-19 18:18:08 +00:00
Filipe Laíns
c3e90bc73e docs: features: make the table readable in plain ascii
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2020-01-19 18:17:54 +00:00
Alex Cherkayev
814b7f30ba docs: features: added some missing feature names and list of implemented features
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2020-01-19 18:17:18 +00:00
Alex Cherkayev
8039c035a7 devices: Add new variant of K800 keyboard
docs: Add K800 new variant to supported
2020-01-12 16:11:03 +00:00
effective-light
430b70711b hidpp20: features: add BATTERY_VOLTAGE (0x1001) support
Signed-off-by: Filipe Laíns <lains@archlinux.org>

Co-authored-by: Filipe Laíns <lains@archlinux.org>
2020-01-12 16:05:21 +00:00
nightsky30
82915eea4b docs: update the USB IDs list 2019-12-29 14:46:59 +00:00
Peter F. Patel-Schneider
995544396c receiver: don't log messages with unknown report IDs 2019-12-26 16:10:48 +00:00
Peter F. Patel-Schneider
4678f52293 don't have window always be on top 2019-12-24 18:54:12 +00:00
Peter F. Patel-Schneider
26c5a5f9ba clarify license status; fix debian packaging copyight notice 2019-12-24 18:53:43 +00:00
Peter F. Patel-Schneider
c6ccc0638d devices: add M310 2019-12-24 12:49:00 +00:00
drupal-daffie
6ba8c6c3fc setup: use setuptools if available 2019-12-24 12:16:35 +00:00
Peter F. Patel-Schneider
9087f4187c docs: adjust documentation to new changes 2019-12-24 12:13:58 +00:00
drupal-daffie
673c81c096 docs: devices: add MX Master 2s 2019-12-16 15:33:50 +00:00
drupal-daffie
43bfa80753 docs: devices: add Mx Master 3 2019-12-16 12:03:03 +00:00
gogogogi
3884ce14d7 docs: readme: add new ppa 2019-12-14 21:22:25 +00:00
spaced
4fafd4f6be hidpp20: features: add very basic implementation of 0x1982 (Backlight 2)
Fixes #547
2019-12-12 18:56:08 +00:00
Chris Rainey
0bec0e02b1 docd: devices: add M330 2019-12-10 23:36:31 +00:00
Filipe Laíns
59c0367283 github: add issue templates 2019-12-01 21:48:57 +00:00
marcelkarger
63f523dac6 po: update German translation 2019-11-30 23:14:32 +00:00
Heimen Stoffels
4822975acb po: added Dutch translation 2019-11-30 23:13:26 +00:00
Chad Condon
c389c9c2b7 ur: repair low resolution smooth scrolling 2019-11-30 23:12:07 +00:00
KTB
76e70799aa Update devices.md for Anywhere MX 2 - R/W DPI
Simple doc update to show that Solaar supports changing DPI for the Logitech Anywhere MX 2.
2019-10-20 23:55:02 +01:00
Tom Swartz
2a94cc9233 Fix typos in docs 2019-10-20 23:53:45 +01:00
Tom Swartz
ae9e862f19 Fix typos in comments 2019-10-20 23:53:45 +01:00
Tom Swartz
12f4e187d6 Fix typos in logging, output 2019-10-20 23:53:45 +01:00
Filipe Laíns
51dd2a5d28 notifications: add missing protocol names
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2019-10-20 23:19:34 +01:00
Alex Cherkayev
6981555804 notifications: fix battery status notification parsing
Fix indicator tooltip (duplicate Solaar line, python list instead of battery status).
2019-08-20 09:40:39 +02:00
spaced
3583759d3a devices: basic support for craft keyboard
* basic support for craft keyboard
* fix issue where _(status) throws exception because namedInt with UTF8.decode
2019-08-20 09:39:11 +02:00
david_david
c92a889b68 po: formatting updates
* po formatting updates

- Update French translation by David Geiger <david.david@mageialinux-online.org>
- Update version into setup.py file

* Update version in fr.po
2019-08-20 09:37:15 +02:00
Peter Wu
b9fb005c9c docs: Deduplicate README contents, use a symlink
docs/index.md and README.md are almost identical, except for some paths
and the metadata table on top of the file. Use absolute paths to the
website to avoid breaking links, and symlink README.md.
2019-08-20 09:36:16 +02:00
Zachary Cook
a06ea6de11 data: fix icon theme for battery level
It was previously assigning levels 1-89 to caution and 90+ to full, which was unintended due to the floor division by 100
2019-08-20 09:35:31 +02:00
Andreas Schneider
a868b477e1 Fix reading and storing DPI in config settings
Fixes #328
Fixes #356
Fixes #545
2019-08-20 09:24:22 +02:00
spaced
c799e038de added to list of supported devices 2019-08-20 09:23:38 +02:00
spaced
8468be2126 add doc for silent mouse M585/M590 2019-08-20 09:23:38 +02:00
spaced
1ff9c3a40b support for silent mouse M585/M590 2019-08-20 09:23:38 +02:00
Chris Johnston
9b201f6b0d copy updated README content 2019-07-27 15:56:53 +01:00
Chris Johnston
afda6f9f66 remove all google analytics stuff from page templates 2019-07-27 15:56:53 +01:00
Chris Johnston
5cc0b8854d update config.yml for new repo path 2019-07-27 15:56:53 +01:00
Chris Johnston
f88951c56d Squash previous changes and rebase master branch
Set theme jekyll-theme-slate

update _config.yml

move some files around

add an index file

delete files that will no longer be needed

include jekyll front matter

Update the index page layout to use updated template

re-create the page layout from the updated template

add a favicon

remove manual gh pages build script

use master branch docs/ folder instead

add favicon to default layout

move layouts and includes back because of restriction with gh pages

testing: move index back into project root

move everything under docs, including config.yml

dont put the favicon in _includes

Fix building locally, fix logo

- resize the original logo document so that it doesn't have extra whitespace
- style the logo to match the original page
- fix issue when building locally, repo format was incorrect

Ignore files that are specific to documentation

add a readme that describes how to build the docs

remove downloads, since installation instructions are provided elsewhere

fix broken links in index page

fix the page header on all non-index pages

use site.baseurl for images

fix urls when on testing site with baseurl
2019-07-27 15:56:53 +01:00
Filipe Laíns
2aab7f71fd release 1.0.1
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2019-07-26 16:55:51 +01:00
Filipe Laíns
6376980213 udev: fix c52b + MX Master
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2019-07-26 17:50:13 +02:00
Filipe Laíns
1bb08d011d base-usb: add new Lightspeed receiver
used in the G305

Signed-off-by: Filipe Laíns <lains@archlinux.org>
2019-07-26 15:23:55 +01:00
Filipe Laíns
966c55e69d base-usb: fix non-unifying for linux 5.2
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2019-07-26 15:18:24 +01:00
Filipe Laíns
6b14004a6f udev: fix writting to the device
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2019-07-26 15:10:59 +01:00
Daehyeok Mun
7a4f7bbb84 docs: fix broken github.io link to new repo url
Signed-off-by: Daehyeok Mun <daehyeok@gmail.com>
2019-07-26 15:38:16 +02:00
Matthias Fulz
155e2f8c40 fix: #531 #537. Better handling of EPIPE during hid write. 2019-07-26 15:35:21 +02:00
Filipe Laíns
6a1968beff release 1.0.0
Signed-off-by: Filipe Laíns <lains@archlinux.org>
2019-07-26 14:33:16 +01:00
Filipe Laíns
f4557233f1 base-usb: add support for Lightspeed receivers
They way we are currently identifying the type of a receiver (unifying,
nano, lightspeed) in the Receiver class is pretty bad. The correct
approach would be to specify the receiver type name string in
base_usb.py.

Signed-off-by: Filipe Laíns <lains@archlinux.org>
2019-07-16 11:10:03 +02:00
muzena
a597b81f5a Update Croatian translation 2019-07-14 23:57:15 +01:00
Peter Wu
a587ae65d1 Merge pull request #477 from doctor64/pointer_info_show
Added status info print and rename some functions
2019-06-29 18:08:52 +02:00
Peter Wu
6522b5fef0 Merge pull request #514 from pdecat/fix-zh_TW
Fix zh_TW translation (nplural=1)
2019-06-29 18:05:49 +02:00
Peter Wu
7f78f0c580 Merge pull request #515 from pdecat/fix-icon-dep
Add gnome-icon-theme as an acceptable dependency for icons
2019-06-29 18:05:14 +02:00
Peter Wu
127a8053d8 Merge pull request #521 from kacpi2442/master
Added basic support for Lenovo dongle,
https://download.lenovo.com/consumer/options/lenovo_n50_wireless_optical_mouse.pdf
2019-06-29 18:04:25 +02:00
Patrick Decat
6c0acee645 Fix UnicodeDecodeError with ngettext and python2 2019-06-29 18:01:54 +02:00
nicolas
60c52eb13f Name for K780
“Multi-Device” and not “Solar”
2019-06-29 17:59:44 +02:00
Benoit Hanotte
8bac8d68f4 Add MX Master settings
Add the same settings to the logitech MX Master as the one from the MX
Master 2 (scroll wheel DPI, smart scoll sensitivity).
2019-06-29 17:57:02 +02:00
Maarti
087a5d2c42 Update of the installation instructions for Debian (#490)
Solaar is available on official Debian repository and the old repo link
`https://pwr.github.io/Solaar/packages/` is dead and causes `404 Not
Found` error and `The repository 'http://pwr.github.io/Solaar/packages
./ Release' does not have a Release file.` error when doing `apt update`
so I updated the installation instructions.
2019-06-29 17:56:07 +02:00
kacpi2442
481511b6c2 Added basic support for Lenovo dongle 2019-04-15 15:40:40 +02:00
Patrick Decat
21d98294bd Add gnome-icon-theme as an acceptable dependency for icons 2019-03-26 15:46:14 +01:00
Patrick Decat
ebbb54758b Fix zh_TW translation (nplural=1) 2019-03-26 15:12:44 +01:00
Peter Wu
c07c115ee3 Avoid collision for wpid 4055 (M185 vs M235)
Hopefully use of a slash does not cause issues. M505 already uses slash
in its codename.

Fixes #499
2019-01-30 16:58:00 +01:00
Peter Dave Hello
8c02320795 docs/devices: Add m235 device information 2019-01-30 16:55:24 +01:00
Markus Heiser
932164458a icons: add application icons from repo's $git-toplevel/share/solaar/
Add application path from the repository to the search paths.

When you Install a project in editable mode (i.e. setuptools "develop mode")
from a local project path, the application path is ``./share``, relative to
git's top level folder. Add this path at the end of search path::

  echo "$(git rev-parse --show-toplevel)/share"
2019-01-30 12:38:54 +01:00
Markus Heiser
de79bf1b5c gtk.main(): make source more readable + comment about cli & gui 2019-01-30 12:38:54 +01:00
Markus Heiser
5944103aef setup.py: fix install_requires and add comment about OS packages 2019-01-30 12:38:54 +01:00
Markus Heiser
ab4226e066 setup.py: fix ModuleNotFoundError: No module named 'solaar'
Fix the "chicken or the egg" problem: while installing solaar, setup.py tries to
import solaar. This will only work if solaar already is installed before. On
first time installation a import exception is raised.::

$ pip install git+https://github.com/pwr/Solaar.git
Collecting git+https://github.com/pwr/Solaar.git
  Cloning https://github.com/pwr/Solaar.git to /tmp/pip-req-build-xzyoskf5
    Complete output from command python setup.py egg_info:
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/tmp/pip-req-build-xzyoskf5/setup.py", line 11, in <module>
        from solaar import NAME, __version__
    ModuleNotFoundError: No module named 'solaar'
2019-01-30 12:38:54 +01:00
Peter Dave Hello
a66121db0d Optimize PNG images losslessly with zopflipng (#484)
11 images recompressed as below:

jekyll/images/bg_hr.png              | Bin 943 -> 96 bytes
jekyll/images/blacktocat.png         | Bin 1428 -> 432 bytes
jekyll/images/icon_download.png      | Bin 1162 -> 230 bytes
jekyll/images/sprite_download.png    | Bin 16799 -> 14650 bytes
share/solaar/icons/light_000.png     | Bin 1750 -> 1657 bytes
share/solaar/icons/light_020.png     | Bin 1942 -> 1895 bytes
share/solaar/icons/light_040.png     | Bin 1578 -> 1461 bytes
share/solaar/icons/light_060.png     | Bin 2442 -> 2319 bytes
share/solaar/icons/light_080.png     | Bin 1910 -> 1803 bytes
share/solaar/icons/light_100.png     | Bin 2376 -> 2249 bytes
share/solaar/icons/light_unknown.png | Bin 1108 -> 1007 bytes
2019-01-30 12:36:20 +01:00
Peter Dave Hello
eacfdea37f Add zh_TW Traditional translation po file (#485) 2019-01-30 12:35:35 +01:00
Peter Dave Hello
68b1f4e413 Update Data of Wireless Mouse M235 (#486) 2019-01-30 12:35:20 +01:00
CD Athuraliya
947035a7b7 Add K400 Plus (#492) 2019-01-30 12:30:36 +01:00
Xaver Maierhofer
e54134cda9 Update arch package information (#496) 2019-01-30 12:29:58 +01:00
Beni Cherniavsky-Paskin
1609c3e98a Display "K400 Plus" rather than just "Plus" (#483) 2018-12-30 18:19:38 +01:00
Alex Cherkayev
ed9aa76547 Added status info on features MOUSE_POINTER, VERTICAL_SCROLLING, HI_RES_SCROLLING, POINTER_SPEED and LOWRES_WHEEL to solaar show.
Renamed functions for HI_RES_SCROLLING and LOWRES_WHEEL features for consistency.
2018-11-20 16:29:38 +02:00
Danny
b8529030e6 setup.py: detect "--prefix=" correctly. (#433) 2018-08-15 18:46:50 +02:00
Peter Wu
1412a07899 Merge pull request #440 from nostrad/master
Improve trackball support
2018-08-15 15:14:08 +02:00
Mattias Jernberg
f79ad67ea7 Add trackball for all settings that mice have 2018-08-13 18:44:16 +02:00
Mattias Jernberg
dd8018a4d5 Prepare for allowing multiple device kinds in settings 2018-08-13 18:44:16 +02:00
Mattias Jernberg
350784eb70 Print an error message when assertion fails 2018-08-13 18:36:52 +02:00
Peter Wu
f0fc63e5b7 Merge pull request #295 from cschreib/master
Added support for MintX icon set (for Linux Mint integration)
2018-08-13 11:33:10 +02:00
Peter Wu
51375d4510 Merge pull request #454 from lopsided98/tree-scroll-fix
Fix device tree GUI hierarchy (Closes #453).
2018-08-12 12:22:50 +02:00
Ben Wolsieffer
2c0ea34694 Fix device tree GUI hierarchy. 2018-08-11 16:24:15 -04:00
Peter Wu
867edf8516 Merge pull request #146 from tristianc/master
Added border around tree view.
2018-08-11 17:55:37 +02:00
Peter Wu
dcd1a88250 Merge pull request #390 from Toshik1978/master
Added Logitech K375s support
2018-08-11 16:36:13 +02:00
Peter Wu
8f95dd323d Merge pull request #410 from lckarssen/add-mx-ergo
Update devices.md with MX Ergo trackball
2018-08-11 16:27:29 +02:00
Peter Wu
336b778398 Merge pull request #452 from lopsided98/hidpp-4.5-fixes
Fix errors related to sleep and power on/off (especially HID++ >=2.0 devices).

Closes #414 by @SonicFrog who originally came up with a similar fix for the connection notice.
2018-08-11 16:26:25 +02:00
Peter Wu
572c7f5e59 Merge pull request #450 from lopsided98/new-m705
Add support for new version of M705 (M-R0073).
2018-08-11 16:11:37 +02:00
Peter Wu
6b12b7935f Merge pull request #428 from Lin-Buo-Ren/patch-add-mk240-nano-information
Information and comments regarding Logitech MK240 NANO Combo
2018-08-11 16:06:08 +02:00
Peter Wu
ade2fbacec Merge pull request #399 from Valantin/patch-1
Add MX Master 2S descriptor
2018-08-11 16:03:18 +02:00
Ben Wolsieffer
a59368f3e7 Fix issues with HID++ >= 2.0 devices (particularly related to sleep).
* Don't assume 0x41 messages only occur when a device is first paired
    (prevents errors when waking from sleep or turning a device on)
  * Delay reads/writes when a device is powered on, to prevent broken pipe
    errors (hacky solution).
  * Don't clear status when a device connects, preventing settings from being
    cleared when a device sleeps or is turned off.
  * Fix typos.
2018-08-10 23:15:37 -04:00
Jason Tibbitts
d021d87656 Python 3.7 compatibility fixes
This fixes the python 3.7 incompatibilities arising from 'async'
becoming a reserved word.

The file lib/solaar/async.py is renamed to asks.py.  I picked the name
because it defines the TaskRunner class and it's the best I could come
up in fifteen seconds.

The async function in solar/ui/__init__.py is renamed to ui_async, and
the various imports of that function are changed to match.

Without this patch it doesn't build at all.  I am running with this
patch applied and everything appears to work as expected.

Signed-off-by: Jason Tibbitts <tibbs@math.uh.edu>
2018-08-07 12:51:32 -04:00
Ben Wolsieffer
5d0d353c74 Add support for new version of M705 (M-R0073). 2018-08-05 00:10:59 -04:00
林博仁(Buo-ren, Lin)
e00d680fc9 Information and comments regarding Logitech MK240 NANO Combo
Signed-off-by: 林博仁(Buo-ren, Lin) <Buo.Ren.Lin@gmail.com>
2018-04-12 14:15:47 +08:00
Peter Wu
59b7285fdf Merge pull request #412 from aimylios/aimylios-fedora
Update link to Fedora package in README.md
2018-02-02 16:20:47 +01:00
aimylios
988bdc2c8d Update link to Fedora package in README.md
The "Fedora Package DB" is not updated any more, refer to the new "Fedora Packages" instead.
2018-01-14 12:15:38 +01:00
Peter Wu
1a67b33860 Merge pull request #382 from mchehab/fix_solaar_start_issues
Fix solaar start issues
2018-01-12 18:11:45 +01:00
Lennart C. Karssen
d43bffc9d9 Update devices.md with MX Ergo trackball
This commit adds the Logitech MX Ergo to the list of supported devices.
2018-01-04 16:52:23 +01:00
Roberto Valentini
f8079f4f9d Add MX Master 2S descriptor
Add descriptor for MX Master 2S to support High Resolution Wheel, correct charge level and DPI configuration
2017-11-16 14:53:27 +01:00
Anton Krivenko
47e7f997d5 Added Logitech K375s support 2017-10-14 22:08:40 +03:00
Peter Wu
8c0cf9fe9b Merge pull request #342 from jrbenito/MK270-desc
Mk270 Combo information and descritptors
2017-09-26 23:16:58 +01:00
Peter Wu
fa8bd83ba3 Merge pull request #387 from ryantig/patch-1
Minor installation.md edit; gpasswd cmd
2017-09-26 23:13:59 +01:00
ryantig
697fb999b4 Minor installation.md edit; gpasswd cmd
Add '-a' after gpasswd to add USER to group plugdev.
Per: ➜ gpasswd --help
Usage: gpasswd [option] GROUP

Options:
  -a, --add USER                add USER to GROUP
  -d, --delete USER             remove USER from GROUP
  -h, --help                    display this help message and exit
  -Q, --root CHROOT_DIR         directory to chroot into
  -r, --remove-password         remove the GROUP's password
  -R, --restrict                restrict access to GROUP to its members
  -M, --members USER,...        set the list of members of GROUP
  -A, --administrators ADMIN,...
                                set the list of administrators for GROUP
Except for the -A and -M options, the options cannot be combined.
2017-09-26 09:23:35 -07:00
Josenivaldo Benito Jr
aeb943fc9e Descriptor for K270 and M185
This K270 is the non unifying version and we know that it has, at
least, one variation (unifying) out there.

M185 mouse is also older, as per PR #337 there is at least two newer
versions of this mouse.

Signed-off-by: Josenivaldo Benito Jr <jrbenito@benito.qsl.br>
2017-09-25 14:57:11 -03:00
Josenivaldo Benito Jr
434af009cb Information regarding MK270 combo
This combo is composed by K270 keyboard (non unifying version) and M185
mouse. Both paired to a nano receiver with PID c534.

Signed-off-by: Josenivaldo Benito Jr <jrbenito@benito.qsl.br>
2017-09-25 14:55:47 -03:00
Peter Wu
cc010cb653 Merge pull request #385 from mchehab/pt-br-translation
Update pt_BR translation
2017-09-21 01:52:22 +01:00
Mauro Carvalho Chehab
e450e959a6 Update pt_BR translation
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-09-20 21:48:08 -03:00
Peter Wu
10f3421021 Merge pull request #345 from jrbenito/M510_v4.5
Add M510 (new version) to descriptors
2017-09-21 00:30:31 +01:00
Peter Wu
8eba60d617 Merge pull request #360 from lasers/remove-dead-links
Remove dead links
2017-09-21 00:25:11 +01:00
Peter Wu
e3d658ea10 Merge pull request #351 from mchehab/mx_anywhere2-v5
Mx anywhere2 v5
2017-09-21 00:16:15 +01:00
Peter Wu
ef1c051e10 Merge pull request #383 from skarmoutsosv/skarmoutsosv-patch-1
Update el.po
2017-09-21 00:11:04 +01:00
Peter Wu
bc566718b4 Merge pull request #384 from michal2229/master
Updated Polish translation
2017-09-21 00:09:05 +01:00
Michal B
22719f21fc Updated Polish translation 2017-09-19 20:00:43 +02:00
Vangelis Skarmoutsos
c51daa922c Update el.po 2017-09-11 21:02:14 +03:00
Mauro Carvalho Chehab
632d8804be listener: don't add elements if queue is full
When Solaar is loaded, if a large number of events happen,
it will lose the register events, as the queue size is too
small (16). So, check if the queue is full, in order to
avoid losing those important events.

Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-09-11 10:36:12 -03:00
Mauro Carvalho Chehab
a4b7194490 listener: fix device registration logic
The "already_known" var actually doesn't track if the device was
already registered or not.

That causes race issues at Solaar, causing it to sometimes not
detect a device.

Change the logic to always call register_new_device if the
corresponding events happen, and updating already_known
to reflect it.

Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-09-11 10:34:23 -03:00
Mauro Carvalho Chehab
ea80c6d639 ui: notify.py: disable python Notify extension
For whatever reason, this doesn't work on Fedora 26:

06:47:05,925    DEBUG [ReceiverListener:hidraw1] logitech_receiver.base: (13) => r[20 02 0100 0000000000000000000000]
06:47:05,925    DEBUG [ReceiverListener:hidraw1] logitech_receiver.notifications: <PairedDevice(2,2011,K520)> (1.0) custom notification Notification(2,01,00,000000000$
06:47:05,925  WARNING [ReceiverListener:hidraw1] logitech_receiver.notifications: <PairedDevice(2,2011,K520)>: unrecognized Notification(2,01,00,000000000000000000000$
06:47:08,806    ERROR [MainThread] solaar.ui.notify: showing <Notify.Notification object at 0x7f82c2484640 (NotifyNotification at 0x556fa0fc5a40)>
Traceback (most recent call last):
  File "./devel/solaar/lib/solaar/ui/notify.py", line 145, in show
    n.show()
Error: g-io-error-quark: Error calling StartServiceByName for org.freedesktop.Notifications: Timeout was reached (24)


So, disable it.

Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-09-11 07:02:48 -03:00
Mauro Carvalho Chehab
a01e4b2efe hidpp20.py: handle gracefully errors at REPROG_CONTROLS_V4
At least with Anywhere Mouse MX 2, one reprogrammed key
fails to read:

    ERROR [MainThread] logitech_receiver.base: (3) device 3 error on feature request {0829}: 2 = invalid argument

That causes "solaar show" to crash.  Instead, let's handle
errors there gracefully, reporting it as:

         7: unknown:00C3              , default: unknown:009C                => unknown:00C3
             virtual, pos:0, group:4, gmask:0

Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-09-10 22:53:19 -03:00
Mauro Carvalho Chehab
801bdfa224 Remove the hid++ high-res wheel notification
The best is to make the logitech-hidpp driver to switch to
hid++ notification mode when it starts. As we don't want users
to mangle with it, let's remove support from it.

PS.: I opted to keep this as a separate patch. This way, if
anyone needs to add support for it, in order to debug the
driver, it is just a matter of reverting this patch.

Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-09-10 21:49:18 -03:00
Mauro Carvalho Chehab
410d100dc6 Add notification for high-resolution Wheel events
The event at address 0 is only produced while in HID++ mode.

The rachet event (address 0x10) happens on both HID and
HID++ modes.

Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-09-10 21:49:18 -03:00
Mauro Carvalho Chehab
7078750a3f MX Anywhere2: Correct feature Smooth Scrool
Set wrongly to HI_RES_SCROLLING. Correct it to HIRES_WHEEL as reported
by MX Anywhere2.

relates to #283

Signed-off-by: Josenivaldo Benito Jr <jrbenito@benito.qsl.br>
2017-09-10 21:49:18 -03:00
Mauro Carvalho Chehab
360c92f6b0 Add support for CLI show to display High Res Wheel settings
Add support for the high resolution wheel found on MX Anywhere 2.

Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-09-10 21:44:30 -03:00
lasers
2377fef3a8 Remove dead links 2017-07-24 03:44:00 -05:00
Peter Wu
684afa871e Merge pull request #337 from doctor64/m185
Basic support for M185 mouse
2017-07-17 00:08:19 +02:00
Peter Wu
dd2f884504 Merge pull request #354 from luzfcb/patch-1
update ubuntu solaar package informations
2017-04-16 12:20:27 +02:00
Fábio C. Barrionuevo da Luz
9dd05bb727 update ubuntu solaar package informations 2017-04-10 21:26:23 -03:00
Alex Cherkayev
e96a0fbfbb Add docs on both variants of Logitech M185 2017-03-21 18:03:07 +02:00
Alex Cherkayev
f9618dd0ab Add M185 keys reporting using REPROG CONTROLS V4 in cli
Add smooth scrolling using LOWRES_WHEEL
Add mouse speed selection using POINTER_SPEED
2017-03-21 18:02:59 +02:00
Alex Cherkayev
db0656967b Add basic 0xc534 receiver and M185 mouse support
Fix connection notification protocol for M185
Fixes from review
2017-03-21 18:00:44 +02:00
Peter Wu
53ec751cf1 Merge pull request #343 from jrbenito/K270-unifying
Wireless Keyboard K270 unifying
2017-03-21 00:07:26 +01:00
Peter Wu
45cc161cc7 Merge pull request #344 from jrbenito/MK520
MK520 Combo - Documentation
2017-03-21 00:02:52 +01:00
Peter Wu
1ccd2d1856 Merge pull request #346 from jrbenito/MK220-mouse
MK220 Combo descriptor for Mouse M150 and new docs
2017-03-20 23:58:49 +01:00
Josenivaldo Benito Jr
d9d37edc2f MK220 Combo descriptor for Mouse M150 and new docs
Thanks to @FabioBeneditto for providing information.

Depends on #337

fixes #222

Signed-off-by: Josenivaldo Benito Jr <jrbenito@benito.qsl.br>
2017-03-10 10:47:23 -03:00
Josenivaldo Benito Jr
ae405871fb Add M510 (new version) to descriptors
Depends on #337

fixes #279

Signed-off-by: Josenivaldo Benito Jr <jrbenito@benito.qsl.br>
2017-03-08 19:48:23 -03:00
Josenivaldo Benito Jr
f4700f07ce MK520 Combo
Wireless Keyboard K520
Wireless Mouse M310

Fully functional on Solaar at this point.

Signed-off-by: Josenivaldo Benito Jr <jrbenito@benito.qsl.br>
2017-03-08 18:59:36 -03:00
Josenivaldo Benito Jr
d2d19a615d Wireless Keyboard K270 unifying
Descriptor and docs for K270 unifying version.

Signed-off-by: Josenivaldo Benito Jr <jrbenito@benito.qsl.br>
2017-03-08 16:23:30 -03:00
Peter Wu
c36cc506b6 Merge pull request #327 from david-geiger/master
Update French translation
2017-01-03 12:27:22 +01:00
daviddavid
7180693f89 Update French translation
- by David Geiger <david.david@mageialinux-online.org>
2016-12-31 16:43:44 +01:00
Peter Wu
aa08356823 Merge pull request #144 from DJm00n/master
Russian translation added.
2016-12-23 15:16:06 +01:00
Dimitriy Ryazantcev
197ff7365d Add Russian translation 2016-12-21 00:18:01 +02:00
Dimitriy Ryazantcev
a0c6a6ce59 Update l10n pot template 2016-12-21 00:18:01 +02:00
Dimitriy Ryazantcev
934ecb821d Update l10n strings in code 2016-12-21 00:18:01 +02:00
Peter Wu
f0cf949336 Merge pull request #322 from jrbenito/anywhere2
Anywhere MX 2 device information and descriptor
2016-12-20 21:29:10 +01:00
Peter Wu
ecd245e8dc Merge pull request #317 from jrbenito/m560-devinfo
M560 device info contributed by @mhalano
2016-12-03 02:19:04 +01:00
Peter Wu
f65f000d38 Merge pull request #319 from jrbenito/k780
K780 add descriptor support and device information
2016-12-03 02:03:35 +01:00
Josenivaldo Benito Jr
3b60f205f7 K780 add descriptor support and device information
Device information provided by @faassen
Tests provided by @ralphdd

relates to #298

Signed-off-by: Josenivaldo Benito Jr <jrbenito@benito.qsl.br>
2016-11-30 14:38:44 -02:00
Josenivaldo Benito Jr
d6c93cfcfe Anywhere MX 2 device information and descriptor
Information from mouse Anywhere MX 2 as provided by @fropeter
Descriptor for mouse based on dump provided

Signed-off-by: Josenivaldo Benito Jr <jrbenito@benito.qsl.br>
2016-11-30 14:24:50 -02:00
Josenivaldo Benito Jr
cbd71f9d24 M510 HID++ V4.5 information
Dump from M510, newer version which uses HID++ V4.5 instead of V1.0.
Wireless PID 4051

Signed-off-by: Josenivaldo Benito Jr <jrbenito@benito.qsl.br>
2016-11-30 14:07:42 -02:00
Josenivaldo Benito Jr
45d5119a5a M560 device info contributed by @mhalano
Signed-off-by: Josenivaldo Benito Jr <jrbenito@benito.qsl.br>
2016-11-30 14:07:27 -02:00
Peter Wu
773cb7f45f Merge pull request #312 from jrbenito/rules
Add receiver to udev rules
2016-11-29 02:16:36 +01:00
Josenivaldo Benito Jr
d74e3a9b92 Add receivers to udev rules
Sync lib/logitech_receiver/base_usb.py PIDs with udev rules

Fixes #125

Signed-off-by: Josenivaldo Benito Jr <jrbenito@benito.qsl.br>
2016-11-24 09:54:24 -02:00
Peter Wu
fe1fba7ac6 Merge pull request #316 from david-geiger/master
Add French translation on desktop file and update maintainer in README.
2016-11-24 11:09:46 +01:00
daviddavid
4e20ef61c8 Add French translation on desktop file
- update README.md
2016-11-23 20:38:30 +01:00
Peter Wu
a750b32d14 Merge pull request #313 from jrbenito/doc
Update installation to point correct rules file
2016-11-23 13:46:27 +01:00
Josenivaldo Benito Jr
69006c48c6 Update installation to point correct rules file
Signed-off-by: Josenivaldo Benito Jr <jrbenito@benito.qsl.br>
2016-11-23 09:55:07 -02:00
Peter Wu
b12d03dfe3 Merge pull request #311 from jrbenito/nanoDocs
README nano receiver broken link
2016-11-22 23:46:00 +01:00
Peter Wu
ddbf93fb24 Merge pull request #309 from jrbenito/pt-br
pt-br: Improve translations
2016-11-22 23:22:23 +01:00
Josenivaldo Benito Jr
65c55b789c README nano receiver broken link
Fixes #261

Signed-off-by: Josenivaldo Benito Jr <jrbenito@benito.qsl.br>
2016-11-22 11:37:40 -02:00
Josenivaldo Benito Jr
d83530bee3 pt-br: Improve translations
Some pt-br translation where ambiguous or too missing 'not' statement.
Add original translator, Mr. Drovetto, to the documentation.

Signed-off-by: Josenivaldo Benito Jr <jrbenito@benito.qsl.br>
2016-11-21 17:25:22 -02:00
Peter Wu
e6c02f5c52 Merge pull request #303 from jrbenito/UTF8
UTF-8 file paths error on python 2
2016-11-18 22:22:11 +01:00
Josenivaldo Benito Jr
122d76d061 UTF-8 file paths error on python 2
Python 2 needs UTF-8 decode since it uses 'ascii' decode by default.
Python 3 might have problems converting back to UTF-8 in case of Unicode
surrogates

Signed-off-by: Josenivaldo Benito Jr <jrbenito@benito.qsl.br>
2016-11-18 15:00:20 -02:00
muzena
fb1442dbcb Add croatian translation 2016-11-15 16:34:20 +01:00
muzena
0b8141f092 Logitech G700 and G700s Gaming mouse support 2016-11-14 16:39:23 +01:00
Peter Wu
137c32262b Merge pull request #242 from drovetto/master
Added brazilian portuguese translation
2016-11-10 13:20:25 +01:00
Peter Wu
7c726738b1 Merge pull request #185 from zipperten/patch-4
Update sv.po
2016-11-10 13:19:35 +01:00
Peter Wu
2570f584b9 Merge pull request #228 from berte/master
add turkish translation file
2016-11-10 13:07:29 +01:00
Peter Wu
4c1f568fab Merge pull request #141 from ghost
Italian translations
2016-11-10 13:04:42 +01:00
Peter Wu
27bd71253e Merge pull request #129 from Tomin1/finnish
Finnish translations
2016-11-10 12:57:06 +01:00
Jhonny Oliveira
9a9a82016f Add support to G700 Gaming Mouse receiver 2016-11-10 12:25:54 +01:00
Jhonny Oliveira
aa03cef61f Add support to MK320 mouse and keyboard combo 2016-11-08 09:17:02 +01:00
Peter Wu
c14e30b6f5 Fix crash when AppIndicator3 is unavailable
Convert ValueError to an ImportError (hack!) to allow the fallback code
to function.

Fixes https://github.com/pwr/Solaar/pull/276
2016-11-06 19:50:32 +01:00
cschreib
b5d43cdc3c Added support for MintX icon set (for Linux Mint integration) 2016-10-22 13:49:50 +02:00
Peter Wu
1edd8a577b Merge pull request #290 from verybadsoldier/invert-online-bit
Fixes #289.
2016-10-03 01:58:51 +02:00
vbs
358e0958bb fixed wrong interpretation of bit 6 of the notification byte which indicates if the link could be established (bit cleared) or not (bit set)
https://lekensteyn.nl/files/logitech/logitech_hidpp10_specification_for_Unifying_Receivers.pdf
2016-09-17 18:05:03 +02:00
Peter Wu
fa5fba796b Merge pull request #263 from MagicFab/patch-1
Update es.po
2016-09-04 22:02:38 +02:00
Peter Wu
ce215228f3 Merge pull request #277 from wsargent/patch-1
Use HTTPS for github based repositories
2016-08-09 15:02:03 +02:00
Peter Wu
28e43395ab Merge pull request #259 from javitonino/support-mx-master
Support mx master
2016-07-24 23:09:28 +02:00
Will Sargent
e09231c05a Use HTTPS for github based repositories
Github Pages support HTTPS natively, so it's better for security to default to that.
2016-07-12 09:02:28 -07:00
Javier Torres
f29de0f3dd Update docs: mx master supports smart shift 2016-06-09 19:46:03 +02:00
Javier Torres
ba540338e2 Add smart shift feature for MX master 2016-06-09 19:46:03 +02:00
Javier Torres
2442fee341 Add support for range features in GUI 2016-06-09 19:46:03 +02:00
Javier Torres
bbadd3e755 Add support for range features in CLI 2016-06-09 19:46:03 +02:00
Javier Torres
2fdce2f938 Add range features 2016-06-09 19:46:03 +02:00
Javier Torres
f1fad2d16b Add range validator 2016-06-09 19:46:03 +02:00
Peter Wu
8a5700b44e Merge pull request #270 from cjmayo/appindicator
Fix: "AppIndicator3 was imported without specifying a version first"
2016-05-21 19:28:19 +02:00
Chris Mayo
e046455a05 Fix: "AppIndicator3 was imported without specifying a version first"
PyGIWarning: AppIndicator3 was imported without specifying a version
first. Use gi.require_version('AppIndicator3', '0.1') before import to
ensure that the right version gets loaded.
2016-05-03 20:20:46 +01:00
Peter Wu
ddbc27486c Merge pull request #136 from erik-smit/gobject_not_allow_None
Fixes a TypeError on older GObject libraries (as evident with Ubuntu 12.04 and OpenSUSE 12.3).
2016-04-17 14:11:15 +02:00
Peter Wu
2041007b38 Merge branch 'features'
Automatically detect FN swap feature and DPI adjustment on some newer
devices. DPI adjustment partially addresses support for the MX Master
(#208), Smart shift is still missing.
2016-04-17 12:43:15 +02:00
Fabian Rodriguez
7b7e17819e Fixed "Hardware" following comments 2016-04-01 07:55:13 -04:00
Fabian Rodriguez
f855cd60e1 Update es.po
MIssing spaces, small terms corrections, typos
2016-03-31 19:22:55 -04:00
Peter Wu
883ed9549d Fix DPI list assertion 2016-03-25 00:06:00 +01:00
Peter Wu
d1858f747b Assume 7 words for the DPI list response
HID++ 2.0 responses are 20 bytes, once you strip the 4 byte common
header and 1 byte sensorIdx, you have 15 bytes left. Since DPI values
are 16-bit words, only 14 bytes should be used.
2016-03-24 16:59:05 +01:00
Peter Wu
aa7d1b6410 Skip sensorIdx in getSensorDpiList response 2016-03-24 15:13:06 +01:00
Peter Wu
bc3a98ddb2 Merge pull request #258 from cjmayo/gentoo
readme Gentoo link updated with official package
2016-03-24 14:58:34 +01:00
Peter Wu
5b01f375e0 Merge pull request #254 from emerham/master
Adding Logitech mx 1100 cordless laser mouse to discriptors
2016-03-24 14:56:55 +01:00
Peter Wu
dd2755909d cli/config: fix error message
Attempt to fix:

    $ bin/solaar config master dpi higher
    solaar: error: coercing to Unicode: need string or buffer, int found

The DPI choices are integers, therefore cast it to a str.
2016-03-18 12:27:16 +01:00
Peter Wu
b052ab9ef0 Fix thinko in Adjustable DPI setting
There are three bytes forming the parameter, the sensor ID is the MSB,
not LSB.
2016-03-18 12:14:15 +01:00
Peter Wu
9c768d60a1 Add full support for adjustable DPI
Feature 0x2201 as used by the MX Master. Valid DPI values are read
directly from the device. Based on Logitech specifications.
2016-03-15 23:37:39 +01:00
Matthew Brabham
d1d0ab85ff Updated mouse device settings and deffinition. Added docs for the MX 1100 2016-03-14 13:05:05 -07:00
Peter Wu
e1eee2e078 Fix "Gtk was imported without specifying a version first"
Fixes the following warnings:

    sys:1: PyGIWarning: Gtk was imported without specifying a version first. Use gi.require_version('Gtk', '3.0') before import to ensure that the right version gets loaded.
    sys:1: PyGIWarning: Notify was imported without specifying a version first. Use gi.require_version('Notify', '0.7') before import to ensure that the right version gets loaded.
2016-03-14 11:33:05 +01:00
Peter Wu
5c38f90cd6 Merge branch 'issue/199'
Fixes #136.
2016-03-14 11:10:49 +01:00
Peter Wu
45d49b9de8 settings: fix Python 3 compat for boolean values
As observed for the fn-swap setting.
2016-03-14 01:48:56 +01:00
Peter Wu
4ccb8ab26d Merge pull request #257 from hobarrera/subtle-critical-battery-notification
Don't open a main window when battery is critical
2016-03-14 00:36:26 +01:00
Peter Wu
ab162583e4 cli: do not die on missing description
The DPI setting has no description, do not try to display it.
2016-03-13 23:59:21 +01:00
Chris Mayo
e25b47aa1c readme Gentoo link updated with official package 2016-03-05 16:27:16 +00:00
Hugo Osvaldo Barrera
63a98819a6 Don't open a main window when battery is critical
The main window suddenly opening when a battery is critical is very
disruptive. It can pop up on all sort of undesirable scenarios.

Rather than catch users of guard, merely show a notification that the
battery is critical.
2016-02-19 03:25:55 -03:00
Peter Wu
27d3d80d30 Merge pull request #256 from SlySven/add_m175DestinguishingDetails
add: wpid for M175 to distinguish between it and M185 wireless mouse (Fixes #255)
2016-02-11 18:30:02 +01:00
Stephen Lyons
478381a994 add: wpid for M 175 to distinguish between it and M185 wireless mouse
I own the former and wanted to correct this detail which caused the wrong
model to be shown in GUI.

Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-02-10 19:09:25 +00:00
Matthew Brabham
51a15a960f Adding Logitech mx 1100 cordless laser mouse to discriptors 2016-01-26 11:04:47 -08:00
Peter Wu
92967eed23 Merge pull request #249 from mulkieran/master-pyudev
Fix some bugs in udev.get_indexed_string.
2016-01-13 15:24:51 +01:00
Peter Wu
57338303e8 Merge pull request #239 from marcbelmont/patch-1
Add setting for K400 Plus keyboard

devices.md was updated in #174
2016-01-09 12:37:35 +01:00
Peter Wu
e735ce10f0 Merge pull request #174 from IrvinPoe/patch-1
Update devices.md with K400 Touch
2016-01-09 12:36:27 +01:00
mulhern
d75b6d2f2b Fix some bugs in udev.get_indexed_string.
* from_device_number raises an exception if no device found, rather than
returning None. So, instead of checking the result, catch the exception.
* Use Attributes.get() method instead of checking containment and using the
index operator. This is really the only correct way, see rhbz#1267584.

Effect of the changes:
Previously, if no device was found this method would raise an exception.
Now it returns None instead.
Previously this method read the value of the attribute corresponding to key
twice, once via 'key in attributes' and again when accessing the key.
Now, it just reads it the one time.

Reason for noticing all these problems:
In pyudev-0.18 the Attributes class is fixed, and no longer has the []
operator or __contains__ method or other methods which require a total
mapping. This patch fixes several bugs while simultaneously avoiding these
removed operators.

Signed-off-by: mulhern <amulhern@redhat.com>
2015-12-23 09:22:48 -05:00
sadj
bd1470dad7 Added brazilian portuguese translation. 2015-10-08 18:52:14 -03:00
Marc Belmont
15f97681ef Add setting for K400 Plus keyboard
The new_fn_swap works on the K400 Plus model.
2015-08-24 19:01:21 +02:00
Behzat
7075ce910a add turkish translation file 2015-07-16 22:07:38 +03:00
Peter Wu
5ba816dd38 [WIP] Support MX Master with DPI adjustment support (#208)
It's not known whether the DPI ranges can be queried, so let's set
hard-code some values for now. Step size is 200. Does this need to
be changed?

TODO: need a capture of whether this is really a read function.
2015-05-31 15:53:26 +02:00
Peter Wu
a515cc3860 Auto-detect FN swap feature for newer devices 2015-05-31 10:56:57 +02:00
Peter Wu
73344cbf26 Simplify feature checking
Make mapping features to settings more readable. No functional changes.
2015-05-31 10:38:49 +02:00
Peter Wu
cf27328d13 Merge branch 'updates'
Documentation updates.
2015-05-27 23:43:10 +02:00
Peter Wu
869f1e4791 doc/devices.md: add MX Master
Information from (IRC) xaver. See also #208.

Product page at http://www.logitech.com/product/mx-master
2015-05-27 23:40:58 +02:00
Peter Wu
e2d65a690e hidpp20: update features list
Based on SetPoint6.65.62_32.exe and Options_2.10.73.exe (features.xml,
defaults.xml, LogiOptionsMgr.exe).

The names are based on the named next to the feature ID. For duplicates,
_2 is appended to the name.

This commands helps parsing numbers from debug prints:

    strings LogiOptionsMgr.exe |
    sed -nr 's/.*(Feature[0-9a-fA-F]{4})/\1 /p' | sort |
    awk 'tolower(a)!=tolower($1){print"";a=$1}1;' | less -S
2015-05-27 23:20:43 +02:00
Peter Wu
3141f06472 Fix crash due to non-locatable icon names (#199) 2015-05-27 23:16:39 +02:00
Peter Wu
b88cf5a07b Ignore HID++ devices on Linux 3.19+
Additionally update the docuentation to reflect new module names.
2015-05-14 23:28:04 +02:00
Peter Wu
a344ad9867 docs: document Smooth Scrolling for more devices
Based on the HI_RES_SCROLLING feature (0x2120) in docs/devices/. Tested
with a M525.
2015-05-14 23:06:14 +02:00
CzBiX
76e327d2fa update docs for M325 2015-05-08 13:27:29 +08:00
CzBiX
0ae0ef195a support switch smooth scroll feature 2015-05-08 13:20:46 +08:00
Peter Wu
b1f74a1280 Merge pull request #213 from titanofold/add-M570
Add M570 Trackball device information
2015-04-24 09:39:37 +02:00
Aaron W. Swenson
30431fbfb8 Add M570 Trackball detail 2015-04-20 14:18:07 -04:00
Peter Wu
fb4c055fbf Merge pull request #193 from dmsc/master
Add support for MK220 mouse-keyboard combo device.
2015-03-07 18:12:21 +01:00
Daniel Serpell
3ea51fe1a2 Add support for MK220 mouse-keyboard combo device.
The MK220 receiver has usbid 046d:c52e, adding this id as a generic
receiver is enough to show the mouse and keyboard charge status.
2015-03-06 08:07:22 -03:00
Peter Wu
afd36764c2 Merge pull request #202 from decibyte/master
k830 support + support for NEW FN INVERSION
2015-03-06 11:45:53 +01:00
Mikkel Munch Mortensen
b694809394 Updates to dos for k830 keyboard. 2015-03-05 19:17:00 +01:00
Mikkel Munch Mortensen
66296265ba Descriptor for k830. 2015-03-05 19:15:12 +01:00
Mikkel Munch Mortensen
952495ce04 Support for NEW_FN_INVERSION. 2015-03-05 19:14:28 +01:00
Peter Wu
29eb377267 Merge pull request #203 from HugoJH/master
Added Spanish Translation
2015-03-05 15:04:45 +01:00
Hugo Jiménez Hernández
47345e1dcb Added Spanish Translation 2015-03-05 13:05:59 +00:00
Peter Wu
36fc6de760 Merge pull request #168 from jtsagata/master
Add Greek language translation
2015-03-05 13:07:25 +01:00
Peter Wu
6c0aca8c63 Merge pull request #170 from SubOptimal/translation
add german translation
2015-03-05 13:06:52 +01:00
Peter Wu
bd93689109 Merge pull request #171 from dirtycold/master
added Chinese (simplified) translation
2015-03-05 13:06:08 +01:00
Peter Wu
4e5d4853d6 Merge pull request #173 from stickster/master
Add Fedora package information to README.md
2015-03-05 13:05:37 +01:00
zipperten
bb2361a986 Update sv.po
minor changes
2014-10-23 09:49:05 +02:00
IrvinPoe
7c8d4815f0 Update devices.md
Add Nano receiver 046d:c52b in the supported devices, and FN swap works on K400.
2014-08-17 17:47:48 +02:00
Paul W. Frields
0f05589cd6 Add Fedora package information to README.md 2014-07-30 14:39:46 -04:00
ZH
21db60a14e fix compiling Chinese simplified translation 2014-07-13 15:13:10 +08:00
ZH
091c28ca8b added Chinese (simplified) translation 2014-07-13 10:13:17 +08:00
Frank Dietrich
9af353dd32 add german translation 2014-07-02 02:12:16 +02:00
Giannis Tsagatakis
981ff00ca3 Add Greek language translation 2014-06-13 14:32:57 +03:00
Daniel Pavel
ec0197df3d Merge pull request #154 from mmehnert/patch-1
Update TK820 compatibility information
2014-04-20 22:54:27 +03:00
mmehnert
2111107ff4 Update TK820 compatibility information 2014-04-19 14:50:21 +02:00
Tristin Celestin
2b08c5e0c9 Added border around tree view. 2014-01-01 21:45:44 -05:00
Daniel Pavel
cc8a6c4ab5 Merge pull request #134 from FrederikNS/patch-1
Added Smooth Scrolling to the Performance Mouse MX
2013-12-13 09:43:16 -08:00
Michele Olivo
437e17cf37 Added Italian translation 2013-12-13 18:09:46 +01:00
Daniel Pavel
22191d7d0c Merge pull request #139 from parkerlreed/patch-1
Update devices.md
2013-12-13 07:48:21 -08:00
parkerlreed
ba890c2d2e Update devices.md
Added a little bit of info for the M325
2013-12-02 10:46:47 -05:00
erik-smit
9a6cdd9cee TypeError: Argument 3 does not allow None as a value 2013-10-31 11:16:38 +01:00
Frederik Nordahl Sabroe
32324f3e66 Added Smooth Scrolling to the Performance Mouse MX
I tested solaar with my Performance Mouse MX, and the smooth scrolling worked like a charm, I just need to find a way to make the scrolling speed slower now.
System is Linux Mint 15.
2013-10-14 17:18:49 +02:00
Tomi Leppänen
ffe297b239 Merge branch 'finnish' of github.com:Tomin1/Solaar into finnish
Conflicts:
	po/fi.po
	po/solaar.pot
2013-09-29 16:37:33 +03:00
Tomi Leppänen
7fe5983f7c Fixed a bit Finnish translation.
Some fixes to Finnish translation.
A few strings were marked as fuzzy.
Run po-compile.sh.
2013-09-29 16:34:02 +03:00
Tomi Leppänen
d5f14bb5f8 Merge branch 'master' into finnish
Conflicts:
	po/solaar.pot - run po-compile.sh
2013-09-29 16:24:06 +03:00
Daniel Pavel
f3049ed451 Merge pull request #126 from slaveriq/master
Fixing a crash when level is type None
2013-09-25 10:08:09 -07:00
David Plassmann
8485494ea7 It should check for None specificly 2013-09-25 14:12:53 +02:00
David Plassmann
7a75813a84 level is returned as None in hidpp10.py when the performanceMX mouse is
charging. Since the battery state is unknown when beeing recharged it
will now return "N/A".
Before it would crash becasue level was None and could not be inserted
using %d.
2013-09-24 16:56:50 +02:00
Daniel Pavel
35830e3d50 Merge pull request #121 from Lekensteyn/doc-updates
Documentation updates: DJ pdf and devices
2013-09-04 16:56:46 -07:00
Tomi Leppänen
46fd4dac56 Merge branch 'master' into finnish
Conflicts:
	po/solaar.pot - Run tools/po-compile.sh
2013-09-01 12:21:51 +03:00
Peter Wu
ebd8635f84 docs/devices: add K750 (from Julien Danjou)
Received from Julien Danjou on the devkit mailing list.
2013-08-29 19:06:03 +02:00
Peter Wu
efbf43b472 docs/logitech: Add DJ receiver spec
docx files is taken from hidpp20 public folder[1] and was converted to
PDF format using:

    loffice --convert-to pdf ...docx
    qpdf --linearize orig.pdf ...pdf

Mirrored on https://lekensteyn.nl/files/logitech/.

 [1]: https://drive.google.com/#folders/0BxbRzx7vEV7eWmgwazJ3NUFfQ28
2013-08-27 18:06:29 +02:00
Peter Wu
8a6d8e2ed1 docs/devices/m525: add ltunify and solaar output 2013-08-27 18:06:29 +02:00
Peter Wu
bff99799ab docs/devices/t650: add reprogrammable keys 2013-08-27 18:06:29 +02:00
Peter Wu
1434b2a50d Update features and keys list
Updated to information available from SetPoint 6.61.15.
2013-08-27 17:55:45 +02:00
Daniel Pavel
c3fdbfb643 translate battery alerts (fixes #119) 2013-08-25 23:03:25 +03:00
Daniel Pavel
a9ebac264f po formatting updates 2013-08-25 01:34:27 +03:00
Daniel Pavel
60a591ab6b Merge pull request #114 from zipperten/patch-2
Update sv.po
2013-08-24 15:32:23 -07:00
Daniel Pavel
ab3a6b50d4 Merge pull request #118 from Lekensteyn/fixes
Regression fixes: --hidraw option, python3, hidpp10
2013-08-24 14:05:11 -07:00
Peter Wu
b193b39701 Fix missing reprogrammable keys
The assumption that the Features IDs are in increasing order does not
hold. This causes the feature check for REPROG CONTROLS (1B00) to fail,
therefore remove the micro-optimisation.

While at it, rename variables and document the functions better.
2013-08-23 21:33:45 +02:00
Daniel Pavel
806d67a72f Merge pull request #117 from Lekensteyn/doc-updates
docs: added T400, T650, Anywhere MX dumps
2013-08-21 13:12:23 -07:00
Peter Wu
9c465cd998 Fix wrong register name for illumination (hidpp10)
Broken since 9a2a28e, this causes a lot of exceptions for every move.
2013-08-21 21:47:24 +02:00
Peter Wu
024a71b618 solaar: add --hidraw option again
This options allows the devices list to be restricted which got removed
in:

    commit 3b75b69970
    Author: Daniel Pavel <daniel.pavel@gmail.com>
    Date:   Fri Aug 9 12:25:47 2013 +0200

        merged solaar-cli functionality into main solaar binary

solaar-cli is still busted, but since it is deprecated, it's probably
fine.
2013-08-21 21:47:24 +02:00
Peter Wu
f144816256 solaar-cli: fix argument parsing in Python 3 again
Fix from e3a887f36c, this got removed
in:

    commit 3b75b69970
    Author: Daniel Pavel <daniel.pavel@gmail.com>
    Date:   Fri Aug 9 12:25:47 2013 +0200

        merged solaar-cli functionality into main solaar binary
2013-08-21 21:47:24 +02:00
Peter Wu
f0eeea8625 docs/devicesmd: update with T400 and Anywhere MX 2013-08-21 21:45:04 +02:00
Peter Wu
72819b6130 docs/devices: add Anywhere MX mouse
Thanks to Nestor from Logitech for providing me this device.

This mouse has two buttons on the left, currently mapped to 8 (bottom
button) and 9 (top button).

Note: setting bit 1 of register 01 does odd things in KDE. I looked in
SetPoint 6.61.15 and could not find an option for "Side Scroll",
perhaps it is not applicable here?
2013-08-21 21:45:04 +02:00
Peter Wu
23e4f32e11 docs/devices: add T650 touchpad
Thanks to Nestor from Logitech for providing me this device.

The firmware on this touchpad features out-of-the-box tap-to-click
(no host software needed). The following features work with no
additional software (tested in Linux 3.11-rc6 with KDE 4.11):

- Left-click: single tap
- Middle-click ("scroll-wheel click"): three finger tap
- Right-click ("context menu"): two finger tap or tap in right corner
- Navigate left ("Back"): three finger slide to left
- Navigate right ("Forward"): three finger swipe to the right
- Scroll (up/down/right/left): slide with two fingers
- Move pointer (any direction): slide

Click and drag is also possible (for example, for selecting text or
moving windows with Super + right/left-click in KDE), just press harder
on the surface. Right click is in the bottom-right corner, left is
anywhere else.

Sliding with three fingers up acts if you pressed Super. Sliding with
three fingers down triggers a key press of Super + D (normally the
"Show Desktop" in MSWIN).

Not working as it requires additional software:

- Pinch-to-zoom.
- Four-finger gestures, likely needs to be controlled via features as
  there are no HID messages at all.
2013-08-21 21:45:04 +02:00
Peter Wu
243d1548dc docs/devices: add Zone Touch Mouse T400
Thanks to Nestor from Logitech for providing me this device.

User experience note: the upper part (covering two-third) of the middle
button is the "METRO START SCREEN" button, the smaller bottom part
provides the "middle mouse button" (MIDLLE BUTTON). This might be OK
for a desktop user, but it's awful if you have a big hand like me and
make much use of it for opening URLs in a new tab or pasting stuff.

On the other hand, the middle button can be remapped and there is both
horizontal and vertical scrolling functionality.
2013-08-21 21:45:04 +02:00
zipperten
c3bc56f306 Update sv.po
fix for paring lock notification.
2013-08-20 22:49:08 +02:00
Daniel Pavel
288c607069 Merge pull request #113 from david-geiger/patch-1
Ouch. Added 'solaar.cli' on setup.py files (line 74 "packages=").
2013-08-13 02:20:58 -07:00
david_david
55c307d0e5 added 'solaar.cli' on setup.py files (line 74 "packages=")
missing packages 'cli' from "/lib/solaar/" and needed for building package rpm.

[david@david ~]$ solaar -dd
Traceback (most recent call last):
  File "/usr/bin/solaar", line 43, in <module>
    import solaar.gtk
  File "/usr/lib/python2.7/site-packages/solaar/gtk.py", line 26, in <module>
    import solaar.cli as _cli
ImportError: No module named cli
2013-08-13 11:02:13 +02:00
Daniel Pavel
69febfcea5 don't rely on upower to check devices after wake-up (#111)
still use upower resume events to ping devices, just in case
the old behaviour is available with a command-line option
2013-08-12 15:22:34 +02:00
Daniel Pavel
9934755566 more translation fixes (#108) 2013-08-12 00:32:19 +02:00
Tomi Leppänen
a7561eaa9b Updated Finnish translation
Merge branch 'finnish' of github.com:Tomin1/Solaar into finnish

Conflicts:
	po/fi.po
2013-08-11 17:24:06 +03:00
Tomi Leppänen
689661169a Updated Finnish translation. 2013-08-11 17:22:40 +03:00
Tomi Leppänen
eac40abc3e Updated Finnish translation. 2013-08-11 16:56:30 +03:00
Tomi Leppänen
372e4e0949 Merge branch 'master' into finnish
Conflicts:
	po/solaar.pot - run tools/po-compile.sh
2013-08-11 16:48:12 +03:00
Daniel Pavel
e42f7f1393 jekyll configuration update 2013-08-09 12:29:02 +02:00
Daniel Pavel
3860d4a56b changelog update 2013-08-09 12:28:47 +02:00
Daniel Pavel
3b75b69970 merged solaar-cli functionality into main solaar binary 2013-08-09 12:25:47 +02:00
Daniel Pavel
a4f0eab855 updated descriptors with a few more devices 2013-08-08 22:44:23 +02:00
Daniel Pavel
f54ea27d97 updated translator credits in about dialog 2013-08-08 22:43:32 +02:00
Daniel Pavel
db48fe1b40 re-formatted translation files 2013-08-08 22:41:57 +02:00
Daniel Pavel
d0a0e902a7 added translator credits to i18n documentation 2013-08-08 22:38:59 +02:00
Daniel Pavel
95a6412d5c po-update.sh without arguments re-formats all translation files 2013-08-08 22:22:39 +02:00
Daniel Pavel
5faecbf4f3 some strings were untranslated; fixes #100 2013-08-08 21:50:04 +02:00
Daniel Pavel
5af1719384 tray: always pick the lowest battery, if the user hasn't already 2013-08-08 21:49:59 +02:00
Daniel Pavel
6a66370ffe scrolling over the tray icon switches among devices; fixes #101
It now works for the standard systray as well, not just the
appindicator.
2013-08-08 21:49:54 +02:00
Daniel Pavel
c0874220d2 don't str() translated device status; fixes #108 2013-08-08 21:49:50 +02:00
Daniel Pavel
9c67b1b494 debian packaging updates 2013-08-08 21:49:35 +02:00
Daniel Pavel
22656d5b82 use Gtk.Application properly 2013-08-08 21:49:35 +02:00
Daniel Pavel
d55963caba clean-up in usb IDs 2013-08-08 21:49:35 +02:00
Daniel Pavel
413cebe40f delay some UI initialization until necessary 2013-08-08 21:49:35 +02:00
Daniel Pavel
140ffae01a Merge pull request #106 from damsweb/master
Update fr.po to fix a few typo/mistakes
2013-08-08 07:12:01 -07:00
Daniel Pavel
68251777fb Merge pull request #107 from damsweb/patch-2
Update README.md to add Mageia
2013-08-08 06:29:21 -07:00
Damien Lallement
188b20a4f1 Update README.md to add Mageia 2013-08-07 16:43:46 +02:00
Damien Lallement
5fba1db11c Update fr.po to fix a few typo/mistakes
Fixing feminine words and fix bad translations for connection.
2013-08-07 14:47:46 +02:00
Daniel Pavel
21b1a722fc Merge pull request #102 from david-geiger/patch-1
Add French translation (fr.po) (pwr/Solaar#97)
2013-08-06 07:51:32 -07:00
Daniel Pavel
715c50685b Merge pull request #103 from zipperten/master
Added Swedich translation
2013-08-06 07:50:46 -07:00
Tomi Leppänen
dd0ba17351 The first version of Finnish translation.
I don't have much experience in translating, so I'd like my translations
to be reviewed by someone with more experience.
Some translations aren't that good. Especially I'd like to know if there
is any better or newer word for pairing in Finnish. Some problems I've
already marked in po/fi.po. I'd imagine that the longest texts need the
most fixing.
2013-08-05 19:47:03 +03:00
david_david
576dd4cdd4 Update fr.po
update "Last-Translator:"
2013-08-05 08:15:44 +02:00
david_david
a2a0380401 Update fr.po
#: lib/solaar/ui/about.py:49
#: lib/solaar/ui/window.py:640
2013-08-04 23:08:47 +02:00
david_david
f1a85f45bd Update fr.po 2013-08-04 11:51:53 +02:00
david_david
200cf48df4 Update fr.po 2013-08-04 11:50:24 +02:00
david_david
14b5993dc3 Create fr.po 2013-08-03 16:48:12 +02:00
david_david
585ba93588 Create fr.po 2013-08-03 16:44:30 +02:00
zipperten
e30a692a6e Added Swedich translation 2013-07-30 01:51:35 +02:00
204 changed files with 51702 additions and 8888 deletions

10
.git-blame-ignore-revs Normal file
View File

@@ -0,0 +1,10 @@
# yapf bulk change
72a8d311bce64b1536c08e754d22bb91efb66460
# isort bulk change
e6369e0c3c240715a0a2daede6c3b225ed63cf60
# pre-commit bulk change
33521558ed7007c24b24127f1448c2c23ecbfb35
# flake8 bulk change
627185079f65c9cc471194b7927c833682e4a7a3
# yapf style update
27c90fa736d8a7a1ef6acda4345d3599862e185c

39
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,39 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: bug
assignees: ''
---
**Information**
<!-- Make sure that your issue is not one of the known issues in the Solaar documentation at https://pwr-solaar.github.io/Solaar/ -->
<!-- Do not bother opening an issue for a version older than 1.0.6. Please update to the latest version and see if your issue persists. -->
- Solaar version (`solaar --version` or `git describe --tags` if cloned from this repository):
- Distribution:
- Kernel version (ex. `uname -srmo`): `KERNEL VERSION HERE`
- Output of `solaar show`:
<details>
```
OUTPUT HERE
```
</details>
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Additional context**
Add any other context about the problem here.

View File

@@ -0,0 +1,35 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: enhancement
assignees: ''
---
**Information**
<!-- Please update to Solaar from this repository before asking for a new feature. -->
- Solaar version (`solaar --version` and `git describe --tags`):
- Distribution:
- Kernel version (ex. `uname -srmo`):
- Output of `solaar show` for the target device (if applicable):
<details>
```
OUTPUT HERE
```
</details>
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

16
.github/workflows/checks.yml vendored Normal file
View File

@@ -0,0 +1,16 @@
name: checks
on: [push, pull_request]
jobs:
pre-commit:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup Python
uses: actions/setup-python@v2
- name: Run pre-commit
uses: pre-commit/action@v2.0.0

3
.gitignore vendored
View File

@@ -5,6 +5,7 @@ __pycache__/
*.mo
/lib/Solaar.egg-info/
/lib/solaar.egg-info/
/build/
/sdist/
/dist/
@@ -14,3 +15,5 @@ __pycache__/
/docs/captures/
/share/logitech_icons/
/share/locale/
/po/*.po~

26
.pre-commit-config.yaml Normal file
View File

@@ -0,0 +1,26 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v3.1.0
hooks:
- id: check-ast
- id: check-builtin-literals
- id: check-merge-conflict
- id: check-yaml
- id: check-toml
- id: debug-statements
- id: double-quote-string-fixer
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/pre-commit/mirrors-yapf
rev: v0.30.0
hooks:
- id: yapf
- repo: https://github.com/pre-commit/mirrors-isort
rev: v4.3.21
hooks:
- id: isort
- repo: https://gitlab.com/pycqa/flake8
rev: 3.8.3
hooks:
- id: flake8
additional_dependencies: ['flake8-bugbear']

View File

@@ -1,2 +1,14 @@
Copyright 2012, 2013
Daniel Pavel <daniel.pavel@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, version 2.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.

259
ChangeLog
View File

@@ -1,7 +1,262 @@
1.0.7:
* Don't use time_ns so as not to require Python 3.7
* Correctly determine setting box in change_click method
* Handle fake Nano connection notifications
* Lock on actual handle, not just on handle number
* Mark Nano receiver C52F as not unpairing
* Upgrade pairing/unpairing documentation
1.0.7rc2:
* Don't signal status change when battery changes from None to None.
* Add Japanese translation
* Use first word of name for code name if no other code name available.
* Better determination of when to add SW ID.
* Check for more HID++ feature request failing.
* Fix bug with new_fn_inversion setting.
* Use correct device number for directly connected devices
* Add debug message when candidate device found
* Update Polish, Taiwanese, and Brazilian Portugese translations
* Add MouseProcess a rule condition like Process but for the window under the mouse
* Add parameters for binary settings to support prefixes
* Add locks to serialize requests to devices
* Fix bug when reprog key requests returns None
* Fix bug for empty process name and class
* Rules can now trigger on both pressing and releasing a diverted key
* Upgrade mouse gestures to allow sequences of movements
* Fix gkeys diversion faked read
* Add suppor for Logitech g pro x superlight receiver
* Convert HID++ 2.0 device kinds to enhanced HID++ 1.0 device kinds
* Update about window, bug report templates, and supported kernels.
1.0.6:
* Update sliding DPI to look for suitable keys
* Add mouse gestures that can trigger rules
* Complain if receivers do not support connection notification
* In polling rate setting, only modify onboard profiles when actually writing polling rate
* Add ability to ignore settings.
* Use symbols for receiver sub-registers
* Add support for wired G700
* Do not set attention icon
* Replace deprecated GTK stock menu icons
* Better handling of icons in tray and tray menus
* Receiver c52e does not unpair
* Match active WM_CLASS as well as active process name in rules
* Correctly set icon theme value when regular battery icons are not available
* Handle exception when device is not available when device is being added
* Perform initial activation of devices in listener threads
* Keep track of serial numbers in the configuration file
* Don't update settings for non-active devices
* Set the current host name if not stored on the device
* Add setting for SMART SHIFT ENHANCED feature
* Don't unnecessarily use long messages for HID++ 1.0 commands
* Correctly select choices in solaar config and use 1-origin addressing
* Add quirk for G915 TKL keyboard because its host mode inteferes with its Fn keys
* Show command outputs both saved and on-device settings
* Update documentation
* Fix bug in hidconsole
* Update French translation
1.0.5:
* Update documentation on devices forgetting settings.
* Improve help messages
* Fix bug in finding receiver to pair
* Solaar config command can set keyed settings.
1.0.5rc2:
* Add setting for polling rate
* Use long HID++ messages for all 2.0 requests
* Update German, Italian, and Polish translations
* Solaar config command no longer selects paired but unconnected devices
* Show HID++ 1.0 remaining pairings value in solaar show for devices that support it
* Add option to not use battery icons in system tray.
* Update Polish and Dutch translation.
* Add Czech translation.
* Remove information on SUSE package as it is very old.
* Turn GKEY notifications into Gn key keypresses that can trigger rules.
* Push device settings to devices after suspend when device is immediately active.
* Reduce unneccessary saving of configuration file.
* Better handling of disconnected devices.
* Implement GUI to edit rules.
* Implement rule-base processing of HID++ feature notifications (depends on X11).
* Add settings for diversion of crown and remappable keys.
* Access widgets by name instead of by index.
* Implement UNIFIED_BATTERY feature and use in battery reports.
* Add a clickable lock icon that determines where each setting can be changed.
1.0.4:
* Update pt_BR translation
1.0.4rc1:
* Support USB and BT connected devices that are not in descriptors.py
* Use FRIENDLY NAME for codename if needed and available.
* Extract manufacturer and product ID from Udev HID information.
* Add Bluetooth and USB product IDs to device descriptors records.
* Support Bluetooth-connected devices.
* Add model ID and unit ID to device identification.
* Support changing DPI by pressing DPI Switch button and sliding horizontally
* Add device-specific notification handlers.
* Add MX Vertical USB information.
* Udev rule adds seat permissions for all Logitech devices.
* Support USB-connected devices in GUI.
* Make probe and config work for USB-connected devices.
* Improve strings and display for settings.
* Correctly handle non-unifying connection notifications.
* Update GUI strings for several settings.
* Better support for EX100 and devices that connect to it.
* Partial support for feature GESTURE_2.
* Simplify interface for settings.
* Use DJ connection notifications to set device active status
* Udev rule sets seat write permissions for hidraw nodes for device as well as receivers.
* Handle USB devices that use HID++ protocol in CLI.
* Use device hidraw nodes where possible.
* Handle receivers with serial numbers that don't provide number of pairings.
* Ignore exceptions when setting locale.
* Correctly discover settings that share a name.
* Don't show pop-up notifications at startup.
* Keep battery voltage updated in GUI.
* Add Portugese translation.
* Update several translations.
* Add Lightspeed receivers c545 and c541.
* Reimplement REPROG_CONTROLS data structure.
1.0.3:
* Clean up documentation files.
* Update documentation on installation.
* Update Swedish and French translations.
* Add Norwegian Nynorsk and Danish translations.
1.0.3rc2:
* Fix bug handling DJ pairing notifications.
* Add Norwegian Bokmål translation.
1.0.3rc1:
* Remove deprecated solaar-cli application.
* Don't install udev or autostart files from python (or pip).
* Solaar needs Python 3.6+ and probably needs kernel 5.2+
* Handle exceptions on dynamic settings when device is not connected.
* Fix inifinite loop on some low-level write errors
* Add support for EX100 keyboard/mouse and receiver (046d:c517)
* Add two settings for THUMB_WHEEL feature - inversion and reporting via HID++
* Update German translation
* Use REPORT RATE feature when available to determine polling rate.
* Improve config command speed when not printing all settings
* Improve config command handling and checking of arguments
* Add setting for CHANGE_HOST feature
* Add argument to settings for values that are not to persist
* Add argument to settings to not wait for reply when writing a value to device
* Add argument to not wait for reply from request to device
* Add settings for MULTIPLATFORM and DUALPLATFORM features
* Remove Logitech documents from documentation directory
* Change config command to not read all settings when only printing or showing one
* Display hosts info in 'solaar show' if device supports it
* Remove non-working smooth-scrool from M510 v1
* Add yapf and flake8 code style checks
* Fix feature k375s Fn inversion
* Update controls (keys and buttons) and tasks (actions)
* Improved way to specify feature settings.
* Don't abort on device notifications with unexpected device numbers, just warn.
* Keep track of non-features so as not to ask device multiple times.
* Implement KEYBOARD DISABLE KEYS feature.
* Don't create notifications for DJ device activity reports.
* Update a few special keys and actions.
* Add keyed choice settings in configuration panel.
* Support remappable keys from reprogrammable keys v4 feature.
* Add setting class for keyed choice.
* Only check for features once per device.
* Use settings interface to show feature values in `solaar show` if no special code for feature.
* Remove maximum window size.
* Process battery voltage notifications.
* Display battery voltage information in main window if regular battery information not available.
* Show next battery level where available.
* Update list of implemented features and provide information on how to implement features.
* Add c53d as a Lightspeed receiver.
1.0.2:
* Add usage document
1.0.2rc3:
* Don't produce error dialog for inaccessible receivers with access control lists.
* Add option --battery-icons=symbolic to use symbolic icons if available.
* Update French translation
* Update installation documentation
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
* Use only standard icons for battery levels. Symbolic icons do not change to white in dark themes because of problems external to Solaar.
* Better reporting of battery levels when charging for some devices.
* Add information on K600 TV, M350 WIPD 4080, and MX Keys
* Remove assertion requiring receivers to still be in window when they are updated.
* Augment long description of Solaar showing up in repositories.
* Update installation directions.
* Install udev rule as well as autostart file when doing system install.
* Add support for Ayatana AppIndicator.
* Use setuptools icon directory on system installs when not using pip.
* Add receiver C517 and several older devices.
* Improved translations for polish.
* Bypass bug in appindicator when solaar is file in current directory.
* Don't check that device kind matches feature kind.
* Better determination of icons for battery levels.
* Use Ayatana AppIndicator if available.
* Improve error reporting when required system packages are not install.
* Better tooltip description
* Add release script to help when creating releases
1.0.2-rc1:
* Look up tray icon filenames to get around a bug in libappindicator.
* Make the default behavior be to show the main window at startup.
* Support c537 nano receiver
* Add logind signals for suspend/resume.
* Remove solaar-gnome3 package
* Ignore features for devices that don't follow feature specification
* Add probe command to command-line interface to dump receiver registers
* Don't terminate on malformed or unknown messages
* Create fewer internal notifications for messages from devices
* Add a button to the main window to terminate (quit) Solaar
* Set up nano receivers as receivers with no unpairing and with re-pairing
* Set up c534 as receiver with max 2 pairings, no unpairing, re-pairing
* Better support receivers that do not unpair or when pairing replace existing pairings
* Add information about receiver pairing to receiver data structure
* Better support devices that only allow a limited number of total re-pairings
* Add --window option to control main window visibility and tray usage
* Ignore receiver if USB id is not retrieved
* Fix bug with double deleting when devices are disconnected
* Determine some receiver information from data structure for USB ids
* Treat battery level of 0 as unknown
* Fix bug on devices with no serial number
* Drop support for python2, and use python3 throughout
* Fix bug in remembering features discovered from device reports
* Show icons in main window device list
* Count offline devices when determining whether pairing is possible
* Update French, Dutch, German, and Croation translations
* Better icons for battery levels
* Support DPI, Backlight 2, Battery Voltage features
* Support M585, M590, M330, MX Master 2s and 3, new M310, new K800, craft keyboard
* Documentation improvements
* Clean up directory structure and remove unused files
1.0.1:
* Updated the repo url.
* Fixed typo which was crashing the application.
* Improved the HID write routine which was causing issues on some devices.
* Fix non-unifying receivers in Linux 5.2.
* Add new Lightspeed receiver (used in the G305)
1.0.0:
* Too many to track...
0.9.3:
* Merged solaar-cli functionality into main solaar.
* Scrolling over the systray icon switches between multiple peripherals.
* Swedish translation courtesy of Daniel Zippert and Emelie Snecker
* French translation courtesy of Papoteur, David Geiger and Damien Lallement.
* Fixed some untranslated strings.
0.9.2:
* Added support for hand detection on the K800.
* Added support for V550 and V450 Nano.
* Fixed side-scrolling wit the M705 Marathon.
* Fixed side-scrolling with the M705 Marathon.
* Fixed identification of the T650 Touchpad.
* Added internationalization support and romanian translation.
* Polish translation courtesy of Adrian Piotrowicz.
@@ -11,7 +266,7 @@
* Make sure devices in the window tree are sorted by registration index.
* Added an autostart .desktop file.
* Replaced single-instance code with GtkApplication.
* Fixed indentification of the M505 mouse.
* Fixed identification of the M505 mouse.
* Fixed an occasional windowing layout bug with the C52F Nano Receiver.
0.9.0:

View File

@@ -1,88 +0,0 @@
**Solaar** is a Linux device manager for Logitech's [Unifying Receiver][unifying]
peripherals. It is able to pair/unpair devices to the receiver, and for most
devices read battery status.
It comes in two flavors, command-line and GUI. Both are able to list the
devices paired to a Unifying Receiver, show detailed info for each device, and
also pair/unpair supported devices with the receiver.
[unifying]: http://logitech.com/en-us/66/6079
## Supported Devices
**Solaar** will detect all devices paired with your Unifying Receiver, and at
the very least display some basic information about them.
For some devices, extra settings (usually not available through the standard
Linux system configuration) are supported. For a full list of supported devices
and their features, see [docs/devices.md](docs/devices.md).
## Pre-built packages
Pre-built packages are available for a few Linux distros.
* Debian 7 (Wheezy) or higher: packages in this [repository](docs/debian.md)
* Ubuntu/Kubuntu 12.04+: [ppa:daniel.pavel/solaar][ppa]
The `solaar` package uses a standard system tray implementation; to ensure
integration with *gnome-shell* or *Unity*, install `solaar-gnome3`.
* a [Gentoo overlay][gentoo], courtesy of Carlos Silva
* an [OpenSUSE rpm][opensuse], courtesy of Mathias Homann
* an [Arch package][arch], courtesy of Arnaud Taffanel
[ppa]: http://launchpad.net/~daniel.pavel/+archive/solaar
[gentoo]: http://code.r3pek.org/gentoo-overlay/src
[opensuse]: http://software.opensuse.org/package/Solaar
[arch]: http://aur.archlinux.org/packages/solaar
## Manual installation
See [docs/installation.md](docs/installation.md) for the step-by-step
procedure for manual installation.
## Known Issues
- KDE/Kubuntu: if some icons appear broken in the application, make sure you've
properly configured the Gtk theme and icon theme in KDE's control panel.
- Some devices using the [Nano Receiver][nano] (which is very similar to the
Unifying Receiver) are supported, but not all. For details, see
[docs/devices.md](docs/devices.md).
- Running the command-line application (`bin/solaar-cli`) while the GUI
application is also running *may* occasionally cause either of them to become
confused about the state of the devices. I haven't encountered this often
enough to be able to be able to diagnose it properly yet.
[nano]: http://logitech.com/mice-pointers/articles/5926
## License
This software is distributed under the terms of the
[GNU Public License, v2](COPYING).
## Thanks
This project began as a third-hand clone of [Noah K. Tilton](https://github.com/noah)'s
logitech-solar-k750 project on GitHub (no longer available). It was developed
further thanks to the diggings in Logitech's HID++ protocol done by many other
people:
- [Julien Danjou](http://julien.danjou.info/blog/2012/logitech-k750-linux-support),
who also provided some internal
[Logitech documentation](http://julien.danjou.info/blog/2012/logitech-unifying-upower)
- [Lars-Dominik Braun](http://6xq.net/git/lars/lshidpp.git)
- [Alexander Hofbauer](http://derhofbauer.at/blog/blog/2012/08/28/logitech-performance-mx)
- [Clach04](http://bitbucket.org/clach04/logitech-unifying-receiver-tools)
- [Peter Wu](https://lekensteyn.nl/logitech-unifying.html)
- [Nestor Lopez Casado](http://drive.google.com/folderview?id=0BxbRzx7vEV7eWmgwazJ3NUFfQ28)
provided some more Logitech specifications for the HID++ protocol
Also thanks to Douglas Wagner, Julien Gascard and Peter Wu for helping with
application testing and supporting new devices.

1
README.md Symbolic link
View File

@@ -0,0 +1 @@
docs/index.md

16
RELEASE.md Normal file
View File

@@ -0,0 +1,16 @@
# Solaar releases
## Please read before making a release
We support two type of releases: normal releases (ex. `1.0.0`) and release
candidates (ex. `1.0.0rc1`). Release candidates must have a `rcX` suffix.
Release routine:
- Update ChangeLog, setup.py, lib/solaar/__init__.py, and docs/_config.yml to the new version
- Create a commit that starts with `release VERSION`
- Push commit to Solaar repository
- Invoke `./release.sh`
- Git tags are signed so you must have GPG set up
- You are required to have a github token with `public_repo` access
in `~/.github-token`

57
Release_Notes Normal file
View File

@@ -0,0 +1,57 @@
Notes on Major Changes in Releases
Version 1.0.7:
Solaar rules can now trigger on both pressing and releasing a diverted key.
The new rule condition MouseProcess is like the Process condition except for the process of the window under the mouse.
Mouse gestures have been upgraded. A mouse gesture is now a sequence of movements separated by no movement periods while the mouse gesture button is held down. The MouseGesture rule condition matches mouse gesture sequences. The old mouse-up, etc., tests are converted to MouseGesture conditions.
Version 1.0.6:
The sliding DPI setting now looks for suitable keys to use to trigger its effects.
If a mouse has a suitable button it can generate mouse gestures, which trigger rule processing. Mouse gestures need to be turned on and the button diverted to produce mouse gestures.
Settings can now be ignored by clicking on the icon at the right-hand edge of a setting until the dialog error icon (usually a red icon) appears. Solaar will not try to restore the value for an ignored setting.
Icon handling in the tray and the tray menu has been updated to work better with some system tray implementations.
The process rule condition also matches against the current X11 WM_CLASS.
The SMART SHIFT ENHANCED feature is supported.
Version 1.0.5:
Solaar has rules that can perform actions such as pressing keys or scrolling when certain HID++ feature notifications happen. Users can change these rules either by editing ~/.config/solaar/rules.yaml or via a GUI. Rules depend on X11 and so are only available under X11. This is an experimental feature for Solaar and may undergo changes in the future.
Each setting has a clickable lock icon that determines whether the setting can be changed.
Version 1.0.4:
Devices that connect directly via Bluetooth or USB are now supported. These devices show up in the GUI as separate lines, not under a receiver. A device that is directly connected and also paired to a receiver will show up twice, but the entry under the receiver will not be active. With this change identifying devices becomes more difficult so occasionally check your Solaar configuration file (at ~/.config/solaar/config.json) to see that there is only one entry for each of your devices.
There are new settings for gestures, thumb wheels, adjusting the wheel ratchet behavior, and changing DPI using a DPI Switch button.
Solaar's Udev rule now adds seat permissions for all Logitech devices. Users who install Solaar themselves will have to install the new Udev rule and activate the rule. One way to do this is to restart the user's computer.
Version 1.0.3:
The separate deprecated solaar-cli command has been removed.
Devices can be switched between hosts using the Change Host setting. The device will try to connect to the other host. Some devices will detect that there is no active host on the other connections and reconnect back.
Version 1.0.2:
The separate unneeded solaar-gnome3 command has been removed. The packaging directories have been removed.
Non-unifying receivers are modelled better. Many of them cannot unpair but instead new pairings replace existing pairings.
Battery icon selection has been simplified.

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# -*- python-mode -*-
# -*- coding: UTF-8 -*-
@@ -22,23 +22,39 @@ from __future__ import absolute_import, unicode_literals
def init_paths():
"""Make the app work in the source tree."""
import sys
import os.path as _path
"""Make the app work in the source tree."""
import sys
import os.path as _path
prefix = _path.normpath(_path.join(_path.realpath(sys.path[0]), '..'))
src_lib = _path.join(prefix, 'lib')
share_lib = _path.join(prefix, 'share', 'solaar', 'lib')
for location in src_lib, share_lib:
init_py = _path.join(location, 'solaar', '__init__.py')
# print ("sys.path[0]: checking", init_py)
if _path.exists(init_py):
# print ("sys.path[0]: found", location, "replacing", sys.path[0])
sys.path[0] = location
break
# Python 2 need conversion from utf-8 filenames
# Python 3 might have problems converting back to UTF-8 in case of Unicode surrogates
try:
if sys.version_info < (3, ):
decoded_path = sys.path[0].decode(sys.getfilesystemencoding())
else:
decoded_path = sys.path[0]
sys.path[0].encode(sys.getfilesystemencoding())
except UnicodeError:
sys.stderr.write(
'ERROR: Solaar cannot recognize encoding of filesystem path, '
'this may happen because non UTF-8 characters in the pathname.\n'
)
sys.exit(1)
prefix = _path.normpath(_path.join(_path.realpath(decoded_path), '..'))
src_lib = _path.join(prefix, 'lib')
share_lib = _path.join(prefix, 'share', 'solaar', 'lib')
for location in src_lib, share_lib:
init_py = _path.join(location, 'solaar', '__init__.py')
# print ("sys.path[0]: checking", init_py)
if _path.exists(init_py):
# print ("sys.path[0]: found", location, "replacing", sys.path[0])
sys.path[0] = location
break
if __name__ == '__main__':
init_paths()
import solaar.gtk
solaar.gtk.main()
init_paths()
import solaar.gtk
solaar.gtk.main()

View File

@@ -1,42 +0,0 @@
#!/usr/bin/env python
# -*- python-mode -*-
# -*- coding: UTF-8 -*-
## Copyright (C) 2012-2013 Daniel Pavel
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2 of the License, or
## (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License along
## with this program; if not, write to the Free Software Foundation, Inc.,
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
from __future__ import absolute_import, unicode_literals
def init_paths():
"""Make the app work in the source tree."""
import sys
import os.path as _path
prefix = _path.normpath(_path.join(_path.realpath(sys.path[0]), '..'))
src_lib = _path.join(prefix, 'lib')
share_lib = _path.join(prefix, 'share', 'solaar', 'lib')
for location in src_lib, share_lib:
init_py = _path.join(location, 'solaar', '__init__.py')
if _path.exists(init_py):
sys.path[0] = location
break
if __name__ == '__main__':
init_paths()
import solaar.cli
solaar.cli.main()

6
docs/.gitignore vendored Normal file
View File

@@ -0,0 +1,6 @@
# ignore documentation-specific files
.jekyll-metadata
Gemfile
Gemfile.lock
_site/

4
docs/README.md Normal file
View File

@@ -0,0 +1,4 @@
# Documentation Readme
This project's documentation is hosted using GitHub pages, which serves static pages using Jekyll.
[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/)

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

BIN
docs/Solaar-menu.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

BIN
docs/Solaar-rule-editor.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 KiB

10
docs/_config.yml Normal file
View File

@@ -0,0 +1,10 @@
title: Solaar
description: Linux Device Manager for Logitech Unifying Receivers and Devices.
tagline: Linux Device Manager for Logitech Unifying Receivers and Devices.
owner: pwr-Solaar
owner_url: https://github.com/pwr-Solaar
repository: pwr-Solaar/Solaar
version: 1.0.7
show_downloads: false
encoding: utf-8
theme: jekyll-theme-slate

View File

@@ -0,0 +1,53 @@
<!DOCTYPE html>
<html lang="{{ site.lang | default: "en-US" }}">
<head>
<meta charset='utf-8'>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,maximum-scale=2">
<link rel="stylesheet" type="text/css" media="screen" href="{{ '/assets/css/style.css?v=' | append: site.github.build_revision | relative_url }}">
<link rel="icon" type="image/png" href="{{ site.baseurl }}/assets/favicon.png" />
{% seo %}
</head>
<body>
<!-- HEADER -->
<div id="header_wrap" class="outer">
<header class="inner">
{% if site.github.is_project_page %}
<a id="forkme_banner" href="{{ site.github.repository_url }}">View on GitHub</a>
{% endif %}
<h1 id="project_title">
<img src="{{ site.baseurl }}/assets/solaar.svg" style="margin-bottom: -10px; width: 48px; height: 48px; border: 0; box-shadow: none;" />
{{ site.title | default: site.github.repository_name }}</h1>
<h2 id="project_tagline">{{ site.description | default: site.github.project_tagline }}</h2>
{% if site.show_downloads %}
<section id="downloads">
<a class="zip_download_link" href="{{ site.github.zip_url }}">Download this project as a .zip file</a>
<a class="tar_download_link" href="{{ site.github.tar_url }}">Download this project as a tar.gz file</a>
</section>
{% endif %}
</header>
</div>
<!-- MAIN CONTENT -->
<div id="main_content_wrap" class="outer">
<section id="main_content" class="inner">
{{ content }}
</section>
</div>
<!-- FOOTER -->
<div id="footer_wrap" class="outer">
<footer class="inner">
{% if site.github.is_project_page %}
<p class="copyright">{{ site.title | default: site.github.repository_name }} maintained by <a href="{{ site.github.owner_url }}">{{ site.github.owner_name }}</a></p>
{% endif %}
<p>Published with <a href="https://pages.github.com">GitHub Pages</a></p>
</footer>
</div>
</body>
</html>

47
docs/_layouts/page.html Normal file
View File

@@ -0,0 +1,47 @@
<!DOCTYPE html>
<html lang="{{ site.lang | default: "en-US" }}">
<head>
<meta charset='utf-8'>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,maximum-scale=2">
<link rel="stylesheet" type="text/css" media="screen" href="{{ '/assets/css/style.css?v=' | append: site.github.build_revision | relative_url }}">
<link rel="icon" type="image/png" href="{{ site.baseurl }}/assets/favicon.png" />
{% seo %}
</head>
<body>
<!-- HEADER -->
<div id="header_wrap" class="outer">
<header class="inner">
{% if site.github.is_project_page %}
<a id="forkme_banner" href="{{ site.github.repository_url }}">View on GitHub</a>
{% endif %}
<h1 id="project_title">
<a href="{{ site.baseurl }}" style="color: #fff;">
<img src="{{ site.baseurl }}/assets/solaar.svg" style="margin-bottom: -10px; width: 48px; height: 48px; border: 0; box-shadow: none;" />
{{ site.title | default: site.github.repository_name }}</h1>
</a>
</header>
</div>
<!-- MAIN CONTENT -->
<div id="main_content_wrap" class="outer">
<section id="main_content" class="inner">
{{ content }}
</section>
</div>
<!-- FOOTER -->
<div id="footer_wrap" class="outer">
<footer class="inner">
{% if site.github.is_project_page %}
<p class="copyright">{{ site.title | default: site.github.repository_name }} maintained by <a href="{{ site.github.owner_url }}">{{ site.github.owner_name }}</a></p>
{% endif %}
<p>Published with <a href="https://pages.github.com">GitHub Pages</a></p>
</footer>
</div>
</body>
</html>

BIN
docs/assets/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

100
docs/assets/solaar.svg Normal file
View File

@@ -0,0 +1,100 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="svg2"
inkscape:version="0.91 r13725"
sodipodi:docname="solaar.svg"
inkscape:export-filename="/home/chris/Git/Solaar/_includes/favicon.png"
inkscape:export-xdpi="66.666672"
inkscape:export-ydpi="66.666672"
width="43.200001"
height="43.200001">
<metadata
id="metadata21">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1807"
inkscape:window-height="797"
id="namedview19"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:zoom="2.36"
inkscape:cx="1.4135593"
inkscape:cy="-4.4"
inkscape:window-x="3000"
inkscape:window-y="840"
inkscape:window-maximized="0"
inkscape:current-layer="svg2" />
<defs
id="defs4">
<linearGradient
id="gradient_blue">
<stop
style="stop-color:#009099;stop-opacity:1"
offset="0"
id="stop7" />
<stop
style="stop-color:#00a899;stop-opacity:0.9"
offset="1"
id="stop9" />
</linearGradient>
<linearGradient
x1="5"
y1="50"
x2="95"
y2="50"
id="gradient_rect"
xlink:href="#gradient_blue"
gradientUnits="userSpaceOnUse" />
<linearGradient
x1="37"
y1="50"
x2="63"
y2="50"
id="gradient_dot"
xlink:href="#gradient_blue"
gradientUnits="userSpaceOnUse" />
</defs>
<g
transform="matrix(0.48,0,0,0.48,-2.4,-2.4)"
id="g13">
<path
d="m 21.5,5.5 c -8.864,0 -16,7.136 -16,16 l 0,57 c 0,8.864 7.136,16 16,16 l 57,0 c 8.864,0 16,-7.136 16,-16 l 0,-57 c 0,-8.864 -7.136,-16 -16,-16 l -57,0 z m 16.1875,11.1875 9.03125,15.625 C 47.784179,32.115965 48.877705,32 50,32 c 1.122295,0 2.215821,0.115965 3.28125,0.3125 l 9.03125,-15.625 10.375,6 -9.03125,15.625 C 65.078123,39.972287 66.191785,41.898777 66.9375,44 L 85,44 85,56 66.9375,56 c -0.745715,2.101223 -1.859377,4.027713 -3.28125,5.6875 l 9.03125,15.625 -10.375,6 -9.03125,-15.625 C 52.215821,67.884035 51.122295,68 50,68 48.877705,68 47.784179,67.884035 46.71875,67.6875 l -9.03125,15.625 -10.375,-6 9.03125,-15.625 C 34.921877,60.027713 33.808215,58.101223 33.0625,56 L 15,56 15,44 33.0625,44 c 0.745715,-2.101223 1.859377,-4.027713 3.28125,-5.6875 l -9.03125,-15.625 10.375,-6 z"
style="fill:url(#gradient_rect);fill-opacity:1;fill-rule:nonzero;stroke:#16161d;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1"
id="path15"
inkscape:connector-curvature="0" />
<path
d="m 62,50 a 12,12 0 1 1 -24,0 12,12 0 1 1 24,0 z"
style="fill:url(#gradient_dot);fill-opacity:1;fill-rule:nonzero;stroke:#16161d;stroke-opacity:1"
id="path17"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.7 KiB

207
docs/capabilities.md Normal file
View File

@@ -0,0 +1,207 @@
---
title: Solaar Capabilities
layout: page
---
# Solaar Capabilities
[**Solaar**][solaar] reports on and controls [Logitech][logitech] devices
(keyboards, mice, and trackballs) that connect to your computer via a
Logitech USB receiver (a very small piece of hardware that plugs into one of
your USB ports).
Solaar is designed to detect all connected devices,
and at the very least display some basic information about them.
At this moment, all [Unifying][unifying] receivers are supported (e.g., devices
with USB ID `046d:c52b` or `046d:c532`) as are several Lightspeed Receivers
and many Nano receivers.
Solaar also reports on and controls some Logitech devices that directly connect
to your computer using a USB cable or via Bluetooth.
Not all such devices supported in Solaar as information needs to be added to Solaar
for each device type that directly connects.
## HID++
The devices that Solaar handles use Logitech's HID++ protocol.
HID++ is a Logitech-proprietary protocol that extends the standard HID
protocol for interfacing with receivers, keyboards, mice, and so on. It allows
Logitech receivers to communicate with multiple devices and modify some
features of the device. As the HID++ protocol is
proprietary, many aspects of it are unknown. Some information about HID++
has been obtained from Logitech but even that is subject to change and
extension.
There are several versions of HID++ and many Logitech
receivers and devices that utilize it. Different receivers and devices
implement different portions of HID++ so even if two devices appear to be
the same in both physical appearance and behavior they may work
differently underneath. (For example, there are versions of the
M510 mouse that use different versions of the HID++ protocol.)
Contrariwise, two different devices may appear different physically but
actually look the same to software. (For example, some M185 mice look the
same to software as some M310 mice.)
The software identity of a receiver can be determined by its USB product ID
(reported by Solaar and also viewable in Linux using `lsusb`). The software
identity of a device that connects to a receiver can be determined by
its wireless PID as reported by Solaar. The software identity of devices that
connect via a USB cable or via bluetooth can be determined by their USB or
Bluetooth product ID.
Even something as fundamental as pairing works differently for different
receivers. For Unifying receivers, pairing adds a new paired device, but
only if there is an open slot on the receiver. So these receivers need to
be able to unpair devices that they have been paired with or else they will
not have any open slots for pairing. Some other receivers, like the
Nano receiver with USB ID `046d:c534`, can only pair with particular kinds of
devices and pairing a new device replaces whatever device of that kind was
previously paired to the receiver. These receivers cannot unpair. Further,
some receivers can pair an unlimited number of times but others can only
pair a limited number of times.
Only some connections between receivers and devices are possible. In should
be possible to connect any device with a Unifying logo on it to any receiver
with a Unifying logo on it. Receivers without the Unifying logo probably
can connect only to the kind of devices they were bought with and devices
without the Unifying logo can probably only connect to the kind of receiver
that they were bought with.
## Supported Features
Solaar uses the HID++ protocol to pair devices to receivers and unpair
devices from receivers, and also uses the HID++ protocol to display
features of receivers and devices. Currently it only displays some
features, and can modify even fewer. For a list of HID++ features
and their support see [the features page](features).
Solaar does not do much beyond using the HID++ protocol to change the
behavior of receivers and devices via changing their settings.
In particular, Solaar cannot change how
the operating system turns the keycodes that a keyboard produces into
characters that are sent to programs. That is the province of HID device
drivers and other software (such as X11).
Settings can only be changed in the Solaar GUI when they are unlocked.
To unlock a setting click on the icon at the right-hand edge of the setting
until an unlocked lock appears (with tooltop "Changes allowed").
Solaar keep tracks of the changeable settings of a device.
Most devices forget changed settings when the are turned off
or go into a power-saving mode. When Solaar starts, it restores on-line
devices to their previously-known state, and while running it restores
devices to their previously-known state when the device itself comes on line.
This information is stored in the file `~/.config/solaar/config.json`.
Updating of settings can be turned off in the Solaar GUI by clicking on the icon
at the right-hand edge of the setting until a red icon appears (with tooltip
"Ignore this setting" ).
Solaar keeps track of settings independently on each computer.
As a result if a device is switched between different computers
Solaar may apply different settings for it on the different computers
Querying a device for its current state can require quite a few HID++
interactions. These interactions can temporarily slow down the device, so
Solaar tries to internally cache information about devices while it is
running. If the device
state is changed by some other means, even sometimes by another invocation
of Solaar, this cached information may become incorrect. Currently there is
no way to force an update of the cached information besides restarting Solaar.
Logitech receivers and devices have firmware in them. Some firmware
can be updated using Logitech software in Windows. For example, there are
security issues with some Logitech receivers and devices and Logitech has
firmware updates to alleviate these problems. Some Logitech firmware can
also be updated in Linux using `fwupdmgr`.
WARNING: Updating firmware can cause a piece of hardware to become
permanently non-functional if something goes wrong with the update or the
update installs the wrong firmware.
## Other Solaar Capabilities
Solaar has a few capabilities that go beyond simply changing device settings.
### Rule-based Processing of HID++ Notifications
Solaar can process HID++ Notifications from devices to, for example,
change the speed of some thumb wheels. These notifications are only sent
for actions that are set in Solaar to their HID++ setting (also known as diverted).
For more information on this capability of Solaar see
[the rules page](https://pwr-solaar.github.io/Solaar/rules). As much of rule processing
depends on X11, this capability is only when running under X11.
Users can edit rules using a GUI by clicking on the `Edit Rule` button in the Solaar main window.
Solaar rules is an experimental feature. Significant changes might be made in response to problems.
### Sliding DPI
A few mice (such as the MX Vertical) have a button that is supposed to be used to change
the sensitivity (DPI) of the mouse by pressing the button and moving the mouse left and right.
Other mice (such as the MX Master 3) don't have a button specific for this purpose
but have buttons that can be used for it.
The DPI Sliding Adjustment setting assigns a button for this purpose.
Pressing the button, if the button is diverted, causes the mouse pointer to stop moving.
When the button is released a new Sensitivity (DPI) value is applied to the mouse,
depending on how far right or left the mouse is moved. If the mouse is moved only a little bit
the previous value that was set is applied to the mouse.
Notifications from Solaar are displayed while the mouse button is done
showing the setting that will be applied.
### Mouse Gestures
Some mice (such as the MX Master 3) have a button that is supposed to be used to
create up/down/left/right mouse gestures. Other mice (such as the MX Vertical) don't
have a button specific for this purpose but have buttons that can be used for it.
The Mouse Gestures setting assigns a button for this purpose.
Pressing the button, if the button is diverted, causes the mouse pointer to stop moving.
When the button is released a MOUSE_GESTURE notification with the total mouse movement
while the button was pressed is sent to the Solaar rule system.
Mouse gestures is an experimental feature.
Significant changes might be made to it in the future.
## System Tray
Solaar's GUI normally uses an icon in the system tray.
This allows users to close Solaar and reopen from the tray.
This aspect of Solaar depends on having an active system tray which may
require some special setup when using Gnome, particularly under Wayland.
If you are running gnome, you most likely need the
`gnome-shell-extension-appindicator` package installed.
In Fedora, this can be done by running
```
sudo dnf install gnome-shell-extension-appindicator
```
The likely command in Ubuntu and related distributions is
```
sudo apt install gnome-shell-extension-appindicator
```
You may have to log out and log in again before the system tray shows up.
## Battery Icons
For many devices, Solaar shows the approximate battery level via icons that
show up in both the main window and the system tray. In previous versions
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`.
Solaar will use the symbolic versions of these icons if started with the
option `--battery-icons=symbolic`. Because of external bugs,
these symbolic icons may be nearly invisible in dark themes.
[solaar]: https://github.com/pwr-Solaar/Solaar
[logitech]: https://www.logitech.com
[unifying]: https://en.wikipedia.org/wiki/Logitech_Unifying_receiver

View File

@@ -1,7 +1,8 @@
---
title: Debian Repository
layout: page
---
# Debian repository
To use this repository with your Debian machine, create a file `solaar.list` in
`/etc/apt/sources.list.d/`, with the following contents:
deb http://pwr.github.io/Solaar/packages/ ./
deb-src http://pwr.github.io/Solaar/packages/ ./
Solaar is now part of the [official Debian repository](https://packages.debian.org/solaar). To install it on your Debian machine, use the following command: `sudo apt install solaar`

View File

@@ -1,49 +1,19 @@
# Supported devices
---
title: Supported Devices
layout: page
---
**Solaar** will detect all devices paired with your receiver, and at the very
least display some basic information about them.
# Supported devices and receivers
At this moment, all [Unifying Receiver][unifying] are supported (devices with
USB ID `046d:c52b` or `046d:c532`), but only some newer [Nano Receiver][nano]s
(devices with USB ID `046d:c52f`). You can check your connected Logitech devices
by running `lsusb -d 046d:` in a console.
These tables provide a partial list of supported Logitech receivers and
devices and to what degree their
features are supported by Solaar. The information in these tables is
based on what devices users have been able to test Solaar with.
For some devices, extra settings (usually not available through the standard
Linux system configuration) are supported:
* The [K750 Solar Keyboard][K750] is also queried for its solar charge status.
Pressing the `Light-Check` button on the keyboard will pop-up the application
window and display the current lighting value (Lux) as reported by the
keyboard, similar to Logitech's *Solar.app* for Windows.
* The state of the `FN` key can be toggled on some keyboards ([K360][K360],
[MK700][K700], [K750][K750] and [K800][K800]). It changes the way the function
keys (`F1`..`F12`) work, i.e. whether holding `FN` while pressing the function
keys will generate the standard `Fx` keycodes or the special function (yellow
icons) keycodes.
* The DPI can be changed on the [Performance MX Mouse][P_MX].
* Smooth scrolling (higher sensitivity on vertical scrolling with the wheel) can
be toggled on the [M705 Marathon Mouse][M705] and [M510 Wireless Mouse][M510].
# Supported features
These tables list all known Logitech [Unifying][unifying] devices, and to what
degree their features are supported by Solaar. If your device is not listed here
at all, it is very unlikely Solaar would be able to support it.
The information in these tables is incomplete, based on what devices myself and
other users have been able to test Solaar with. If your device works with
Solaar, but its supported features are not specified here, I would love to hear
about it.
Devices marked with an asterisk (*) use a Nano receiver that knows the Unifying
protocol, and should be fully supported by Solaar.
The HID++ column specifies the device's HID++ version.
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
the features the device supports.
The Battery column specifies if Solaar is able to read the device's battery
level.
@@ -51,89 +21,217 @@ level.
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 solaar-cli, but it is not possible to
assign different keys.
## Adding new receivers and devices
Adding a new receiver requires knowing whether the receiver is a regular
Unifying receiver, a nano receiver, or a lightspeed receiver. Add a line to
`../lib/logitech_receiver/base_usb.py` defining the receiver as one of these.
If the receiver has an unusual number of pairing slots, then this also needs
to be specified. Then add the receiver to the tuple of receivers (ALL).
Most new devices do not need to be known to Solaar to work. However, an
entry in `lib/logitech-receiver/descriptors.py` can provide a better name for
the device and a feature list can speed up Solaar startup a bit. The
arguments to the _D function are the device's long name, its short name
(codename), its HID++ protocol version, its wireless product ID (wpid), and
a tuple of known feature settings (from `lib/logitech/settings_templates.py`).
If the device can connect via a USB cable its USB product ID should be included.
If the device can connect via Bluetooth its Bluetooth product ID should be included.
Some Logitech devices are not suited for use in Solaar. If the device only
connects via a USB cable Solaar might not be able to do much or anything
with the device so it may not be useful to add it to Solaar. One example is
the MX518 Gaming Mouse.
Keyboards:
### Receivers
| Device | HID++ | Battery | Other supported features |
|------------------|-------|---------|-----------------------------------------|
| K230 | 2.0 | yes | |
| K270 | | | |
| K340 | | | |
| K350 | | | |
| K360 | 2.0 | yes | FN swap, reprog keys |
| K400 Touch | 2.0 | yes | |
| K750 Solar | 2.0 | yes | FN swap, Lux reading, light button |
| K800 Illuminated | 1.0 | yes | FN swap, reprog keys |
| MK700 | 1.0 | yes | FN swap, reprog keys |
| USB ID | Kind | Max Paired Devices |
------------|------------|--------------------|
| 046d:c517 | 27MHz old | 4 |
| 046d:c518 | Nano | 1 |
| 046d:c51a | Nano | 1 |
| 046d:c51b | Nano | 1 |
| 046d:c521 | Nano | 1 |
| 046d:c525 | Nano | 1 |
| 046d:c526 | Nano | 1 |
| 046d:c52b | Unifying | 6 |
| 046d:c52e | Nano | 1 |
| 046d:c52f | Nano | 1 |
| 046d:c531 | Nano | 1 |
| 046d:c532 | Unifying | 6 |
| 046d:c534 | Nano | 2 |
| 046d:c539 | Lightspeed | 1 |
| 046d:c53a | Lightspeed | 1 |
| 046d:c53d | Lightspeed | 1 |
| 046d:c53f | Lightspeed | 1 |
| 046d:c545 | Lightspeed | 1 |
| 046d:c541 | Lightspeed | 1 |
| 17ef:6042 | Nano | 1 |
Some Nano receivers are only partly supported
as they do not fully implement the HID++ 1.0 protocol.
The receiver with USB Id 046d:c517 is an old 27 MHz receiver, supporting only
subset of HID++ 1.0 protocol. Only hardware pairing is supported.
Mice:
### Keyboards (Unifying)
| Device | HID++ | Battery | DPI | Other supported features |
|------------------|-------|---------|-------|---------------------------------|
| V450 Nano | 1.0 | yes | - | smooth scrolling |
| V550 Nano | 1.0 | yes | - | smooth scrolling |
| VX Nano | 1.0 | yes | - | smooth scrolling |
| M175 * | | yes | | |
| M185 * | | yes | | |
| M187 * | 2.0 | yes | | |
| M215 * | 1.0 | yes | | |
| M235 * | | yes | | |
| M305 * | 1.0 | yes | | |
| M310 * | | yes | | |
| M315 * | | yes | | |
| M317 | | | | |
| M325 | | | | |
| M345 | 2.0 | yes | - | |
| M505 | 1.0 | yes | | |
| M510 | 1.0 | yes | | smooth scrolling |
| M515 Couch | 2.0 | yes | - | |
| M525 | 2.0 | yes | - | |
| M600 Touch | 2.0 | yes | | |
| M705 Marathon | 1.0 | yes | - | smooth scrolling |
| T400 Zone Touch | | | | |
| T620 Touch | 2.0 | | | |
| Performance MX | 1.0 | yes | R/W | |
| Anywhere MX | 1.0 | yes | - | |
| Cube | 2.0 | yes | | |
| Device | WPID | HID++ | Battery | Other supported features |
|------------------|------|-------|---------|-----------------------------------------|
| K230 | 400D | 2.0 | yes | |
| K270 | 4003 | 2.0 | yes | |
| K340 | 2007 | 1.0 | yes | |
| K350 | 200A | 1.0 | yes | |
| K360 | 4004 | 2.0 | yes | FN swap, reprog keys |
| K375s | 4071 | | | FN swap |
| K400 Touch | 400E | 2.0 | yes | FN swap |
| K400 Touch | 4024 | 2.0 | yes | FN swap |
| K400 Plus | 404D | 2.0 | | FN swap, disable keys, touchpad gestures|
| K520 | 2011 | 1.0 | yes | FN swap |
| K600 TV | 4078 | 2.0 | yes | FN swap |
| K750 Solar | 4002 | 2.0 | yes | FN swap, Lux reading, light button |
| K780 | 405B | 2.0 | yes | FN swap |
| K800 Illuminated | 2010 | 1.0 | yes | FN swap, reprog keys, LEDs |
| K800 (new ver) | 406E | 2.0 | yes | FN swap |
| K830 Illuminated | 4032 | 2.0 | yes | FN swap |
| MX Keys | 408A | 2.0 | yes | |
| N545 | 2006 | | yes | |
| TK820 | | 2.0 | yes | FN swap |
| Craft | 4066 | 2.0 | | |
* The [K750 Solar Keyboard][K750] can be queried for its solar charge status.
Pressing the `Light-Check` button on the keyboard will pop-up the application
window and display the current lighting value (Lux) as reported by the
keyboard, similar to Logitech's *Solar.app* for Windows.
Trackballs:
* FN swap changes the way the function keys (`F1``F12`) work, i.e., whether holding `FN` while pressing the function keys will generate the standard `Fx` keycodes or the special function (yellow icons) keycodes.
| Device | HID++ | Battery | DPI | Other supported features |
|------------------|-------|---------|-------|---------------------------------|
| M570 Trackball | | | | |
### Mice (Unifying)
| Device | WPID | HID++ | Battery | DPI | Other supported features |
|------------------|------|-------|---------|-------|-----------------------------------------|
| M150 | 4022 | 2.0 | | | |
| M185 | 4055 | 2.0 | | R/W | smooth scrolling |
| M310 | 4031 | 2.0 | yes | | |
| M310 | 4055 | 2.0 | | R/W | smooth scrolling |
| M317 | | | | | |
| M325 | 400A | 2.0 | yes | 1000 | smooth scrolling |
| M330 | | 2.0 | yes | 1000 | smooth scrolling |
| M345 | 4017 | 2.0 | yes | | smooth scrolling |
| M350 | 101C | 1.0 | yes | | |
| M350 | 4080 | 2.0 | | | |
| M505 | 101D | 1.0 | yes | | smooth scrolling, side scrolling |
| M510 | 1025 | 1.0 | yes | | smooth scrolling, side scrolling |
| M510 | 4051 | 2.0 | yes | | smooth scrolling |
| M515 Couch | 4007 | 2.0 | yes | | smooth scrolling |
| M525 | 4013 | 2.0 | yes | | smooth scrolling |
| M560 | | 2.0 | yes | | smooth scrolling |
| M585 | 406B | 2.0 | yes | R/W | smooth scrolling |
| M590 | 406B | 2.0 | yes | R/W | smooth scrolling |
| M600 Touch | 401A | 2.0 | yes | | |
| M705 Marathon | 101B | 1.0 | yes | | smooth scrolling, side scrolling |
| M705 Marathon | 406D | 2.0 | yes | R/W | smooth scrolling |
| M720 Triathlon | 405E | 2.0 | yes | | |
| T400 Zone Touch | | 2.0 | yes | | smooth scrolling |
| T620 Touch | | 2.0 | yes | | |
| Performance MX | 101A | 1.0 | yes | R/W | smooth scrolling, side scrolling |
| Anywhere MX | 1017 | 1.0 | yes | R/W | smooth scrolling, side scrolling |
| Anywhere MX 2 | 404A | 2.0 | yes | R/W | smooth scrolling |
| MX Master | 4041 | 2.0 | yes | R/W | smooth scrolling, smart shift |
| MX Master 2S | 4069 | 2.0 | yes | R/W | smooth scrolling, smart shift, gestures |
| Cube | | 2.0 | yes | | |
Touchpads:
### Mice (Nano)
| Device | HID++ | Battery | DPI | Other supported features |
|------------------|-------|---------|-------|---------------------------------|
| Wireless Touch | 2.0 | | | |
| T650 Touchpad | 2.0 | | | |
| Device | WPID | HID++ | Battery | DPI | Other supported features |
|------------------|------|-------|---------|-------|---------------------------------|
| G7 | 1002 | 1.0 | yes | | |
| G700 | 1023 | 1.0 | yes | | smooth scrolling, side scrolling|
| G700s | 102A | 1.0 | yes | | smooth scrolling, side scrolling|
| V450 Nano | 1011 | 1.0 | yes | | smooth scrolling |
| V550 Nano | 1013 | 1.0 | yes | | smooth scrolling, side scrolling|
| VX Nano | 100B | 1.0 | yes | | smooth scrolling, side scrolling|
| VX Nano | 100F | 1.0 | yes | | smooth scrolling, side scrolling|
| M175 | 4008 | | yes | | |
| M185 (old) | 4038 | 2.0 | yes | R/W | smooth scrolling (note) |
| M185 (new) | 4054 | 2.0 | no | R/W | smooth scrolling (note) |
| M187 | 4019 | 2.0 | yes | | |
| M215 | 1020 | 1.0 | yes | | |
| M235 | 4055 | 2.0 | yes | R/W | smooth scrolling |
| M305 | 101F | 1.0 | yes | | side scrolling |
| M310 | 1024 | 1.0 | yes | | |
| M315 | | | yes | | |
| M330 | | ?.? | yes | ? | smooth scrolling |
| MX 1100 | 1014 | 1.0 | yes | | smooth scrolling, side scrolling|
* (old): M185 with P/N: 810-003496
* (new): M185 with P/N: 810-005238 or 810-005232
* (note): Currently, smooth scrolling events are not processed in xfce and this
setting is useful only to disable smooth scrolling.
Mouse-Keyboard combos:
### Mice (Mini)
| Device | HID++ | Battery | Other supported features |
|------------------|-------|---------|-----------------------------------------|
| MK330 | | | |
| MK520 | | | |
| MK550 | | | |
| MK710 | 1.0 | yes | FN swap, reprog keys |
| Device | WPID | HID++ | Battery | DPI | Other supported features |
|-------------------|------|-------|---------|-------|---------------------------------|
| MX610 | 1001 | 1.0 | yes | | |
| MX610 left handed | 1004 | 1.0 | yes | | |
| MX620 | 100A | 1.0 | yes | | |
| MX620 | 1016 | 1.0 | yes | | |
| V400 | 1003 | 1.0 | yes | | |
| V450 | 1005 | 1.0 | yes | | |
| VX Revolution | 1006 | 1.0 | yes | | |
| VX Revolution | 100D | 1.0 | yes | | |
| MX Air | 1007 | 1.0 | yes | | |
| MX Air | 100E | 1.0 | yes | | |
| MX Revolution | 1008 | 1.0 | yes | | |
| MX Revolution | 100C | 1.0 | yes | | |
### Trackballs (Unifying)
[unifying]: http://logitech.com/en-us/66/6079
[nano]: http://logitech.com/mice-pointers/articles/5926
| Device | WPID | HID++ | Battery | DPI | Other supported features |
|-------------------|------|-------|---------|-------|---------------------------------|
| M570 Trackball | | 1.0 | yes | | |
| MX Ergo Trackball | | 2.0 | yes | | |
### Touchpads (Unifying)
| Device | WPID | HID++ | Battery | DPI | Other supported features |
|------------------|------|-------|---------|-------|---------------------------------|
| Wireless Touch | 4011 | 2.0 | yes | | |
| T650 Touchpad | 4101 | 2.0 | yes | | smooth scrolling |
### Mice and Keyboards sold as combos
| Device | WPID | HID++ | Battery | Other supported features |
|------------------|------|-------|---------|-----------------------------------------|
| MK220 | | 2.0 | yes | |
| MK270 | 4023 | 2.0 | yes | reprog keys |
| MK320 | 200F | | | |
| MK330 | | | | |
| MK345 | 4023 | 2.0 | yes | reprog keys |
| MK520 | | M2/K1 | yes | FN swap, reprog keys |
| MK550 | | | | |
| MK700 | 2008 | 1.0 | yes | FN swap, reprog keys |
| MK710 | | 1.0 | yes | FN swap, reprog keys |
| EX100 keyboard | 0065 | 1.0 | yes | |
| EX100 mouse | 003f | 1.0 | yes | |
* The EX100 is an old, preunifying receiver and device set, supporting only part of HID++ 1.0 features
[solaar]: https://github.com/pwr-Solaar/Solaar
[logitech]: https://www.logitech.com
[unifying]: https://en.wikipedia.org/wiki/Logitech_Unifying_receiver
[G700s]: https://gaming.logitech.com/en-us/product/g700s-rechargeable-wireless-gaming-mouse
[K360]: http://logitech.com/product/keyboard-k360
[K700]: http://logitech.com/product/wireless-desktop-mk710
[K750]: http://logitech.com/product/k750-keyboard
[K800]: http://logitech.com/product/wireless-illuminated-keyboard-k800
[K830]: http://logitech.com/product/living-room-keyboard-k830
[M510]: http://logitech.com/product/wireless-mouse-m510
[M705]: http://logitech.com/product/marathon-mouse-m705
[P_MX]: http://logitech.com/product/performance-mouse-mx
[A_MX]: http://logitech.com/product/anywhere-mouse-mx
[M325]: http://logitech.com/product/wireless-mouse-m325
[M330]: https://www.logitech.com/en-us/product/m330-silent-plus

View File

@@ -0,0 +1,48 @@
1: Wireless Mouse M510
Codename : M510v2
Kind : mouse
Wireless PID : 4051
Protocol : HID++ 4.5
Polling rate : 8 ms (125Hz)
Serial number: 8989B04C
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}
6: unknown:1802 {1802} internal, hidden
7: unknown:1810 {1810} internal, hidden
8: unknown:1830 {1830} internal, hidden
9: unknown:1862 {1862} internal, hidden
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}
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}
Has 7 reprogrammable keys:
0: LEFT CLICK , default: LeftClick => LEFT CLICK
divertable, mse, pos:0, group:1, gmask:1
1: RIGHT CLICK , default: RightClick => RIGHT CLICK
divertable, mse, pos:0, group:1, gmask:1
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
divertable, mse, reprogrammable, pos:0, group:2, gmask:3
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
divertable, mse, reprogrammable, pos:0, group:2, gmask:3
6: FORWARD AS BUTTON 5 , default: BrowserForwardEx => FORWARD AS BUTTON 5
divertable, mse, reprogrammable, pos:0, group:2, gmask:3
Battery: 70%, discharging.

View File

@@ -0,0 +1,51 @@
Unifying Receiver
Device path : /dev/hidraw0
USB id : 046d:c52b
Serial : A7F5923B
Firmware : 24.01.B0023
Bootloader : 01.08
Other : AA.AD
Has 1 paired device(s) out of a maximum of 6.
Notifications: wireless, software present (0x000900)
Device activity counters: 1=11
1: Wireless Mouse MX Anywhere 2
Codename : MX Anywhere 2
Kind : mouse
Wireless PID : 404A
Protocol : HID++ 4.5
Polling rate : 8 ms (125Hz)
Serial number: F3B81C5B
Bootloader: BOT 23.00.B0007
Firmware: MPM 02.00.B0007
Firmware: MPM 02.00.B0007
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}
13: unknown:1813 {1813} internal, hidden
14: unknown:1830 {1830} internal, hidden
15: unknown:1890 {1890} internal, hidden
16: unknown:1891 {1891} internal, hidden
17: unknown:18A1 {18A1} internal, hidden
18: unknown:18C0 {18C0} internal, hidden
19: unknown:1DF3 {1DF3} internal, hidden
20: unknown:1E00 {1E00} hidden
21: unknown:1EB0 {1EB0} internal, hidden
22: unknown:1803 {1803} internal, hidden
23: unknown:1861 {1861} internal, hidden
24: unknown:9000 {9000} internal, hidden
25: unknown:1805 {1805} internal, hidden
Battery: 0%, recharging.

View File

@@ -0,0 +1,88 @@
Receiver
LZ301AR-DJ
M/N:C-U0007
(ltunify)
Serial number: D1759614
Firmware version: 012.001.00019
Bootloader version: BL.002.014
Supported notification flags: 00 09 00
- 01: Wireless Notifications
- 08: Software Present
Mouse
(ltunify)
HID++ version: 1.0
Device index 1
Mouse
Name: Anywhere MX
Wireless Product ID: 1017
Serial number: 13865F99
Firmware version: 016.001.00040
Bootloader version: BL.002.010
(solaar)
Unifying Receiver
Device path : /dev/hidraw2
USB id : 046d:c52b
Serial : D1759614
Firmware : 12.01.B0019
Bootloader : 02.14
Has 1 paired device(s) out of a maximum of 6.
Notifications: (none)
Device activity counters: 1=19
1: Anywhere Mouse MX
Codename : Anywhere MX
Kind : mouse
Wireless PID : 1017
Protocol : HID++ 1.0
Polling rate : 8 ms (125Hz)
Serial number: 13865F99
Firmware: 16.01.B0040
Bootloader: 02.10
Other: 00.06
The power switch is located on the base.
Notifications: (none).
Battery: 100%, discharging.
(scan-registers)
# Old notification flags: 000000
# 00 - Enabled Notifications, supported flags: Battery Status (10)
>> ( 0.792) [10 01 8100 100000] b'\x10\x01\x81\x00\x10\x00\x00'
# 01 - scrolling settings?
# Flags:
# 0x40 - Enable Smooth Scrolling
# 0x02 - "confuse KDE", see https://github.com/pwr/Solaar/issues/115
<< ( 0.011) [10 01 8101 000000] b'\x10\x01\x81\x01\x00\x00\x00'
>> ( 1.710) [10 01 8101 020000] b'\x10\x01\x81\x01\x02\x00\x00'
# 0D - battery level. first byte is remaining charge in percent; second is
# (guessed) maximum?; third is charge status (30=discharging)
# "10 ix 0D 64 64 30 00" is a battery notification (when enabled)
<< ( 9.789) [10 01 810D 000000] b'\x10\x01\x81\r\x00\x00\x00'
>> ( 9.816) [10 01 810D 646430] b'\x10\x01\x81\rdd0'
# 63 - DPI (range 0x80-0x8e (inclusive))
<< ( 75.521) [10 01 8163 000000] b'\x10\x01\x81c\x00\x00\x00'
>> ( 75.550) [10 01 8163 890000] b'\x10\x01\x81c\x89\x00\x00'
# D0 - ?
<< ( 163.118) [10 01 81D0 000000] b'\x10\x01\x81\xd0\x00\x00\x00'
>> ( 163.148) [10 01 81D0 000000] b'\x10\x01\x81\xd0\x00\x00\x00'
# D4 - ?
<< ( 166.034) [10 01 81D4 000000] b'\x10\x01\x81\xd4\x00\x00\x00'
>> ( 166.063) [10 01 81D4 000008] b'\x10\x01\x81\xd4\x00\x00\x08'
# F1 - firmware/bootloader version
<< ( 187.172) [10 01 81F1 000000] b'\x10\x01\x81\xf1\x00\x00\x00'
>> ( 187.199) [10 01 8F81 F10300] b'\x10\x01\x8f\x81\xf1\x03\x00'
# F3 - ?
<< ( 188.629) [10 01 81F3 000000] b'\x10\x01\x81\xf3\x00\x00\x00'
>> ( 188.661) [10 01 81F3 000000] b'\x10\x01\x81\xf3\x00\x00\x00'
# FD - ?
<< ( 195.715) [10 01 83FD 000000] b'\x10\x01\x83\xfd\x00\x00\x00'
>> ( 195.746) [11 01 83FD 00000000000000000000000000000000] b'\x11\x01\x83\xfd\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'

113
docs/devices/craft.txt Normal file
View File

@@ -0,0 +1,113 @@
Unifying Receiver
Device path : /dev/hidraw0
USB id : 046d:c52b
Serial : E21FAD57
Firmware : 24.06.B0030
Bootloader : 01.08
Other : AA.AC
Has 2 paired device(s) out of a maximum of 6.
Notifications: wireless, software present (0x000900)
Device activity counters: 1=243, 2=173
1: Craft Advanced Keyboard
Codename : Craft
Kind : keyboard
Wireless PID : 4066
Protocol : HID++ 4.5
Polling rate : 8 ms (125Hz)
Serial number: 428C2F81
Bootloader: BOT 41.00.B0014
Firmware: MPK 07.01.B0015
Other:
Other:
The power switch is located on the edge of top right corner.
Supports 39 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: unknown:1982 {1982}
11: REPROG CONTROLS V4 {1B04}
12: unknown:1C00 {1C00}
13: K375S FN INVERSION {40A3}
14: ENCRYPTION {4100}
15: LOCK KEY STATE {4220}
16: KEYBOARD DISABLE {4521}
17: unknown:4531 {4531}
18: unknown:4600 {4600}
19: unknown:00C2 {00C2}
20: unknown:1803 {1803} internal, hidden
21: unknown:1806 {1806} internal, hidden
22: unknown:1813 {1813} internal, hidden
23: unknown:1805 {1805} internal, hidden
24: unknown:1830 {1830} internal, hidden
25: unknown:1890 {1890} internal, hidden
26: unknown:1891 {1891} internal, hidden
27: unknown:1801 {1801} internal, hidden
28: unknown:18A1 {18A1} internal, hidden
29: unknown:9280 {9280} internal, hidden
30: unknown:1A20 {1A20} internal, hidden
31: unknown:1DF3 {1DF3} internal, hidden
32: unknown:1E00 {1E00} hidden
33: unknown:1EB0 {1EB0} internal, hidden
34: unknown:1861 {1861} internal, hidden
35: unknown:18B0 {18B0} internal, hidden
36: unknown:92C0 {92C0} internal, hidden
37: unknown:9203 {9203} internal, hidden
38: unknown:3615 {3615} internal, hidden
Has 24 reprogrammable keys:
0: unknown:00D1 , default: unknown:00AE => unknown:00D1
divertable, nonstandard, persistently divertable, pos:0, group:0, gmask:0
1: unknown:00D2 , default: unknown:00AF => unknown:00D2
divertable, nonstandard, persistently divertable, pos:0, group:0, gmask:0
2: unknown:00D3 , default: unknown:00B0 => unknown:00D3
divertable, nonstandard, persistently divertable, pos:0, group:0, gmask:0
3: unknown:00C7 , default: unknown:00A3 => unknown:00C7
divertable, is FN, FN sensitive, persistently divertable, reprogrammable, pos:1, group:0, gmask:0
4: unknown:00C8 , default: unknown:00A4 => unknown:00C8
divertable, is FN, FN sensitive, persistently divertable, reprogrammable, pos:2, group:0, gmask:0
5: unknown:00E0 , default: unknown:00BF => unknown:00E0
divertable, is FN, FN sensitive, persistently divertable, reprogrammable, pos:3, group:0, gmask:0
6: unknown:00E1 , default: unknown:00C0 => unknown:00E1
divertable, is FN, FN sensitive, persistently divertable, reprogrammable, pos:4, group:0, gmask:0
7: SHOW DESKTOP , default: ShowDesktop => SHOW DESKTOP
divertable, is FN, FN sensitive, persistently divertable, reprogrammable, pos:5, group:0, gmask:0
8: unknown:00E2 , default: unknown:00C1 => unknown:00E2
divertable, is FN, FN sensitive, persistently divertable, reprogrammable, pos:6, group:0, gmask:0
9: unknown:00E3 , default: unknown:00C2 => unknown:00E3
divertable, is FN, FN sensitive, persistently divertable, reprogrammable, pos:7, group:0, gmask:0
10: unknown:00E4 , default: Previous => unknown:00E4
divertable, is FN, FN sensitive, persistently divertable, reprogrammable, pos:8, group:0, gmask:0
11: unknown:00E5 , default: Play/Pause => unknown:00E5
divertable, is FN, FN sensitive, persistently divertable, reprogrammable, pos:9, group:0, gmask:0
12: unknown:00E6 , default: Next => unknown:00E6
divertable, is FN, FN sensitive, persistently divertable, reprogrammable, pos:10, group:0, gmask:0
13: unknown:00E7 , default: Mute => unknown:00E7
divertable, is FN, FN sensitive, persistently divertable, reprogrammable, pos:11, group:0, gmask:0
14: unknown:00E8 , default: Volume Down => unknown:00E8
divertable, is FN, FN sensitive, persistently divertable, reprogrammable, pos:12, group:0, gmask:0
15: unknown:00E9 , default: Volume Up => unknown:00E9
divertable, nonstandard, persistently divertable, reprogrammable, pos:0, group:0, gmask:0
16: Calculator , default: Calculator => Calculator
divertable, nonstandard, persistently divertable, reprogrammable, pos:0, group:0, gmask:0
17: unknown:00BF , default: unknown:009B => unknown:00BF
divertable, nonstandard, persistently divertable, reprogrammable, pos:0, group:0, gmask:0
18: unknown:00EA , default: unknown:00C3 => unknown:00EA
divertable, nonstandard, persistently divertable, reprogrammable, pos:0, group:0, gmask:0
19: Lock PC , default: WindowsLock => Lock PC
divertable, nonstandard, persistently divertable, reprogrammable, pos:0, group:0, gmask:0
20: unknown:00EC , default: unknown:00B8 => unknown:00EC
divertable, nonstandard, persistently divertable, pos:0, group:0, gmask:0
21: unknown:00EB , default: unknown:00B6 => unknown:00EB
divertable, nonstandard, persistently divertable, pos:0, group:0, gmask:0
22: unknown:00DE , default: Do Nothing One => unknown:00DE
is FN, pos:0, group:0, gmask:0
23: unknown:0034 , default: Do Nothing One => unknown:0034
nonstandard, pos:0, group:0, gmask:0
Battery: 0%, full.

120
docs/devices/ex100.txt Normal file
View File

@@ -0,0 +1,120 @@
./scan-registers.sh ff /dev/hidraw4
# Old notification flags: 000100
>> ( 0.035) [10 FF 8100 000100] '\x10\xff\x81\x00\x00\x01\x00'
<< ( 0.015) [10 FF 8101 000000] '\x10\xff\x81\x01\x00\x00\x00'
>> ( 0.020) [10 FF 8101 000200] '\x10\xff\x81\x01\x00\x02\x00'
<< ( 0.030) [10 FF 8102 000000] '\x10\xff\x81\x02\x00\x00\x00'
>> ( 0.036) [10 FF 8102 000200] '\x10\xff\x81\x02\x00\x02\x00'
--
<< ( 0.142) [10 FF 8109 000000] '\x10\xff\x81\t\x00\x00\x00'
>> ( 0.148) [10 FF 8109 010000] '\x10\xff\x81\t\x01\x00\x00'
--
<< ( 1.790) [10 FF 8170 000000] '\x10\xff\x81p\x00\x00\x00'
>> ( 1.796) [10 FF 8170 012100] '\x10\xff\x81p\x01!\x00'
<< ( 1.806) [10 FF 8171 000000] '\x10\xff\x81q\x00\x00\x00'
>> ( 1.812) [10 FF 8171 011200] '\x10\xff\x81q\x01\x12\x00'
--
<< ( 1.838) [10 FF 8173 000000] '\x10\xff\x81s\x00\x00\x00'
>> ( 1.844) [10 FF 8173 643F00] '\x10\xff\x81sd?\x00'
--
<< ( 2.046) [10 FF 8180 000000] '\x10\xff\x81\x80\x00\x00\x00'
>> ( 2.052) [10 FF 8180 030000] '\x10\xff\x81\x80\x03\x00\x00'
--
<< ( 3.326) [10 FF 81D0 000000] '\x10\xff\x81\xd0\x00\x00\x00'
>> ( 3.332) [10 FF 81D0 000000] '\x10\xff\x81\xd0\x00\x00\x00'
devices
01 mouse
Red button pressed
>> ( 1676.106) [10 01 0810 000000] '\x10\x01\x08\x10\x00\x00\x00'
>> ( 1676.114) [10 01 4600 000021] '\x10\x01F\x00\x00\x00!'
>> ( 1676.122) [10 FF 4600 211100] '\x10\xffF\x00!\x11\x00'
Power lewel?
?? Input: 10 01 81 07 00 00 00
<< ( 1739.032) [10 01 8107 000000] '\x10\x01\x81\x07\x00\x00\x00'
>> ( 1739.040) [10 01 8107 030000] '\x10\x01\x81\x07\x03\x00\x00'
[10 01 8107 070000] '\x10\x01\x81\x07\x07\x00\x00'
power change
>> ( 2441.563) [10 01 0703 000000] '\x10\x01\x07\x03\x00\x00\x00'
>> ( 100.159) [10 01 0707 000000] '\x10\x01\x07\x07\x00\x00\x00'
enable power event
<< ( 59.190) [10 01 8000 100000] '\x10\x01\x80\x00\x10\x00\x00'
>> ( 59.193) [10 01 8000 000000] '\x10\x01\x80\x00\x00\x00\x00'
03 keyboard
Power level?
?? Input: 10 03 81 07 00 00 00
<< ( 1777.961) [10 03 8107 000000] '\x10\x03\x81\x07\x00\x00\x00'
>> ( 1777.967) [10 03 8107 070000] '\x10\x03\x81\x07\x07\x00\x00'
power on
>> ( 1571.805) [10 03 0810 000000] '\x10\x03\x08\x10\x00\x00\x00'
>> ( 1574.709) [10 03 0800 000000] '\x10\x03\x08\x00\x00\x00\x00'
red button pressed
>> ( 1619.043) [10 03 0810 000000] '\x10\x03\x08\x10\x00\x00\x00'
>> ( 1619.051) [10 03 4600 000011] '\x10\x03F\x00\x00\x00\x11'
>> ( 1619.059) [10 FF 4600 221100] '\x10\xffF\x00"\x11\x00'
>> ( 1621.747) [10 03 0800 000000] '\x10\x03\x08\x00\x00\x00\x00'
Fn pressed
>> ( 1651.715) [10 03 032C 100000] '\x10\x03\x03,\x10\x00\x00'
>> ( 1652.170) [10 03 0300 000000] '\x10\x03\x03\x00\x00\x00\x00'
$ bin/solaar probe
Nano Receiver
Device path : /dev/hidraw3
USB id : 046d:c517
Serial : None
Has 2 paired device(s) out of a maximum of 6.
Notifications: wireless (0x000100)
Register Dump
Notification Register 0x00: 0x000100
Connection State 0x02: 0x000200
Device Activity 0xb3: None
Pairing Register 0xb5 0x00: None
Pairing Register 0xb5 0x10: None
Pairing Register 0xb5 0x20: None
Pairing Register 0xb5 0x30: None
Pairing Name 0xb5 0x40: None
Pairing Register 0xb5 0x01: None
Pairing Register 0xb5 0x11: None
Pairing Register 0xb5 0x21: None
Pairing Register 0xb5 0x31: None
Pairing Name 0xb5 0x41: None
Pairing Register 0xb5 0x02: None
Pairing Register 0xb5 0x12: None
Pairing Register 0xb5 0x22: None
Pairing Register 0xb5 0x32: None
Pairing Name 0xb5 0x42: None
Pairing Register 0xb5 0x03: None
Pairing Register 0xb5 0x13: None
Pairing Register 0xb5 0x23: None
Pairing Register 0xb5 0x33: None
Pairing Name 0xb5 0x43: None
Pairing Register 0xb5 0x04: None
Pairing Register 0xb5 0x14: None
Pairing Register 0xb5 0x24: None
Pairing Register 0xb5 0x34: None
Pairing Name 0xb5 0x44: None
Pairing Register 0xb5 0x05: None
Pairing Register 0xb5 0x15: None
Pairing Register 0xb5 0x25: None
Pairing Register 0xb5 0x35: None
Pairing Name 0xb5 0x45: None
Firmware 0xf1 0x00: None
Firmware 0xf1 0x01: None
Firmware 0xf1 0x02: None
Firmware 0xf1 0x03: None
Firmware 0xf1 0x04: None
Battery status:
1.9V critical
2.3V low
2.5V full

View File

@@ -0,0 +1,42 @@
Unifying Receiver
Device path : /dev/hidraw2
USB id : 046d:c52b
Serial : C03E9E2E
Firmware : 12.01.B0019
Bootloader : 02.14
Has 2 paired device(s) out of a maximum of 6.
Notifications: wireless, software present (0x000900)
Device activity counters: 2=118
2: Wireless Keyboard K270(unifying)
Codename : K270(unifying)
Kind : keyboard
Wireless PID : 4003
Protocol : HID++ 2.0
Polling rate : 20 ms (50Hz)
Serial number: FE8C8542
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}
5: unknown:1820 {1820} hidden
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}
Has 8 reprogrammable keys:
0: Play/Pause => Play/Pause nonstandard
1: Mute => Mute nonstandard
2: Volume Down => Volume Down nonstandard
3: Volume Up => Volume Up nonstandard
4: MY HOME => HomePage nonstandard, reprogrammable
5: Mail => Email nonstandard, reprogrammable
6: SLEEP => Sleep nonstandard, reprogrammable
7: Calculator => Calculator nonstandard, reprogrammable
Battery: 90%, discharging.

View File

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

39
docs/devices/k750.txt Normal file
View File

@@ -0,0 +1,39 @@
(from Julien Danjou)
(solaar)
2: Wireless Solar Keyboard K750
Codename : K750
Kind : keyboard
Wireless PID : 4002
Protocol : HID++ 2.0
Polling rate : 20 ms (50Hz)
Serial number: 5692B2EC
Firmware: RQK 33.00.B0015
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}
6: unknown:1DF3 {1DF3} hidden
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
2: SEARCH => Search FN sensitive, is FN, reprogrammable
3: Calculator => Calculator FN sensitive, is FN, reprogrammable
4: MEDIA PLAYER => Music FN sensitive, is FN, reprogrammable
5: Previous => Previous FN sensitive, is FN
6: Play/Pause => Play/Pause FN sensitive, is FN
7: Next => Next FN sensitive, is FN
8: Mute => Mute FN sensitive, is FN
9: Volume Down => Volume Down FN sensitive, is FN
10: Volume Up => Volume Up FN sensitive, is FN
11: SLEEP => Sleep FN sensitive, is FN, reprogrammable
Battery status unavailable.

44
docs/devices/k780.txt Normal file
View File

@@ -0,0 +1,44 @@
2: K780 Multi-Device Keyboard
Codename : K780
Kind : keyboard
Wireless PID : 405B
Protocol : HID++ 4.5
Polling rate : 20 ms (50Hz)
Serial number: 4D71FEE1
Bootloader: BOT 25.00.B0005
Firmware: MPK 01.00.B0018
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}
18: unknown:1803 {1803} internal, hidden
19: unknown:1806 {1806} internal, hidden
20: unknown:1805 {1805} internal, hidden
21: unknown:1813 {1813} internal, hidden
22: unknown:1830 {1830} internal, hidden
23: unknown:1861 {1861} internal, hidden
24: unknown:1890 {1890} internal, hidden
25: unknown:1891 {1891} internal, hidden
26: unknown:18A1 {18A1} internal, hidden
27: unknown:1DF3 {1DF3} internal, hidden
28: unknown:1E00 {1E00} hidden
29: unknown:1EB0 {1EB0} internal, hidden
30: unknown:18B0 {18B0} internal, hidden
Battery: 90%, discharging.

557
docs/devices/k800-new.txt Normal file
View File

@@ -0,0 +1,557 @@
[kamil@kamil-pc Solaar]$ bin/solaar -dd show
16:01:46,533 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 FF 83B5 030000]
16:01:46,539 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 FF 83B5 03DC279AB20A06090000000000000000]
16:01:46,539 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 FF 80B2 000000]
16:01:46,550 DEBUG [MainThread] logitech_receiver.base: (3) => r[20 01 4101 71401E0000000400000000]
16:01:46,551 DEBUG [MainThread] logitech_receiver.base: (3) => r[20 02 4101 6E401A4000000400000000]
16:01:46,551 DEBUG [MainThread] logitech_receiver.base: (3) => r[20 00 4102 0000000000000000000000]
16:01:46,551 DEBUG [MainThread] logitech_receiver.base: (3) => r[10 FF 8F80 B20300]
16:01:46,551 DEBUG [MainThread] logitech_receiver.base: (3) device 0xFF error on request {80B2}: 3 = invalid value
16:01:46,551 DEBUG [MainThread] solaar.cli: [/dev/hidraw0] => <UnifyingReceiver(/dev/hidraw0,3)>
16:01:46,646 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 FF 8102 000000]
16:01:46,651 DEBUG [MainThread] logitech_receiver.base: (3) => r[10 FF 8102 000200]
Unifying Receiver
Device path : /dev/hidraw0
USB id : 046d:c52b
Serial : DC279AB2
16:01:46,652 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 FF 81F1 010000]
16:01:46,657 DEBUG [MainThread] logitech_receiver.base: (3) => r[10 FF 81F1 012411]
16:01:46,658 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 FF 81F1 020000]
16:01:46,664 DEBUG [MainThread] logitech_receiver.base: (3) => r[10 FF 81F1 020036]
16:01:46,664 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 FF 81F1 040000]
16:01:46,669 DEBUG [MainThread] logitech_receiver.base: (3) => r[10 FF 81F1 040209]
16:01:46,670 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 FF 81F1 030000]
16:01:46,675 DEBUG [MainThread] logitech_receiver.base: (3) => r[10 FF 81F1 03AAAC]
Firmware : 24.11.B0036
Bootloader : 02.09
Other : AA.AC
Has 2 paired device(s) out of a maximum of 6.
16:01:46,676 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 FF 8100 000000]
16:01:46,681 DEBUG [MainThread] logitech_receiver.base: (3) => r[10 FF 8100 000900]
Notifications: wireless, software present (0x000900)
16:01:46,682 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 FF 83B3 000000]
16:01:46,687 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 FF 83B3 51060000000000000000000000000000]
Device activity counters: 1=81, 2=6
16:01:46,688 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 FF 8102 000000]
16:01:46,693 DEBUG [MainThread] logitech_receiver.base: (3) => r[10 FF 8102 000200]
16:01:46,694 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 FF 83B5 200000]
16:01:46,699 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 FF 83B5 20090840710402020700000000000000]
16:01:46,700 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 FF 83B5 400000]
16:01:46,705 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 FF 83B5 40094D58204D61737465720000000000]
16:01:46,706 INFO [MainThread] logitech_receiver.receiver: <UnifyingReceiver(/dev/hidraw0,3)>: found new device 1 (4071)
16:01:46,706 DEBUG [MainThread] logitech_receiver.base: (3) pinging device 1
16:01:46,706 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 001E 000016]
16:01:47,033 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 000F 00000000000000000000000000000000]
16:01:47,049 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 001E 04051600000000000000000000000000]
1: Wireless Mouse MX Master
Codename : MX Master
Kind : mouse
Wireless PID : 4071
Protocol : HID++ 4.5
Polling rate : 8 ms (125Hz)
16:01:47,049 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 FF 83B5 300000]
16:01:47,055 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 FF 83B5 30A6A400641E00000001000000000000]
Serial number: A6A40064
16:01:47,055 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 0009 000100]
16:01:47,061 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 000B 00000000000000000000000000000000]
16:01:47,077 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 0009 01000100000000000000000000000000]
16:01:47,077 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 0108 000000]
16:01:47,093 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 000D 00000000000000000000000000000000]
16:01:47,101 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 0108 1F000000000000000000000000000000]
16:01:47,101 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 000C 000300]
16:01:47,109 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 000B 00000000000000000000000000000000]
16:01:47,117 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 000C 02000200000000000000000000000000]
16:01:47,117 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 020D 000000]
16:01:47,125 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 000B 00000000000000000000000000000000]
16:01:47,133 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 020D 040382B4290006B01E40710000030000]
16:01:47,134 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 021E 000000]
16:01:47,141 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 000B 00000000000000000000000000000000]
16:01:47,149 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 021E 01424F54561000050040717622661101]
16:01:47,150 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 021C 010000]
16:01:47,171 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 021C 004D504D1210000500B01E7622661101]
16:01:47,171 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 021E 020000]
16:01:47,191 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 021E 004D504D121000050140717622661101]
16:01:47,191 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 021F 030000]
16:01:47,213 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 021F 050000000000005A0000000000000000]
Bootloader: BOT 56.10.B0005
Firmware: MPM 12.10.B0005
Firmware: MPM 12.10.B0005
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}
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}
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}
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}
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}
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}
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}
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}
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]
16:01:47,835 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 000C 08600000000000000000000000000000]
8: unknown:1806 {1806} internal, hidden
16:01:47,835 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 0119 090000]
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}
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}
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}
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}
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
Ratchet per turn: 24
Scroll lines: 0
16:01:48,017 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 011A 0D0000]
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}
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}
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]
16:01:48,137 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 0E1D 02000000000000000000000000000000]
16:01:48,137 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 0E38 000000]
16:01:48,159 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 0E38 01000000000000000000000000000000]
Multiplier: 8
Has invert
Normal wheel motion
Has ratchet switch
Normal wheel mode
High resolution mode
HID notification
16:01:48,159 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 011F 0F0000]
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}
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: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]
16:01:48,279 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 0009 11600000000000000000000000000000]
17: unknown:1813 {1813} internal, hidden
16:01:48,279 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 011C 120000]
16:01:48,299 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 011C 18306000000000000000000000000000]
16:01:48,299 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 000C 183000]
16:01:48,319 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 000C 12600000000000000000000000000000]
18: unknown:1830 {1830} internal, hidden
16:01:48,319 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 011B 130000]
16:01:48,339 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 011B 18906000000000000000000000000000]
16:01:48,339 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 0008 189000]
16:01:48,359 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 0008 13600000000000000000000000000000]
19: unknown:1890 {1890} internal, hidden
16:01:48,359 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 011B 140000]
16:01:48,381 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 011B 18916000000000000000000000000000]
16:01:48,381 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 0008 189100]
16:01:48,401 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 0008 14600000000000000000000000000000]
20: unknown:1891 {1891} internal, hidden
16:01:48,401 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 011C 150000]
16:01:48,421 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 011C 18A16000000000000000000000000000]
16:01:48,421 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 000F 18A100]
16:01:48,441 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 000F 15600000000000000000000000000000]
21: unknown:18A1 {18A1} internal, hidden
16:01:48,441 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 011A 160000]
16:01:48,461 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 011A 18C06000000000000000000000000000]
16:01:48,461 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 0008 18C000]
16:01:48,481 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 0008 16600000000000000000000000000000]
22: unknown:18C0 {18C0} internal, hidden
16:01:48,481 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 011E 170000]
16:01:48,501 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 011E 1DF36000000000000000000000000000]
16:01:48,501 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 0009 1DF300]
16:01:48,521 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 0009 17600000000000000000000000000000]
23: unknown:1DF3 {1DF3} internal, hidden
16:01:48,521 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 011E 180000]
16:01:48,541 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 011E 1E004000000000000000000000000000]
16:01:48,541 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 0009 1E0000]
16:01:48,561 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 0009 18400000000000000000000000000000]
24: unknown:1E00 {1E00} hidden
16:01:48,561 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 0119 190000]
16:01:48,581 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 0119 1EB06000000000000000000000000000]
16:01:48,581 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 0009 1EB000]
16:01:48,603 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 0009 19600000000000000000000000000000]
25: unknown:1EB0 {1EB0} internal, hidden
16:01:48,603 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 011F 1A0000]
16:01:48,623 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 011F 18036000000000000000000000000000]
16:01:48,623 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 000F 180300]
16:01:48,643 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 000F 1A600000000000000000000000000000]
26: unknown:1803 {1803} internal, hidden
16:01:48,643 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 0118 1B0000]
16:01:48,663 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 0118 18616000000000000000000000000000]
16:01:48,663 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 0009 186100]
16:01:48,683 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 0009 1B600000000000000000000000000000]
27: unknown:1861 {1861} internal, hidden
16:01:48,683 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 0118 1C0000]
16:01:48,703 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 0118 90016000000000000000000000000000]
16:01:48,703 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 000F 900100]
16:01:48,723 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 000F 1C600000000000000000000000000000]
28: unknown:9001 {9001} internal, hidden
16:01:48,723 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 0119 1D0000]
16:01:48,743 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 0119 92006000000000000000000000000000]
16:01:48,743 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 000D 920000]
16:01:48,763 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 000D 1D600000000000000000000000000000]
29: unknown:9200 {9200} internal, hidden
16:01:48,763 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 011F 1E0000]
16:01:48,783 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 011F 92026000000000000000000000000000]
16:01:48,783 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 000C 920200]
16:01:48,805 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 000C 1E600000000000000000000000000000]
30: unknown:9202 {9202} internal, hidden
16:01:48,805 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 0119 1F0000]
16:01:48,825 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 0119 18056000000000000000000000000000]
16:01:48,825 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 000B 180500]
16:01:48,845 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 000B 1F600000000000000000000000000000]
31: unknown:1805 {1805} internal, hidden
16:01:48,845 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 0A0A 000000]
16:01:48,865 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 01 0A0A 08000000000000000000000000000000]
Has 8 reprogrammable keys:
16:01:48,865 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 01 0A1C 000000]
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
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
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
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
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
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
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
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
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]
16:01:49,207 DEBUG [MainThread] logitech_receiver.hidpp20: device 1 battery 50% charged, next level 20% charge, status 0 = discharging
Battery: 50%, discharging.
16:01:49,207 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 FF 83B5 210000]
16:01:49,213 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 FF 83B5 210814406E0402010700000000000000]
16:01:49,213 INFO [MainThread] logitech_receiver.receiver: <UnifyingReceiver(/dev/hidraw0,3)>: found new device 2 (406E)
16:01:49,213 DEBUG [MainThread] logitech_receiver.base: (3) pinging device 2
16:01:49,213 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 001F 0000F4]
16:01:49,245 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 001F 0405F400000000000000000000000000]
2: Wireless Illuminated Keyboard K800 new
Codename : new
Kind : keyboard
Wireless PID : 406E
Protocol : HID++ 4.5
Polling rate : 20 ms (50Hz)
16:01:49,245 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 FF 83B5 310000]
16:01:49,251 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 FF 83B5 31636E14131A40000007000000000000]
Serial number: 636E1413
16:01:49,251 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 000A 000100]
16:01:49,285 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 000A 01000100000000000000000000000000]
16:01:49,285 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 010B 000000]
16:01:49,325 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 010B 18000000000000000000000000000000]
16:01:49,325 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 0009 000300]
16:01:49,365 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 0009 02000200000000000000000000000000]
16:01:49,365 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 020C 000000]
16:01:49,405 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 020C 0254FC62F90004406E00000000010000]
16:01:49,405 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 021E 000000]
16:01:49,446 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 021E 01424F546000000200406ED4E7454501]
16:01:49,446 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 021C 010000]
16:01:49,487 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 021C 0052514B6801000901406ED4E7454501]
Bootloader: BOT 60.00.B0002
Firmware: RQK 68.01.B0009
The power switch is located on the top right corner.
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}
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}
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}
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}
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}
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}
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}
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}
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}
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}
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}
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}
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}
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]
16:01:50,493 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 0008 0D600000000000000000000000000000]
13: unknown:1803 {1803} internal, hidden
16:01:50,494 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 011D 0E0000]
16:01:50,533 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 011D 18066001000000000000000000000000]
16:01:50,533 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 000C 180600]
16:01:50,575 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 000C 0E600100000000000000000000000000]
14: unknown:1806 {1806} internal, hidden
16:01:50,576 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 011A 0F0000]
16:01:50,615 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 011A 18116000000000000000000000000000]
16:01:50,615 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 0008 181100]
16:01:50,655 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 0008 0F600000000000000000000000000000]
15: unknown:1811 {1811} internal, hidden
16:01:50,656 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 011B 100000]
16:01:50,695 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 011B 18306000000000000000000000000000]
16:01:50,696 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 000F 183000]
16:01:50,735 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 000F 10600000000000000000000000000000]
16: unknown:1830 {1830} internal, hidden
16:01:50,736 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 0119 110000]
16:01:50,775 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 0119 18906000000000000000000000000000]
16:01:50,776 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 000A 189000]
16:01:50,815 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 000A 11600000000000000000000000000000]
17: unknown:1890 {1890} internal, hidden
16:01:50,816 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 0118 120000]
16:01:50,858 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 0118 18A16000000000000000000000000000]
16:01:50,858 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 000F 18A100]
16:01:50,897 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 000F 12600000000000000000000000000000]
18: unknown:18A1 {18A1} internal, hidden
16:01:50,898 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 0118 130000]
16:01:50,937 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 0118 1DF36000000000000000000000000000]
16:01:50,938 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 000B 1DF300]
16:01:50,977 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 000B 13600000000000000000000000000000]
19: unknown:1DF3 {1DF3} internal, hidden
16:01:50,978 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 011B 140000]
16:01:51,017 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 011B 1E004000000000000000000000000000]
16:01:51,018 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 000E 1E0000]
16:01:51,057 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 000E 14400000000000000000000000000000]
20: unknown:1E00 {1E00} hidden
16:01:51,058 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 011B 150000]
16:01:51,097 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 011B 1EB06000000000000000000000000000]
16:01:51,098 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 000F 1EB000]
16:01:51,137 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 000F 15600000000000000000000000000000]
21: unknown:1EB0 {1EB0} internal, hidden
16:01:51,138 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 011D 160000]
16:01:51,179 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 011D 18616000000000000000000000000000]
16:01:51,180 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 000E 186100]
16:01:51,220 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 000E 16600000000000000000000000000000]
22: unknown:1861 {1861} internal, hidden
16:01:51,220 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 011D 170000]
16:01:51,260 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 011D 1A206000000000000000000000000000]
16:01:51,260 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 0008 1A2000]
16:01:51,300 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 0008 17600000000000000000000000000000]
23: unknown:1A20 {1A20} internal, hidden
16:01:51,300 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 0118 180000]
16:01:51,339 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 0118 18B06000000000000000000000000000]
16:01:51,340 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 000E 18B000]
16:01:51,379 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 000E 18600000000000000000000000000000]
24: unknown:18B0 {18B0} internal, hidden
16:01:51,380 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 080E 000000]
16:01:51,419 DEBUG [MainThread] logitech_receiver.base: (3) => r[11 02 080E 0F000000000000000000000000000000]
Has 15 reprogrammable keys:
16:01:51,420 DEBUG [MainThread] logitech_receiver.base: (3) <= w[10 02 081C 000000]
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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.

41
docs/devices/k830.txt Normal file
View File

@@ -0,0 +1,41 @@
# Provided by Mikkel Munch Mortensen
(solaar)
3: Illuminated Living-Room Keyboard K830
Codename : K830
Kind : keyboard
Wireless PID : 4032
Protocol : HID++ 4.1
Polling rate : 8 ms (125Hz)
Serial number: 9F7C6FD7
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}
13: TOUCHPAD RAW XY {6100} hidden
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
19: unknown:18A0 {18A0} internal, hidden
20: unknown:1DF3 {1DF3} internal, hidden
21: unknown:1E00 {1E00} hidden
22: unknown:1EB0 {1EB0} internal, hidden
23: unknown:1861 {1861} internal, hidden
24: unknown:1A20 {1A20} internal, hidden
25: unknown:18B0 {18B0} internal, hidden
26: unknown:1F07 {1F07} internal, hidden
Battery: 50%, discharging.

48
docs/devices/m185_new.txt Normal file
View File

@@ -0,0 +1,48 @@
P/N: 810-005238
Unifying Receiver
Device path : /dev/hidraw3
USB id : 046d:c534
Serial : 0
Firmware : 29.01.B0016
Has 1 paired device(s) out of a maximum of 6.
Notifications: (none)
2: Wireless Mouse M185
Codename : M185
Kind : mouse
Wireless PID : 4054
Protocol : HID++ 4.5
Polling rate : 8 ms (125Hz)
Serial number: 1377ED51
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}
9: unknown:1802 {1802} internal, hidden
10: unknown:1810 {1810} internal, hidden
11: unknown:1830 {1830} internal, hidden
12: unknown:1850 {1850} internal, hidden
13: unknown:1869 {1869} internal, hidden
14: unknown:1890 {1890} internal, hidden
15: unknown:18B1 {18B1} internal, hidden
16: unknown:1DF3 {1DF3} internal, hidden
17: unknown:1E00 {1E00} hidden
18: unknown:1F03 {1F03} internal, hidden
19: unknown:1E80 {1E80} internal, hidden
Has 3 reprogrammable keys:
0: LEFT CLICK , default: LeftClick => LEFT CLICK
mse, reprogrammable, pos:0, group:1, gmask:1
1: RIGHT CLICK , default: RightClick => RIGHT CLICK
mse, reprogrammable, pos:0, group:1, gmask:1
2: MIDDLE BUTTON , default: MiddleMouseButton => MIDDLE BUTTON
divertable, mse, reprogrammable, pos:0, group:2, gmask:3
Battery status unavailable.

50
docs/devices/m185_old.txt Normal file
View File

@@ -0,0 +1,50 @@
P/N: 810-003496
Unifying Receiver
Device path : /dev/hidraw3
USB id : 046d:c52f
Serial : 6D0342C5
Firmware : 30.00.B0009
Has 1 paired device(s) out of a maximum of 1.
Notifications: (none)
1: Wireless Mouse
Codename : Wireless Mouse
Kind : mouse
Wireless PID : 4055
Protocol : HID++ 4.5
Polling rate : 8 ms (125Hz)
Serial number: 6D0342C5
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}
6: unknown:1810 {1810} internal, hidden
7: unknown:1830 {1830} internal, hidden
8: unknown:1802 {1802} internal, hidden
9: unknown:1862 {1862} internal, hidden
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}
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}
Has 3 reprogrammable keys:
0: LEFT CLICK , default: LeftClick => LEFT CLICK
mse, reprogrammable, pos:0, group:1, gmask:1
1: RIGHT CLICK , default: RightClick => RIGHT CLICK
mse, reprogrammable, pos:0, group:1, gmask:1
2: MIDDLE BUTTON , default: MiddleMouseButton => MIDDLE BUTTON
divertable, mse, reprogrammable, pos:0, group:2, gmask:3
Battery: 5%, discharging.

40
docs/devices/m235.txt Normal file
View File

@@ -0,0 +1,40 @@
Wireless Mouse M235
Codename : M235
Kind : mouse
Wireless PID : 4055
Protocol : HID++ 4.5
Polling rate : 8 ms (125Hz)
Serial number: 00000000
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}
6: unknown:1810 {1810} internal, hidden
7: unknown:1830 {1830} internal, hidden
8: unknown:1802 {1802} internal, hidden
9: unknown:1862 {1862} internal, hidden
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}
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}
Has 3 reprogrammable keys:
0: LEFT CLICK , default: LeftClick => LEFT CLICK
divertable, mse, pos:0, group:1, gmask:1
1: RIGHT CLICK , default: RightClick => RIGHT CLICK
divertable, mse, pos:0, group:1, gmask:1
2: MIDDLE BUTTON , default: MiddleMouseButton => MIDDLE BUTTON
divertable, mse, reprogrammable, pos:0, group:2, gmask:3
Battery: 70%, discharging.

29
docs/devices/m325.txt Normal file
View File

@@ -0,0 +1,29 @@
Wireless Mouse M325
Codename : M325
Kind : mouse
Wireless PID : 400A
Protocol : HID++ 2.0
Polling rate : 8 ms (125Hz)
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}
6: unknown:1DF3 {1DF3} hidden
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}
Has 5 reprogrammable keys:
0: LEFT CLICK => LeftClick mse, reprogrammable
1: RIGHT CLICK => RightClick mse, reprogrammable
2: MIDDLE BUTTON => MiddleMouseButton mse, reprogrammable
3: BACK AS BUTTON 4 => Back mse, reprogrammable
4: FORWARD AS BUTTON 5 => BrowserForward mse, reprogrammable

View File

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

View File

@@ -1,2 +1,56 @@
No non-error messages received for GET_REG and GET_REG_LONG. Perhaps because
this is a HID++ 2.0 device?
Mouse
(ltunify)
HID++ version: 2.0
Device index 1
Mouse
Name: M525
Wireless Product ID: 4013
Serial number: DAFA335E
Device was unavailable, version information not available.
Total number of HID++ 2.0 features: 12
0: [0000] IRoot
1: [0001] IFeatureSet
2: [0003] IFirmwareInfo
3: [0005] GetDeviceNameType
4: [1000] batteryLevelStatus
5: [1D4B] WirelessDeviceStatus
6: [1DF3] H unknown
7: [1B00] SpecialKeysMSEButtons
8: [1DF0] H unknown
9: [1F03] H unknown
10: [2100] VerticalScrolling
11: [2120] HiResScrolling
12: [2200] MousePointer
(O = obsolete feature; H = SW hidden feature;
I = reserved for internal use)
(solaar)
1: Wireless Mouse M525
Codename : M525
Kind : mouse
Wireless PID : 4013
Protocol : HID++ 2.0
Polling rate : 8 ms (125Hz)
Serial number: DAFA335E
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}
6: unknown:1DF3 {1DF3} hidden
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}
Has 5 reprogrammable keys:
0: LEFT CLICK => LeftClick mse, reprogrammable
1: RIGHT CLICK => RightClick mse, reprogrammable
2: MIDDLE BUTTON => MiddleMouseButton mse, reprogrammable
3: BACK AS BUTTON 4 => Back mse, reprogrammable
4: FORWARD AS BUTTON 5 => BrowserForward mse, reprogrammable
Battery: 90%, discharging.

41
docs/devices/m560.txt Normal file
View File

@@ -0,0 +1,41 @@
1: Wireless Mouse M560
Codename : M560
Kind : mouse
Wireless PID : 402D
Protocol : HID++ 2.0
Polling rate : 8 ms (125Hz)
Serial number: 16E6E42A
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}
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}
12: unknown:1DF3 {1DF3} internal, hidden
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}
Has 7 reprogrammable keys:
0: LEFT CLICK => LeftClick mse, reprogrammable
1: RIGHT CLICK => RightClick mse, reprogrammable
2: BACK AS BUTTON 4 => Win8BackHorzLeft mse, reprogrammable
3: FORWARD AS BUTTON 5 => Win8ForwardHorzRight mse, reprogrammable
4: unknown:00B0 => Win8MetroWin7Forward mse, reprogrammable
5: SHOW DESKTOP HPP => Win8ShowDesktopWin7Back mse, reprogrammable
6: unknown:00AF => Win8Charm Appswitch GifAnimation mse, reprogrammable, unknown:000020
Battery: 70%, discharging.

24
docs/devices/m570.txt Normal file
View File

@@ -0,0 +1,24 @@
Unifying Receiver
Device path : /dev/hidraw0
USB id : 046d:c52b
Serial : BAFF9007
Firmware : 12.03.B0025
Bootloader : 02.15
Other : AA.AA
Has 1 paired device(s) out of a maximum of 6.
Notifications: wireless, software present (0x000900)
Device activity counters: 1=221
1: Wireless Trackball M570
Codename : M570
Kind : mouse
Wireless PID : 1028
Protocol : HID++ 1.0
Polling rate : 8 ms (125Hz)
Serial number: 891DC05A
Firmware: 26.00.B0003
Bootloader: 02.06
Other: 00.01
The power switch is located on the base.
Notifications: battery status (0x100000).
Battery: 100%, discharging.

82
docs/devices/m585.txt Normal file
View File

@@ -0,0 +1,82 @@
Unifying Receiver
Device path : /dev/hidraw0
USB id : 046d:c52b
Serial : E21FAD57
Firmware : 24.06.B0030
Bootloader : 01.08
Other : AA.AC
Has 2 paired device(s) out of a maximum of 6.
Notifications: wireless, software present (0x000900)
Device activity counters: 1=190, 2=66
2: Multi Device Silent Mouse M585/M590
Codename : M585/M590
Kind : mouse
Wireless PID : 406B
Protocol : HID++ 4.5
Polling rate : 8 ms (125Hz)
Serial number: 22AEB299
Bootloader: BOT 48.01.B0002
Firmware: MPM 05.10.B0011
Other:
The power switch is located on the base.
Supports 35 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: unknown:0007 {0007}
8: BATTERY STATUS {1000}
9: CHANGE HOST {1814}
10: unknown:1815 {1815}
11: REPROG CONTROLS V4 {1B04}
12: unknown:1C00 {1C00}
13: POINTER SPEED {2205}
Pointer Speed: 1.31640625
14: VERTICAL SCROLLING {2100}
Roller type: standard
Ratchet per turn: 18
Scroll lines: 0
15: unknown:00C2 {00C2}
16: unknown:1802 {1802} internal, hidden
17: unknown:1803 {1803} internal, hidden
18: unknown:1806 {1806} internal, hidden
19: unknown:1805 {1805} internal, hidden
20: unknown:1813 {1813} internal, hidden
21: unknown:1830 {1830} internal, hidden
22: unknown:1861 {1861} internal, hidden
23: unknown:1890 {1890} internal, hidden
24: unknown:1891 {1891} internal, hidden
25: unknown:18A1 {18A1} internal, hidden
26: unknown:1DF3 {1DF3} internal, hidden
27: unknown:1E00 {1E00} hidden
28: unknown:1EB0 {1EB0} internal, hidden
29: unknown:18B1 {18B1} internal, hidden
30: unknown:1850 {1850} internal, hidden
31: unknown:1E22 {1E22}
32: unknown:1F03 {1F03} internal, hidden
33: unknown:18C0 {18C0} internal, hidden
34: LOWRES WHEEL {2130}
Wheel Reports: HID
Has 8 reprogrammable keys:
0: LEFT CLICK , default: LeftClick => LEFT CLICK
mse, reprogrammable, pos:0, group:1, gmask:1
1: RIGHT CLICK , default: RightClick => RIGHT CLICK
mse, reprogrammable, pos:0, group:1, gmask:1
2: MIDDLE BUTTON , default: MiddleMouseButton => MIDDLE BUTTON
divertable, mse, persistently divertable, reprogrammable, pos:0, group:2, gmask:3
3: BACK AS BUTTON 4 , default: BackEx => BACK AS BUTTON 4
divertable, mse, persistently divertable, reprogrammable, pos:0, group:2, gmask:3
4: FORWARD AS BUTTON 5 , default: BrowserForwardEx => FORWARD AS BUTTON 5
divertable, mse, persistently divertable, reprogrammable, pos:0, group:2, gmask:3
5: LEFT SCROLL AS AC PAN , default: HorzScrollLeftSet => LEFT SCROLL AS AC PAN
divertable, mse, persistently divertable, reprogrammable, pos:0, group:2, gmask:3
6: RIGHT SCROLL AS AC PAN , default: HorzScrollRightSet => RIGHT SCROLL AS AC PAN
divertable, mse, persistently divertable, reprogrammable, pos:0, group:2, gmask:3
7: unknown:00D7 , default: unknown:00B4 => unknown:00D7
divertable, virtual, pos:0, group:3, gmask:0
Battery: 50%, discharging.

View File

@@ -36,7 +36,7 @@ registers:
<< ( 259.270) [10 02 81F1 000000] '\x10\x02\x81\xf1\x00\x00\x00'
>> ( 259.283) [10 02 8F81 F10300] '\x10\x02\x8f\x81\xf1\x03\x00'
# writing 01 here will trigger an avalance of events, most likely
# writing 01 here will trigger an avalanche of events, most likely
# raw input from the mouse; disable by writing 00
<< ( 261.300) [10 02 81F3 000000] '\x10\x02\x81\xf3\x00\x00\x00'
>> ( 261.315) [10 02 81F3 000000] '\x10\x02\x81\xf3\x00\x00\x00'

View File

@@ -0,0 +1,81 @@
Unifying Receiver
Device path : /dev/hidraw1
USB id : 046d:c534
Serial : 0
Firmware : 29.00.B0015
Has 2 paired device(s) out of a maximum of 6.
Notifications: (none)
1: Wireless Keyboard MK270
Codename : MK270
Kind : keyboard
Wireless PID : 4023
Protocol : HID++ 2.0
Polling rate : 20 ms (50Hz)
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}
10: unknown:1810 {1810} internal, hidden
11: unknown:1830 {1830} internal, hidden
12: unknown:1890 {1890} internal, hidden
13: unknown:18A0 {18A0} internal, hidden
14: unknown:18B0 {18B0} internal, hidden
15: unknown:1DF3 {1DF3} internal, hidden
16: unknown:1E00 {1E00} hidden
17: unknown:1868 {1868} internal, hidden
Has 11 reprogrammable keys:
0: MY HOME => HomePage is FN, FN sensitive, reprogrammable
1: Mail => Email is FN, FN sensitive, reprogrammable
2: SEARCH => Search is FN, FN sensitive, reprogrammable
3: Calculator => Calculator is FN, FN sensitive, reprogrammable
4: MEDIA PLAYER => Music is FN, FN sensitive, reprogrammable
5: Previous => Previous is FN, FN sensitive
6: Play/Pause => Play/Pause is FN, FN sensitive
7: Next => Next is FN, FN sensitive
8: Mute => Mute is FN, FN sensitive
9: Volume Down => Volume Down is FN, FN sensitive
10: Volume Up => Volume Up is FN, FN sensitive
Battery: 30%, discharging.
2: Wireless Mouse
Codename :
Kind : mouse
Wireless PID : 4022
Protocol : HID++ 2.0
Polling rate : 8 ms (125Hz)
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}
9: unknown:1810 {1810} internal, hidden
10: unknown:1830 {1830} internal, hidden
11: unknown:1850 {1850} internal, hidden
12: unknown:1890 {1890} internal, hidden
13: unknown:18B0 {18B0} internal, hidden
14: unknown:1DF3 {1DF3} internal, hidden
15: unknown:1868 {1868} internal, hidden
16: unknown:1869 {1869} internal, hidden
17: unknown:1E00 {1E00} hidden
Has 3 reprogrammable keys:
0: LEFT CLICK => LeftClick mse, reprogrammable
1: RIGHT CLICK => RightClick mse, reprogrammable
2: MIDDLE BUTTON => MiddleMouseButton mse, reprogrammable
Battery: 30%, discharging.

77
docs/devices/mk220.txt Normal file
View File

@@ -0,0 +1,77 @@
Unifying Receiver
Device path : /dev/hidraw1
USB id : 046d:c52e
Serial : 758596BF
Firmware : 23.01.B0006
Has 2 paired device(s) out of a maximum of 2.
Notifications: wireless, software present (0x000900)
1: Wireless Mouse M150
Codename : M150
Kind : mouse
Wireless PID : 400C
Protocol : HID++ 2.0
Polling rate : 8 ms (125Hz)
Serial number: 93850883
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}
4: unknown:1850 {1850} hidden
5: unknown:1860 {1860} hidden
6: BATTERY STATUS {1000}
7: WIRELESS DEVICE STATUS {1D4B}
8: unknown:1DF3 {1DF3} hidden
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}
Has 3 reprogrammable keys:
0: LEFT CLICK => LeftClick mse, reprogrammable
1: RIGHT CLICK => RightClick mse, reprogrammable
2: MIDDLE BUTTON => MiddleMouseButton mse, reprogrammable
Battery: 90%, discharging.
2: Wireless Keyboard K220
Codename : K220
Kind : keyboard
Wireless PID : 4005
Protocol : HID++ 2.0
Polling rate : 20 ms (50Hz)
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}
6: unknown:1820 {1820} hidden
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}
Has 12 reprogrammable keys:
0: FN F1 => Do Nothing One is FN, reprogrammable
1: FN F2 => Do Nothing One is FN, reprogrammable
2: FN F3 => Do Nothing One is FN, reprogrammable
3: FN F4 => Do Nothing One is FN, reprogrammable
4: FN F5 => Do Nothing One is FN, reprogrammable
5: FN F6 => Do Nothing One is FN, reprogrammable
6: FN F7 => Do Nothing One is FN, reprogrammable
7: FN F8 => Do Nothing One is FN, reprogrammable
8: FN F9 => Do Nothing One is FN, reprogrammable
9: Mute => Mute is FN
10: Volume Down => Volume Down is FN
11: Volume Up => Volume Up is FN
Battery: 90%, discharging.

129
docs/devices/mk240-nano.md Normal file
View File

@@ -0,0 +1,129 @@
# Logitech MK240 NANO Device Information
## `solaar show all` Dump
```
Unifying Receiver (NOTE: NOT claimed to be supporting Unifying from the package box, the only advanced feature that may be related is 128-bit AES encryption) (M/N: C-U0010)
Device path : /dev/hidraw0
USB id : 046d:c534
Serial : 0
Firmware : 29.01.B0016
Has 2 paired device(s) out of a maximum of 6.
Notifications: wireless, software present (0x000900)
1: Wireless Keyboard MK270 (NOTE: The Product is actually "MK240 NANO Wireless Keyboard and Mouse Combo" with the "K240"(M/N: Y-R0036) keyboard model)
Codename : MK270
Kind : keyboard
Wireless PID : 4023
Protocol : HID++ 2.0
Polling rate : 20 ms (50Hz)
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}
10: unknown:1810 {1810} internal, hidden
11: unknown:1830 {1830} internal, hidden
12: unknown:1890 {1890} internal, hidden
13: unknown:18A0 {18A0} internal, hidden
14: unknown:18B0 {18B0} internal, hidden
15: unknown:1DF3 {1DF3} internal, hidden
16: unknown:1E00 {1E00} hidden
17: unknown:1868 {1868} internal, hidden
Has 11 reprogrammable keys:
0: MY HOME => HomePage is FN, FN sensitive, reprogrammable
1: Mail => Email is FN, FN sensitive, reprogrammable
2: SEARCH => Search is FN, FN sensitive, reprogrammable
3: Calculator => Calculator is FN, FN sensitive, reprogrammable
4: MEDIA PLAYER => Music is FN, FN sensitive, reprogrammable
5: Previous => Previous is FN, FN sensitive
6: Play/Pause => Play/Pause is FN, FN sensitive
7: Next => Next is FN, FN sensitive
8: Mute => Mute is FN, FN sensitive
9: Volume Down => Volume Down is FN, FN sensitive
10: Volume Up => Volume Up is FN, FN sensitive
Battery: 30%, discharging. (NOTE: Capacity readings appears to be faked, or in extremely low sensitivity)
2: Wireless Mouse M150 (NOTE: The Product is actually "MK240 NANO Wireless Keyboard and Mouse Combo" with the "M212"(M/N: M-R0041) mouse model)
Codename : M150
Kind : mouse
Wireless PID : 4022
Protocol : HID++ 2.0
Polling rate : 8 ms (125Hz)
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}
9: unknown:1810 {1810} internal, hidden
10: unknown:1830 {1830} internal, hidden
11: unknown:1850 {1850} internal, hidden
12: unknown:1890 {1890} internal, hidden
13: unknown:18B0 {18B0} internal, hidden
14: unknown:1DF3 {1DF3} internal, hidden
15: unknown:1868 {1868} internal, hidden
16: unknown:1869 {1869} internal, hidden
17: unknown:1E00 {1E00} hidden
Has 3 reprogrammable keys:
0: LEFT CLICK => LeftClick mse, reprogrammable
1: RIGHT CLICK => RightClick mse, reprogrammable
2: MIDDLE BUTTON => MiddleMouseButton mse, reprogrammable
Battery: 30%, discharging. (NOTE: Capacity readings appears to be faked, or in extremely low sensitivity, in the Logitech SetPoint utility battery level is displayed as "HIGH")
```
## Connect Utility Report
```
Re-Connect Software Version : 2.00.3
Dj Api Version : 2, 50, 25
接收器(Receiver)
Name : 無線接收器(Wireless Receiver)
ModelId : 0x46dc534
Serial Number :
Handle : 0xff000001
Wireless Status : 0x3
Firmware version : 029.001.00016
Bootloader version :
Dfu Status : 0x1
Is Dfu Cancellable : Yes
Max Device Capacity : 6
滑鼠(Mouse)
Name :
ModelId : 0x0
Serial Number : 4022-00-00-00-00
Handle : 0x2000003
Wireless Status : 0x0
Firmware version : 038.000.00044
Bootloader version :
Dfu Status : 0x1
Is Dfu Cancellable : No
Battery Status : 0x2
Parent Handle : 0xff000001
鍵盤(Keyboard)
Name :
ModelId : 0x0
Serial Number : 4023-4B-BB-BA-4A
Handle : 0x1000002
Wireless Status : 0x0
Firmware version : 049.000.00029
Bootloader version :
Dfu Status : 0x1
Is Dfu Cancellable : No
Battery Status : 0x2
Parent Handle : 0xff000001
```

85
docs/devices/mk270.txt Normal file
View File

@@ -0,0 +1,85 @@
Unifying Receiver
Device path : /dev/hidraw9
USB id : 046d:c534
Serial : 00000000
Firmware : 29.00.B0015
Has 2 paired device(s) out of a maximum of 6.
Notifications: (none)
1: Wireless Keyboard
Codename : MK270
Kind : keyboard
Wireless PID : 4023
Protocol : HID++ 2.0
Polling rate : 20 ms (50Hz)
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}
10: unknown:1810 {1810} internal, hidden
11: unknown:1830 {1830} internal, hidden
12: unknown:1890 {1890} internal, hidden
13: unknown:18A0 {18A0} internal, hidden
14: unknown:18B0 {18B0} internal, hidden
15: unknown:1DF3 {1DF3} internal, hidden
16: unknown:1E00 {1E00} hidden
17: unknown:1868 {1868} internal, hidden
Has 11 reprogrammable keys:
0: MY HOME => HomePage FN sensitive, is FN, reprogrammable
1: Mail => Email FN sensitive, is FN, reprogrammable
2: SEARCH => Search FN sensitive, is FN, reprogrammable
3: Calculator => Calculator FN sensitive, is FN, reprogrammable
4: MEDIA PLAYER => Music FN sensitive, is FN, reprogrammable
5: Previous => Previous FN sensitive, is FN
6: Play/Pause => Play/Pause FN sensitive, is FN
7: Next => Next FN sensitive, is FN
8: Mute => Mute FN sensitive, is FN
9: Volume Down => Volume Down FN sensitive, is FN
10: Volume Up => Volume Up FN sensitive, is FN
Battery: 30%, discharging.
2: Wireless Mouse
Codename : M185
Kind : mouse
Wireless PID : 4038
Protocol : HID++ 2.0
Polling rate : 8 ms (125Hz)
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}
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}
12: unknown:1DF3 {1DF3} internal, hidden
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}
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.

60
docs/devices/mk520.txt Normal file
View File

@@ -0,0 +1,60 @@
Unifying Receiver
Device path : /dev/hidraw3
USB id : 046d:c52b
Serial : AF9C98A0
Firmware : 12.03.B0025
Bootloader : 02.15
Other : AA.AA
Has 2 paired device(s) out of a maximum of 6.
Notifications: wireless, software present (0x000900)
Device activity counters: 1=22, 2=167
1: Wireless Mouse M310/M310t
Codename : M310/M310t
Kind : mouse
Wireless PID : 4031
Protocol : HID++ 2.0
Polling rate : 8 ms (125Hz)
Serial number: 03E8C0B4
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}
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}
12: unknown:1DF3 {1DF3} internal, hidden
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}
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.
2: Wireless Keyboard K520
Codename : K520
Kind : keyboard
Wireless PID : 2011
Protocol : HID++ 1.0
Polling rate : 20 ms (50Hz)
Serial number: ACDE97EF
Firmware: 26.00.B0012
Other: 00.07
The power switch is located on the top case.
Notifications: (none).
Battery: full, discharging.

View File

@@ -0,0 +1,84 @@
Unifying Receiver
Device path : /dev/hidraw7
USB id : 046d:c52b
Serial : BB7D9447
Firmware : 24.01.B0023
Bootloader : 01.08
Other : AA.AD
Has 2 paired device(s) out of a maximum of 6.
Notifications: wireless, software present (0x000900)
Device activity counters: 2=156
1: Wireless Mouse MX Master 2S
Codename : MX Master 2S
Kind : mouse
Wireless PID : 4069
Protocol : HID++ 4.5
Polling rate : 8 ms (125Hz)
Serial number: EAB71F76
Bootloader: BOT 56.01.B0006
Firmware: MPM 12.01.B0006
Firmware: MPM 12.01.B0006
Other:
The power switch is located on the base.
Supports 32 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: unknown:1806 {1806} internal, hidden
9: CHANGE HOST {1814}
10: REPROG CONTROLS V4 {1B04}
11: ADJUSTABLE DPI {2201}
12: VERTICAL SCROLLING {2100}
Roller type: 3G
Ratchet per turn: 24
Scroll lines: 0
13: SMART SHIFT {2110}
14: HIRES WHEEL {2121}
Multiplier: 8
Has invert
Normal wheel motion
Has ratchet switch
Normal wheel mode
High resolution mode
HID notification
15: GESTURE 2 {6501}
16: unknown:00C2 {00C2}
17: unknown:1813 {1813} internal, hidden
18: unknown:1830 {1830} internal, hidden
19: unknown:1890 {1890} internal, hidden
20: unknown:1891 {1891} internal, hidden
21: unknown:18A1 {18A1} internal, hidden
22: unknown:18C0 {18C0} internal, hidden
23: unknown:1DF3 {1DF3} internal, hidden
24: unknown:1E00 {1E00} hidden
25: unknown:1EB0 {1EB0} internal, hidden
26: unknown:1803 {1803} internal, hidden
27: unknown:1861 {1861} internal, hidden
28: unknown:9001 {9001} internal, hidden
29: unknown:9200 {9200} internal, hidden
30: unknown:9202 {9202} internal, hidden
31: unknown:1805 {1805} internal, hidden
Has 8 reprogrammable keys:
0: LEFT CLICK , default: LeftClick => LEFT CLICK
mse, pos:0, group:1, gmask:1
1: RIGHT CLICK , default: RightClick => RIGHT CLICK
mse, pos:0, group:1, gmask:1
2: MIDDLE BUTTON , default: MiddleMouseButton => MIDDLE BUTTON
mse, reprogrammable, divertable, pos:0, group:3, gmask:7
3: BACK AS BUTTON 4 , default: BackEx => BACK AS BUTTON 4
mse, reprogrammable, divertable, pos:0, group:2, gmask:3
4: FORWARD AS BUTTON 5 , default: BrowserForwardEx => FORWARD AS BUTTON 5
mse, reprogrammable, divertable, pos:0, group:2, gmask:3
5: unknown:00C3 , default: unknown:00A9 => unknown:00C3
mse, reprogrammable, divertable, pos:0, group:3, gmask:7
6: unknown:00C4 , default: unknown:009D => unknown:00C4
mse, reprogrammable, divertable, pos:0, group:3, gmask:7
7: unknown:00D7 , default: unknown:00B4 => unknown:00D7
divertable, virtual, pos:0, group:4, gmask:0
Battery: 50%, discharging.

View File

@@ -0,0 +1,82 @@
Unifying Receiver
Device path : /dev/hidraw0
USB id : 046d:c52b
Serial : 32A29DF4
Firmware : 12.09.B0030
Bootloader : 04.16
Other : AA.AA
Has 1 paired device(s) out of a maximum of 6.
Notifications: wireless (0x000100)
Device activity counters: 1=18
1: Wireless Mouse MX Master 3
Codename : MX Master 3
Kind : mouse
Wireless PID : 4082
Protocol : HID++ 4.5
Polling rate : 8 ms (125Hz)
Serial number: B0C9EC6E
Bootloader: BOT 95.00.B0013
Firmware: MPM 19.00.B0013
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}
Multiplier: 15
Has invert
Normal wheel motion
Has ratchet switch
Normal wheel mode
Low resolution mode
HID notification
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
20: unknown:1813 {1813} internal, hidden
21: unknown:1805 {1805} internal, hidden
22: unknown:1830 {1830} internal, hidden
23: unknown:1890 {1890} internal, hidden
24: unknown:1891 {1891} internal, hidden
25: unknown:18A1 {18A1} internal, hidden
26: unknown:1DF3 {1DF3} internal, hidden
27: unknown:1E00 {1E00} hidden
28: unknown:1EB0 {1EB0} internal, hidden
29: unknown:1861 {1861} internal, hidden
30: unknown:9001 {9001} internal, hidden
31: unknown:9203 {9203} internal, hidden
32: unknown:9205 {9205} internal, hidden
33: unknown:9300 {9300} internal, hidden
Has 8 reprogrammable keys:
0: LEFT CLICK , default: LeftClick => LEFT CLICK
mse, pos:0, group:1, gmask:1
1: RIGHT CLICK , default: RightClick => RIGHT CLICK
mse, pos:0, group:1, gmask:1
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
divertable, mse, reprogrammable, pos:0, group:2, gmask:3
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
divertable, mse, reprogrammable, pos:0, group:3, gmask:7
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
divertable, virtual, pos:0, group:4, gmask:0
Battery: 100%, discharging.

View File

@@ -0,0 +1,54 @@
Unifying Receiver
Device path : /dev/hidraw3
USB id : 046d:c52b
Serial : 0E039B8F
Firmware : 24.01.B0023
Bootloader : 01.08
Other : AA.AC
Has 1 paired device(s) out of a maximum of 6.
Notifications: wireless, software present (0x000900)
Device activity counters: 1=134
1: Wireless Mouse MX Master
Codename : MX Master
Kind : mouse
Wireless PID : 4041
Protocol : HID++ 4.5
Polling rate : 8 ms (125Hz)
Serial number: A975E230
Bootloader: BOT 18.00.B0012
Firmware: MPM 11.00.B0012
Firmware: MPM 11.00.B0012
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}
15: unknown:1813 {1813} internal, hidden
16: unknown:1830 {1830} internal, hidden
17: unknown:1890 {1890} internal, hidden
18: unknown:18A1 {18A1} internal, hidden
19: unknown:18C0 {18C0} internal, hidden
20: unknown:1DF3 {1DF3} internal, hidden
21: unknown:1E00 {1E00} hidden
22: unknown:1EB0 {1EB0} internal, hidden
23: unknown:1803 {1803} internal, hidden
24: unknown:1861 {1861} internal, hidden
25: unknown:9000 {9000} internal, hidden
26: unknown:9200 {9200} internal, hidden
27: unknown:9240 {9240} internal, hidden
28: unknown:1805 {1805} internal, hidden
Battery: 50%, discharging.

View File

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

109
docs/devices/t400.txt Normal file
View File

@@ -0,0 +1,109 @@
Receiver
LZ2388S-DJ
M/N:C-U0007
(ltunify)
Serial number: E6B794F8
Firmware version: 012.001.00019
Bootloader version: BL.002.014
Mouse
(ltunify)
HID++ version: 2.0
Device index 1
Mouse
Name: T400
Wireless Product ID: 4026
Serial number: 131A3093
Device was unavailable, version information not available.
Total number of HID++ 2.0 features: 27
0: [0000] IRoot
1: [0001] IFeatureSet
2: [0002] unknown
3: [0003] IFirmwareInfo
4: [0005] GetDeviceNameType
5: [00C0] DFUControl
6: [1000] batteryLevelStatus
7: [1802] HI unknown
8: [1810] HI unknown
9: [1830] HI unknown
10: [1850] HI unknown
11: [1860] HI unknown
12: [1890] HI unknown
13: [18A0] HI unknown
14: [18E3] HI unknown
15: [1B00] SpecialKeysMSEButtons
16: [1D4B] WirelessDeviceStatus
17: [1DF3] HI unknown
18: [1E00] H unknown
19: [1E80] HI unknown
20: [1F03] HI unknown
21: [1F04] HI unknown
22: [2100] VerticalScrolling
23: [2101] H unknown
24: [2120] HiResScrolling
25: [2200] MousePointer
26: [6110] H TouchmouseRawPoints
27: [1B03] ReprogControlsV3
(O = obsolete feature; H = SW hidden feature;
I = reserved for internal use)
(solaar)
Unifying Receiver
Device path : /dev/hidraw2
USB id : 046d:c52b
Serial : E6B794F8
Firmware : 12.01.B0019
Bootloader : 02.14
Has 1 paired device(s) out of a maximum of 6.
Notifications: (none)
Device activity counters: 1=134
1: Zone Touch Mouse T400
Codename : T400
Kind : mouse
Wireless PID : 4026
Protocol : HID++ 2.0
Polling rate : 8 ms (125Hz)
Serial number: 131A3093
Firmware: RQM 39.00.B0029
Bootloader: BL 03.00
Hardware: 72
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}
7: unknown:1802 {1802} internal, hidden
8: unknown:1810 {1810} internal, hidden
9: unknown:1830 {1830} internal, hidden
10: unknown:1850 {1850} internal, hidden
11: unknown:1860 {1860} internal, hidden
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}
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}
23: unknown:2101 {2101} hidden
24: HI RES SCROLLING {2120}
25: MOUSE POINTER {2200}
26: TOUCHMOUSE RAW POINTS {6110} hidden
27: REPROG CONTROLS V3 {1B03}
Has 7 reprogrammable keys:
0: LEFT CLICK => LeftClick mse, reprogrammable
1: RIGHT CLICK => RightClick mse, reprogrammable
2: MIDDLE BUTTON => MiddleMouseButton mse, reprogrammable
3: METRO START SCREEN => MetroStartScreen mse, reprogrammable
4: ZOOMIN => Do Nothing mse, reprogrammable
5: ZOOMOUT => Do Nothing mse, reprogrammable
6: BACK HSCROLL => TouchBackForwardHorzScroll
Battery: 100%, discharging.

94
docs/devices/t650.txt Normal file
View File

@@ -0,0 +1,94 @@
Receiver
LZ2458D-DJ
M/N:C-U0008
(ltunify)
Serial number: 28E69A3E
Firmware version: 024.000.00018
Bootloader version: BL.000.006
Touchpad
(ltunify)
HID++ version: 2.0
Device index 1
Touchpad
Name: T650
Wireless Product ID: 4101
Serial number: 22205A4D
Device was unavailable, version information not available.
Total number of HID++ 2.0 features: 22
0: [0000] IRoot
1: [0001] IFeatureSet
2: [0002] unknown
3: [0003] IFirmwareInfo
4: [0005] GetDeviceNameType
5: [1000] batteryLevelStatus
6: [1D4B] WirelessDeviceStatus
7: [1DF3] HI unknown
8: [1B00] SpecialKeysMSEButtons
9: [1F03] HI unknown
10: [2100] VerticalScrolling
11: [2120] HiResScrolling
12: [2200] MousePointer
13: [00C0] DFUControl
14: [1E80] HI unknown
15: [6100] TouchpadRawXy
16: [1860] HI unknown
17: [1E00] H unknown
18: [1B01] ReprogControlsV2
19: [1890] HI unknown
20: [18E5] HI unknown
21: [18A0] HI unknown
22: [1830] HI unknown
(O = obsolete feature; H = SW hidden feature;
I = reserved for internal use)
(solaar)
Unifying Receiver
Device path : /dev/hidraw2
USB id : 046d:c52b
Serial : 28E69A3E
Firmware : 24.00.B0018
Bootloader : 00.06
Has 1 paired device(s) out of a maximum of 6.
Notifications: (none)
Device activity counters: 1=221
1: Wireless Rechargeable Touchpad T650
Codename : T650
Kind : touchpad
Wireless PID : 4101
Protocol : HID++ 2.0
Polling rate : 8 ms (125Hz)
Serial number: 22205A4D
Firmware: RQM 41.01.B0037
Bootloader: BL 03.00
Hardware: 72
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}
7: unknown:1DF3 {1DF3} internal, hidden
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}
14: unknown:1E80 {1E80} internal, hidden
15: TOUCHPAD RAW XY {6100}
16: unknown:1860 {1860} internal, hidden
17: unknown:1E00 {1E00} hidden
18: REPROG CONTROLS V2 {1B01}
19: unknown:1890 {1890} internal, hidden
20: unknown:18E5 {18E5} internal, hidden
21: unknown:18A0 {18A0} internal, hidden
22: unknown:1830 {1830} internal, hidden
Has 2 reprogrammable keys:
0: LEFT CLICK => LeftClick mse, reprogrammable
1: RIGHT CLICK => RightClick mse, reprogrammable
Battery: 50%, discharging.

214
docs/features.md Normal file
View File

@@ -0,0 +1,214 @@
---
title: List of HID++ 2.0 features
layout: page
---
# List of HID++ 2.0 features
## Feature status
See functions in `hidpp20.py` and `settings_templates.py`
Feature | ID | Status | Notes
---------------------------------------|----------|:------------------:|------
`ROOT` | `0x0000` | :heavy_check_mark: | System
`FEATURE_SET` | `0x0001` | :heavy_check_mark: | System
`FEATURE_INFO` | `0x0002` | :heavy_check_mark: | System
`DEVICE_FW_VERSION` | `0x0003` | :heavy_check_mark: | `get_firmware`, read only
`DEVICE_UNIT_ID` | `0x0004` | :x: |
`DEVICE_NAME` | `0x0005` | :heavy_check_mark: | `get_kind`, `get_name`, read only
`DEVICE_GROUPS` | `0x0006` | :x: |
`DEVICE_FRIENDLY_NAME` | `0x0007` | :x: |
`KEEP_ALIVE` | `0x0008` | :x: |
`RESET` | `0x0020` | :x: | aka “Config Change”
`CRYPTO_ID` | `0x0021` | :x: |
`TARGET_SOFTWARE` | `0x0030` | :x: |
`WIRELESS_SIGNAL_STRENGTH` | `0x0080` | :x: |
`DFUCONTROL_LEGACY` | `0x00C0` | :x: |
`DFUCONTROL_UNSIGNED` | `0x00C1` | :x: |
`DFUCONTROL_SIGNED` | `0x00C2` | :x: |
`DFU` | `0x00D0` | :x: |
`BATTERY_STATUS` | `0x1000` | :heavy_check_mark: | `get_battery`, read only
`BATTERY_VOLTAGE` | `0x1001` | :heavy_check_mark: | `get_voltage`, read only
`CHARGING_CONTROL` | `0x1010` | :x: |
`LED_CONTROL` | `0x1300` | :x: |
`GENERIC_TEST` | `0x1800` | :x: |
`DEVICE_RESET` | `0x1802` | :x: |
`OOBSTATE` | `0x1805` | :x: |
`CONFIG_DEVICE_PROPS` | `0x1806` | :x: |
`CHANGE_HOST` | `0x1814` | :heavy_check_mark: |
`HOSTS_INFO` | `0x1815` | :heavy_plus_sign: | `get_host_names`, partial listing only
`BACKLIGHT` | `0x1981` | :x: |
`BACKLIGHT2` | `0x1982` | :heavy_check_mark: | `_feature_backlight2`
`BACKLIGHT3` | `0x1983` | :x: |
`PRESENTER_CONTROL` | `0x1A00` | :x: |
`SENSOR_3D` | `0x1A01` | :x: |
`REPROG_CONTROLS` | `0x1B00` | :heavy_plus_sign: | `get_keys`, only listing
`REPROG_CONTROLS_V2` | `0x1B01` | :x: |
`REPROG_CONTROLS_V2_2` | `0x1B02` | :x: |
`REPROG_CONTROLS_V3` | `0x1B03` | :x: |
`REPROG_CONTROLS_V4` | `0x1B04` | :heavy_plus_sign: | `get_keys`, _feature_reprogrammable_keys
`REPORT_HID_USAGE` | `0x1BC0` | :x: |
`PERSISTENT_REMAPPABLE_ACTION` | `0x1C00` | :wrench: |
`WIRELESS_DEVICE_STATUS` | `0x1D4B` | :heavy_plus_sign: | status reporting from device
`REMAINING_PAIRING` | `0x1DF0` | :x: |
`FIRMWARE_PROPERTIES` | `0x1F1F` | :x: |
`ADC_MEASUREMENT` | `0x1F20` | :x: |
`LEFT_RIGHT_SWAP` | `0x2001` | :x: |
`SWAP_BUTTON_CANCEL` | `0x2005` | :x: |
`POINTER_AXIS_ORIENTATION` | `0x2006` | :x: |
`VERTICAL_SCROLLING` | `0x2100` | :heavy_check_mark: | `get_vertical_scrolling_info`, read only
`SMART_SHIFT` | `0x2110` | :heavy_check_mark: | `_feature_smart_shift`
`HI_RES_SCROLLING` | `0x2120` | :heavy_check_mark: | `get_hi_res_scrolling_info`, `_feature_hi_res_scroll`
`HIRES_WHEEL` | `0x2121` | :heavy_check_mark: | `get_hires_wheel`, `_feature_hires_smooth_invert`, `_feature_hires_smooth_resolution`
`LOWRES_WHEEL` | `0x2130` | :heavy_check_mark: | `get_lowres_wheel_status`, `_feature_lowres_smooth_scroll`
`THUMB_WHEEL` | `0x2150` | :heavy_check_mark: | `_feature_thumb_mode`, `_feature_thumb_invert`
`MOUSE_POINTER` | `0x2200` | :heavy_check_mark: | `get_mouse_pointer_info`, read only
`ADJUSTABLE_DPI` | `0x2201` | :heavy_check_mark: | `_feature_adjustable_dpi`
`POINTER_SPEED` | `0x2205` | :heavy_check_mark: | `get_pointer_speed_info`, `_feature_pointer_speed`
`ANGLE_SNAPPING` | `0x2230` | :x: |
`SURFACE_TUNING` | `0x2240` | :x: |
`HYBRID_TRACKING` | `0x2400` | :x: |
`FN_INVERSION` | `0x40A0` | :heavy_check_mark: | `_feature_fn_swap`
`NEW_FN_INVERSION` | `0x40A2` | :heavy_check_mark: | `get_new_fn_inversion`, `_feature_new_fn_swap`
`K375S_FN_INVERSION` | `0x40A3` | :heavy_check_mark: | `_feature_k375s_fn_swap`
`ENCRYPTION` | `0x4100` | :x: |
`LOCK_KEY_STATE` | `0x4220` | :x: |
`SOLAR_DASHBOARD` | `0x4301` | :x: |
`KEYBOARD_LAYOUT` | `0x4520` | :x: | read only
`KEYBOARD_DISABLE_KEYS` | `0x4521` | :heavy_check_mark: | `_feature_disable_keyboard_keys`
`KEYBOARD_DISABLE_BY_USAGE` | `0x4522` | :x: |
`DUALPLATFORM` | `0x4530` | :heavy_check_mark: | `_feature_dualplatform`, untested
`MULTIPLATFORM` | `0x4531` | :heavy_check_mark: | `_feature_multiplatform`
`KEYBOARD_LAYOUT_2` | `0x4540` | :x: | read only
`CROWN` | `0x4600` | :x: |
`TOUCHPAD_FW_ITEMS` | `0x6010` | :x: |
`TOUCHPAD_SW_ITEMS` | `0x6011` | :x: |
`TOUCHPAD_WIN8_FW_ITEMS` | `0x6012` | :x: |
`TAP_ENABLE` | `0x6020` | :x: |
`TAP_ENABLE_EXTENDED` | `0x6021` | :x: |
`CURSOR_BALLISTIC` | `0x6030` | :x: |
`TOUCHPAD_RESOLUTION` | `0x6040` | :x: |
`TOUCHPAD_RAW_XY` | `0x6100` | :x: |
`TOUCHMOUSE_RAW_POINTS` | `0x6110` | :x: |
`TOUCHMOUSE_6120` | `0x6120` | :x: |
`GESTURE` | `0x6500` | :x: |
`GESTURE_2` | `0x6501` | :heavy_plus_sign: | `_feature_gesture2_gestures`, `_feature_gesture2_params`
`GKEY` | `0x8010` | :x: |
`MKEYS` | `0x8020` | :x: |
`MR` | `0x8030` | :x: |
`BRIGHTNESS_CONTROL` | `0x8040` | :x: |
`REPORT_RATE` | `0x8060` | :x: | in progress
`COLOR_LED_EFFECTS` | `0x8070` | :x: |
`RGB_EFFECTS` | `0X8071` | :x: |
`PER_KEY_LIGHTING` | `0x8080` | :x: |
`PER_KEY_LIGHTING_V2` | `0x8081` | :x: |
`MODE_STATUS` | `0x8090` | :x: |
`ONBOARD_PROFILES` | `0x8100` | :x: | in progress
`MOUSE_BUTTON_SPY` | `0x8110` | :x: |
`LATENCY_MONITORING` | `0x8111` | :x: |
`GAMING_ATTACHMENTS` | `0x8120` | :x: |
`FORCE_FEEDBACK` | `0x8123` | :x: |
`SIDETONE` | `0x8300` | :x: |
`EQUALIZER` | `0x8310` | :x: |
`HEADSET_OUT` | `0x8320` | :x: |
A “read only” note means the feature is a read-only feature and cannot be changed.
## Implementing a feature
Features are implemented as settable features in
lib/logitech_receiver/settings_templates.py
some features also have direct implementation in
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,
will permit storing and restoring changed settings, and
will output the feature settings in `solaar show`.
Adding a setting implementation involves several steps, described here and
illustrated by the pointer speed setting implementation.
First add a name, a label, and a description for the setting in the common strings section.
The name is used in the persistent settings structure to store and restore changed settings and
should be a valid Python identifier. (Some older settings have dashes.)
The label is displayed in the Solaar main window and the description is used as a tooltip there.
The label and description should be specified as translatable strings.
```python
_POINTER_SPEED = ('pointer_speed',
_("Sensitivity (Pointer Speed)"),
_("How fast the pointer moves"))
```
Next implement an interface for the setting by creating
a reader/writer, a validator, and a setting instance for it.
Most settings use device features and thus need feature interfaces.
Some settings use device register and thus need register interfaces.
Only implement a register interface for the setting if you are very brave and
you have access to a device that has a register interface for the setting.
Register interfaces cannot be auto-discovered and need to be stated in descriptors.py
for each device with the register interface.
The reader/writer instance is responsible for reading raw values
from the device and writing values to it.
There are different classes for feature interfaces and register interfaces.
Pointer speed is a feature so the _FeatureRW reader/writer is used.
Reader/writers take the register or feature ID and the command numbers for reading and writing,
plus other arguments for complex interfaces.
The validator instance is responsible for turning read raw values into Python data
and Python data into raw values to be written and validating that the Python data is
acceptable for the setting.
There are several possible kinds of Python data for setting interfaces,
ranging from simple toggles, to ranges, to fixed lists, to
dynamic choices, to maps of dynamic choices.
Pointer speed is a setting whose values are integers in a range so a _RangeV validator is used.
The arguments to this class are the
the minimum and maximum values for the value
and the byte size of the value on the device.
Settings that are toggles or choices work similarly,
but their validators have different arguments.
Map settings have more complicated validators.
The setting instance keeps everything together and provides control.
It takes the strings for the setting, the reader/writer, the validator, and
which kinds of devices can have this setting.
(This last is no longer used because keyboards with integrated trackpads only
report that they are keyboards.)
```python
def _feature_pointer_speed():
"""Pointer Speed feature"""
# min and max values taken from usb traces of Win software
validator = _RangeV(0x002e, 0x01ff, 2)
rw = _FeatureRW(_F.POINTER_SPEED)
return _Setting(_POINTER_SPEED, rw, validator, device_kind=(_DK.mouse, _DK.trackball))
```
Settings where the acceptable values are determined from the device
need an auxiliary function to receive and decipher the permissible choices.
See `_feature_adjustable_dpi_choices` for an example.
Finally, add an element to _SETTINGS_TABLE with
the common strings for the setting,
the feature ID (if any),
the feature implementation (if any),
the register implementation (if any).
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.
This table is used to generate the data structures for describing devices in descriptors.py
and is also used to auto-discover feature implementations.
```python
_S( _POINTER_SPEED, _F.POINTER_SPEED, _feature_pointer_speed ),
```
The values to be used need to be determined from documentation of the
feature or from reverse-engineering behavior of Logitech software under
Windows or MacOS.
For more information on implementing feature settings
see the comments in lib/logitech_receiver/settings_templates.py.

View File

@@ -0,0 +1,2 @@
Documentation on HID++ can be found in the Google drive directory
https://drive.google.com/drive/folders/0BxbRzx7vEV7eWmgwazJ3NUFfQ28

View File

@@ -1,3 +1,8 @@
---
title: Translating Solaar
layout: page
---
# Translating Solaar
First, make sure you have installed the `gettext` package.
@@ -5,15 +10,15 @@ First, make sure you have installed the `gettext` package.
Here are the steps to add/update a translation (you should run all scripts from
the source root):
1. Get an up-to-date copy of the source files. Preferrably, make a clone on
1. Get an up-to-date copy of the source files. Preferably, make a clone on
GitHub and clone it locally on your machine; this way you can later make a
pull request to the main project.
2. Run `./tools/po-update.sh <language>`; it will create/update the file
`./po/<language>.po`.
3. Edit `./po/<language>.po` with your favourite editor (just make sure it saves
the file with the UTF-8 encoding). For each string in english (msgid), edit
3. Edit `./po/<language>.po` with your favorite editor (just make sure it saves
the file with the UTF-8 encoding). For each string in English (msgid), edit
the translation (msgstr); if you leave msgstr empty, the string will remain
untranslated.
@@ -22,9 +27,38 @@ the source root):
4. Run `./tools/po-compile.sh`. It will bring up-to-date all the compiled
language files, necessary at runtime.
5. Start Solaar (`./bin/solaar`). By default it will pick up the system languge
5. Start Solaar (`./bin/solaar`). By default, it will pick up the system language
from your environment; to start it in another language, run
`LANGUAGE=<language> ./bin/solaar`.
You can edit the translation iteratively, just repeat from step 3.
If the upstream changes, do a `git pull` and then repeat from step 2.
Before opening a pull request, please run `./tools/po-update.sh` again. It will
format and sort the translation file, and ensure a minimal diff when updating
a translation.
## Supported languages
Currently Solaar has been translated in the following languages:
- Français: [Papoteur][papoteur], [David Geiger][david-geiger],
[Damien Lallement][damsweb]
- Italiano: [Michele Olivo][micheleolivo]
- Polski: [Adrian Piotrowicz][nexces]
- Portuguese-BR: [Drovetto][drovetto], [Josenivaldo Benito Jr.][jrbenito]
- Română: Daniel Pavel
- Russian: [Dimitriy Ryazantcev][DJm00n]
- Slovak: [Jose Riha][jose1711]
- Svensk: [Daniel Zippert][zipperten], Emelie Snecker
[papoteur]: http://github.com/papoteur
[david-geiger]: http://github.com/david-geiger
[damsweb]: http://github.com/damsweb
[DJm00n]: https://github.com/DJm00n
[jose1711]: https://github.com/jose1711
[nexces]: http://github.com/nexces
[zipperten]: http://github.com/zipperten
[micheleolivo]: http://github.com/micheleolivo
[drovetto]: https://github.com/drovetto
[jrbenito]: https://github.com/jrbenito/

View File

@@ -1,34 +0,0 @@
# battery icon names across various icon themes
B = 'battery'
CG = 'charging'
GB = 'gpm-battery'
theme (unknown) 0 0-CG 20 20-CG 40 40-CG 60 60-CG 80 80-CG 100 100-CG 100-full
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
gnome B-missing B-empty - B-caution B-caution-CG B-low B-low-CG - - B-good B-good-CG B-full B-full-CG B-full-charged
Humanity GB-missing GB-000 GB-000-CG GB-020 GB-020-CG GB-040 GB-040-CG GB-060 GB-060-CG GB-080 GB-080-CG GB-100 GB-100-CG GB-charged
(gnome) - B_empty - B-caution - B-low - B_two_thirds - B_third_fourth - B_full B_plugged B_charged
elementary B-missing B-000 B-000-CG B-020 B-020-CG B-040 B-040-CG B-060 B-060-CG B-080 B-080-CG B-100 B-100-CG B-charged
(gnome) - B-empty - B-caution B-caution-CG B-low B-low-CG - - B-good B-good-CG B-full B-full-CG B-full-charged
- B_empty - - - - - B_two_thirds - B_third_fourth - B_full B_plugged B_charged
faenza - GB-000 GB-000-CG GB-020 GB-020-CG GB-040 GB-040-CG GB-060 GB-060-CG GB-080 GB-080-CG GB-100 GB-100-CG GB-charged
(gnome) - B_empty - B_caution - B_low - B_two_thirds - B_third_fourth - B_full B_plugged B_charged
ubuntu-mono GB-missing GB-000 GB-000-CG GB-020 GB-020-CG GB-040 GB-040-CG GB-060 GB-060-CG GB-080 GB-080-CG GB-100 GB-100-CG GB-charged
(Humanity) B-000 B-000-CG B-020 B-020-CG B-040 B-040-CG B-060 B-060-CG B-080 B-080-CG B-100 B-100-CG B-charged
B_empty - B-caution - B-low - - - - - B_full - B_charged
oxygen B-missing B-low B-CG-low B-caution B-CG-caution B-040 B-CG-040 B-060 B-CG-060 B-080 B-CG-080 B-100 B-CG -
moblin - - - B-low - B-caution - - - B-good - B-full B-charging -
nuvola B-missing B-low - - - - - - - - - - B-charging -
# weather icons (for lux)

174
docs/index.md Normal file
View File

@@ -0,0 +1,174 @@
---
title: Solaar
layout: default
---
**Solaar** is a Linux manager for many Logitech keyboards, mice, and trackpads
that connect wirelessly to a USB [Unifying][unifying], Lightspeed, or Nano receiver,
connect directly via a USB cable, or connect via Bluetooth.
Solaar does not work with peripherals from other companies.
Documentation here is for the current verison of Solaar.
Some Linux distributions distribute old versions of Solaar.
If you are using an old version and something described here does not work you should upgrade
using one of the methods described below.
Solaar can be used as a GUI application or via its command-line interface.
Both interfaces are able to list the connected devices and
show information about each device, often including battery status.
Solaar is able to pair and unpair devices with
receivers as supported by the device and receiver.
Solaar can also control some changeable features of devices,
such as smooth scrolling or function key behavior.
Solaar keeps track of these changed settings on a per-computer basis and the GUI application restores them whenever a device connects.
(Devices forget most settings when powered down.)
For more information on how to use Solaar see
[the usage page](https://pwr-solaar.github.io/Solaar/usage),
and for more information on its capabilities see
[the capabilities page](https://pwr-solaar.github.io/Solaar/capabilities).
Solaar's GUI normally uses an icon in the system tray and starts with its main window visible.
This aspect of Solaar depends on having an active system tray, which is not the default
situation for recent versions of Gnome. For information on to set up a system tray under Gnome see
[the capabilities page](https://pwr-solaar.github.io/Solaar/capabilities).
Solaar's GUI can be started in several ways
- `--window=show` (the default) starts with its main window visible,
- `--window=hide` starts with its main window hidden,
- `--window=only` does not use the system tray, and starts with main window visible.
For more information on Solaar's command-line interface use the help option,
as in `solaar --help`.
Solaar does not process normal input from devices. It is thus unable
to fix problems that arise from incorrect handling of mouse movements or keycodes
by Linux drivers or other software.
Solaar has progressed past version 1.0. Problems with earlier versions should
not be reported as bugs. Instead, upgrade to a recent version or manually install
the current version from [GitHub](https://github.com/pwr-Solaar/Solaar).
Some capabilities of Solaar have been developed by observing the behavior of
Logitech receivers and devices and generalizing from these observations.
If your Logitech receiver or device behaves strangely this may be caused by
an incorrect behavior generalization.
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
## Supported Devices
Solaar will detect all devices paired with supported Unifying, Lightspeed, or Nano
receivers, and at the very least display some basic information about them.
Solaar will detect some Logitech devices that connect via a USB cable or Bluetooth.
Solaar can pair and unpair a Logitech device showing the Unifying logo
(Solaar's version of the [logo][logo])
with any Unifying receiver and
can pair and unpair Lightspeed devices with Lightspeed receivers for the same model.
Solaar can pair some Logitech devices with Logitech Nano receivers but not all Logitech
devices can be paired with Nano receivers.
Logitech devices without a Unifying logo
generally cannot be paired with Unifying receivers.
Solaar does not handle connecting or disconnecting via Bluetooth,
which is done using the usual Bluetooth mechanisms.
For a partial list of supported devices
and their features, see [the devices page](https://pwr-solaar.github.io/Solaar/devices).
[logo]: https://pwr-solaar.github.io/Solaar/assets/solaar.svg
## Prebuilt packages
Up-to-date prebuilt packages are available for some Linux distros
(e.g., Fedora 33+) in their standard repositories.
If a recent version of Solaar is not
available from the standard repositories for your distribution you can try
one of these packages.
- Arch solaar package in the [community repository][arch]
- Ubuntu/Kubuntu 16.04+: use the solaar package from [universe repository][universe repository]
- Ubuntu/Kubuntu stable packages: use the [Solaar stable ppa][ppa2], courtesy of [gogo][ppa4]
- Ubuntu/Kubuntu git build packages: use the [Solaar git ppa][ppa1], courtesy of [gogo][ppa4]
- a [Gentoo package][gentoo], courtesy of Carlos Silva and Tim Harder
- a [Mageia package][mageia], courtesy of David Geiger
Solaar uses a standard system tray implementation; solaar-gnome3 is no longer required for gnome or unity integration.
[ppa4]: https://launchpad.net/~trebelnik-stefina
[ppa2]: https://launchpad.net/~solaar-unifying/+archive/ubuntu/stable
[ppa1]: https://launchpad.net/~solaar-unifying/+archive/ubuntu/ppa
[ppa]: http://launchpad.net/~daniel.pavel/+archive/solaar
[arch]: https://www.archlinux.org/packages/community/any/solaar/
[gentoo]: https://packages.gentoo.org/packages/app-misc/solaar
[mageia]: http://mageia.madb.org/package/show/release/cauldron/application/0/name/solaar
[universe repository]: http://packages.ubuntu.com/search?keywords=solaar&searchon=names&suite=all&section=all
## Manual installation
See [the installation page](https://pwr-solaar.github.io/Solaar/installation)
for the step-by-step procedure for manual installation.
## Known Issues
- If some icons appear broken in the application, make sure you've properly
configured the Gtk theme and icon theme in your control panel.
- There are several implementations of the system tray. Some of these have problems
that can result in missing or wrong-sized icons.
- The icon in the system tray can show up as 'black on black' in dark
themes or as non-symbolic when the theme uses symbolic icons. This is due to problems
in some system tray implementations. Changing to a different theme may help.
The `--battery-icons=symbolic` option can be used to force symbolic icons.
- Sometimes the system tray icon does not show up. The cause of this is unknown.
Either wait a while and try again or try with the `--window=hide` option.
- Running the command-line application while the GUI
application is also running *may* occasionally cause either of them to become
confused about the state of the devices.
- Some Linux drivers view or modify the setting Scroll Wheel Resolution to
implement smooth scrolling. If Solaar changes this setting after the driver is
set up scrolling can be either very fast or very slow. To fix this problem
click on the icon at the right edge of the setting to set it to
"Ignore this setting".
The mouse has to be reset (e.g., by turning it off and on again) before this fix will take effect.
- Many gaming mice have both the ONBOARD PROFILES feature and the REPORT RATE feature.
On these mice changing the Polling Rate setting requires modifying a setting in
the ONBOARD PROFILES feature, which can modify how the mouse works. Changing the
Polling Rate setting to "Ignore this setting" (see above) prevents Solaar from
modifying the ONBOARD PROFILES feature.
The mouse has to be reset (e.g., by turning it off and on again) before this fix will take effect.
## License
This software is distributed under the terms of the
[GNU Public License, v2](COPYING).
## Thanks
This project began as a third-hand clone of [Noah K. Tilton](https://github.com/noah)'s
logitech-solar-k750 project on GitHub (no longer available). It was developed
further thanks to the diggings in Logitech's HID++ protocol done by many other
people:
- [Julien Danjou](http://julien.danjou.info/blog/2012/logitech-k750-linux-support),
who also provided some internal
[Logitech documentation](http://julien.danjou.info/blog/2012/logitech-unifying-upower)
- [Lars-Dominik Braun](http://6xq.net/git/lars/lshidpp.git)
- [Alexander Hofbauer](http://derhofbauer.at/blog/blog/2012/08/28/logitech-performance-mx)
- [Clach04](http://bitbucket.org/clach04/logitech-unifying-receiver-tools)
- [Peter Wu](https://lekensteyn.nl/logitech-unifying.html)
- [Nestor Lopez Casado](http://drive.google.com/folderview?id=0BxbRzx7vEV7eWmgwazJ3NUFfQ28)
provided some more Logitech specifications for the HID++ protocol
Also, thanks to Douglas Wagner, Julien Gascard, and Peter Wu for helping with
application testing and supporting new devices.

View File

@@ -1,53 +1,112 @@
---
title: Manual Installation
layout: page
---
# Manual installation
### Requirements
## Downloading
You should have a reasonably new kernel (3.2+), with the `logitech-djreceiver`
driver enabled and loaded; also, the `udev` package must be installed and the
daemon running. If you have a modern Linux distribution (2011+), you're most
likely good to go.
Clone Solaar from GitHub by `git clone https://github.com/pwr-Solaar/Solaar.git`
The command-line application (`bin/solaar-cli`) requires Python 2.7.3 or 3.2+
(either version should work), and the `python-pyudev`/`python3-pyudev` package.
## Requirements for Solaar
The GUI application (`bin/solaar`) also requires Gtk3, and its GObject
Introspection bindings. The Debian/Ubuntu package names are
`python-gi`/`python3-gi` and `gir1.2-gtk-3.0`; if you're using another
distribution the required packages are most likely named something similar.
If the desktop notifications bindings are also installed (`gir1.2-notify-0.7`),
you will also get desktop notifications when devices come online/go offline.
Installing Solaar from a repository should have set up all these requirements
so in this situation you should be able to skip this section.
For gnome-shell/Unity support, you also need to have `gir1.2-appindicator3-0.1`
installed.
Solaar needs a reasonably new kernel with kernel modules `hid-logitech-dj`
and `hid-logitech-hidpp` loaded.
Most of Solaar should work fine with any kernel more recent than 5.2,
but newer kernels might be needed for some devices to be correctly recognized and handled.
The `udev` package must be installed and its daemon running.
Solaar requires Python 3.6+ and requires several packages to be installed.
If you are running the system version of Python you should have the
`python3-pyudev`, `python3-psutil`, `python3-xlib`,
and `python3-yaml` or `python3-pyyaml` packages installed.
To run the GUI Solaar also requires Gtk3 and its GObject introspection bindings.
If you are running the system verison of Python
the Debian/Ubuntu packages you should have
`python3-gi` and `gir1.2-gtk-3.0` installed.
in Fedora you need `gtk3` and `python3-gobject`.
You may have to install `gcc` and the Python development package (`python3-dev` or `python3-devel`,
depending on your distribution).
### Installation
If you are running a version of Python different from the system version,
you may need to use pip to install projects that provide the above Python packages.
Normally USB devices are not accessible for r/w by regular users, so you will
need to do a one-time udev rule installation to allow access to the Logitech
Unifying Receiver.
If desktop notifications bindings are also installed
(`gir1.2-notify-0.7` for Debian/Ubuntu),
you will also see desktop notifications when devices come online/go offline.
For GNOME Shell/Budgie Desktop/KDE/XFCE support, you also need to have
`gir1.2-ayatanaappindicator3-0.1` installed in Debian/Ubuntu. Although it is
recommended to install and use `gir1.2-ayatanaappindicator3-0.1` if it is
available, you can also use `gir1.2-appindicator3-0.1` if necessary (e.g.,
for Unity in Ubuntu).
You can run the `rules.d/install.sh` script from Solaar to do this installation
automatically (make sure to run it as your regular desktop user, it will switch
to root when necessary), or you can do all the required steps by hand, as the
root user:
### Installing Solaar's udev rule
1. Copy `rules.d/99-logitech-unifying-receiver.rules` from Solaar to
`/etc/udev/rules.d/`. The `udev` daemon will automatically pick up this file
using inotify.
Solaar needs to write to HID devices for receivers and devices.
To be able to do this without running as root requires a udev rule
that gives seated users write access to the HID devices for Logitech receiver and devices.
By default, the rule allows all members of the `plugdev` group to have
read/write access to the Unifying Receiver device. (standard Debian/Ubuntu
group for pluggable devices). It may need changes, specific to your
particular system's configuration. If in doubt, replacing `GROUP="plugdev"`
with `GROUP="<your username>"` should just work.
You can install this rule by copying, as root,
`rules.d/42-logitech-unify-permissions.rules` from Solaar to
`/etc/udev/rules.d`.
You will probably also have to tell udev to reload its rule via
`sudo udevadm control --reload-rules`.
2. Physically remove the Unifying Receiver and re-insert it.
For this rule to set up the correct permissions for your receivers and devices
you will then need to either disconnect your receivers and
any USB-connected or Bluetooth-connected devices and
re-connect them or reboot your computer.
This is necessary because if the receiver is already plugged-in, it already
has a `/dev/hidrawX` device node, but with the old (`root:root`) permissions.
Plugging it again will re-create the device node with the right permissions.
## Running from the Download Directories
3. Make sure your desktop users are part of the `plugdev` group, by running
`gpasswd <desktop username> plugdev`. If these users were not assigned to the
group before, they must re-login for the changes to take effect.
To run Solaar from the download directories, first install the Solaar udev rule if necessary.
Then cd to the solaar directory and run `bin/solaar` for the GUI
or `bin/solaar <command> <arguments>` for the CLI.
Do not run Solaar as root, you may encounter problems with X11 integration and with the system tray.
## Installing Solaar Using Pip
Python programs are usually installed using [pip][pip].
The pip instructions for Solaar are in `setup.py`, the standard place to put such instructions.
To install Solaar for yourself only run `pip install --user .` from the solaar directory.
This tells pip to install into your `.local` directory, but does not install Solaar's udev rule.
(See above for installing the udev rule.)
Once the udev rule has been installed you can then run Solaar as `~/.local/bin/solaar`.
Installing python programs to system directories using pip is generally frowned on both
because this runs arbitrary code as root and because this can override existing python libraries
that other users or even the system depend on. If you want to install solaar to /usr/local run
`sudo bash -c 'umask 022 ; pip install .'` in the solaar directory.
(The umask is needed so that the created files and directories can be read and executed by everyone.)
Then solaar can be run as /usr/local/bin/solaar.
You will also have to install the udev rule.
[pip]: https://en.wikipedia.org/wiki/Pip_(package_manager)
## Solaar in other languages
If you want to have Solaar's user messages in some other language you need to run
`tools/po-compile.sh` to create the translation files before running or installing Solaar
and set the LANGUAGE environment variable appropriately when running Solaar.
## Running Solaar at Startup
Distributions can cause Solaar can be run automatically at user login by installing a desktop file at
`/etc/xdg/autostart/solaar.desktop`.
If you install Solaar yourself you may need to create or modify this file or install a startup file under your home directory.
## Installing 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`.
This will not install the Solaar udev rule, which you will need to copy from
`~/.local/share/solaar/udev-rules.d/42-logitech-unify-permissions.rules`
to `/etc/udev/rules.d` as root.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,26 +0,0 @@
The battery/charging level and status is reported only if the related
reporting flag in register 0x00 is enabled by the host. The
"Battery/Charging Level" byte indicates the battery level if the
"Charging State" indicates 0x00 ("Not Charging"). If "Charging State"
indicates 0x21 to 0x23 ("Charging"), the "Battery/Charging Level" byte
indicates the level of charging.
10 ix 07 r0 r1 r2 00
r0 -> Battery/Charging Level
0x00 = Reserved/Unknown
0x01 = Critical
0x02 = Critical (legacy value, don't use)
0x03 = Low
0x04 = Low (legacy value, don't use)
0x05 = Good
0x06 = Good (legacy value, don't use)
0x07 = Full
0x08..0xFF = Reserved
r1 -> Charging state
0x00 = Not charging
0x01..0x1F = Reserved (not charging)
0x20 = Unknown charging state
0x21 = Charging
0x22 = Charging complete
0x23 = Charging error
0x24..0xFF = Reserved

View File

@@ -1,278 +0,0 @@
*Read short register command*
10 ix 81 02 00 00 00
ix
Index 0x0n: Device #n
0xFF: Transceiver
*Response to Read command (success)*
10 ix 81 02 00 r1 r2
ix
Index (same as command)
r1
Number of Connected Devices
bit 0..7: Number of connected devices (receivers only)
r2
Number of Remaining Pairing Slots
bit 0..7: Number of remaining pairing slots
*Read long register command*
10 ix 83 B5 nn 00 00
ix
Index 0xFF: Transceiver
nn
0x20 Device 1
0x21 Device 2
0x22 Device 3
0x23 Device 4
0x24 Device 5
0x25 Device 6
0x26..0x2F Reserved for future extensions
*Response to Read command (success)*
11 ix 83 B5 nn r1 r2 r3 r4 r5 r6 r7 r8 r9 ra rb rc rd 00 00
ix
Index (same as command)
nn
(same format as above)
r1
Destination ID
r2
Reserved
r3
Wireless PID MSB
r4
Wireless PID LSB
r5
Reserved
r6
Reserved
r7
Device type
0 undefined
1 keyboard
2 mouse
3 numpad
4 presenter
5 reserved
6 reserved
7 remote control
8 trackball
9 touchpad
a tablet
b gamepad
c joystick
r8
Reserved
r9
Reserved
Alternatively, if enabled, you can also receive a notification when a new
device is paired:
This message is sent by a receiver to the host SW to report a freshly
connected device. Enable the HID++ connection reporting by setting the
corresponding bit in register 0x00 via HID++ Set Register command.
*Notification*
10 ix 41 r0 r1 r2 r3
ix
Index
r0
bits [0..2] Protocol type
0x03 = eQUAD
0x04 = eQuad step 4 DJ
bits [3..7] Reserved
r1
Device Info
bit0..3 = Device Type
0x00 = Unknown
0x01 = Keyboard
0x02 = Mouse
0x03 = Numpad
0x04 = Presenter
r2
Wireless PID LSB
r3
Wireless PID MSB
To enable the notifications:
Enable HID++ Notifications:
This register defines a number of flags that allow the SW to turn on or off
individual spontaneous HID++ reports. Not setting a flag means default
reporting. See the table below for more details on each flag.
For all bits: *0 = disabled* (default value at power-up), 1 = enabled.
*Read short register command*
10 ix 81 00 00 00 00
ix
Index 0x0n: Device #n
0xFF: Transceiver
*Response to Read command (success)*
10 ix 81 00 r0 r1 r2
ix
Index (same as command)
r0
HID++ Reporting Flags (Devices)
bit 0..3. reserved
bit 4: Battery Status
bit 5..7 reserved
r1
HID++ Reporting Flags (Receiver)
bit 0: Wireless notifications
bit 1..7 reserved
r2
*Write short register command*
10 ix 80 00 p0 p1 p2
ix
Index 0x0n: Device #n
0xFF: Transceiver
p0
HID++ Reporting Flags (Devices)
(same format as above)
p1
HID++ Reporting Flags (Receiver)
(same format as above)
p2
*Response to Write command (success)*
10 ix 80 00 zz zz zz
ix
Index (same as command)
zz
(don't care, recommended to return 0)

162
docs/rules.md Normal file
View File

@@ -0,0 +1,162 @@
---
title: Rule Processing of HID++ Notifications
layout: page
---
Rule processing is an experimental feature. Significant changes might be made in response to problems.
Note that rule processing only fully works under X11.
When running under Wayland with X11 libraries loaded most features will not be available and errors may result.
Features known not to work under Wayland include process conditions and
anything to do with simulating keyboard or mouse input.
Logitech devices that use HID++ version 2.0 or greater produce feature-based
notifications that Solaar can process using a simple rule language. For
example, using rules Solaar can emulate an `XF86_MonBrightnessDown` key tap
in response to the pressing of the `Brightness Down` key on Craft keyboards,
which normally does not produce any input at all when the keyboard is in
Windows mode.
Solaar's rules only activate on HID++ notifications so device actions that
normally produce HID output need rule processing have to be first be set to
this mode. Currently Solaar can set (divert) some mouse scroll wheels, some
mouse thumb wheels, the crown of Craft keyboards, and some keys to produce
HID++ notifications. Look for `HID++` or `Diversion` settings to see what
diversion can be done with your devices. Runing Solaar with the `-dd`
option will show information about notifications, including their feature
name, report number, and data.
In response to a feature-based HID++ notification Solaar runs a sequence of
rules. A `Rule` is a sequence of components, which are either sub-rules,
conditions, or actions. Conditions and actions are dictionaries with one
entry whose key is the name of the condition or action and whose value is
the argument of the action.
If the last thing that a rule does is execute an action, no more rules are
processed for the notification.
Rules are evaluated by evaluating each of their components in order. The
evaluation of a rule is terminated early if a condition component evaluates
to false or the last evaluated sub-component of a component is an action. A
rule is false if its last evaluated component evaluates to a false value.
`Not` conditions take a single component and are true if their component
evaluates to a false value.
`Or` conditions take a sequence of components and are evaluated by
evaluating each of their components in order.
An Or condition is terminated early if a component evaluates to true or the
last evaluated sub-component of a component is an action.
A Or condition is true if its last evaluated component evaluates to a true
value. `And` conditions take a sequence of components are evaluted the same
as rules.
`Process` conditions are true if the process for focus input window
or the window's Window manager class or instance name starts with their string argument.
`MouseProcess` conditions are true if the process for the window under the mouse
or the window's Window manager class or instance name starts with their string argument.
`Feature` conditions are if true if the name of the feature of the current
notification is their string argument.
`Report` conditions are if true if the report number in the current
notification is their integer argument.
`Modifiers` conditions take either a string or a sequence of strings, which
can only be `Shift`, `Control`, `Alt`, and `Super`.
Modifiers conditions are true if their argument is the current keyboard
modifiers.
`Key` conditions are true if the Logitech name of the last diverted key or button down is their
string argument. Alternatively, if the argument is a list `[name, action]` where `action`
is either `'pressed'` or `'released'`, the key down or key up events of `name` argument are
matched, respectively. Logitech key and button names are shown in the `Key/Button Diversion`
setting. Some keyboards have Gn keys, which are diverted using the 'Divert G Keys' setting.
`Test` conditions are true if their test evaluates to true on the feature,
report, and data of the current notification.
Test conditions can return a number instead of a boolean.
Test conditions consisting of a sequence of three or four integers use the first
two to select bytes of the notification data.
Writing this kind of test condition is not trivial.
Three-element test conditions are true if the selected bytes bit-wise anded
with its third element is non-zero.
The value of these test conditions is the result of the and.
Four-element test conditions are true if the selected bytes form a signed
integer between the third and fourth elements.
The value of these test condition is the signed value of the selected bytes
if that is non-zero otherwise True.
The other test conditions are mnemonic shorthands for meaningful feature,
report, and data combinations.
A `crown_right` test is the rotation amount of a `CROWN` right rotation.
A `crown_left` test is the rotation amount of a `CROWN` left rotation.
A `crown_right_ratchet` test is the ratchet amount of a `CROWN` right ratchet rotation.
A `crown_left_ratchet` test is the ratchet amount of a `CROWN` left ratchet rotation.
A `crown_tap` test is true for a `CROWN` tap.
A `crown_start_press` test is true for the start of a `CROWN` press.
A `crown_stop_press` test is true for the end of a `CROWN` press.
A `crown_pressed` test is true for a `CROWN` notification with the Crown pressed.
A `thumb_wheel_up` test is the rotation amount of a `THUMB WHEEL` upward rotation.
A `thumb_wheel_down` test is the rotation amount of a `THUMB WHEEL` downward rotation.
`lowres_wheel_up`, `lowres_wheel_down`, `hires_wheel_up`, `hires_wheel_down` are the
same but for `LOWRES WHEEL` and `HIRES WHEEL`.
`True` and `False` tests return True and False, respectively.
`Mouse Gesture` conditions are true if the actions taken while the mouse's 'Gesture' button is held match the configured list when the 'Gesture' button is released.
The available actions are `Mouse Up`, `Mouse Down`, `Mouse Left`, `Mouse Right`, `Mouse Up-left`, `Mouse Up-Right`, `Mouse Down-left`, `Mouse Down-right`, and buttons that are diverted.
An example would be mapping `Mouse Up` -> `Mouse Up`. To perform this gesture, you would hold down the 'Gesture' button, move the mouse upwards, pause momentarily, move the mouse upwards, and release the 'Gesture' button.
Another example would be mapping `Back Button` -> `Back Button`. With this one, you would hold down the 'Gesture' button, double-tap the 'Back' button, and then release the 'Gesture' button.
Mouse movements and buttons can be mixed and chained together however you like.
It's possible to create a `No-op` gesture by clicking 'Delete' on the initial Action when you first create the rule. This gesture will trigger when you simply click the 'Gesture' button.
A `KeyPress` action takes a sequence of X11 key symbols and simulates a chorded keypress on the keyboard.
Any key symbols that correspond to modifier keys that are in the current keyboard modifiers are ignored.
A `MouseScroll` action takes a sequence of two numbers and simulates a horizontal and vertical mouse scroll of these amounts.
If the previous condition in the parent rule returns a number the scroll amounts are multiplied by this number.
A `MouseClick` action takes a mouse button name (`left`, `middle` or `right`) and a positive number, and simulates that number of clicks of the specified button.
An `Execute` actions takes a program and arguments and executes it asynchronously.
Solaar has several built-in rules, which are run after user-created rules and so can be overridden by user-created rules.
One rule turns
`Brightness Down` key press notifications into `XF86_MonBrightnessDown` key taps
and `Brightness Up` key press notifications into `XF86_MonBrightnessUp` key taps.
Another rule makes Craft crown ratchet movements move between tabs when the crown is pressed
and up and down otherwise.
A third rule turns Craft crown ratchet movements into `XF86_AudioNext` or `XF86_AudioPrev` key taps when the crown is pressed and `XF86_AudioRaiseVolume` or `XF86_AudioLowerVolume` otherwise.
A fourth rule doubles the speed of `THUMB WHEEL` movements unless the `Control` modifier is on.
All of these rules are only active if the key or feature is diverted, of course.
Solaar reads rules from a YAML configuration file (normally `~/.config/solaar/rules.yaml`).
This file contains zero or more documents, each a rule.
Here is a file with three rules:
```
%YAML 1.3
---
- Feature: CROWN
- Process: quodlibet
- Rule: [ Test: crown_start_press, KeyPress: XF86_AudioMute ]
- Rule: [ Test: crown_pressed, Test: crown_right_ratchet, KeyPress: XF86_AudioNext ]
- Rule: [ Test: crown_pressed, Test: crown_left_ratchet, KeyPress: XF86_AudioPrev ]
- Rule: [ Test: crown_right_ratchet, KeyPress: XF86_AudioRaiseVolume ]
- Rule: [ Test: crown_left_ratchet, KeyPress: XF86_AudioLowerVolume ]
...
---
- Feature: THUMB WHEEL
- Rule: [ Modifiers: Control, Test: thumb_wheel_up, MouseScroll: [-2, 0] ]
- Rule:
- Modifiers: Control
- Test: thumb_wheel_down
- MouseScroll: [-2, 0]
- Rule: [ Or: [ Test: thumb_wheel_up, Test: thumb_wheel_down ], MouseScroll: [-1, 0] ]
...
---
- Feature: LOWRES WHEEL
- Rule: [ Or: [ Test: lowres_wheel_up, Test: lowres_wheel_down ], MouseScroll: [0, 2] ]
...
```
Here is an example showing how to divert the Back Button on an MX Master 3 so that pressing
the button will initiate rule processing and a rule that triggers on this notification and
switches the mouse to host 3 after popping up a simple notification.
![Solaar-divert-back](Solaar-main-window-back-divert.png)
![Solaar-rule-back-host](Solaar-rule-editor.png)

164
docs/usage.md Normal file
View File

@@ -0,0 +1,164 @@
---
title: Solaar Usage
layout: page
---
# Solaar usage
Under normal usage Solaar creates an icon in your system tray. This icon is
usually a battery icon showing the approximate battery level for your device
with the lowest known battery level. If there are no devices with battery information,
then the icon is one of the Solaar icons.
Solaar also has a main window. When the main window is invisible,
click on the icon in the system tray to bring up the menu, and then
click on a receiver or device in the menu to see information about
that receiver or device.
The following is an image of the Solaar menu and the icon (the battery
symbol is in the system tray at the left of the image). The icon can
also be other battery icons or versions of the Logitech Unifying icon.
![Solaar-menu](Solaar-menu.png)
Clicking on “Quit” in the Solaar menu terminates the program, and “About Solaar” pops up a window with further information.
## Solaar options
There are several options that affect how Solaar behaves:
* `--help` shows a help message and then quits
* `---window=show` starts Solaar with the main window showing
* `---window=hide` starts Solaar with the main window not showing
* `---window=only` starts Solaar with no system tray icon and the main window showing
* `--battery-icons=symbolic` uses symbolic icons for battery levels
## Solaar main window
The Solaar main window shows your Logitech receivers and devices that Solaar
knows about and can be used to pair new devices, unpair paired devices, and
view and change some settings of the selected receiver or device.
To select a receiver or device click on it in the left side of the window.
Closing the main window does not terminate Solaar (unless Solaar is not using the system tray).
Clicking on “Quit Solaar” terminates the program, and “About Solaar” pops up a window with further information.
The light bulb (or a similar icon) displays detailed information
about the selected receiver or device (useful for debugging).
### Pairing and unpairing devices
When a receiver is selected in the main window, you can pair a new device by
clicking on the “Pair new device” button.
Then turn on the device and it should pair with the receiver if that is possible
and the device is not already paired with another active receiver.
For multi-host devices first select the host position that you want.
Some Lightspeed devices may pair by pressing a special pairing button.
![Solaar-main-window-receiver](Solaar-main-window-receiver.png)
When a device is selected you can unpair the device if your receiver supports
unpairing. To unpair the device, just click on the “Unpair” button and
confirm in the window that pops up.
A receiver with the Unifying logo should be able to pair with any device
with the Unifying logo. If there are no open pairing slots, however, you will
not be able to pair a new device. In this case to pair a new device you
first need to unpair a device.
Other receivers can only pair with certain kinds of devices.
Most of these receivers do not allow unpairing - instead
pairing a new device replaces an existing paired device of the same kind.
Some receivers can only pair a limited number of times.
### Viewing and changing device settings
When a device is selected you can see the approximate battery level of the
device, if that is reported by the device, and the status of the link
between the device and its receiver.
You can also see and change the settings of devices.
Changing settings is performed by clicking on buttons,
moving sliders, or selecting from alternatives.
![Solaar-main-window-keyboard](Solaar-main-window-keyboard.png)
![Solaar-main-window-mouse](Solaar-main-window-mouse.png)
Device setings now have a clickable icon that determines whether the
setting can be changed and whether the setting is ignored.
![Solaar-divert-back](Solaar-main-window-back-divert.png)
If the selected device that is connected to a receiver is powered down or
otherwise disconnected its settings cannot be changed
but it still can be unpaired if its receiver allows unpairing.
![Solaar-main-window-offline](Solaar-main-window-offline.png)
#### Remapping key and button actions
For many devices Solaar can remap some of their keys or buttons to
perform a different action. (This changes the information that the
device sends when the key or button is activated.) Only some keys on some
devices can be remapped and they can only be remapped to a limited
number of actions. The remapping is done by selecting a key
or button in the left-hand box on the “Action” setting line and then
selecting the action to be performed in the right-hand box. The default
action is always the shown first in the list. As with all settings,
Solaar will remember past action settings and restore them on the device
from then on.
![Solaar-main-window-actions](Solaar-main-window-button-actions.png)
The names of the keys, buttons, and actions are mostly taken from Logitech
documentation and may not be completely obvious.
It is possible to end up with an unusable system, for example by having no
way to do a mouse left click, so exercise caution when remapping keys or
buttons that are needed to operate your system.
## Solaar command line interface
Solaar also has a command line interface that can do most of what can be
done using the main window. For more information on the
command line interface, run `solaar --help` to see the commands and
then `solaar <command> --help` to see the arguments to any of the commands.
## Solaar settings
Solaar supports at least the following settings:
Setting | Description
---------------------------------|------------
Hand Detection | Turn on backlight when your hands hover over the keyboard
Scroll Wheel Smooth Scrolling | Higher-speed vertical scrolling
Side Scrolling | When off, side scrolling sends custom button events
Scroll Wheel High Resolution | Higher-speed vertical scrolling
Scroll Wheel HID++ Scrolling | When on, vertical scrolling uses HID++ events
Scroll Wheel Direction | Reverse direction of vertical scrolling
Scroll Wheel Resolution | Higher-speed vertical scrolling (use with caution)
Scroll Wheel Rachet | Shift wheel ratchet on and off based on wheel speed
Thumb Wheel HID++ Scrolling | When on, thumb-wheel scrolling uses HID++ events
Thumb Wheel Direction | Reverse direction of thumb-wheel scrolling
Sensitivity (DPI) | Mouse movement sensitivity
Sensitivity (Pointer Speed) | Mouse movement sensitivity
Backlight | Turn on backlight
Swap Fx function | Change Fn keys to normally do their special action
DPI Sliding Adjustment | Change Sensitivity (DPI) by holding a button and moving the mouse
Mouse Gestures | Create HID++ events by holding a button and moving the mouse
Key/Button Actions | Change what a key or button does
Key/Button Diversion | Divert keys and buttons to create HID++ events
Divert crown events | Divert crown actions to create HID++ events
Divert G Keys | Divert G keys to create HID++ events
Disable keys | Disable one or more keys
Set OS | Change keys to match OS
Change Host | Connect to a different host
Gestures | Turn on and off various (mostly touchpad) gestures
Gesture params | Modify parameters for gestures
HID++ events are mostly not processed by Linux input drivers.
Settings that involve sending HID++ events exist so that these events can be
processed by Solaar rules instead of by Linux.
Different Logitech devices may implement the same functionality in different ways,
thus the different settings that do the same thing.

View File

@@ -1,12 +0,0 @@
Unifying receiver:
046d:c52b interface: 2 driver: logitech-djreceiver
046d:c532 interface: 2 driver: logitech-djreceiver
Nano receiver, Advanced/Unifying ready:
046d:c52f interface: 1 driver: hid-generic
Nano receiver:
046d:c51a interface: 1 driver: hid-generic
046d:c526 interface: 1 driver: hid-generic

View File

@@ -9,8 +9,8 @@
# The latest version can be obtained from
# http://www.linux-usb.org/usb.ids
#
# Version: 2013.05.24
# Date: 2013-05-24 20:34:03
# Version: 2019.11.05
# Date: 2019-11-05 20:34:06
#
# Vendors, devices and interfaces. Please keep sorted.
@@ -24,6 +24,7 @@
0082 Acer Aspire 5672 Webcam
0200 WingMan Extreme Joystick
0203 M2452 Keyboard
0242 Chillstream for Xbox 360
0301 M4848 Mouse
0401 HP PageScan
0402 NEC PageScan
@@ -40,16 +41,25 @@
080f Webcam C120
0810 QuickCam Pro
0819 Webcam C210
081a Webcam C260
081b Webcam C310
081d HD Webcam C510
0820 QuickCam VC
0821 HD Webcam C910
0823 HD Webcam B910
0825 Webcam C270
0826 HD Webcam C525
0828 HD Webcam B990
082b Webcam C170
082c HD Webcam C615
082d HD Pro Webcam C920
0830 QuickClip
0836 B525 HD Webcam
0837 BCC950 ConferenceCam
0840 QuickCam Express
0843 Webcam C930e
0850 QuickCam Web
085c C922 Pro Stream Webcam
0870 QuickCam Express
0890 QuickCam Traveler
0892 OrbiCam
@@ -96,7 +106,7 @@
08d7 QuickCam Communicate STX
08d8 QuickCam for Notebook Deluxe
08d9 QuickCam IM/Connect
08da QuickCam Messanger
08da QuickCam Messenger
08dd QuickCam for Notebooks
08e0 QuickCam Express
08e1 Labtec Webcam
@@ -147,14 +157,25 @@
0a0b ClearChat Pro USB
0a0c Clear Chat Comfort USB Headset
0a13 Z-5 Speakers
0a14 USB Headset
0a15 G35 Headset
0a17 G330 Headset
0a1f G930
0a29 H600 [Wireless Headset]
0a37 USB Headset H540
0a38 Headset H340
0a44 Headset H390
0a45 960 Headset
0a4d G430 Surround Sound Gaming Headset
0a5b G933 Wireless Headset Dongle
0a66 [G533 Wireless Headset Dongle]
0b02 C-UV35 [Bluetooth Mini-Receiver] (HID proxy mode)
8801 Video Camera
b014 Bluetooth Mouse M336/M337/M535
b305 BT Mini-Receiver
bfe4 Premium Optical Wheel Mouse
c000 N43 [Pilot Mouse]
c001 N48/M-BB48 [FirstMouse Plus]
c001 N48/M-BB48/M-UK96A [FirstMouse Plus]
c002 M-BA47 [MouseMan Plus]
c003 MouseMan
c004 WingMan Gaming Mouse
@@ -212,20 +233,32 @@
c061 RX1500 Laser Mouse
c062 M-UAS144 [LS1 Laser Mouse]
c063 DELL Laser Mouse
c064 M110 corded optical mouse (M-B0001)
c066 G9x Laser Mouse
c068 G500 Laser Mouse
c069 M500 Laser Mouse
c069 M-U0007 [Corded Mouse M500]
c06a USB Optical Mouse
c06b G700 Wireless Gaming Mouse
c06c Optical Mouse
c077 M105 Optical Mouse
c07c M-R0017 [G700s Rechargeable Gaming Mouse]
c07d G502 Mouse
c07e G402 Gaming Mouse
c080 G303 Gaming Mouse
c083 G403 Prodigy Gaming Mouse
c084 G203 Gaming Mouse
c101 UltraX Media Remote
c110 Harmony 785/885 Remote
c110 Harmony 785/880/885 Remote
c111 Harmony 525 Remote
c112 Harmony 890 Remote
c11f Harmony 900/1100 Remote
c121 Harmony One Remote
c122 Harmony 700 Remote
c124 Harmony 300 Remote
c122 Harmony 650/700 Remote
c124 Harmony 300/350 Remote
c125 Harmony 200 Remote
c126 Harmony Link
c129 Harmony Hub
c12b Harmony Touch/Ultimate Remote
c201 WingMan Extreme Joystick with Throttle
c202 WingMan Formula
c207 WingMan Extreme Digital 3D
@@ -236,14 +269,14 @@
c20c WingMan Precision
c20d WingMan Attack 2
c20e WingMan Formula GP
c211 iTouch Cordless Reciever
c211 iTouch Cordless Receiver
c212 WingMan Extreme Digital 3D
c213 J-UH16 (Freedom 2.4 Cordless Joystick)
c214 ATK3 (Attack III Joystick)
c215 Extreme 3D Pro
c216 Dual Action Gamepad
c218 Logitech RumblePad 2 USB
c219 Cordless RumblePad 2
c216 F310 Gamepad [DirectInput Mode]
c218 F510 Gamepad [DirectInput Mode]
c219 F710 Gamepad [DirectInput Mode]
c21a Precision Gamepad
c21c G13 Advanced Gameboard
c21d F310 Gamepad [XInput Mode]
@@ -255,12 +288,20 @@
c225 G11/G15 Keyboard / G keys
c226 G15 Refresh Keyboard
c227 G15 Refresh Keyboard
c228 G19 Gaming Keyboard
c229 G19 Gaming Keyboard Macro Interface
c22a Gaming Keyboard G110
c22b Gaming Keyboard G110 G-keys
c22d G510 Gaming Keyboard
c22e G510 Gaming Keyboard onboard audio
c231 G13 Virtual Mouse
c245 G400 Optical Mouse
c246 Gaming Mouse G300
c248 G105 Gaming Keyboard
c24a G600 Gaming Mouse
c24c G400s Optical Mouse
c24d G710 Gaming Keyboard
c24e G500s Laser Gaming Mouse
c281 WingMan Force
c283 WingMan Force 3D
c285 WingMan Strike Force 3D
@@ -276,13 +317,14 @@
c29c Speed Force Wireless Wheel for Wii
c2a0 Wingman Force Feedback Mouse
c2a1 WingMan Force Feedback Mouse
c2ab G13 Joystick
c301 iTouch Keyboard
c302 iTouch Pro Keyboard
c303 iTouch Keyboard
c305 Internet Keyboard
c307 Internet Keyboard
c308 Internet Navigator Keyboard
c309 Internet Keyboard
c309 Y-BF37 [Internet Navigator Keyboard]
c30a iTouch Composite
c30b NetPlay Keyboard
c30c Internet Keys (X)
@@ -298,8 +340,14 @@
c318 Illuminated Keyboard
c31a Comfort Wave 450
c31b Compact Keyboard K300
c31c Keyboard K120 for Business
c31c Keyboard K120
c31d Media Keyboard K200
c31f Comfort Keyboard K290
c326 Washable Keyboard K310
c328 Corded Keyboard K280e
c332 G502 Proteus Spectrum Optical Mouse
c335 G910 Orion Spectrum Mechanical Keyboard
c33a G413 Gaming Keyboard
c401 TrackMan Marble Wheel
c402 Marble Mouse (2-button)
c403 Turbo TrackMan Marble FX
@@ -332,12 +380,24 @@
c526 Nano Receiver
c529 Logitech Keyboard + Mice
c52b Unifying Receiver
c52d R700 Remote Presenter receiver
c52e MK260 Wireless Combo Receiver
c52f Unifying Receiver
c531 C-U0007 [Unifying Receiver]
c532 Unifying Receiver
c534 Unifying Receiver
c603 3Dconnexion Spacemouse Plus XT
c605 3Dconnexion CADman
c606 3Dconnexion Spacemouse Classic
c621 3Dconnexion Spaceball 5000
c623 3Dconnexion Space Traveller 3D Mouse
c625 3Dconnexion Space Pilot 3D Mouse
c626 3Dconnexion Space Navigator 3D Mouse
c627 3Dconnexion Space Explorer 3D Mouse
c628 3Dconnexion Space Navigator for Notebooks
c629 3Dconnexion SpacePilot Pro 3D Mouse
c62b 3Dconnexion Space Mouse Pro
c640 NuLOOQ navigator
c702 Cordless Presenter
c703 Elite Keyboard Y-RP20 + Mouse MX900 (Bluetooth)
c704 diNovo Wireless Desktop
@@ -360,5 +420,10 @@
c720 Bluetooth wireless hub
ca03 MOMO Racing
ca04 Formula Vibration Feedback Wheel
ca84 Cordless Controller for Xbox
ca88 Thunderpad for Xbox
ca8a Precision Vibration Feedback Wheel for Xbox
caa3 DriveFX Racing Wheel
cab1 Cordless Keyboard for Wii HID Receiver
d001 QuickCam Pro
f301 Controller

View File

@@ -1,12 +0,0 @@
title: Solaar
tagline: Linux devices manager for the Logitech Unifying Receiver.
owner: pwr
owner_url: https://github.com/pwr
repository: https://github.com/pwr/Solaar
version: 0.9.1
tar_download: https://github.com/pwr/Solaar/archive/0.9.1.tar.gz
ga_id: UA-36908718-1
pygments: true
safe: true
lsi: false

View File

@@ -1,14 +0,0 @@
<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" style="width: 48px; height:48px; margin-bottom: -10px;">
<defs>
<linearGradient id="gradient_blue">
<stop style="stop-color:#009099;stop-opacity:1" offset="0" />
<stop style="stop-color:#00a899;stop-opacity:0.9" offset="1" />
</linearGradient>
<linearGradient x1="5" y1="50" x2="95" y2="50" id="gradient_rect" xlink:href="#gradient_blue" gradientUnits="userSpaceOnUse" />
<linearGradient x1="37" y1="50" x2="63" y2="50" id="gradient_dot" xlink:href="#gradient_blue" gradientUnits="userSpaceOnUse" />
</defs>
<g transform="scale(0.48)">
<path d="M 21.5,5.5 C 12.636,5.5 5.5,12.636 5.5,21.5 L 5.5,78.5 C 5.5,87.364 12.636,94.5 21.5,94.5 L 78.5,94.5 C 87.364,94.5 94.5,87.364 94.5,78.5 L 94.5,21.5 C 94.5,12.636 87.364,5.5 78.5,5.5 L 21.5,5.5 z M 37.6875,16.6875 46.71875,32.3125 C 47.784179,32.115965 48.877705,32 50,32 51.122295,32 52.215821,32.115965 53.28125,32.3125 L 62.3125,16.6875 72.6875,22.6875 63.65625,38.3125 C 65.078123,39.972287 66.191785,41.898777 66.9375,44 L 85,44 85,56 66.9375,56 C 66.191785,58.101223 65.078123,60.027713 63.65625,61.6875 L 72.6875,77.3125 62.3125,83.3125 53.28125,67.6875 C 52.215821,67.884035 51.122295,68 50,68 48.877705,68 47.784179,67.884035 46.71875,67.6875 L 37.6875,83.3125 27.3125,77.3125 36.34375,61.6875 C 34.921877,60.027713 33.808215,58.101223 33.0625,56 L 15,56 15,44 33.0625,44 C 33.808215,41.898777 34.921877,39.972287 36.34375,38.3125 L 27.3125,22.6875 37.6875,16.6875 z" style="fill:url(#gradient_rect);fill-opacity:1;fill-rule:nonzero;stroke:#16161d;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1" />
<path d="M 62,50 A 12,12 0 1 1 38,50 12,12 0 1 1 62,50 z" style="fill:url(#gradient_dot);fill-opacity:1;fill-rule:nonzero;stroke:#16161d;stroke-opacity:1" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.9 KiB

View File

@@ -1,56 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<meta name="description" content="{{ site.tagline }}" />
<link rel="stylesheet" type="text/css" media="screen" href="style/stylesheet.css">
<link rel="icon" type="image/png" href="images/favicon.png" />
<title>{{ page.title }}</title>
</head>
<body>
<div id="header_wrap" class="outer">
<header class="inner">
<a id="forkme_banner" href="{{ site.repository }}">View on GitHub</a>
<h1 id="project_title">{% include solaar.svg %} {{ site.title }}</h1>
<h2 id="project_tagline">{{ site.tagline }}</h2>
<section id="downloads">
<a class="tar_download_link" href="{{ site.tar_download }}">Solaar {{ site.version }}</a>
<p style="color: #fff">
Latest version:<br/>
<span style="float: right; font-weight: bolder;">{{ site.version }}</span>
</p>
</section>
</header>
</div>
<div id="main_content_wrap" class="outer">
<section id="main_content" class="inner">
{{ content }}
</section>
</div>
<div id="footer_wrap" class="outer">
<footer class="inner">
<p class="copyright"><a href="{{ site.repository }}">{{ site.title }}</a> maintained by <a href="{{ site.owner_url }}">{{ site.owner }}</a></p>
<p><a href="https://github.com/jsncostello/slate">Slate</a> theme by <a href="https://github.com/jsncostello">Jason Costello</a></p>
</footer>
</div>
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
try {
var pageTracker = _gat._getTracker("{{ site.ga_id }}");
pageTracker._trackPageview();
} catch(err) {}
</script>
</body>
</html>

View File

@@ -1,47 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<meta name="description" content="{{ site.tagline }}" />
<link rel="stylesheet" type="text/css" media="screen" href="style/stylesheet.css">
<link rel="icon" type="image/png" href="images/favicon.png" />
<title>{{ page.title }}</title>
</head>
<body>
<div id="header_wrap" class="outer">
<header class="inner">
<h1 id="project_title">
<a href="index.html">{% include solaar.svg %} {{ site.title }}</a>
</h1>
</header>
</div>
<div id="main_content_wrap" class="outer">
<section id="main_content" class="inner">
{{ content }}
</section>
</div>
<div id="footer_wrap" class="outer">
<footer class="inner">
<p class="copyright"><a href="{{ site.repository }}">{{ site.title }}</a> maintained by <a href="{{ site.owner_url }}">{{ site.owner }}</a></p>
<p><a href="https://github.com/jsncostello/slate">Slate</a> theme by <a href="https://github.com/jsncostello">Jason Costello</a></p>
</footer>
</div>
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
try {
var pageTracker = _gat._getTracker("{{ site.ga_id }}");
pageTracker._trackPageview();
} catch(err) {}
</script>
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 943 B

After

Width:  |  Height:  |  Size: 96 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 432 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 230 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -1,70 +0,0 @@
.highlight .hll { background-color: #ffffcc }
.highlight { background: #f0f3f3; }
.highlight .c { color: #0099FF; font-style: italic } /* Comment */
.highlight .err { color: #AA0000; background-color: #FFAAAA } /* Error */
.highlight .k { color: #006699; font-weight: bold } /* Keyword */
.highlight .o { color: #555555 } /* Operator */
.highlight .cm { color: #0099FF; font-style: italic } /* Comment.Multiline */
.highlight .cp { color: #009999 } /* Comment.Preproc */
.highlight .c1 { color: #0099FF; font-style: italic } /* Comment.Single */
.highlight .cs { color: #0099FF; font-weight: bold; font-style: italic } /* Comment.Special */
.highlight .gd { background-color: #FFCCCC; border: 1px solid #CC0000 } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #FF0000 } /* Generic.Error */
.highlight .gh { color: #003300; font-weight: bold } /* Generic.Heading */
.highlight .gi { background-color: #CCFFCC; border: 1px solid #00CC00 } /* Generic.Inserted */
.highlight .go { color: #AAAAAA } /* Generic.Output */
.highlight .gp { color: #000099; font-weight: bold } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #003300; font-weight: bold } /* Generic.Subheading */
.highlight .gt { color: #99CC66 } /* Generic.Traceback */
.highlight .kc { color: #006699; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #006699; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #006699; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #006699 } /* Keyword.Pseudo */
.highlight .kr { color: #006699; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #007788; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #FF6600 } /* Literal.Number */
.highlight .s { color: #CC3300 } /* Literal.String */
.highlight .na { color: #330099 } /* Name.Attribute */
.highlight .nb { color: #336666 } /* Name.Builtin */
.highlight .nc { color: #00AA88; font-weight: bold } /* Name.Class */
.highlight .no { color: #336600 } /* Name.Constant */
.highlight .nd { color: #9999FF } /* Name.Decorator */
.highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */
.highlight .ne { color: #CC0000; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #CC00FF } /* Name.Function */
.highlight .nl { color: #9999FF } /* Name.Label */
.highlight .nn { color: #00CCFF; font-weight: bold } /* Name.Namespace */
.highlight .nt { color: #330099; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #003333 } /* Name.Variable */
.highlight .ow { color: #000000; font-weight: bold } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mf { color: #FF6600 } /* Literal.Number.Float */
.highlight .mh { color: #FF6600 } /* Literal.Number.Hex */
.highlight .mi { color: #FF6600 } /* Literal.Number.Integer */
.highlight .mo { color: #FF6600 } /* Literal.Number.Oct */
.highlight .sb { color: #CC3300 } /* Literal.String.Backtick */
.highlight .sc { color: #CC3300 } /* Literal.String.Char */
.highlight .sd { color: #CC3300; font-style: italic } /* Literal.String.Doc */
.highlight .s2 { color: #CC3300 } /* Literal.String.Double */
.highlight .se { color: #CC3300; font-weight: bold } /* Literal.String.Escape */
.highlight .sh { color: #CC3300 } /* Literal.String.Heredoc */
.highlight .si { color: #AA0000 } /* Literal.String.Interpol */
.highlight .sx { color: #CC3300 } /* Literal.String.Other */
.highlight .sr { color: #33AAAA } /* Literal.String.Regex */
.highlight .s1 { color: #CC3300 } /* Literal.String.Single */
.highlight .ss { color: #FFCC33 } /* Literal.String.Symbol */
.highlight .bp { color: #336666 } /* Name.Builtin.Pseudo */
.highlight .vc { color: #003333 } /* Name.Variable.Class */
.highlight .vg { color: #003333 } /* Name.Variable.Global */
.highlight .vi { color: #003333 } /* Name.Variable.Instance */
.highlight .il { color: #FF6600 } /* Literal.Number.Integer.Long */
.type-csharp .highlight .k { color: #0000FF }
.type-csharp .highlight .kt { color: #0000FF }
.type-csharp .highlight .nf { color: #000000; font-weight: normal }
.type-csharp .highlight .nc { color: #2B91AF }
.type-csharp .highlight .nn { color: #000000 }
.type-csharp .highlight .s { color: #A31515 }
.type-csharp .highlight .sc { color: #A31515 }

View File

@@ -1,442 +0,0 @@
/*******************************************************************************
Slate Theme for Github Pages
by Jason Costello, @jsncostello
*******************************************************************************/
@import url(pygment_trac.css);
/*******************************************************************************
MeyerWeb Reset
*******************************************************************************/
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font: inherit;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
ol, ul {
list-style: none;
}
blockquote, q {
}
table {
border-collapse: collapse;
border-spacing: 0;
}
a:focus {
outline: none;
}
/*******************************************************************************
Theme Styles
*******************************************************************************/
body {
box-sizing: border-box;
color:#373737;
background: #212121;
font-size: 18px;
font-family: 'Myriad Pro', Calibri, Helvetica, Arial, sans-serif;
line-height: 1.4;
-webkit-font-smoothing: antialiased;
}
h1, h2, h3, h4, h5, h6 {
margin: 20px 0;
font-weight: 700;
color:#222222;
font-family: 'Lucida Grande', 'Calibri', Helvetica, Arial, sans-serif;
letter-spacing: -1px;
}
h1 {
font-size: 36px;
font-weight: 700;
}
h2 {
padding-bottom: 0px;
font-size: 32px;
background: url('../images/bg_hr.png') repeat-x bottom;
}
h3 {
font-size: 24px;
}
h4 {
font-size: 21px;
}
h5 {
font-size: 18px;
}
h6 {
font-size: 16px;
}
p {
margin: 10px 0 15px 0;
}
footer p {
color: #f2f2f2;
}
a {
text-decoration: none;
color: #007edf;
text-shadow: none;
transition: color 0.5s ease;
transition: text-shadow 0.5s ease;
-webkit-transition: color 0.5s ease;
-webkit-transition: text-shadow 0.5s ease;
-moz-transition: color 0.5s ease;
-moz-transition: text-shadow 0.5s ease;
-o-transition: color 0.5s ease;
-o-transition: text-shadow 0.5s ease;
-ms-transition: color 0.5s ease;
-ms-transition: text-shadow 0.5s ease;
}
#main_content a:hover {
color: #0069ba;
text-shadow: #0090ff 0px 0px 2px;
}
footer a:hover {
color: #43adff;
text-shadow: #0090ff 0px 0px 2px;
}
em {
font-style: italic;
}
strong {
font-weight: bold;
}
img {
position: relative;
margin: 0 auto;
max-width: 739px;
padding: 5px;
margin: 10px 0 10px 0;
border: 1px solid #ebebeb;
box-shadow: 0 0 5px #ebebeb;
-webkit-box-shadow: 0 0 5px #ebebeb;
-moz-box-shadow: 0 0 5px #ebebeb;
-o-box-shadow: 0 0 5px #ebebeb;
-ms-box-shadow: 0 0 5px #ebebeb;
}
img.logo {
max-width: 48px;
width: 48px;
height: 48px;
margin: 0;
padding: 0;
border: 0;
bottom: -10px;
box-shadow: none;
-webkit-box-shadow: 0;
-moz-box-shadow: 0;
-o-box-shadow: 0;
-ms-box-shadow: 0;
}
pre, code {
width: 100%;
color: #222;
background-color: #fff;
font-family: Monaco, "Bitstream Vera Sans Mono", "Lucida Console", Terminal, monospace;
font-size: 14px;
border-radius: 2px;
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
}
pre {
width: 100%;
padding: 10px;
box-shadow: 0 0 10px rgba(0,0,0,.1);
overflow: auto;
}
code {
padding: 3px;
margin: 0 3px;
box-shadow: 0 0 10px rgba(0,0,0,.1);
}
pre code {
display: block;
box-shadow: none;
}
blockquote {
color: #666;
margin-bottom: 20px;
padding: 0 0 0 20px;
border-left: 3px solid #bbb;
}
ul, ol, dl {
margin-bottom: 15px
}
ul li {
list-style: inside;
padding-left: 20px;
}
ol li {
list-style: decimal inside;
padding-left: 20px;
}
dl dt {
font-weight: bold;
}
dl dd {
padding-left: 20px;
font-style: italic;
}
dl p {
padding-left: 20px;
font-style: italic;
}
hr {
height: 1px;
margin-bottom: 5px;
border: none;
background: url('../images/bg_hr.png') repeat-x center;
}
table {
border: 1px solid #373737;
margin-bottom: 20px;
text-align: left;
width: 100%;
}
th {
font-family: 'Lucida Grande', 'Helvetica Neue', Helvetica, Arial, sans-serif;
padding: 10px;
background: #373737;
color: #fff;
}
td {
padding: 10px;
border: 1px solid #373737;
}
form {
background: #f2f2f2;
padding: 20px;
}
img {
width: 100%;
max-width: 100%;
}
/*******************************************************************************
Full-Width Styles
*******************************************************************************/
.outer {
width: 100%;
}
.inner {
position: relative;
max-width: 940px;
padding: 20px 10px;
margin: 0 auto;
}
.copyright {
float: right;
}
#forkme_banner {
display: block;
position: absolute;
top:0;
right: 10px;
z-index: 10;
padding: 10px 50px 10px 10px;
color: #fff;
background: url('../images/blacktocat.png') #0090ff no-repeat 95% 50%;
font-weight: 700;
box-shadow: 0 0 10px rgba(0,0,0,.5);
border-bottom-left-radius: 2px;
border-bottom-right-radius: 2px;
}
#header_wrap {
background: #212121;
}
#header_wrap .inner {
padding 50px 10px 30px 10px;
}
#project_title {
margin: 0;
color: #fff;
font-size: 42px;
font-weight: 700;
text-shadow: #111 0px 0px 10px;
}
#project_tagline {
color: #fff;
font-size: 24px;
font-weight: 300;
background: none;
text-shadow: #111 0px 0px 10px;
}
#downloads {
position: absolute;
width: 240px;
z-index: 10;
bottom: 0px;
right: 0;
height: 80px;
background: url('../images/icon_download.png') no-repeat 15% 70%;
}
.zip_download_link {
display: block;
float: right;
width: 90px;
height:70px;
text-indent: -5000px;
overflow: hidden;
background: url(../images/sprite_download.png) no-repeat bottom left;
}
.tar_download_link {
display: block;
float: right;
width: 90px;
height:70px;
text-indent: -5000px;
overflow: hidden;
background: url(../images/sprite_download.png) no-repeat bottom right;
margin-left: 10px;
}
.zip_download_link:hover {
background: url(../images/sprite_download.png) no-repeat top left;
}
.tar_download_link:hover {
background: url(../images/sprite_download.png) no-repeat top right;
}
#main_content_wrap {
background: #f2f2f2;
border-top: 1px solid #111;
border-bottom: 1px solid #111;
}
#main_content {
padding-top: 40px;
}
#footer_wrap {
background: #212121;
}
/*******************************************************************************
Small Device Styles
*******************************************************************************/
@media screen and (max-width: 480px) {
body {
font-size:14px;
}
#downloads {
display: none;
}
.inner {
min-width: 320px;
max-width: 480px;
}
#project_title {
font-size: 32px;
}
h1 {
font-size: 28px;
}
h2 {
font-size: 24px;
}
h3 {
font-size: 21px;
}
h4 {
font-size: 18px;
}
h5 {
font-size: 14px;
}
h6 {
font-size: 12px;
}
code, pre {
min-width: 320px;
max-width: 480px;
font-size: 11px;
}
}

View File

@@ -16,22 +16,21 @@
## You should have received a copy of the GNU General Public License along
## with this program; if not, write to the Free Software Foundation, Inc.,
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
"""Generic Human Interface Device API."""
from __future__ import absolute_import, division, print_function, unicode_literals
__version__ = '0.9'
from hidapi.udev import close # noqa: F401
from hidapi.udev import enumerate # noqa: F401
from hidapi.udev import find_paired_node # noqa: F401
from hidapi.udev import find_paired_node_wpid # noqa: F401
from hidapi.udev import get_manufacturer # noqa: F401
from hidapi.udev import get_product # noqa: F401
from hidapi.udev import get_serial # noqa: F401
from hidapi.udev import monitor_glib # noqa: F401
from hidapi.udev import open # noqa: F401
from hidapi.udev import open_path # noqa: F401
from hidapi.udev import read # noqa: F401
from hidapi.udev import write # noqa: F401
from hidapi.udev import (
enumerate,
open,
close,
open_path,
monitor_glib,
read,
write,
get_manufacturer,
get_product,
get_serial,
)
__version__ = '0.9'

View File

@@ -21,9 +21,12 @@ from __future__ import absolute_import, division, print_function, unicode_litera
import os
import sys
from select import select as _select
import time
from binascii import hexlify, unhexlify
from select import select as _select
from threading import Lock
import hidapi as _hid
#
@@ -31,10 +34,10 @@ import hidapi as _hid
#
try:
read_packet = raw_input
read_packet = raw_input
except NameError:
# Python 3 equivalent of raw_input
read_packet = input
# Python 3 equivalent of raw_input
read_packet = input
interactive = os.isatty(0)
prompt = '?? Input: ' if interactive else ''
@@ -42,217 +45,227 @@ start_time = time.time()
strhex = lambda d: hexlify(d).decode('ascii').upper()
try:
unicode
# this is certanly Python 2
is_string = lambda d: isinstance(d, unicode)
# no easy way to distinguish between b'' and '' :(
# or (isinstance(d, str) \
# and not any((chr(k) in d for k in range(0x00, 0x1F))) \
# and not any((chr(k) in d for k in range(0x80, 0xFF))) \
# )
except:
# this is certanly Python 3
# In Py3, unicode and str are equal (the unicode object does not exist)
is_string = lambda d: isinstance(d, str)
unicode # noqa: F821
# this is certanly Python 2
is_string = lambda d: isinstance(d, unicode) # noqa: F821
# no easy way to distinguish between b'' and '' :(
# or (isinstance(d, str) \
# and not any((chr(k) in d for k in range(0x00, 0x1F))) \
# and not any((chr(k) in d for k in range(0x80, 0xFF))) \
# )
except Exception:
# this is certanly Python 3
# In Py3, unicode and str are equal (the unicode object does not exist)
is_string = lambda d: isinstance(d, str)
#
#
#
from threading import Lock
print_lock = Lock()
del Lock
def _print(marker, data, scroll=False):
t = time.time() - start_time
if is_string(data):
s = marker + ' ' + data
else:
hexs = strhex(data)
s = '%s (% 8.3f) [%s %s %s %s] %s' % (marker, t, hexs[0:2], hexs[2:4], hexs[4:8], hexs[8:], repr(data))
t = time.time() - start_time
if is_string(data):
s = marker + ' ' + data
else:
hexs = strhex(data)
s = '%s (% 8.3f) [%s %s %s %s] %s' % (marker, t, hexs[0:2], hexs[2:4], hexs[4:8], hexs[8:], repr(data))
with print_lock:
# allow only one thread at a time to write to the console, otherwise
# the output gets garbled, especially with ANSI codes.
with print_lock:
# allow only one thread at a time to write to the console, otherwise
# the output gets garbled, especially with ANSI codes.
if interactive and scroll:
# scroll the entire screen above the current line up by 1 line
sys.stdout.write('\033[s' # save cursor position
'\033[S' # scroll up
'\033[A' # cursor up
'\033[L' # insert 1 line
'\033[G') # move cursor to column 1
sys.stdout.write(s)
if interactive and scroll:
# restore cursor position
sys.stdout.write('\033[u')
else:
sys.stdout.write('\n')
if interactive and scroll:
# scroll the entire screen above the current line up by 1 line
sys.stdout.write(
'\033[s' # save cursor position
'\033[S' # scroll up
'\033[A' # cursor up
'\033[L' # insert 1 line
'\033[G'
) # move cursor to column 1
sys.stdout.write(s)
if interactive and scroll:
# restore cursor position
sys.stdout.write('\033[u')
else:
sys.stdout.write('\n')
# flush stdout manually...
# because trying to open stdin/out unbuffered programatically
# works much too differently in Python 2/3
sys.stdout.flush()
# flush stdout manually...
# because trying to open stdin/out unbuffered programmatically
# works much too differently in Python 2/3
sys.stdout.flush()
def _error(text, scroll=False):
_print('!!', text, scroll)
_print('!!', text, scroll)
def _continuous_read(handle, timeout=2000):
while True:
try:
reply = _hid.read(handle, 128, timeout)
except OSError as e:
_error("Read failed, aborting: " + str(e), True)
break
assert reply is not None
if reply:
_print('>>', reply, True)
while True:
try:
reply = _hid.read(handle, 128, timeout)
except OSError as e:
_error('Read failed, aborting: ' + str(e), True)
break
assert reply is not None
if reply:
_print('>>', reply, True)
def _validate_input(line, hidpp=False):
try:
data = unhexlify(line.encode('ascii'))
except Exception as e:
_error("Invalid input: " + str(e))
return None
try:
data = unhexlify(line.encode('ascii'))
except Exception as e:
_error('Invalid input: ' + str(e))
return None
if hidpp:
if len(data) < 4:
_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")
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")
return None
if data[:1] == b'\x10':
if len(data) > 7:
_error("Invalid HID++ request: maximum length of a 0x10 request is 7 bytes")
return None
while len(data) < 7:
data = (data + b'\x00' * 7)[:7]
elif data[:1] == b'\x11':
if len(data) > 20:
_error("Invalid HID++ request: maximum length of a 0x11 request is 20 bytes")
return None
while len(data) < 20:
data = (data + b'\x00' * 20)[:20]
if hidpp:
if len(data) < 4:
_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')
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')
return None
if data[:1] == b'\x10':
if len(data) > 7:
_error('Invalid HID++ request: maximum length of a 0x10 request is 7 bytes')
return None
while len(data) < 7:
data = (data + b'\x00' * 7)[:7]
elif data[:1] == b'\x11':
if len(data) > 20:
_error('Invalid HID++ request: maximum length of a 0x11 request is 20 bytes')
return None
while len(data) < 20:
data = (data + b'\x00' * 20)[:20]
return data
return data
def _open(args):
device = args.device
if args.hidpp and not device:
for d in _hid.enumerate(vendor_id=0x046d):
if d.driver == 'logitech-djreceiver':
device = d.path
break
if not device:
sys.exit("!! No HID++ receiver found.")
if not device:
sys.exit("!! Device path required.")
def matchfn(bid, vid, pid):
if vid == 0x046d:
return {'vid': 0x046d}
print (".. Opening device", device)
handle = _hid.open_path(device)
if not handle:
sys.exit("!! Failed to open %s, aborting." % device)
device = args.device
if args.hidpp and not device:
for d in _hid.enumerate(matchfn):
if d.driver == 'logitech-djreceiver':
device = d.path
break
if not device:
sys.exit('!! No HID++ receiver found.')
if not device:
sys.exit('!! Device path required.')
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.")
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('.. Opening device', device)
handle = _hid.open_path(device)
if not handle:
sys.exit('!! Failed to open %s, aborting.' % device)
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.')
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.')
return handle
return handle
#
#
#
def _parse_arguments():
import argparse
arg_parser = argparse.ArgumentParser()
arg_parser.add_argument('--history', help="history file (default ~/.hidconsole-history)")
arg_parser.add_argument('--hidpp', action='store_true', 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")
return arg_parser.parse_args()
import argparse
arg_parser = argparse.ArgumentParser()
arg_parser.add_argument('--history', help='history file (default ~/.hidconsole-history)')
arg_parser.add_argument('--hidpp', action='store_true', 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'
)
return arg_parser.parse_args()
def main():
args = _parse_arguments()
handle = _open(args)
args = _parse_arguments()
handle = _open(args)
if interactive:
print (".. Press ^C/^D to exit, or type hex bytes to write to the device.")
if interactive:
print('.. Press ^C/^D to exit, or type hex bytes to write to the device.')
import readline
if args.history is None:
import os.path
args.history = os.path.join(os.path.expanduser('~'), '.hidconsole-history')
try:
readline.read_history_file(args.history)
except:
# file may not exist yet
pass
import readline
if args.history is None:
import os.path
args.history = os.path.join(os.path.expanduser('~'), '.hidconsole-history')
try:
readline.read_history_file(args.history)
except Exception:
# file may not exist yet
pass
try:
from threading import Thread
t = Thread(target=_continuous_read, args=(handle,))
t.daemon = True
t.start()
try:
from threading import Thread
t = Thread(target=_continuous_read, args=(handle, ))
t.daemon = True
t.start()
if interactive:
# move the cursor at the bottom of the screen
sys.stdout.write('\033[300B') # move cusor at most 300 lines down, don't scroll
if interactive:
# move the cursor at the bottom of the screen
sys.stdout.write('\033[300B') # move cusor at most 300 lines down, don't scroll
while t.is_alive():
line = read_packet(prompt)
line = line.strip().replace(' ', '')
# print ("line", line)
if not line:
continue
while t.is_alive():
line = read_packet(prompt)
line = line.strip().replace(' ', '')
# print ("line", line)
if not line:
continue
data = _validate_input(line, args.hidpp)
if data is None:
continue
data = _validate_input(line, args.hidpp)
if data is None:
continue
_print('<<', data)
_hid.write(handle, data)
# wait for some kind of reply
if args.hidpp and not interactive:
rlist, wlist, xlist = _select([handle], [], [], 1)
if data[1:2] == b'\xFF':
# the receiver will reply very fast, in a few milliseconds
time.sleep(0.010)
else:
# the devices might reply quite slow
time.sleep(0.700)
except EOFError:
if interactive:
print ("")
else:
time.sleep(1)
_print('<<', data)
_hid.write(handle, data)
# wait for some kind of reply
if args.hidpp and not interactive:
rlist, wlist, xlist = _select([handle], [], [], 1)
if data[1:2] == b'\xFF':
# the receiver will reply very fast, in a few milliseconds
time.sleep(0.010)
else:
# the devices might reply quite slow
time.sleep(0.700)
except EOFError:
if interactive:
print('')
else:
time.sleep(1)
finally:
print (".. Closing handle %r" % handle)
_hid.close(handle)
if interactive:
readline.write_history_file(args.history)
finally:
print('.. Closing handle %r' % handle)
_hid.close(handle)
if interactive:
readline.write_history_file(args.history)
if __name__ == '__main__':
main()
main()

View File

@@ -16,7 +16,6 @@
## You should have received a copy of the GNU General Public License along
## with this program; if not, write to the Free Software Foundation, Inc.,
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
"""Generic Human Interface Device API.
It is currently a partial pure-Python implementation of the native HID API
@@ -28,337 +27,422 @@ necessary.
from __future__ import absolute_import, division, print_function, unicode_literals
import os as _os
import errno as _errno
from select import select as _select
from pyudev import Context as _Context, Monitor as _Monitor, Device as _Device
native_implementation = 'udev'
import os as _os
# the tuple object we'll expose when enumerating devices
from collections import namedtuple
DeviceInfo = namedtuple('DeviceInfo', [
'path',
'vendor_id',
'product_id',
'serial',
'release',
'manufacturer',
'product',
'interface',
'driver',
])
del namedtuple
from logging import DEBUG as _DEBUG
from logging import getLogger
from select import select as _select
from time import sleep
from time import time as _timestamp
from pyudev import Context as _Context
from pyudev import Device as _Device
from pyudev import DeviceNotFoundError
from pyudev import Devices as _Devices
from pyudev import Monitor as _Monitor
_log = getLogger(__name__)
del getLogger
native_implementation = 'udev'
DeviceInfo = namedtuple(
'DeviceInfo', [
'path',
'vendor_id',
'product_id',
'serial',
'release',
'manufacturer',
'product',
'interface',
'driver',
'bus_id',
'isDevice',
]
)
del namedtuple
#
# exposed API
# docstrings mostly copied from hidapi.h
#
def init():
"""This function is a no-op, and exists only to match the native hidapi
implementation.
:returns: ``True``.
"""
return True
def init():
"""This function is a no-op, and exists only to match the native hidapi
implementation.
:returns: ``True``.
"""
return True
def exit():
"""This function is a no-op, and exists only to match the native hidapi
implementation.
"""This function is a no-op, and exists only to match the native hidapi
implementation.
:returns: ``True``.
"""
return True
:returns: ``True``.
"""
return True
def _match(action, device, vendor_id=None, product_id=None, interface_number=None, hid_driver=None):
usb_device = device.find_parent('usb', 'usb_device')
# print ("* parent", action, device, "usb:", usb_device)
if not usb_device:
return
# The filterfn is used to determine whether this is a device of interest to Solaar.
# It is given the bus id, vendor id, and product id and returns a dictionary
# with the required hid_driver and usb_interface and whether this is a receiver or device.
def _match(action, device, filterfn):
hid_device = device.find_parent('hid')
if not hid_device:
return
hid_id = hid_device.get('HID_ID')
if not hid_id:
return # there are reports that sometimes the id isn't set up right so be defensive
bid, vid, pid = hid_id.split(':')
vid = usb_device.get('ID_VENDOR_ID')
pid = usb_device.get('ID_MODEL_ID')
if not ((vendor_id is None or vendor_id == int(vid, 16)) and
(product_id is None or product_id == int(pid, 16))):
return
filter = filterfn(int(bid, 16), int(vid, 16), int(pid, 16))
if not filter:
return
if action == 'add':
hid_device = device.find_parent('hid')
if not hid_device:
return
hid_driver_name = hid_device.get('DRIVER')
# print ("** found hid", action, device, "hid:", hid_device, hid_driver_name)
if hid_driver:
if isinstance(hid_driver, tuple):
if hid_driver_name not in hid_driver:
return
elif hid_driver_name != hid_driver:
return
hid_driver = filter.get('hid_driver')
interface_number = filter.get('usb_interface')
isDevice = filter.get('isDevice')
intf_device = device.find_parent('usb', 'usb_interface')
# print ("*** usb interface", action, device, "usb_interface:", intf_device)
if interface_number is None:
usb_interface = None if intf_device is None else intf_device.attributes.asint('bInterfaceNumber')
else:
usb_interface = None if intf_device is None else intf_device.attributes.asint('bInterfaceNumber')
if usb_interface is None or interface_number != usb_interface:
return
if action == 'add':
hid_driver_name = hid_device.get('DRIVER')
# print ("** found hid", action, device, "hid:", hid_device, hid_driver_name)
if hid_driver:
if isinstance(hid_driver, tuple):
if hid_driver_name not in hid_driver:
return
elif hid_driver_name != hid_driver:
return
attrs = usb_device.attributes
d_info = DeviceInfo(path=device.device_node,
vendor_id=vid[-4:],
product_id=pid[-4:],
serial=hid_device.get('HID_UNIQ'),
release=attrs.get('bcdDevice'),
manufacturer=attrs.get('manufacturer'),
product=attrs.get('product'),
interface=usb_interface,
driver=hid_driver_name)
return d_info
intf_device = device.find_parent('usb', 'usb_interface')
# print ("*** usb interface", action, device, "usb_interface:", intf_device)
usb_interface = None if intf_device is None else intf_device.attributes.asint('bInterfaceNumber')
if _log.isEnabledFor(_DEBUG):
_log.debug(
'Found device BID %s VID %s PID %s INTERFACE %s FILTER %s', bid, vid, pid, usb_interface, interface_number
)
if not (interface_number is None or interface_number == usb_interface):
return
attrs = intf_device.attributes if intf_device else None
elif action == 'remove':
# print (dict(device), dict(usb_device))
d_info = DeviceInfo(
path=device.device_node,
bus_id=int(bid, 16),
vendor_id=vid[-4:],
product_id=pid[-4:],
driver=hid_driver_name,
interface=usb_interface,
isDevice=isDevice,
serial=hid_device.get('HID_UNIQ'),
release=attrs.get('bcdDevice') if attrs else None,
manufacturer=attrs.get('manufacturer') if attrs else None,
product=attrs.get('product') if attrs else None
)
return d_info
d_info = DeviceInfo(path=device.device_node,
vendor_id=vid[-4:],
product_id=pid[-4:],
serial=None,
release=None,
manufacturer=None,
product=None,
interface=None,
driver=None)
return d_info
elif action == 'remove':
# print (dict(device), dict(usb_device))
d_info = DeviceInfo(
path=device.device_node,
bus_id=None,
vendor_id=vid[-4:],
product_id=pid[-4:],
driver=None,
interface=None,
isDevice=isDevice,
serial=None,
release=None,
manufacturer=None,
product=None
)
return d_info
def monitor_glib(callback, *device_filters):
from gi.repository import GLib
def find_paired_node(receiver_path, index, timeout):
"""Find the node of a device paired with a receiver"""
context = _Context()
receiver_phys = _Devices.from_device_file(context, receiver_path).find_parent('hid').get('HID_PHYS')
c = _Context()
if not receiver_phys:
return None
# already existing devices
# for device in c.list_devices(subsystem='hidraw'):
# # print (device, dict(device), dict(device.attributes))
# for filter in device_filters:
# d_info = _match('add', device, *filter)
# if d_info:
# GLib.idle_add(callback, 'add', d_info)
# break
phys = f'{receiver_phys}:{index}'
timeout += _timestamp()
delta = _timestamp()
while delta < timeout:
for dev in context.list_devices(subsystem='hidraw'):
dev_phys = dev.find_parent('hid').get('HID_PHYS')
if dev_phys and dev_phys == phys:
return dev.device_node
delta = _timestamp()
m = _Monitor.from_netlink(c)
m.filter_by(subsystem='hidraw')
def _process_udev_event(monitor, condition, cb, filters):
if condition == GLib.IO_IN:
event = monitor.receive_device()
if event:
action, device = event
# print ("***", action, device)
if action == 'add':
for filter in filters:
d_info = _match(action, device, *filter)
if d_info:
GLib.idle_add(cb, action, d_info)
break
elif action == 'remove':
# the GLib notification does _not_ match!
pass
return True
try:
# io_add_watch_full may not be available...
GLib.io_add_watch_full(m, GLib.PRIORITY_LOW, GLib.IO_IN, _process_udev_event, callback, device_filters)
# print ("did io_add_watch_full")
except AttributeError:
try:
# and the priority parameter appeared later in the API
GLib.io_add_watch(m, GLib.PRIORITY_LOW, GLib.IO_IN, _process_udev_event, callback, device_filters)
# print ("did io_add_watch with priority")
except:
GLib.io_add_watch(m, GLib.IO_IN, _process_udev_event, callback, device_filters)
# print ("did io_add_watch")
m.start()
return None
def enumerate(vendor_id=None, product_id=None, interface_number=None, hid_driver=None):
"""Enumerate the HID Devices.
def find_paired_node_wpid(receiver_path, index):
"""Find the node of a device paired with a receiver, get wpid from udev"""
context = _Context()
receiver_phys = _Devices.from_device_file(context, receiver_path).find_parent('hid').get('HID_PHYS')
List all the HID devices attached to the system, optionally filtering by
vendor_id, product_id, and/or interface_number.
if not receiver_phys:
return None
:returns: a list of matching ``DeviceInfo`` tuples.
"""
for dev in _Context().list_devices(subsystem='hidraw'):
dev_info = _match('add', dev, vendor_id, product_id, interface_number, hid_driver)
if dev_info:
yield dev_info
phys = f'{receiver_phys}:{index}'
for dev in context.list_devices(subsystem='hidraw'):
dev_phys = dev.find_parent('hid').get('HID_PHYS')
if dev_phys and dev_phys == phys:
# get hid id like 0003:0000046D:00000065
hid_id = dev.find_parent('hid').get('HID_ID')
# get wpid - last 4 symbols
udev_wpid = hid_id[-4:]
return udev_wpid
return None
def monitor_glib(callback, filterfn):
from gi.repository import GLib
c = _Context()
# already existing devices
# for device in c.list_devices(subsystem='hidraw'):
# # print (device, dict(device), dict(device.attributes))
# for filter in device_filters:
# d_info = _match('add', device, *filter)
# if d_info:
# GLib.idle_add(callback, 'add', d_info)
# break
m = _Monitor.from_netlink(c)
m.filter_by(subsystem='hidraw')
def _process_udev_event(monitor, condition, cb, filterfn):
if condition == GLib.IO_IN:
event = monitor.receive_device()
if event:
action, device = event
# print ("***", action, device)
if action == 'add':
d_info = _match(action, device, filterfn)
if d_info:
GLib.idle_add(cb, action, d_info)
elif action == 'remove':
# the GLib notification does _not_ match!
pass
return True
try:
# io_add_watch_full may not be available...
GLib.io_add_watch_full(m, GLib.PRIORITY_LOW, GLib.IO_IN, _process_udev_event, callback, filterfn)
# print ("did io_add_watch_full")
except AttributeError:
try:
# and the priority parameter appeared later in the API
GLib.io_add_watch(m, GLib.PRIORITY_LOW, GLib.IO_IN, _process_udev_event, callback, filterfn)
# print ("did io_add_watch with priority")
except Exception:
GLib.io_add_watch(m, GLib.IO_IN, _process_udev_event, callback, filterfn)
# print ("did io_add_watch")
m.start()
def enumerate(filterfn):
"""Enumerate the HID Devices.
List all the HID devices attached to the system, optionally filtering by
vendor_id, product_id, and/or interface_number.
:returns: a list of matching ``DeviceInfo`` tuples.
"""
for dev in _Context().list_devices(subsystem='hidraw'):
dev_info = _match('add', dev, filterfn)
if dev_info:
yield dev_info
def open(vendor_id, product_id, serial=None):
"""Open a HID device by its Vendor ID, Product ID and optional serial number.
"""Open a HID device by its Vendor ID, Product ID and optional serial number.
If no serial is provided, the first device with the specified IDs is opened.
If no serial is provided, the first device with the specified IDs is opened.
:returns: an opaque device handle, or ``None``.
"""
for device in enumerate(vendor_id, product_id):
if serial is None or serial == device.serial:
return open_path(device.path)
:returns: an opaque device handle, or ``None``.
"""
def matchfn(bid, vid, pid):
return vid == vendor_id and pid == product_id
for device in enumerate(matchfn):
if serial is None or serial == device.serial:
return open_path(device.path)
def open_path(device_path):
"""Open a HID device by its path name.
"""Open a HID device by its path name.
:param device_path: the path of a ``DeviceInfo`` tuple returned by
enumerate().
:param device_path: the path of a ``DeviceInfo`` tuple returned by enumerate().
:returns: an opaque device handle, or ``None``.
"""
assert device_path
assert device_path.startswith('/dev/hidraw')
return _os.open(device_path, _os.O_RDWR | _os.O_SYNC)
:returns: an opaque device handle, or ``None``.
"""
assert device_path
assert device_path.startswith('/dev/hidraw')
return _os.open(device_path, _os.O_RDWR | _os.O_SYNC)
def close(device_handle):
"""Close a HID device.
"""Close a HID device.
:param device_handle: a device handle returned by open() or open_path().
"""
assert device_handle
_os.close(device_handle)
:param device_handle: a device handle returned by open() or open_path().
"""
assert device_handle
_os.close(device_handle)
def write(device_handle, data):
"""Write an Output report to a HID device.
"""Write an Output report to a HID device.
:param device_handle: a device handle returned by open() or open_path().
:param data: the data bytes to send including the report number as the
first byte.
:param device_handle: a device handle returned by open() or open_path().
:param data: the data bytes to send including the report number as the
first byte.
The first byte of data[] must contain the Report ID. For
devices which only support a single report, this must be set
to 0x0. The remaining bytes contain the report data. Since
the Report ID is mandatory, calls to hid_write() will always
contain one more byte than the report contains. For example,
if a hid report is 16 bytes long, 17 bytes must be passed to
hid_write(), the Report ID (or 0x0, for devices with a
single report), followed by the report data (16 bytes). In
this example, the length passed in would be 17.
The first byte of data[] must contain the Report ID. For
devices which only support a single report, this must be set
to 0x0. The remaining bytes contain the report data. Since
the Report ID is mandatory, calls to hid_write() will always
contain one more byte than the report contains. For example,
if a hid report is 16 bytes long, 17 bytes must be passed to
hid_write(), the Report ID (or 0x0, for devices with a
single report), followed by the report data (16 bytes). In
this example, the length passed in would be 17.
write() will send the data on the first OUT endpoint, if
one exists. If it does not, it will send the data through
the Control Endpoint (Endpoint 0).
"""
assert device_handle
assert data
assert isinstance(data, bytes), (repr(data), type(data))
bytes_written = _os.write(device_handle, data)
if bytes_written != len(data):
raise IOError(_errno.EIO, 'written %d bytes out of expected %d' % (bytes_written, len(data)))
write() will send the data on the first OUT endpoint, if
one exists. If it does not, it will send the data through
the Control Endpoint (Endpoint 0).
"""
assert device_handle
assert data
assert isinstance(data, bytes), (repr(data), type(data))
retrycount = 0
bytes_written = 0
while (retrycount < 3):
try:
retrycount += 1
bytes_written = _os.write(device_handle, data)
except IOError as e:
if e.errno == _errno.EPIPE:
sleep(0.1)
else:
break
if bytes_written != len(data):
raise IOError(_errno.EIO, 'written %d bytes out of expected %d' % (bytes_written, len(data)))
def read(device_handle, bytes_count, timeout_ms=-1):
"""Read an Input report from a HID device.
"""Read an Input report from a HID device.
:param device_handle: a device handle returned by open() or open_path().
:param bytes_count: maximum number of bytes to read.
:param timeout_ms: can be -1 (default) to wait for data indefinitely, 0 to
read whatever is in the device's input buffer, or a positive integer to
wait that many milliseconds.
:param device_handle: a device handle returned by open() or open_path().
:param bytes_count: maximum number of bytes to read.
:param timeout_ms: can be -1 (default) to wait for data indefinitely, 0 to
read whatever is in the device's input buffer, or a positive integer to
wait that many milliseconds.
Input reports are returned to the host through the INTERRUPT IN endpoint.
The first byte will contain the Report number if the device uses numbered
reports.
Input reports are returned to the host through the INTERRUPT IN endpoint.
The first byte will contain the Report number if the device uses numbered
reports.
:returns: the data packet read, an empty bytes string if a timeout was
reached, or None if there was an error while reading.
"""
assert device_handle
timeout = None if timeout_ms < 0 else timeout_ms / 1000.0
rlist, wlist, xlist = _select([device_handle], [], [device_handle], timeout)
:returns: the data packet read, an empty bytes string if a timeout was
reached, or None if there was an error while reading.
"""
assert device_handle
timeout = None if timeout_ms < 0 else timeout_ms / 1000.0
rlist, wlist, xlist = _select([device_handle], [], [device_handle], timeout)
if xlist:
assert xlist == [device_handle]
raise IOError(_errno.EIO, 'exception on file descriptor %d' % device_handle)
if xlist:
assert xlist == [device_handle]
raise IOError(_errno.EIO, 'exception on file descriptor %d' % device_handle)
if rlist:
assert rlist == [device_handle]
data = _os.read(device_handle, bytes_count)
assert data is not None
assert isinstance(data, bytes), (repr(data), type(data))
return data
else:
return b''
if rlist:
assert rlist == [device_handle]
data = _os.read(device_handle, bytes_count)
assert data is not None
assert isinstance(data, bytes), (repr(data), type(data))
return data
else:
return b''
_DEVICE_STRINGS = {
0: 'manufacturer',
1: 'product',
2: 'serial',
0: 'manufacturer',
1: 'product',
2: 'serial',
}
def get_manufacturer(device_handle):
"""Get the Manufacturer String from a HID device.
"""Get the Manufacturer String from a HID device.
:param device_handle: a device handle returned by open() or open_path().
"""
return get_indexed_string(device_handle, 0)
:param device_handle: a device handle returned by open() or open_path().
"""
return get_indexed_string(device_handle, 0)
def get_product(device_handle):
"""Get the Product String from a HID device.
"""Get the Product String from a HID device.
:param device_handle: a device handle returned by open() or open_path().
"""
return get_indexed_string(device_handle, 1)
:param device_handle: a device handle returned by open() or open_path().
"""
return get_indexed_string(device_handle, 1)
def get_serial(device_handle):
"""Get the serial number from a HID device.
"""Get the serial number from a HID device.
:param device_handle: a device handle returned by open() or open_path().
"""
serial = get_indexed_string(device_handle, 2)
if serial is not None:
return ''.join(hex(ord(c)) for c in serial)
:param device_handle: a device handle returned by open() or open_path().
"""
serial = get_indexed_string(device_handle, 2)
return serial
def get_indexed_string(device_handle, index):
"""Get a string from a HID device, based on its string index.
"""Get a string from a HID device, based on its string index.
Note: currently not working in the ``hidraw`` native implementation.
Note: currently not working in the ``hidraw`` native implementation.
:param device_handle: a device handle returned by open() or open_path().
:param index: the index of the string to get.
"""
if index not in _DEVICE_STRINGS:
return None
:param device_handle: a device handle returned by open() or open_path().
:param index: the index of the string to get.
:returns: the value corresponding to index, or None if no value found
:rtype: bytes or NoneType
"""
try:
key = _DEVICE_STRINGS[index]
except KeyError:
return None
assert device_handle
stat = _os.fstat(device_handle)
dev = _Device.from_device_number(_Context(), 'char', stat.st_rdev)
if dev:
hid_dev = dev.find_parent('hid')
if hid_dev:
assert 'HID_ID' in hid_dev
bus, _ignore, _ignore = hid_dev['HID_ID'].split(':')
assert device_handle
stat = _os.fstat(device_handle)
try:
dev = _Device.from_device_number(_Context(), 'char', stat.st_rdev)
except (DeviceNotFoundError, ValueError):
return None
if bus == '0003': # USB
usb_dev = dev.find_parent('usb', 'usb_device')
assert usb_dev
key = _DEVICE_STRINGS[index]
attrs = usb_dev.attributes
if key in attrs:
return attrs[key]
hid_dev = dev.find_parent('hid')
if hid_dev:
assert 'HID_ID' in hid_dev
bus, _ignore, _ignore = hid_dev['HID_ID'].split(':')
elif bus == '0005': # BLUETOOTH
# TODO
pass
if bus == '0003': # USB
usb_dev = dev.find_parent('usb', 'usb_device')
assert usb_dev
return usb_dev.attributes.get(key)
elif bus == '0005': # BLUETOOTH
# TODO
pass

View File

@@ -16,7 +16,6 @@
## You should have received a copy of the GNU General Public License along
## with this program; if not, write to the Free Software Foundation, Inc.,
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
"""Low-level interface for devices connected through a Logitech Universal
Receiver (UR).
@@ -34,23 +33,20 @@ from __future__ import absolute_import, division, print_function, unicode_litera
import logging
from . import listener, status # noqa: F401
from .base import DeviceUnreachable, NoReceiver, NoSuchDevice # noqa: F401
from .common import strhex # noqa: F401
from .device import Device # noqa: F401
from .hidpp20 import FeatureCallError, FeatureNotSupported # noqa: F401
from .receiver import Receiver # noqa: F401
_DEBUG = logging.DEBUG
_log = logging.getLogger(__name__)
_log.setLevel(logging.root.level)
# if logging.root.level > logging.DEBUG:
# _log.addHandler(logging.NullHandler())
# _log.propagate = 0
# _log.addHandler(logging.NullHandler())
# _log.propagate = 0
del logging
__version__ = '0.9'
from .common import strhex
from .base import NoReceiver, NoSuchDevice, DeviceUnreachable
from .receiver import Receiver, PairedDevice
from .hidpp20 import FeatureNotSupported, FeatureCallError
from . import listener
from . import status

View File

@@ -22,18 +22,29 @@
from __future__ import absolute_import, division, print_function, unicode_literals
from time import time as _timestamp
import threading as _threading
from collections import namedtuple
from contextlib import contextmanager
from logging import DEBUG as _DEBUG
from logging import INFO as _INFO
from logging import getLogger
from random import getrandbits as _random_bits
from time import time as _timestamp
from logging import getLogger, DEBUG as _DEBUG
_log = getLogger(__name__)
del getLogger
import hidapi as _hid
from .common import strhex as _strhex, KwException as _KwException, pack as _pack
from . import hidpp10 as _hidpp10
from . import hidpp20 as _hidpp20
import hidapi as _hid
from .base_usb import ALL as _RECEIVER_USB_IDS
from .base_usb import DEVICES as _DEVICE_IDS
from .base_usb import other_device_check as _other_device_check
from .common import KwException as _KwException
from .common import pack as _pack
from .common import strhex as _strhex
_log = getLogger(__name__)
del getLogger
#
#
@@ -44,6 +55,17 @@ _LONG_MESSAGE_SIZE = 20
_MEDIUM_MESSAGE_SIZE = 15
_MAX_READ_SIZE = 32
HIDPP_SHORT_MESSAGE_ID = 0x10
HIDPP_LONG_MESSAGE_ID = 0x11
DJ_MESSAGE_ID = 0x20
# mapping from report_id to message length
report_lengths = {
HIDPP_SHORT_MESSAGE_ID: _SHORT_MESSAGE_SIZE,
HIDPP_LONG_MESSAGE_ID: _LONG_MESSAGE_SIZE,
DJ_MESSAGE_ID: _MEDIUM_MESSAGE_SIZE,
0x21: _MAX_READ_SIZE
}
"""Default timeout on read (in seconds)."""
DEFAULT_TIMEOUT = 4
# the receiver itself should reply very fast, within 500ms
@@ -57,239 +79,274 @@ _PING_TIMEOUT = DEFAULT_TIMEOUT * 2
# Exceptions that may be raised by this API.
#
class NoReceiver(_KwException):
"""Raised when trying to talk through a previously open handle, when the
receiver is no longer available. Should only happen if the receiver is
physically disconnected from the machine, or its kernel driver module is
unloaded."""
pass
"""Raised when trying to talk through a previously open handle, when the
receiver is no longer available. Should only happen if the receiver is
physically disconnected from the machine, or its kernel driver module is
unloaded."""
pass
class NoSuchDevice(_KwException):
"""Raised when trying to reach a device number not paired to the receiver."""
pass
"""Raised when trying to reach a device number not paired to the receiver."""
pass
class DeviceUnreachable(_KwException):
"""Raised when a request is made to an unreachable (turned off) device."""
pass
"""Raised when a request is made to an unreachable (turned off) device."""
pass
#
#
#
from .base_usb import ALL as _RECEIVER_USB_IDS
def match(record, bus_id, vendor_id, product_id):
return ((record.get('bus_id') is None or record.get('bus_id') == bus_id)
and (record.get('vendor_id') is None or record.get('vendor_id') == vendor_id)
and (record.get('product_id') is None or record.get('product_id') == product_id))
def filter_receivers(bus_id, vendor_id, product_id):
"""Check that this product is a Logitech receiver and if so return the receiver record for further checking"""
for record in _RECEIVER_USB_IDS: # known receivers
if match(record, bus_id, vendor_id, product_id):
return record
def receivers():
"""List all the Linux devices exposed by the UR attached to the machine."""
for receiver_usb_id in _RECEIVER_USB_IDS:
for d in _hid.enumerate(*receiver_usb_id):
yield d
"""Enumerate all the receivers attached to the machine."""
for dev in _hid.enumerate(filter_receivers):
yield dev
def filter_devices(bus_id, vendor_id, product_id):
"""Check that this product is of interest and if so return the device record for further checking"""
for record in _DEVICE_IDS: # known devices
if match(record, bus_id, vendor_id, product_id):
return record
return _other_device_check(bus_id, vendor_id, product_id) # USB and BT devices unknown to Solaar
def wired_devices():
"""Enumerate all the USB-connected and Bluetooth devices attached to the machine."""
for dev in _hid.enumerate(filter_devices):
yield dev
def filter_either(bus_id, vendor_id, product_id):
return filter_receivers(bus_id, vendor_id, product_id) or filter_devices(bus_id, vendor_id, product_id)
def notify_on_receivers_glib(callback):
"""Watch for matching devices and notifies the callback on the GLib thread."""
_hid.monitor_glib(callback, *_RECEIVER_USB_IDS)
"""Watch for matching devices and notifies the callback on the GLib thread."""
return _hid.monitor_glib(callback, filter_either)
#
#
#
def open_path(path):
"""Checks if the given Linux device path points to the right UR device.
"""Checks if the given Linux device path points to the right UR device.
:param path: the Linux device path.
:param path: the Linux device path.
The UR physical device may expose multiple linux devices with the same
interface, so we have to check for the right one. At this moment the only
way to distinguish betheen them is to do a test ping on an invalid
(attached) device number (i.e., 0), expecting a 'ping failed' reply.
The UR physical device may expose multiple linux devices with the same
interface, so we have to check for the right one. At this moment the only
way to distinguish betheen them is to do a test ping on an invalid
(attached) device number (i.e., 0), expecting a 'ping failed' reply.
:returns: an open receiver handle if this is the right Linux device, or
``None``.
"""
return _hid.open_path(path)
:returns: an open receiver handle if this is the right Linux device, or
``None``.
"""
return _hid.open_path(path)
def open():
"""Opens the first Logitech Unifying Receiver found attached to the machine.
"""Opens the first Logitech Unifying Receiver found attached to the machine.
:returns: An open file handle for the found receiver, or ``None``.
"""
for rawdevice in receivers():
handle = open_path(rawdevice.path)
if handle:
return handle
:returns: An open file handle for the found receiver, or ``None``.
"""
for rawdevice in receivers():
handle = open_path(rawdevice.path)
if handle:
return handle
def close(handle):
"""Closes a HID device handle."""
if handle:
try:
if isinstance(handle, int):
_hid.close(handle)
else:
handle.close()
# _log.info("closed receiver handle %r", handle)
return True
except:
# _log.exception("closing receiver handle %r", handle)
pass
"""Closes a HID device handle."""
if handle:
try:
if isinstance(handle, int):
_hid.close(handle)
else:
handle.close()
# _log.info("closed receiver handle %r", handle)
return True
except Exception:
# _log.exception("closing receiver handle %r", handle)
pass
return False
return False
def write(handle, devnumber, data):
"""Writes some data to the receiver, addressed to a certain device.
def write(handle, devnumber, data, long_message=False):
"""Writes some data to the receiver, addressed to a certain device.
:param handle: an open UR handle.
:param devnumber: attached device number.
:param data: data to send, up to 5 bytes.
:param handle: an open UR handle.
:param devnumber: attached device number.
:param data: data to send, up to 5 bytes.
The first two (required) bytes of data must be the SubId and address.
The first two (required) bytes of data must be the SubId and address.
:raises NoReceiver: if the receiver is no longer available, i.e. has
been physically removed from the machine, or the kernel driver has been
unloaded. The handle will be closed automatically.
"""
# the data is padded to either 5 or 18 bytes
assert data is not None
assert isinstance(data, bytes), (repr(data), type(data))
:raises NoReceiver: if the receiver is no longer available, i.e. has
been physically removed from the machine, or the kernel driver has been
unloaded. The handle will be closed automatically.
"""
# the data is padded to either 5 or 18 bytes
assert data is not None
assert isinstance(data, bytes), (repr(data), type(data))
if len(data) > _SHORT_MESSAGE_SIZE - 2 or data[:1] == b'\x82':
wdata = _pack('!BB18s', 0x11, 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]), devnumber, _strhex(wdata[2:4]), _strhex(wdata[4:]))
if long_message or len(data) > _SHORT_MESSAGE_SIZE - 2 or data[:1] == b'\x82':
wdata = _pack('!BB18s', HIDPP_LONG_MESSAGE_ID, devnumber, data)
else:
wdata = _pack('!BB5s', HIDPP_SHORT_MESSAGE_ID, devnumber, data)
if _log.isEnabledFor(_DEBUG):
_log.debug('(%s) <= w[%02X %02X %s %s]', handle, ord(wdata[:1]), devnumber, _strhex(wdata[2:4]), _strhex(wdata[4:]))
try:
_hid.write(int(handle), wdata)
except Exception as reason:
_log.error("write failed, assuming handle %r no longer available", handle)
close(handle)
raise NoReceiver(reason=reason)
try:
_hid.write(int(handle), wdata)
except Exception as reason:
_log.error('write failed, assuming handle %r no longer available', handle)
close(handle)
raise NoReceiver(reason=reason)
def read(handle, timeout=DEFAULT_TIMEOUT):
"""Read some data from the receiver. Usually called after a write (feature
call), to get the reply.
"""Read some data from the receiver. Usually called after a write (feature
call), to get the reply.
:param: handle open handle to the receiver
:param: timeout how long to wait for a reply, in seconds
:param: handle open handle to the receiver
:param: timeout how long to wait for a reply, in seconds
:returns: a tuple of (devnumber, message data), or `None`
:returns: a tuple of (devnumber, message data), or `None`
:raises NoReceiver: if the receiver is no longer available, i.e. has
been physically removed from the machine, or the kernel driver has been
unloaded. The handle will be closed automatically.
"""
reply = _read(handle, timeout)
if reply:
return reply[1:]
:raises NoReceiver: if the receiver is no longer available, i.e. has
been physically removed from the machine, or the kernel driver has been
unloaded. The handle will be closed automatically.
"""
reply = _read(handle, timeout)
if reply:
return reply
# sanity checks on message report id and size
def check_message(data):
assert isinstance(data, bytes), (repr(data), type(data))
report_id = ord(data[:1])
if report_id in report_lengths: # is this an HID++ or DJ message?
if report_lengths.get(report_id) == len(data):
return True
else:
_log.warn('unexpected message size: report_id %02X message %s' % (report_id, _strhex(data)))
return False
def _read(handle, timeout):
"""Read an incoming packet from the receiver.
"""Read an incoming packet from the receiver.
:returns: a tuple of (report_id, devnumber, data), or `None`.
:returns: a tuple of (report_id, devnumber, data), or `None`.
:raises NoReceiver: if the receiver is no longer available, i.e. has
been physically removed from the machine, or the kernel driver has been
unloaded. The handle will be closed automatically.
"""
try:
# convert timeout to milliseconds, the hidapi expects it
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", handle)
close(handle)
raise NoReceiver(reason=reason)
:raises NoReceiver: if the receiver is no longer available, i.e. has
been physically removed from the machine, or the kernel driver has been
unloaded. The handle will be closed automatically.
"""
try:
# convert timeout to milliseconds, the hidapi expects it
timeout = int(timeout * 1000)
data = _hid.read(int(handle), _MAX_READ_SIZE, timeout)
except Exception as reason:
_log.warn('read failed, assuming handle %r no longer available', handle)
close(handle)
raise NoReceiver(reason=reason)
if data:
assert isinstance(data, bytes), (repr(data), type(data))
report_id = ord(data[:1])
assert ((report_id & 0xF0 == 0) or
(report_id == 0x10 and len(data) == _SHORT_MESSAGE_SIZE) or
(report_id == 0x11 and len(data) == _LONG_MESSAGE_SIZE) or
(report_id == 0x20 and len(data) == _MEDIUM_MESSAGE_SIZE)), \
"unexpected message size: report_id %02X message %s" % (report_id, _strhex(data))
if report_id & 0xF0 == 0x00:
if _log.isEnabledFor(_DEBUG):
_log.debug("(%s) => r[%02X %s] ignoring unknown report", handle, report_id, _strhex(data[1:]))
return
devnumber = ord(data[1:2])
if data and check_message(data): # ignore messages that fail check
report_id = ord(data[:1])
devnumber = ord(data[1:2])
if _log.isEnabledFor(_DEBUG):
_log.debug("(%s) => r[%02X %02X %s %s]", handle, report_id, devnumber, _strhex(data[2:4]), _strhex(data[4:]))
if _log.isEnabledFor(_DEBUG):
_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:]
return report_id, devnumber, data[2:]
#
#
#
def _skip_incoming(handle, ihandle, notifications_hook):
"""Read anything already in the input buffer.
"""Read anything already in the input buffer.
Used by request() and ping() before their write.
"""
Used by request() and ping() before their write.
"""
while True:
try:
# 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", handle)
close(handle)
raise NoReceiver(reason=reason)
while True:
try:
# 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', handle)
close(handle)
raise NoReceiver(reason=reason)
if data:
assert isinstance(data, bytes), (repr(data), type(data))
report_id = ord(data[:1])
if _log.isEnabledFor(_DEBUG):
assert ((report_id & 0xF0 == 0) or
(report_id == 0x10 and len(data) == _SHORT_MESSAGE_SIZE) or
(report_id == 0x11 and len(data) == _LONG_MESSAGE_SIZE) or
(report_id == 0x20 and len(data) == _MEDIUM_MESSAGE_SIZE)), \
"unexpected message size: report_id %02X message %s" % (report_id, _strhex(data))
if notifications_hook and report_id & 0xF0:
n = make_notification(ord(data[1:2]), data[2:])
if n:
notifications_hook(n)
else:
# nothing in the input buffer, we're done
return
if data:
if check_message(data): # only process messages that pass check
# report_id = ord(data[:1])
if notifications_hook:
n = make_notification(ord(data[:1]), ord(data[1:2]), data[2:])
if n:
notifications_hook(n)
else:
# nothing in the input buffer, we're done
return
def make_notification(devnumber, data):
"""Guess if this is a notification (and not just a request reply), and
return a Notification tuple if it is."""
sub_id = ord(data[:1])
if sub_id & 0x80 == 0x80:
# this is either a HID++1.0 register r/w, or an error reply
return
def make_notification(report_id, devnumber, data):
"""Guess if this is a notification (and not just a request reply), and
return a Notification tuple if it is."""
address = ord(data[1:2])
if (
# standard HID++ 1.0 notification, SubId may be 0x40 - 0x7F
(sub_id >= 0x40)
or
# custom HID++1.0 battery events, where SubId is 0x07/0x0D
(sub_id in (0x07, 0x0D) and len(data) == 5 and data[4:5] == b'\x00')
or
# custom HID++1.0 illumination event, where SubId is 0x17
(sub_id == 0x17 and len(data) == 5)
or
# HID++ 2.0 feature notifications have the SoftwareID 0
(address & 0x0F == 0x00)
):
return _HIDPP_Notification(devnumber, sub_id, address, data[2:])
sub_id = ord(data[:1])
if sub_id & 0x80 == 0x80:
# this is either a HID++1.0 register r/w, or an error reply
return
from collections import namedtuple
_HIDPP_Notification = namedtuple('_HIDPP_Notification', ('devnumber', 'sub_id', 'address', 'data'))
_HIDPP_Notification.__str__ = lambda self: 'Notification(%d,%02X,%02X,%s)' % (self.devnumber, self.sub_id, self.address, _strhex(self.data))
# DJ input records are not notifications
if report_id == DJ_MESSAGE_ID and (sub_id < 0x10):
return
address = ord(data[1:2])
if (
# standard HID++ 1.0 notification, SubId may be 0x40 - 0x7F
(sub_id >= 0x40) or # noqa: E131
# custom HID++1.0 battery events, where SubId is 0x07/0x0D
(sub_id in (0x07, 0x0D) and len(data) == 5 and data[4:5] == b'\x00') or
# custom HID++1.0 illumination event, where SubId is 0x17
(sub_id == 0x17 and len(data) == 5) or
# HID++ 2.0 feature notifications have the SoftwareID 0
(address & 0x0F == 0x00)
): # noqa: E129
return _HIDPP_Notification(report_id, devnumber, sub_id, address, data[2:])
_HIDPP_Notification = namedtuple('_HIDPP_Notification', ('report_id', 'devnumber', 'sub_id', 'address', 'data'))
_HIDPP_Notification.__str__ = lambda self: 'Notification(%02x,%d,%02X,%02X,%s)' % (
self.report_id, self.devnumber, self.sub_id, self.address, _strhex(self.data)
)
_HIDPP_Notification.__unicode__ = _HIDPP_Notification.__str__
del namedtuple
@@ -297,186 +354,220 @@ del namedtuple
#
#
def request(handle, devnumber, request_id, *params):
"""Makes a feature call to a device and waits for a matching reply.
This function will wait for a matching reply indefinitely.
:param handle: an open UR handle.
:param devnumber: attached device number.
:param request_id: a 16-bit integer.
:param params: parameters for the feature call, 3 to 16 bytes.
:returns: the reply data, or ``None`` if some error occured.
"""
# import inspect as _inspect
# print ('\n '.join(str(s) for s in _inspect.stack()))
assert isinstance(request_id, int)
if devnumber != 0xFF and request_id < 0x8000:
# For HID++ 2.0 feature requests, randomize the SoftwareId to make it
# easier to recognize the reply for this request. also, always set the
# most significant bit (8) in SoftwareId, to make notifications easier
# to distinguish from request replies.
# This only applies to peripheral requests, ofc.
request_id = (request_id & 0xFFF0) | 0x08 | _random_bits(3)
timeout = _RECEIVER_REQUEST_TIMEOUT if devnumber == 0xFF else _DEVICE_REQUEST_TIMEOUT
# be extra patient on long register read
if request_id & 0xFF00 == 0x8300:
timeout *= 2
if params:
params = b''.join(_pack('B', p) if isinstance(p, int) else p for p in params)
else:
params = b''
# if _log.isEnabledFor(_DEBUG):
# _log.debug("(%s) device %d request_id {%04X} params [%s]", handle, devnumber, request_id, _strhex(params))
request_data = _pack('!H', request_id) + params
ihandle = int(handle)
notifications_hook = getattr(handle, 'notifications_hook', None)
_skip_incoming(handle, ihandle, notifications_hook)
write(ihandle, devnumber, request_data)
# we consider timeout from this point
request_started = _timestamp()
delta = 0
while delta < timeout:
reply = _read(handle, timeout)
if reply:
report_id, reply_devnumber, reply_data = reply
if reply_devnumber == devnumber:
if report_id == 0x10 and reply_data[:1] == b'\x8F' and reply_data[1:3] == request_data[:2]:
error = ord(reply_data[3:4])
# if error == _hidpp10.ERROR.resource_error: # device unreachable
# _log.warn("(%s) device %d error on request {%04X}: unknown device", handle, devnumber, request_id)
# raise DeviceUnreachable(number=devnumber, request=request_id)
# if error == _hidpp10.ERROR.unknown_device: # unknown device
# _log.error("(%s) device %d error on request {%04X}: unknown device", handle, devnumber, request_id)
# raise NoSuchDevice(number=devnumber, request=request_id)
if _log.isEnabledFor(_DEBUG):
_log.debug("(%s) device 0x%02X error on request {%04X}: %d = %s",
handle, devnumber, request_id, error, _hidpp10.ERROR[error])
return
if reply_data[:1] == b'\xFF' and reply_data[1:3] == request_data[:2]:
# 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",
handle, devnumber, request_id, error, _hidpp20.ERROR[error])
raise _hidpp20.FeatureCallError(number=devnumber, request=request_id, error=error, params=params)
if reply_data[:2] == request_data[:2]:
if request_id & 0xFE00 == 0x8200:
# long registry r/w should return a long reply
assert report_id == 0x11
elif request_id & 0xFE00 == 0x8000:
# short registry r/w should return a short reply
assert report_id == 0x10
if devnumber == 0xFF:
if request_id == 0x83B5 or request_id == 0x81F1:
# these replies have to match the first parameter as well
if reply_data[2:3] == params[:1]:
return reply_data[2:]
else:
# hm, not mathing my request, and certainly not a notification
continue
else:
return reply_data[2:]
else:
return reply_data[2:]
else:
# a reply was received, but did not match our request in any way
# reset the timeout starting point
request_started = _timestamp()
if notifications_hook:
n = make_notification(reply_devnumber, reply_data)
if n:
notifications_hook(n)
# elif _log.isEnabledFor(_DEBUG):
# _log.debug("(%s) ignoring reply %02X [%s]", handle, reply_devnumber, _strhex(reply_data))
# elif _log.isEnabledFor(_DEBUG):
# _log.debug("(%s) ignoring reply %02X [%s]", handle, reply_devnumber, _strhex(reply_data))
delta = _timestamp() - request_started
# 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]",
delta, timeout, devnumber, request_id, _strhex(params))
# raise DeviceUnreachable(number=devnumber, request=request_id)
request_lock = _threading.Lock() # serialize all requests
handles_lock = {}
def ping(handle, devnumber):
"""Check if a device is connected to the receiver.
def handle_lock(handle):
with request_lock:
if handles_lock.get(handle) is None:
if _log.isEnabledFor(_INFO):
_log.info('New lock %s', repr(handle))
handles_lock[handle] = _threading.Lock() # Serialize requests on the handle
return handles_lock[handle]
: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)
# import inspect as _inspect
# print ('\n '.join(str(s) for s in _inspect.stack()))
# context manager for locks with a timeout
@contextmanager
def acquire_timeout(lock, handle, timeout):
result = lock.acquire(timeout=timeout)
try:
if not result:
_log.error('lock on handle %d not acquired, probably due to timeout', int(handle))
yield result
finally:
if result:
lock.release()
assert devnumber != 0xFF
assert devnumber > 0x00
assert devnumber < 0x0F
# randomize the SoftwareId and mark byte to be able to identify the ping
# reply, and set most significant (0x8) bit in SoftwareId so that the reply
# is always distinguishable from notifications
request_id = 0x0018 | _random_bits(3)
request_data = _pack('!HBBB', request_id, 0, 0, _random_bits(8))
# a very few requests (e.g., host switching) do not expect a reply, but use no_reply=True with extreme caution
def request(handle, devnumber, request_id, *params, no_reply=False, return_error=False, long_message=False, protocol=1.0):
"""Makes a feature call to a device and waits for a matching reply.
:param handle: an open UR handle.
:param devnumber: attached device number.
:param request_id: a 16-bit integer.
:param params: parameters for the feature call, 3 to 16 bytes.
:returns: the reply data, or ``None`` if some error occurred. or no reply expected
"""
ihandle = int(handle)
notifications_hook = getattr(handle, 'notifications_hook', None)
_skip_incoming(handle, ihandle, notifications_hook)
write(ihandle, devnumber, request_data)
# import inspect as _inspect
# print ('\n '.join(str(s) for s in _inspect.stack()))
# we consider timeout from this point
request_started = _timestamp()
delta = 0
with acquire_timeout(handle_lock(handle), handle, 10.):
assert isinstance(request_id, int)
if (devnumber != 0xFF or protocol >= 2.0) and request_id < 0x8000:
# For HID++ 2.0 feature requests, randomize the SoftwareId to make it
# easier to recognize the reply for this request. also, always set the
# most significant bit (8) in SoftwareId, to make notifications easier
# to distinguish from request replies.
# This only applies to peripheral requests, ofc.
request_id = (request_id & 0xFFF0) | 0x08 | _random_bits(3)
while delta < _PING_TIMEOUT:
reply = _read(handle, _PING_TIMEOUT)
timeout = _RECEIVER_REQUEST_TIMEOUT if devnumber == 0xFF else _DEVICE_REQUEST_TIMEOUT
# be extra patient on long register read
if request_id & 0xFF00 == 0x8300:
timeout *= 2
if reply:
report_id, reply_devnumber, reply_data = reply
if reply_devnumber == devnumber:
if reply_data[:2] == request_data[:2] and reply_data[4:5] == request_data[-1:]:
# HID++ 2.0+ device, currently connected
return ord(reply_data[2:3]) + ord(reply_data[3:4]) / 10.0
if params:
params = b''.join(_pack('B', p) if isinstance(p, int) else p for p in params)
else:
params = b''
# if _log.isEnabledFor(_DEBUG):
# _log.debug("(%s) device %d request_id {%04X} params [%s]", handle, devnumber, request_id, _strhex(params))
request_data = _pack('!H', request_id) + params
if report_id == 0x10 and reply_data[:1] == b'\x8F' and reply_data[1:3] == request_data[:2]:
assert reply_data[-1:] == b'\x00'
error = ord(reply_data[3:4])
ihandle = int(handle)
notifications_hook = getattr(handle, 'notifications_hook', None)
try:
_skip_incoming(handle, ihandle, notifications_hook)
except NoReceiver:
_log.warn('device or receiver disconnected')
return None
write(ihandle, devnumber, request_data, long_message)
if error == _hidpp10.ERROR.invalid_SubID__command: # a valid reply from a HID++ 1.0 device
return 1.0
if no_reply:
return None
if error == _hidpp10.ERROR.resource_error: # device unreachable
return
# we consider timeout from this point
request_started = _timestamp()
delta = 0
if error == _hidpp10.ERROR.unknown_device: # no paired device with that number
_log.error("(%s) device %d error on ping request: unknown device", handle, devnumber)
raise NoSuchDevice(number=devnumber, request=request_id)
while delta < timeout:
reply = _read(handle, timeout)
if notifications_hook:
n = make_notification(reply_devnumber, reply_data)
if n:
notifications_hook(n)
# elif _log.isEnabledFor(_DEBUG):
# _log.debug("(%s) ignoring reply %02X [%s]", handle, reply_devnumber, _strhex(reply_data))
if reply:
report_id, reply_devnumber, reply_data = reply
if reply_devnumber == devnumber:
if report_id == HIDPP_SHORT_MESSAGE_ID and reply_data[:1] == b'\x8F' and reply_data[1:3] == request_data[:2
]:
error = ord(reply_data[3:4])
delta = _timestamp() - request_started
if _log.isEnabledFor(_DEBUG):
_log.debug(
'(%s) device 0x%02X error on request {%04X}: %d = %s', handle, devnumber, request_id, error,
_hidpp10.ERROR[error]
)
return _hidpp10.ERROR[error] if return_error else None
if reply_data[:1] == b'\xFF' and reply_data[1:3] == request_data[:2]:
# 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', handle, devnumber, request_id, error,
_hidpp20.ERROR[error]
)
raise _hidpp20.FeatureCallError(number=devnumber, request=request_id, error=error, params=params)
_log.warn("(%s) timeout (%0.2f/%0.2f) on device %d ping", handle, delta, _PING_TIMEOUT, devnumber)
# raise DeviceUnreachable(number=devnumber, request=request_id)
if reply_data[:2] == request_data[:2]:
if request_id & 0xFE00 == 0x8200:
# long registry r/w should return a long reply
assert report_id == HIDPP_LONG_MESSAGE_ID
elif request_id & 0xFE00 == 0x8000:
# short registry r/w should return a short reply
assert report_id == HIDPP_SHORT_MESSAGE_ID
if devnumber == 0xFF:
if request_id == 0x83B5 or request_id == 0x81F1:
# these replies have to match the first parameter as well
if reply_data[2:3] == params[:1]:
return reply_data[2:]
else:
# hm, not matching my request, and certainly not a notification
continue
else:
return reply_data[2:]
else:
return reply_data[2:]
else:
# a reply was received, but did not match our request in any way
# reset the timeout starting point
request_started = _timestamp()
if notifications_hook:
n = make_notification(report_id, reply_devnumber, reply_data)
if n:
notifications_hook(n)
# elif _log.isEnabledFor(_DEBUG):
# _log.debug("(%s) ignoring reply %02X [%s]", handle, reply_devnumber, _strhex(reply_data))
# elif _log.isEnabledFor(_DEBUG):
# _log.debug("(%s) ignoring reply %02X [%s]", handle, reply_devnumber, _strhex(reply_data))
delta = _timestamp() - request_started
# 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]', delta, timeout, devnumber, request_id,
_strhex(params)
)
# raise DeviceUnreachable(number=devnumber, request=request_id)
def ping(handle, devnumber, long_message=False):
"""Check if a device is connected to the receiver.
: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)
# import inspect as _inspect
# print ('\n '.join(str(s) for s in _inspect.stack()))
with acquire_timeout(handle_lock(handle), handle, 10.):
# randomize the SoftwareId and mark byte to be able to identify the ping
# reply, and set most significant (0x8) bit in SoftwareId so that the reply
# is always distinguishable from notifications
request_id = 0x0018 | _random_bits(3)
request_data = _pack('!HBBB', request_id, 0, 0, _random_bits(8))
ihandle = int(handle)
notifications_hook = getattr(handle, 'notifications_hook', None)
try:
_skip_incoming(handle, ihandle, notifications_hook)
except NoReceiver:
_log.warn('device or receiver disconnected')
return
write(ihandle, devnumber, request_data, long_message)
# we consider timeout from this point
request_started = _timestamp()
delta = 0
while delta < _PING_TIMEOUT:
reply = _read(handle, _PING_TIMEOUT)
if reply:
report_id, reply_devnumber, reply_data = reply
if reply_devnumber == devnumber:
if reply_data[:2] == request_data[:2] and reply_data[4:5] == request_data[-1:]:
# HID++ 2.0+ device, currently connected
return ord(reply_data[2:3]) + ord(reply_data[3:4]) / 10.0
if report_id == HIDPP_SHORT_MESSAGE_ID and reply_data[:1] == b'\x8F' and reply_data[1:3] == request_data[:2
]:
assert reply_data[-1:] == b'\x00'
error = ord(reply_data[3:4])
if error == _hidpp10.ERROR.invalid_SubID__command: # a valid reply from a HID++ 1.0 device
return 1.0
if error == _hidpp10.ERROR.resource_error: # device unreachable
return
if error == _hidpp10.ERROR.unknown_device: # no paired device with that number
_log.error('(%s) device %d error on ping request: unknown device', handle, devnumber)
raise NoSuchDevice(number=devnumber, request=request_id)
if notifications_hook:
n = make_notification(report_id, reply_devnumber, reply_data)
if n:
notifications_hook(n)
# elif _log.isEnabledFor(_DEBUG):
# _log.debug("(%s) ignoring reply %02X [%s]", handle, reply_devnumber, _strhex(reply_data))
delta = _timestamp() - request_started
_log.warn('(%s) timeout (%0.2f/%0.2f) on device %d ping', handle, delta, _PING_TIMEOUT, devnumber)
# raise DeviceUnreachable(number=devnumber, request=request_id)

View File

@@ -17,47 +17,206 @@
## with this program; if not, write to the Free Software Foundation, Inc.,
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
## According to Logitech, they use the following product IDs (as of September 2020)
## USB product IDs for receivers: 0xC526 - 0xC5xx
## Wireless PIDs for hidpp10 devices: 0x2006 - 0x2019
## Wireless PIDs for hidpp20 devices: 0x4002 - 0x4097, 0x4101 - 0x4102
## USB product IDs for hidpp20 devices: 0xC07D - 0xC093, 0xC32B - 0xC344
## Bluetooth product IDs (for hidpp20 devices): 0xB012 - 0xB0xx, 0xB32A - 0xB3xx
# USB ids of Logitech wireless receivers.
# Only receivers supporting the HID++ protocol can go in here.
from __future__ import absolute_import, division, print_function, unicode_literals
from .descriptors import DEVICES as _DEVICES
from .i18n import _
_UNIFYING_DRIVER = 'logitech-djreceiver'
_GENERIC_DRIVER = ('hid-generic', 'generic-usb')
# max_devices is only used for receivers that do not support reading from _R.receiver_info offset 0x03, default to 1
# may_unpair is only used for receivers that do not support reading from _R.receiver_info offset 0x03, default to False
# unpair is for receivers that do support reading from _R.receiver_info offset 0x03, no default
## should this last be changed so that may_unpair is used for all receivers? writing to _R.receiver_pairing doesn't seem right
# re_pairs determines whether a receiver pairs by replacing existing pairings, default to False
## currently only one receiver is so marked - should there be more?
# ex100_27mhz_wpid_fix enable workarounds for EX100 and possible other old 27Mhz receivers
_DRIVER = ('hid-generic', 'generic-usb', 'logitech-djreceiver')
# each tuple contains (vendor_id, product_id, usb interface number, hid driver)
_unifying_receiver = lambda product_id: {
'vendor_id': 0x046d,
'product_id': product_id,
'usb_interface': 2,
'hid_driver': _DRIVER, # noqa: F821
'name': _('Unifying Receiver')
}
_nano_receiver = lambda product_id: {
'vendor_id': 0x046d,
'product_id': product_id,
'usb_interface': 1,
'hid_driver': _DRIVER, # noqa: F821
'name': _('Nano Receiver'),
'may_unpair': False,
're_pairs': True
}
_nano_receiver_no_unpair = lambda product_id: {
'vendor_id': 0x046d,
'product_id': product_id,
'usb_interface': 1,
'hid_driver': _DRIVER, # noqa: F821
'name': _('Nano Receiver'),
'may_unpair': False,
'unpair': False,
're_pairs': True
}
_nano_receiver_max2 = lambda product_id: {
'vendor_id': 0x046d,
'product_id': product_id,
'usb_interface': 1,
'hid_driver': _DRIVER, # noqa: F821
'name': _('Nano Receiver'),
'max_devices': 2,
'may_unpair': False,
're_pairs': True
}
_nano_receiver_maxn = lambda product_id, max: {
'vendor_id': 0x046d,
'product_id': product_id,
'usb_interface': 1,
'hid_driver': _DRIVER, # noqa: F821
'name': _('Nano Receiver'),
'max_devices': max,
'may_unpair': False,
're_pairs': True
}
_lenovo_receiver = lambda product_id: {
'vendor_id': 0x17ef,
'product_id': product_id,
'usb_interface': 1,
'hid_driver': _DRIVER, # noqa: F821
'name': _('Nano Receiver')
}
_lightspeed_receiver = lambda product_id: {
'vendor_id': 0x046d,
'product_id': product_id,
'usb_interface': 2,
'hid_driver': _DRIVER, # noqa: F821
'name': _('Lightspeed Receiver')
}
_ex100_receiver = lambda product_id: {
'vendor_id': 0x046d,
'product_id': product_id,
'usb_interface': 1,
'hid_driver': _DRIVER, # noqa: F821
'name': _('EX100 Receiver 27 Mhz'),
'max_devices': 4,
'may_unpair': False,
're_pairs': True,
'ex100_27mhz_wpid_fix': True
}
# standard Unifying receivers (marked with the orange Unifying logo)
UNIFYING_RECEIVER = (0x046d, 0xc52b, 2, _UNIFYING_DRIVER)
UNIFYING_RECEIVER_2 = (0x046d, 0xc532, 2, _UNIFYING_DRIVER)
UNIFYING_RECEIVER_C52B = _unifying_receiver(0xc52b)
UNIFYING_RECEIVER_C532 = _unifying_receiver(0xc532)
# Nano receviers that support the Unifying protocol
NANO_RECEIVER_ADVANCED = (0x046d, 0xc52f, 1, _GENERIC_DRIVER)
NANO_RECEIVER_ADVANCED = _nano_receiver_no_unpair(0xc52f)
# ex100 old style receiver pre-unifyimg protocol
EX100_27MHZ_RECEIVER_C517 = _ex100_receiver(0xc517)
# Nano receivers that don't support the Unifying protocol
NANO_RECEIVER_C517 = (0x046d, 0xc517, 1, _GENERIC_DRIVER)
NANO_RECEIVER_C518 = (0x046d, 0xc518, 1, _GENERIC_DRIVER)
NANO_RECEIVER_C51A = (0x046d, 0xc51a, 1, _GENERIC_DRIVER)
NANO_RECEIVER_C51B = (0x046d, 0xc51b, 1, _GENERIC_DRIVER)
NANO_RECEIVER_C521 = (0x046d, 0xc521, 1, _GENERIC_DRIVER)
NANO_RECEIVER_C525 = (0x046d, 0xc525, 1, _GENERIC_DRIVER)
NANO_RECEIVER_C526 = (0x046d, 0xc526, 1, _GENERIC_DRIVER)
NANO_RECEIVER_C518 = _nano_receiver(0xc518)
NANO_RECEIVER_C51A = _nano_receiver(0xc51a)
NANO_RECEIVER_C51B = _nano_receiver(0xc51b)
NANO_RECEIVER_C521 = _nano_receiver(0xc521)
NANO_RECEIVER_C525 = _nano_receiver(0xc525)
NANO_RECEIVER_C526 = _nano_receiver(0xc526)
NANO_RECEIVER_C52e = _nano_receiver_no_unpair(0xc52e)
NANO_RECEIVER_C531 = _nano_receiver(0xc531)
NANO_RECEIVER_C534 = _nano_receiver_max2(0xc534)
NANO_RECEIVER_C537 = _nano_receiver(0xc537)
NANO_RECEIVER_6042 = _lenovo_receiver(0x6042)
# Lightspeed receivers
LIGHTSPEED_RECEIVER_C539 = _lightspeed_receiver(0xc539)
LIGHTSPEED_RECEIVER_C53a = _lightspeed_receiver(0xc53a)
LIGHTSPEED_RECEIVER_C53f = _lightspeed_receiver(0xc53f)
LIGHTSPEED_RECEIVER_C53d = _lightspeed_receiver(0xc53d)
LIGHTSPEED_RECEIVER_C545 = _lightspeed_receiver(0xc545)
LIGHTSPEED_RECEIVER_C541 = _lightspeed_receiver(0xc541)
LIGHTSPEED_RECEIVER_C547 = _lightspeed_receiver(0xc547)
ALL = (
UNIFYING_RECEIVER,
UNIFYING_RECEIVER_2,
NANO_RECEIVER_ADVANCED,
NANO_RECEIVER_C517,
NANO_RECEIVER_C518,
NANO_RECEIVER_C51A,
NANO_RECEIVER_C51B,
NANO_RECEIVER_C521,
NANO_RECEIVER_C525,
NANO_RECEIVER_C526,
)
UNIFYING_RECEIVER_C52B,
UNIFYING_RECEIVER_C532,
NANO_RECEIVER_ADVANCED,
EX100_27MHZ_RECEIVER_C517,
NANO_RECEIVER_C518,
NANO_RECEIVER_C51A,
NANO_RECEIVER_C51B,
NANO_RECEIVER_C521,
NANO_RECEIVER_C525,
NANO_RECEIVER_C526,
NANO_RECEIVER_C52e,
NANO_RECEIVER_C531,
NANO_RECEIVER_C534,
NANO_RECEIVER_C537,
NANO_RECEIVER_6042,
LIGHTSPEED_RECEIVER_C539,
LIGHTSPEED_RECEIVER_C53a,
LIGHTSPEED_RECEIVER_C53f,
LIGHTSPEED_RECEIVER_C53d,
LIGHTSPEED_RECEIVER_C545,
LIGHTSPEED_RECEIVER_C541,
LIGHTSPEED_RECEIVER_C547,
)
_wired_device = lambda product_id, interface: {
'vendor_id': 0x046d,
'product_id': product_id,
'bus_id': 0x3,
'usb_interface': interface,
'isDevice': True
}
_bt_device = lambda product_id: {'vendor_id': 0x046d, 'product_id': product_id, 'bus_id': 0x5, 'isDevice': True}
DEVICES = []
for _ignore, d in _DEVICES.items():
if d.usbid:
DEVICES.append(_wired_device(d.usbid, d.interface if d.interface else 2))
if d.btid:
DEVICES.append(_bt_device(d.btid))
def other_device_check(bus_id, vendor_id, product_id):
"""Check whether product is a Logitech USB-connected or Bluetooth device based on bus, vendor, and product IDs
This allows Solaar to support receiverless HID++ 2.0 devices that it knows nothing about"""
if vendor_id != 0x46d: # Logitech
return
if bus_id == 0x3: # USB
if (product_id >= 0xC07D and product_id <= 0xC093 or product_id >= 0xC32B and product_id <= 0xC344):
return _wired_device(product_id, 2)
elif bus_id == 0x5: # Bluetooth
if (product_id >= 0xB012 and product_id <= 0xB0FF or product_id >= 0xB32A and product_id <= 0xB3FF):
return _bt_device(product_id)
def product_information(usb_id):
if isinstance(usb_id, str):
usb_id = int(usb_id, 16)
for r in ALL:
if usb_id == r.get('product_id'):
return r
return {}
del _DRIVER, _unifying_receiver, _nano_receiver, _lenovo_receiver, _lightspeed_receiver

View File

@@ -22,256 +22,255 @@
from __future__ import absolute_import, division, print_function, unicode_literals
from binascii import hexlify as _hexlify
from collections import namedtuple
from struct import pack, unpack
try:
unicode
# if Python2, unicode_literals will mess our first (un)pack() argument
_pack_str = pack
_unpack_str = unpack
pack = lambda x, *args: _pack_str(str(x), *args)
unpack = lambda x, *args: _unpack_str(str(x), *args)
unicode # noqa: F821
# if Python2, unicode_literals will mess our first (un)pack() argument
_pack_str = pack
_unpack_str = unpack
pack = lambda x, *args: _pack_str(str(x), *args)
unpack = lambda x, *args: _unpack_str(str(x), *args)
is_string = lambda d: isinstance(d, unicode) or isinstance(d, str)
# no easy way to distinguish between b'' and '' :(
# or (isinstance(d, str) \
# and not any((chr(k) in d for k in range(0x00, 0x1F))) \
# and not any((chr(k) in d for k in range(0x80, 0xFF))) \
# )
except:
# this is certanly Python 3
# In Py3, unicode and str are equal (the unicode object does not exist)
is_string = lambda d: isinstance(d, str)
is_string = lambda d: isinstance(d, unicode) or isinstance(d, str) # noqa: F821
# no easy way to distinguish between b'' and '' :(
# or (isinstance(d, str) \
# and not any((chr(k) in d for k in range(0x00, 0x1F))) \
# and not any((chr(k) in d for k in range(0x80, 0xFF))) \
# )
except Exception:
# this is certainly Python 3
# In Py3, unicode and str are equal (the unicode object does not exist)
is_string = lambda d: isinstance(d, str)
#
#
#
class NamedInt(int):
"""An reqular Python integer with an attached name.
"""A regular Python integer with an attached name.
Caution: comparison with strings will also match this NamedInt's name
(case-insensitive)."""
Caution: comparison with strings will also match this NamedInt's name
(case-insensitive)."""
def __new__(cls, value, name):
assert is_string(name)
obj = int.__new__(cls, value)
obj.name = str(name)
return obj
def __new__(cls, value, name):
assert is_string(name)
obj = int.__new__(cls, value)
obj.name = str(name)
return obj
def bytes(self, count=2):
return int2bytes(self, count)
def bytes(self, count=2):
return int2bytes(self, count)
def __eq__(self, other):
if isinstance(other, NamedInt):
return int(self) == int(other) and self.name == other.name
if isinstance(other, int):
return int(self) == int(other)
if is_string(other):
return self.name.lower() == other.lower()
# this should catch comparisons with bytes in Py3
if other is not None:
raise TypeError('Unsupported type ' + str(type(other)))
def __eq__(self, other):
if isinstance(other, NamedInt):
return int(self) == int(other) and self.name == other.name
if isinstance(other, int):
return int(self) == int(other)
if is_string(other):
return self.name.lower() == other.lower()
# this should catch comparisons with bytes in Py3
if other is not None:
raise TypeError('Unsupported type ' + str(type(other)))
def __ne__(self, other):
return not self.__eq__(other)
def __ne__(self, other):
return not self.__eq__(other)
def __hash__(self):
return int(self)
def __hash__(self):
return int(self)
def __str__(self):
return self.name
def __str__(self):
return self.name
__unicode__ = __str__
__unicode__ = __str__
def __repr__(self):
return 'NamedInt(%d, %r)' % (int(self), self.name)
def __repr__(self):
return 'NamedInt(%d, %r)' % (int(self), self.name)
class NamedInts(object):
"""An ordered set of NamedInt values.
"""An ordered set of NamedInt values.
Indexing can be made by int or string, and will return the corresponding
NamedInt if it exists in this set, or `None`.
Indexing can be made by int or string, and will return the corresponding
NamedInt if it exists in this set, or `None`.
Extracting slices will return all present NamedInts in the given interval
(extended slices are not supported).
Extracting slices will return all present NamedInts in the given interval
(extended slices are not supported).
Assigning a string to an indexed int will create a new NamedInt in this set;
if the value already exists in the set (int or string), ValueError will be
raised.
"""
__slots__ = ('__dict__', '_values', '_indexed', '_fallback')
Assigning a string to an indexed int will create a new NamedInt in this set;
if the value already exists in the set (int or string), ValueError will be
raised.
"""
__slots__ = ('__dict__', '_values', '_indexed', '_fallback')
def __init__(self, **kwargs):
def _readable_name(n):
if not is_string(n):
raise TypeError("expected (unicode) string, got " + str(type(n)))
return n.replace('__', '/').replace('_', ' ')
def __init__(self, **kwargs):
def _readable_name(n):
if not is_string(n):
raise TypeError('expected (unicode) string, got ' + str(type(n)))
return n.replace('__', '/').replace('_', ' ')
# print (repr(kwargs))
values = {k: NamedInt(v, _readable_name(k)) for (k, v) in kwargs.items()}
self.__dict__ = values
self._values = sorted(list(values.values()))
self._indexed = {int(v): v for v in self._values}
# assert len(values) == len(self._indexed), "(%d) %r\n=> (%d) %r" % (len(values), values, len(self._indexed), self._indexed)
self._fallback = None
# print (repr(kwargs))
values = {k: NamedInt(v, _readable_name(k)) for (k, v) in kwargs.items()}
self.__dict__ = values
self._values = sorted(list(values.values()))
self._indexed = {int(v): v for v in self._values}
# assert len(values) == len(self._indexed)
# "(%d) %r\n=> (%d) %r" % (len(values), values, len(self._indexed), self._indexed)
self._fallback = None
@classmethod
def range(cls, from_value, to_value, name_generator=lambda x: str(x), step=1):
values = {name_generator(x): x for x in range(from_value, to_value + 1, step)}
return NamedInts(**values)
@classmethod
def list(cls, items, name_generator=lambda x: str(x)):
values = {name_generator(x): x for x in items}
return NamedInts(**values)
def flag_names(self, value):
unknown_bits = value
for k in self._indexed:
assert bin(k).count('1') == 1
if k & value == k:
unknown_bits &= ~k
yield str(self._indexed[k])
@classmethod
def range(cls, from_value, to_value, name_generator=lambda x: str(x), step=1):
values = {name_generator(x): x for x in range(from_value, to_value + 1, step)}
return NamedInts(**values)
if unknown_bits:
yield 'unknown:%06X' % unknown_bits
def flag_names(self, value):
unknown_bits = value
for k in self._indexed:
assert bin(k).count('1') == 1
if k & value == k:
unknown_bits &= ~k
yield str(self._indexed[k])
def __getitem__(self, index):
if isinstance(index, int):
if index in self._indexed:
return self._indexed[int(index)]
if self._fallback and isinstance(index, int):
value = NamedInt(index, self._fallback(index))
self._indexed[index] = value
self._values = sorted(self._values + [value])
return value
if unknown_bits:
yield 'unknown:%06X' % unknown_bits
elif is_string(index):
if index in self.__dict__:
return self.__dict__[index]
def __getitem__(self, index):
if isinstance(index, int):
if index in self._indexed:
return self._indexed[int(index)]
if self._fallback and isinstance(index, int):
value = NamedInt(index, self._fallback(index))
self._indexed[index] = value
self._values = sorted(self._values + [value])
return value
elif isinstance(index, slice):
if index.start is None and index.stop is None:
return self._values[:]
elif is_string(index):
if index in self.__dict__:
return self.__dict__[index]
return (next((x for x in self._values if str(x) == index), None))
v_start = int(self._values[0]) if index.start is None else int(index.start)
v_stop = (self._values[-1] + 1) if index.stop is None else int(index.stop)
elif isinstance(index, slice):
if index.start is None and index.stop is None:
return self._values[:]
if v_start > v_stop or v_start > self._values[-1] or v_stop <= self._values[0]:
return []
v_start = int(self._values[0]) if index.start is None else int(index.start)
v_stop = (self._values[-1] + 1) if index.stop is None else int(index.stop)
if v_start <= self._values[0] and v_stop > self._values[-1]:
return self._values[:]
if v_start > v_stop or v_start > self._values[-1] or v_stop <= self._values[0]:
return []
start_index = 0
stop_index = len(self._values)
for i, value in enumerate(self._values):
if value < v_start:
start_index = i + 1
elif index.stop is None:
break
if value >= v_stop:
stop_index = i
break
if v_start <= self._values[0] and v_stop > self._values[-1]:
return self._values[:]
return self._values[start_index:stop_index]
start_index = 0
stop_index = len(self._values)
for i, value in enumerate(self._values):
if value < v_start:
start_index = i + 1
elif index.stop is None:
break
if value >= v_stop:
stop_index = i
break
def __setitem__(self, index, name):
assert isinstance(index, int), type(index)
if isinstance(name, NamedInt):
assert int(index) == int(name), repr(index) + ' ' + repr(name)
value = name
elif is_string(name):
value = NamedInt(index, name)
else:
raise TypeError('name must be a string')
return self._values[start_index:stop_index]
if str(value) in self.__dict__:
raise ValueError('%s (%d) already known' % (value, int(value)))
if int(value) in self._indexed:
raise ValueError('%d (%s) already known' % (int(value), value))
def __setitem__(self, index, name):
assert isinstance(index, int), type(index)
if isinstance(name, NamedInt):
assert int(index) == int(name), repr(index) + ' ' + repr(name)
value = name
elif is_string(name):
value = NamedInt(index, name)
else:
raise TypeError('name must be a string')
self._values = sorted(self._values + [value])
self.__dict__[str(value)] = value
self._indexed[int(value)] = value
if str(value) in self.__dict__:
raise ValueError('%s (%d) already known' % (value, int(value)))
if int(value) in self._indexed:
raise ValueError('%d (%s) already known' % (int(value), value))
def __contains__(self, value):
if isinstance(value, int):
return value in self._indexed
elif is_string(value):
return value in self.__dict__
self._values = sorted(self._values + [value])
self.__dict__[str(value)] = value
self._indexed[int(value)] = value
def __iter__(self):
for v in self._values:
yield v
def __contains__(self, value):
if isinstance(value, int):
return value in self._indexed
elif is_string(value):
return value in self.__dict__ or value in self._values
def __len__(self):
return len(self._values)
def __iter__(self):
for v in self._values:
yield v
def __repr__(self):
return 'NamedInts(%s)' % ', '.join(repr(v) for v in self._values)
def __len__(self):
return len(self._values)
def __repr__(self):
return 'NamedInts(%s)' % ', '.join(repr(v) for v in self._values)
def strhex(x):
assert x is not None
"""Produce a hex-string representation of a sequence of bytes."""
return _hexlify(x).decode('ascii').upper()
assert x is not None
"""Produce a hex-string representation of a sequence of bytes."""
return _hexlify(x).decode('ascii').upper()
def bytes2int(x):
"""Convert a bytes string to an int.
The bytes are assumed to be in most-significant-first order.
"""
assert isinstance(x, bytes)
assert len(x) < 9
qx = (b'\x00' * 8) + x
result, = unpack('!Q', qx[-8:])
# assert x == int2bytes(result, len(x))
return result
"""Convert a bytes string to an int.
The bytes are assumed to be in most-significant-first order.
"""
assert isinstance(x, bytes)
assert len(x) < 9
qx = (b'\x00' * 8) + x
result, = unpack('!Q', qx[-8:])
# assert x == int2bytes(result, len(x))
return result
def int2bytes(x, count=None):
"""Convert an int to a bytes representation.
The bytes are ordered in most-significant-first order.
If 'count' is not given, the necessary number of bytes is computed.
"""
assert isinstance(x, int)
result = pack('!Q', x)
assert isinstance(result, bytes)
# assert x == bytes2int(result)
"""Convert an int to a bytes representation.
The bytes are ordered in most-significant-first order.
If 'count' is not given, the necessary number of bytes is computed.
"""
assert isinstance(x, int)
result = pack('!Q', x)
assert isinstance(result, bytes)
# assert x == bytes2int(result)
if count is None:
return result.lstrip(b'\x00')
if count is None:
return result.lstrip(b'\x00')
assert isinstance(count, int)
assert count > 0
assert x.bit_length() <= count * 8
return result[-count:]
assert isinstance(count, int)
assert count > 0
assert x.bit_length() <= count * 8
return result[-count:]
class KwException(Exception):
"""An exception that remembers all arguments passed to the constructor.
They can be later accessed by simple member access.
"""
def __init__(self, **kwargs):
super(KwException, self).__init__(kwargs)
"""An exception that remembers all arguments passed to the constructor.
They can be later accessed by simple member access.
"""
def __init__(self, **kwargs):
super(KwException, self).__init__(kwargs)
def __getattr__(self, k):
try:
return super(KwException, self).__getattr__(k)
except AttributeError:
return self.args[0][k]
def __getattr__(self, k):
try:
return super(KwException, self).__getattr__(k)
except AttributeError:
return self.args[0][k]
from collections import namedtuple
"""Firmware information."""
FirmwareInfo = namedtuple('FirmwareInfo', [
'kind',
'name',
'version',
'extras'])
FirmwareInfo = namedtuple('FirmwareInfo', ['kind', 'name', 'version', 'extras'])
"""Reprogrammable keys informations."""
ReprogrammableKeyInfo = namedtuple('ReprogrammableKeyInfo', [
'index',
'key',
'task',
'flags'])
BATTERY_APPROX = NamedInts(empty=0, critical=5, low=20, good=50, full=90)
del namedtuple

Some files were not shown because too many files have changed in this diff Show More