Coder Social home page Coder Social logo

solaar's Introduction

Solaar

Solaar is a Linux manager for many Logitech keyboards, mice, and other devices that connect wirelessly to a Unifying, Bolt, Lightspeed or Nano receiver as well as many Logitech devices that connect via a USB cable or Bluetooth.

More Information - Usage - Capabilities - Rules - Manual Installation

License: GPL v2

 

 

Solaar supports:

  • pairing/unpairing of devices with receivers
  • configuring device settings
  • custom button configuration
  • running rules in response to special messages from devices

For more information see the main Solaar documentation page. -

Installation Packages

Up-to-date prebuilt packages are available for some Linux distros (e.g., Fedora) 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:

Solaar is available from some other repositories but may be several versions behind the current version:

solaar's People

Contributors

antonsoroko avatar chris-johnston avatar danfro avatar david-geiger avatar doctor64 avatar drupal-daffie avatar effective-light avatar ejsc1 avatar ffy00 avatar javitonino avatar jeblad avatar jocelynthode avatar johnveness avatar jrbenito avatar lekensteyn avatar matthag avatar matthaiks avatar mchehab avatar muzena avatar peterdavehello avatar pfps avatar pwr avatar rongronggg9 avatar sidevesh avatar spaced avatar talal avatar tomin1 avatar uhle avatar viniciusbm avatar vtec234 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

solaar's Issues

merge/hide notifications on startup

With two devices plugged in, Solaar shows me three notifications, basically:

  • Receiver: You have two devices!
  • Keyboard connected
  • Mouse connected

What about being less verbose with notifications and merging them?

Keep records of battery charge per device

From #69:

Have the ability to check how long the batteries lasted. This can be accomplished by resetting a timer that only starts when it detects the battery at 100%. When the percent is at 100% the timer starts and it will only reset itself when the percent makes a huge jump, for example, changing from 50% battery to 100% which would only mean I changed to new batteries or the mouse was charged. This would at least give an estimate of how long the batteries lasted and can give the user an idea to benchmark 2 things: How good a Logitech mouse uses certain batteries and how long certain batteries last.

Python3 breakage due to use of unicode class

unicode does not exist in Python 3, it has been replaced by str. After commit feedbcf (nice commit hash btw), I could not start the program unless I specify python2 as interpreter.

Trace:

Traceback (most recent call last):
  File "bin/solaar", line 26, in <module>
    solaar.gtk.main()
  File "/home/peter/projects/Solaar/lib/solaar/gtk.py", line 114, in main
    _run(args)
  File "/home/peter/projects/Solaar/lib/solaar/gtk.py", line 44, in _run
    import solaar.ui as ui
  File "/home/peter/projects/Solaar/lib/solaar/ui/__init__.py", line 47, in <module>
    from . import status_icon
  File "/home/peter/projects/Solaar/lib/solaar/ui/status_icon.py", line 9, in <module>
    from . import (action as _action,
  File "/home/peter/projects/Solaar/lib/solaar/ui/action.py", line 9, in <module>
    from . import notify, pair_window
  File "/home/peter/projects/Solaar/lib/solaar/ui/pair_window.py", line 14, in <module>
    from logitech.unifying_receiver import status as _status
  File "/home/peter/projects/Solaar/lib/logitech/unifying_receiver/__init__.py", line 29, in <module>
    from .base import NoReceiver, NoSuchDevice, DeviceUnreachable
  File "/home/peter/projects/Solaar/lib/logitech/unifying_receiver/base.py", line 17, in <module>
    from . import hidpp10 as _hidpp10
  File "/home/peter/projects/Solaar/lib/logitech/unifying_receiver/hidpp10.py", line 14, in <module>
    from .hidpp20 import FIRMWARE_KIND
  File "/home/peter/projects/Solaar/lib/logitech/unifying_receiver/hidpp20.py", line 38, in <module>
    TOUCH_MOUSE=0x6110)
  File "/home/peter/projects/Solaar/lib/logitech/unifying_receiver/common.py", line 71, in __init__
    values = {k: NamedInt(v, _readable_name(k)) for (k, v) in kwargs.items()}
  File "/home/peter/projects/Solaar/lib/logitech/unifying_receiver/common.py", line 71, in <dictcomp>
    values = {k: NamedInt(v, _readable_name(k)) for (k, v) in kwargs.items()}
  File "/home/peter/projects/Solaar/lib/logitech/unifying_receiver/common.py", line 20, in __new__
    obj.name = unicode(name)
NameError: global name 'unicode' is not defined

grep for all unicode words:

hidapi/hidconsole.py:36:    if type(data) == unicode:
logitech/unifying_receiver/common.py:18:        assert isinstance(name, str) or isinstance(name, unicode)
logitech/unifying_receiver/common.py:20:        obj.name = unicode(name)
logitech/unifying_receiver/common.py:33:        if isinstance(other, str) or isinstance(other, unicode):
logitech/unifying_receiver/common.py:67:            if not isinstance(n, str) and not isinstance(n, unicode):
logitech/unifying_receiver/common.py:103:       elif isinstance(index, str) or isinstance(index, unicode):
logitech/unifying_receiver/common.py:138:       elif isinstance(name, str) or isinstance(name, unicode):
logitech/unifying_receiver/common.py:155:       if isinstance(value, str) or isinstance(value, unicode):

Better way to have access to /dev/hidraw* with udev (no need of group)

Hi.

I'm the packager of Solaar for Mageia.
I encountered an issue with Mageia and the udev rules as we don't have the 'plugdev' group under Mageia and as by default our user is not part of 'users' of other group.
My idea was to use uaccess, so I did a sed in the udev rules:

s/GROUP="plugdev", MODE="0660"/TAG+="uaccess"/

With this, no more need to be part of X or Y group.
I also renamed the udev rules to be launched sooner.

FYI: http://svnweb.mageia.org/packages/cauldron/solaar/current/SPECS/solaar.spec?revision=441943&view=markup

solaar-cli: does not terminate on succesful pairing

Debug output:

$ bin/solaar-cli -dd pair 
2013-05-26 21:37:59,677    DEBUG LUR.base: (3) <= w[10 FF 83B5 030000]
2013-05-26 21:37:59,679    DEBUG LUR.base: (3) => r[11 FF 83B5 0308D89AA60D06600000000000000000]
2013-05-26 21:37:59,679    DEBUG LUR.base: (3) <= w[10 FF 83B5 040000]
2013-05-26 21:37:59,681    DEBUG LUR.base: (3) => r[10 FF 8F83 B50300]
2013-05-26 21:37:59,681    DEBUG LUR.base: (3) device 0xFF error on request {83B5}: 3 = invalid value
2013-05-26 21:37:59,681    DEBUG LUR.base: (3) <= w[10 FF 83B5 200000]
2013-05-26 21:37:59,685    DEBUG LUR.base: (3) => r[11 FF 83B5 205E0840130400020C00000000000000]
2013-05-26 21:37:59,685     INFO LUR.receiver: <UnifyingReceiver(/dev/hidraw0,3)>: found device 1 (4013)
2013-05-26 21:37:59,685    DEBUG LUR.base: (3) <= w[10 FF 83B5 210000]
2013-05-26 21:37:59,687    DEBUG LUR.base: (3) => r[10 FF 8F83 B50300]
2013-05-26 21:37:59,687    DEBUG LUR.base: (3) device 0xFF error on request {83B5}: 3 = invalid value
2013-05-26 21:37:59,687    DEBUG LUR.base: (3) <= w[10 FF 83B5 220000]
2013-05-26 21:37:59,689    DEBUG LUR.base: (3) => r[10 FF 8F83 B50300]
2013-05-26 21:37:59,689    DEBUG LUR.base: (3) device 0xFF error on request {83B5}: 3 = invalid value
2013-05-26 21:37:59,689    DEBUG LUR.base: (3) <= w[10 FF 83B5 230000]
2013-05-26 21:37:59,691    DEBUG LUR.base: (3) => r[10 FF 8F83 B50300]
2013-05-26 21:37:59,691    DEBUG LUR.base: (3) device 0xFF error on request {83B5}: 3 = invalid value
2013-05-26 21:37:59,691    DEBUG LUR.base: (3) <= w[10 FF 83B5 240000]
2013-05-26 21:37:59,693    DEBUG LUR.base: (3) => r[10 FF 8F83 B50300]
2013-05-26 21:37:59,693    DEBUG LUR.base: (3) device 0xFF error on request {83B5}: 3 = invalid value
2013-05-26 21:37:59,693    DEBUG LUR.base: (3) <= w[10 FF 83B5 250000]
2013-05-26 21:37:59,695    DEBUG LUR.base: (3) => r[10 FF 8F83 B50300]
2013-05-26 21:37:59,695    DEBUG LUR.base: (3) device 0xFF error on request {83B5}: 3 = invalid value
2013-05-26 21:37:59,695    DEBUG LUR.base: (3) <= w[10 FF 8100 000000]
2013-05-26 21:37:59,697    DEBUG LUR.base: (3) => r[10 FF 8100 001900]
2013-05-26 21:37:59,697    DEBUG LUR.base: (3) <= w[10 FF 80B2 010014]
2013-05-26 21:37:59,699    DEBUG LUR.base: (3) => r[10 FF 4A01 000000]
2013-05-26 21:37:59,701    DEBUG LUR.base: (3) => r[10 FF 80B2 000000]
Pairing: turn your new device on (timing out in 20 seconds).
2013-05-26 21:38:09,831    DEBUG LUR.base: (3) => r[10 02 4104 710440]
2013-05-26 21:38:09,832    DEBUG LUR.base: (3) <= w[10 FF 83B5 210000]
2013-05-26 21:38:09,843    DEBUG LUR.base: (3) => r[10 FF 4A00 000034]
2013-05-26 21:38:09,845    DEBUG LUR.base: (3) => r[11 FF 83B5 21611440040402010D00000000000000]
2013-05-26 21:38:09,845     INFO LUR.receiver: <UnifyingReceiver(/dev/hidraw0,3)>: found device 2 (4004)
2013-05-26 21:38:09,885    DEBUG LUR.base: (3) => r[10 02 4104 B10440]
2013-05-26 21:38:09,889    DEBUG LUR.base: (3) => r[11 02 0700 01010100000000000000000000000000]
(long silence here)

I have only tested with two HID++2.0 devices, a HID++1.0 keyboard is not near me. ltunify works without issues.

Issues with battery and lux images after installing

Hi there, glad I found this awesome project -- thanks!

I have some minor issues with images not appearing on my Arch Linux install. Let me know if this is something I did wrong or an actual bug 🐛.

Screenshot

What I did:

  1. replaced /usr/bin/env python with /usr/bin/env/python2 in solaar, solaar-cli, and setup.py.
  2. ran sudo ./setup.py

What's wrong:

looks like the battery and lux images are not being found correctly. I see the following on the console (repeating indefinitely)

Edit: also the main tray icon seems to be missing.

AssertionError
Traceback (most recent call last):
  File "/usr/lib/python2.7/site-packages/Solaar-0.8.4-py2.7.egg/solaar/ui/status_icon.py", line 126, in update
    icon.set_from_pixbuf(_icon_with_battery(battery_level, bool(battery_status)))
  File "/usr/lib/python2.7/site-packages/Solaar-0.8.4-py2.7.egg/solaar/ui/status_icon.py", line 61, in _icon_with_battery
    assert mask

Let me know if you need any additional info. Thanks!

[bug] Crash on suspend/resume due to udev monitor being interrupted

2013-05-03 10:08:19,608    DEBUG [ReceiverListener] LUR.base: (8) => r[10 02 4104 521340]
2013-05-03 10:08:19,609    DEBUG [ReceiverListener] LUR.status: <PairedDevice(2,4013,M525)>: unifying connection notification: software=True, encrypted=False, link=False, payload=False
2013-05-03 10:08:19,609    DEBUG [ReceiverListener] solaar.listener: <UnifyingReceiver(/dev/hidraw0,8)>: status_changed <PairedDevice(2,4013,M525)>: inactive, Battery: 90% (0) 
Exception in thread monitor_async_handle_receivers_events:
Traceback (most recent call last):
  File "/usr/lib/python3.3/threading.py", line 639, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.3/threading.py", line 596, in run
    self._target(*self._args, **self._kwargs)
  File "/home/peter/projects/Solaar/lib/hidapi/udev.py", line 136, in monitor
    for action, device in m:
  File "/usr/lib/python3.3/site-packages/pyudev/monitor.py", line 410, in __iter__
    events = notifier.poll()
InterruptedError: [Errno 4] Interrupted system call

2013-05-03 10:08:19,625    DEBUG [ReceiverListener] LUR.base: (8) => r[10 01 4104 711020]
2013-05-03 10:08:19,626    DEBUG [ReceiverListener] LUR.status: <PairedDevice(1,2010,K800)>: unifying connection notification: software=True, encrypted=True, link=False, payload=False
2013-05-03 10:08:19,626    DEBUG [ReceiverListener] solaar.listener: <UnifyingReceiver(/dev/hidraw0,8)>: status_changed <PairedDevice(1,2010,K800)>: inactive, Battery: 90% (0) 
2013-05-03 10:08:20,127    DEBUG [ReceiverListener] solaar.listener: <UnifyingReceiver(/dev/hidraw0,8)>: polling status: [<PairedDevice(1,2010,K800)>, <PairedDevice(2,4013,M525)>]
2013-05-03 10:08:20,128  WARNING [ReceiverListener] solaar.listener: <UnifyingReceiver(/dev/hidraw0,8)>: possible sleep detected, closing this listener
2013-05-03 10:08:20,128     INFO [ReceiverListener] solaar.listener: <UnifyingReceiver(/dev/hidraw0,8)>: notifications listener has stopped
2013-05-03 10:08:20,128    DEBUG [ReceiverListener] LUR.base: (8) <= w[10 FF 8000 000000]
2013-05-03 10:08:20,131    DEBUG [ReceiverListener] LUR.base: (8) => r[10 FF 8000 000000]
2013-05-03 10:08:20,131    DEBUG [ReceiverListener] LUR.base: (8) <= w[10 FF 8100 000000]
2013-05-03 10:08:20,133    DEBUG [ReceiverListener] LUR.base: (8) => r[10 FF 8100 000000]
2013-05-03 10:08:20,133     INFO [ReceiverListener] LUR.receiver: <UnifyingReceiver(/dev/hidraw0,8)>: device notifications disabled ()
2013-05-03 10:08:20,133    DEBUG [ReceiverListener] LUR.listener: <_ThreadedHandle(/dev/hidraw0)> closing [8]

Wishlist

This are no bugs so much as Wishlist. If this is permitted, I have 3 wishes.

  1. To have an option that shows in the tray icon the battery percent and not just the battery icon and how much battery it has. This would save the user from having to click on the Solaar icon, then on the specific mouse option to see the percent.
  2. Have an option to show the percent right next to the name of the mouse when I click on the Solaar icon. For example, I have a Anywhere Mouse, so instead of just saying Anywhere Mouse, it would say "Anywhere Mouse - 25%". Saves me from having to click on it to see the percent.
  3. Have the ability to check how long the batteries lasted. This can be accomplished by resetting a timer that only starts when it detects the battery at 100%. When the percent is at 100% the timer starts and it will only reset itself when the percent makes a huge jump, for example, changing from 50% battery to 100% which would only mean I changed to new batteries or the mouse was charged. This would at least give an estimate of how long the batteries lasted and can give the user an idea to benchmark 2 things: How good a Logitech mouse uses certain batteries and how long certain batteries last.

Changing DPI doesn't work

At least on Kubuntu 13.04 (Solaar installed from PPA) with Performance MX.

Traceback (most recent call last):
  File "/usr/lib/python2.7/threading.py", line 552, in __bootstrap_inner
    self.run()
  File "/usr/lib/python2.7/threading.py", line 505, in run
    self.__target(*self.__args, **self.__kwargs)
  File "/opt/extras.ubuntu.com/solaar/share/solaar/lib/solaar/ui/config_panel.py", line 36, in _process_apply_queue
    value = setting.write(value)
  File "/opt/extras.ubuntu.com/solaar/share/solaar/lib/logitech/unifying_receiver/settings.py", line 58, in write
    data_bytes = self._validator.prepare_write(value)
  File "/opt/extras.ubuntu.com/solaar/share/solaar/lib/logitech/unifying_receiver/settings.py", line 164, in prepare_write
    raise ValueError("invalid choice " + repr(value))
ValueError: invalid choice ' 1500'

Show the battery percent in the systray icon

From #69:

To have an option that shows in the tray icon the battery percent and not just the battery icon and how much battery it has. This would save the user from having to click on the Solaar icon, then on the specific mouse option to see the percent.

gh-pages: typo in URL, lists look ugly

There is a small typo in the Launchpad URL on gh-pages, it lists httpwp://... instead of https://... I did not do a pull request as I do not know whether you need to manually edit those pages or via GH.

Text in <li> should not be wrapped in <p> , it now looks quite ugly (note the bullets):
screenshot

I haven't run it over http://validator.nu/, but it might be a good idea to uncover some formatting issues.

Notification do not always get processed and gets crazy with debug patch

I observe that a device does not get removed from the UI, nor does the debugging log show any indication that the Device Disconnection (0x40) notif is processed. I ran the ltunify unpair 1 tool in order to unpair device at device index 1.

My initial debugging attempts made me think that there is a race condition going on in notification processing, or that side-effects of functions str cause the thread to enter paths where it cannot process further notifications.
With the debugging patch on the bottom, but without the WTF LEVEL OVER 1000 line, I still got no notification although the I got eggs lines indicate that the notification got queued.

When the WTF LEVEL OVER 1000 line is present, my console got rapidly spammed with:

Traceback (most recent call last):
  File "/usr/lib/python3.3/site-packages/gi/overrides/GLib.py", line 629, in <lambda>
    return (lambda data: callback(*data), user_data)
  File "/home/peter/projects/Solaar/lib/solaar/ui/status_icon.py", line 86, in update
    receiver = device.receiver
AttributeError: '_GHOST_DEVICE' object has no attribute 'receiver'

The preceding messages:

2013-05-03 12:34:34,065    DEBUG [ReceiverListener] LUR.base: (8) => r[10 FF 8100 001900]
2013-05-03 12:34:34,067    DEBUG [ReceiverListener] LUR.base: (8) => r[10 01 4104 121340]
2013-05-03 12:34:34,067    DEBUG [ReceiverListener] LUR.listener: WTF LEVEL over 1000: Notification(1,41,04,121340)
2013-05-03 12:34:34,067    DEBUG [ReceiverListener] solaar.listener: WTF LEVEL 10000 Notification(1,41,04,121340)
2013-05-03 12:34:34,068    DEBUG [ReceiverListener] LUR.status: wtf is happening Notification(1,41,04,121340)
2013-05-03 12:34:34,068    DEBUG [ReceiverListener] LUR.status: <PairedDevice(1,4013,M525)>: unifying connection notification: software=True, encrypted=False, link=True, payload=False
2013-05-03 12:34:34,068    DEBUG [ReceiverListener] solaar.listener: <UnifyingReceiver(/dev/hidraw0,8)>: status_changed <PairedDevice(1,4013,M525)>: active, Battery: 90% <small>(discharging)</small> (0) 
2013-05-03 12:34:34,068    DEBUG [ReceiverListener] LUR.base: (8) <= w[10 01 0409 000000]
2013-05-03 12:34:34,069    DEBUG [ReceiverListener] LUR.base: (8) => r[10 FF 8002 000000]
2013-05-03 12:34:34,125    DEBUG [ReceiverListener] LUR.base: (8) => r[10 01 4002 000000]
2013-05-03 12:34:34,129    DEBUG [ReceiverListener] LUR.base: (8) => r[11 01 0409 5A050000000000000000000000000000]
2013-05-03 12:34:34,129    DEBUG [ReceiverListener] LUR.hidpp20: device 1 battery 90% charged, next level 5% charge, status 0 = discharging
2013-05-03 12:34:34,129    DEBUG [ReceiverListener] LUR.status: <PairedDevice(1,4013,M525)>: battery 90% charged, discharging
2013-05-03 12:34:34,129    DEBUG [ReceiverListener] solaar.listener: <UnifyingReceiver(/dev/hidraw0,8)>: status_changed <PairedDevice(1,4013,M525)>: active, Battery: 90% <small>(discharging)</small> (0) 
2013-05-03 12:34:34,130    DEBUG [ReceiverListener] LUR.listener: WTF LEVEL over 1000: Notification(1,40,02,000000)
2013-05-03 12:34:34,130    DEBUG [ReceiverListener] solaar.listener: WTF LEVEL 10000 Notification(1,40,02,000000)
2013-05-03 12:34:34,130    DEBUG [ReceiverListener] LUR.status: wtf is happening Notification(1,40,02,000000)
2013-05-03 12:34:34,130    DEBUG [ReceiverListener] solaar.listener: <UnifyingReceiver(/dev/hidraw0,8)>: status_changed <PairedDevice(1,4013,M525)>: inactive, None (FF) unpaired

read-dev-usbmon log:

12:34:34.063 Send       report_id=10 short device=FF RECV type=81 GET_REG                 reg=00 ENABLED_NOTIFS  params=00 00 00 
12:34:34.065 Recv       report_id=10 short device=FF RECV type=81 GET_REG                 reg=00 ENABLED_NOTIFS  params=00 19 00 
12:34:34.065 Send       report_id=10 short device=FF RECV type=80 SET_REG                 reg=02 CONNECTION_STATE  params=02 00 00 
12:34:34.067 Recv       report_id=10 short device=01 DEV1 type=41 NOTIF_DEVICE_PAIRED     params=04 12 13 40 
12:34:34.069 Recv       report_id=10 short device=FF RECV type=80 SET_REG                 reg=02 CONNECTION_STATE  params=00 00 00 
12:34:34.069 Send       report_id=10 short device=01 DEV1 type=04 SYSTEM_CONTROL          params=09 00 00 00 
12:34:34.069 Send       report_id=10 short device=FF RECV type=80 SET_REG                 reg=B2 DEVICE_PAIRING  params=03 01 00 
12:34:34.125 Recv       report_id=10 short device=01 DEV1 type=40 NOTIF_DEVICE_UNPAIRED   params=02 00 00 00 
12:34:34.127 Recv       report_id=20 unkn  device=01 DEV1 type=40 NOTIF_DEVICE_UNPAIRED   params=00 00 00 00  00 00 00 00  00 00 00 00 
12:34:34.129 Recv       report_id=11 long  device=01 DEV1 type=04 SYSTEM_CONTROL          params=09 5A 05 00  00 00 00 00  00 00 00 00  00 00 00 00  00

Debugging patch:

diff --git a/lib/logitech/unifying_receiver/base.py b/lib/logitech/unifying_receiver/base.py
index 2e841fa..f4db02b 100644
--- a/lib/logitech/unifying_receiver/base.py
+++ b/lib/logitech/unifying_receiver/base.py
@@ -349,6 +349,10 @@ def request(handle, devnumber, request_id, *params):

            if notifications_hook:
                n = make_notification(reply_devnumber, reply_data)
+               #print("I got eggs: " + str(reply_data) + " with " + str(n))
+               #print("Hook is: " + repr(notifications_hook));
+               #import traceback
+               #traceback.print_stack()
                if n:
                    notifications_hook(n)

diff --git a/lib/logitech/unifying_receiver/listener.py b/lib/logitech/unifying_receiver/listener.py
index ddf4515..4a44de8 100644
--- a/lib/logitech/unifying_receiver/listener.py
+++ b/lib/logitech/unifying_receiver/listener.py
@@ -153,6 +153,7 @@ class EventsListener(_threading.Thread):
                n = self._queued_notifications.get()

            if n:
+               _log.debug("WTF LEVEL over 1000: " + str(n))
                # if _log.isEnabledFor(_DEBUG):
                #   _log.debug("%s: processing %s", self.receiver, n)
                try:
diff --git a/lib/logitech/unifying_receiver/status.py b/lib/logitech/unifying_receiver/status.py
index fe73d10..10d9b83 100644
--- a/lib/logitech/unifying_receiver/status.py
+++ b/lib/logitech/unifying_receiver/status.py
@@ -210,6 +210,7 @@ class DeviceStatus(dict):
        assert n.sub_id < 0x80

        # 0x40 to 0x7F appear to be HID++ 1.0 notifications
+       _log.debug("wtf is happening " + str(n));
        if n.sub_id >= 0x40:
            return self._process_hidpp10_notification(n)

diff --git a/lib/solaar/listener.py b/lib/solaar/listener.py
index 740c052..fafcd1f 100644
--- a/lib/solaar/listener.py
+++ b/lib/solaar/listener.py
@@ -117,6 +117,7 @@ class ReceiverListener(_listener.EventsListener):

    def _notifications_handler(self, n):
        assert self.receiver
+       _log.debug("WTF LEVEL 10000 " + str(n))
        # _log.debug("%s: handling %s", self.receiver, n)
        if n.devnumber == 0xFF:
            # a receiver notification

Consistently use byte/str everywhere

Python2 and python3 differ in the handling of bytes and unicode. In python2, unicode is not equal to str. In Python3, bytes are not equal to str:

$ for v in 2 3; do python$v -c "print(type(u''), type(b''), type(''))";done
(<type 'unicode'>, <type 'str'>, <type 'str'>)
<class 'str'> <class 'bytes'> <class 'str'>
$ for v in 2 3; do echo|python$v -c $'import os\nprint(type(os.read(0, 1)))';done
<type 'str'>
<class 'bytes'>

Todo:

  • read in hidapi/udev.py returns type bytes on Python3 instead of str.
  • Change every check for type(foo) == unicode or type(foo) == str (or isinstance). unicode has gone in Python3, this became str. isinstance('', bytes) is True for python2, but False in python3.
  • Currently bytes are printed verbatim (in hidconsole at least). On Python 2 one could see '\xffX' where python 3 shows b'\xffX'. Changing it to '\xff\x58' would give a more consistent output, but I think you did this to spot text easier in the protocol. Does it matter that the output is different?

Possible helpful resources:

Doesn't get root access by himself (Ubuntu)

Hello,

Solaar doesn't get root access but he need it.

Of course the reflex is to execute "sudo solaar" in a terminal, but the real command is not solaar.

# Here is a (bad) solution
sudo /opt/extras.ubuntu.com/solaar/bin/solaar

Some icons is not displayed in Kubuntu

That probably packaging issue (Solaar installed from PPA) because some despondency left:

solaar

Icon in tray and also icon of Quit item in tray menu is not displayed.

Gnome 3 / gnome-shell support

Solaar does not integrate well into Gnome3 at the moment. Even with the Icon Whitelist it isn't really useable. Since i have 3 devices with unified support it would be great to have this great program work in my prefered environment.

Replace systray icon with battery status

Is it possible to replace the systray-solaar-icon with the battery symbol if only one device is connected (or show the battery status for the device with lowest battery level) if no device with solar cell is present?

Or show the battery levels of each connectet device in the tooltip?

Update icon for better rendering

Hi,

Please update icon of solar to 256x256 or provide a svg file.
For now, under GNOME3, rendering is not smooth because of the icon enlargement.

Thanks!

Show the battery percent in the devices tree

From #69:

Have an option to show the percent right next to the name of the mouse when I click on the Solaar icon. For example, I have a Anywhere Mouse, so instead of just saying Anywhere Mouse, it would say "Anywhere Mouse - 25%". Saves me from having to click on it to see the percent.

Command line switch for hiding main window on startup

Would be nice to be able to start the gui part minimized to system tray instead of showing the main window on startup. As -h for --hidden is a bad idea, what's about -M and --no-mainwindow?

Thank's a lot for this great tool - really makes me enjoy my logitech mouse...

Btw.:
The tool doesn't report the battery level on my mouse (Performance MX) - if i can help with that in any way please let me know...

Solved: Main window is empty on second opening

When starting solaar (with 'python solaar' in the bin dir (which means python3)) and opening the main window for the first time, everything is working fine:

bildschirmfoto1

As soon as I close the main window and reopen it, it's empty:

bildschirmfoto2

Console log says:

** (solaar:2765): WARNING **: Error retrieving accessibility bus address: org.freedesktop.DBus.Error.ServiceUnknown: The name org.a11y.Bus was not provided by any .service files

(solaar:2765): Gtk-WARNING **: Error loading theme icon 'Unifying Receiver' for stock: Symbol »Unifying Receiver« nicht im Thema vorhanden

(solaar:2765): Gtk-WARNING **: Error loading theme icon 'Performance Mouse MX' for stock: Symbol »Performance Mouse MX« nicht im Thema vorhanden
TypeError: _hide() takes exactly 1 argument (2 given)

** (solaar:2765): CRITICAL **: atk_bridge_adaptor_cleanup: assertion `inited' failed

(last error is on closing solaar with right click on systray icon -> quit)

Update: seems to be solved by latest commits...

Low battery notification

(some code paths are related to #27)

Currently the battery status in the UI is updated unconditionally. If a the battery status is not changed, it is still overwritten.

If notifications for low battery levels are added, it is probably not a bad idea to compare the values before setting them (relying on notifications preventing duplication is not enough, if the battery level keeps updated, the user would get annoyed by many notifications).

Update PKGBUILD for Archlinux

The PKGBUILD for the stable release of Solaar, included in git repo, is obsolete:
with systemd the udev rules are automatically reloaded, install script is no needed
This PKGBUILD is enough

pkgname=solaar
pkgver=0.8.8.1
pkgrel=1
pkgdesc="Device manager for Logitech's Unifying receiver peripherals"
url="http://pwr.github.com/Solaar/"
license=('GPL2')
groups=()
arch=('any')
depends=('python' 'python-pyudev' 'python-gobject' 'pygtk')
makedepends=('python')
options=(!emptydirs)
source=("https://github.com/pwr/Solaar/archive/${pkgver}.tar.gz")
md5sums=('2fee5353702b32e6958a51c2e603178f')

package() {
  cd "$srcdir/Solaar-${pkgver}/"
  python3 setup.py install --root="$pkgdir/" --optimize=1
  install -d "${pkgdir}"/usr/lib/udev/rules.d/
  install -m644 rules.d/99-logitech-unifying-receiver.rules "${pkgdir}"/usr/lib/udev/rules.d/99-logitech-unifying-receiver.rules
}

Use notifications instead of polling for determining battery status

I can confirm seeing a 07 register notification when the battery drops from three bars ("full" /"90%") to two bars ("good" / "50%"). This required setting the Battery Status flag in the HID++ notifications register of the device (K800).

Does HID++ 2.0 have similar notifications?

Concurrent device access causes interference between programs

When I tried to run scan-registers.sh while solar was running, it tagges wrong messages as a response to another (solar periodically reads the battery register 07).

Part of the solution:

  • Use the following hints to match responses and requests:
    • the device index, type and register.
    • in case type=ERROR_MSG (8F), compare the device index and the Sub ID plus register of the error message to the request.
  • Let messages be asynchronous (in a dedicated I/O thread?), on submission it will be queued. A queue item could have the attributes time of submission (for expirity), a callback function and the actual message.

Build 0.8.8-3 crash

Build 0.8.8-3 (latest update in PPA) is crash for me in Kubuntu 13.04 x86_64:

Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/gi/overrides/GLib.py", line 629, in <lambda>
    return (lambda data: callback(*data), user_data)
  File "/opt/extras.ubuntu.com/solaar/share/solaar/lib/solaar/ui/status_icon.py", line 199, in update
    _update_image(icon)
  File "/opt/extras.ubuntu.com/solaar/share/solaar/lib/solaar/ui/status_icon.py", line 113, in _update_image
    icon.set_from_pixbuf(_icon_with_battery(battery_level, bool(battery_status)))
  File "/opt/extras.ubuntu.com/solaar/share/solaar/lib/solaar/ui/status_icon.py", line 78, in _icon_with_battery
    assert mask

Please let me know if I need to provide additional data.

Logitech Wireless Keyboard MK700 Fn functionality

Hi, I've just bought myself a new Logitech combo, MK710. Which is a K710 Keyboard and a M705 Mouse. I've ditched the mouse for a Performance MX mouse instead and with Solaar it works fine to switch the DPI so thanks for that.. 👍
But I'm trying to find a way to switch the Fn functionality for the keyboard. As I see your script should be able to handle that, but I guess it needs some identifier in the code to see that it's a K710 and that it has this ability as of now with 0.8.7 it tells me that there is no options for this keyboard.

Can I provide any information for you to make this happen? In case which information do you need and how to get it.. :)

Solaar is not able to show the battery status for either the mouse or the keyboard, saw that you had a post about the mouse here already so I guess there is no need to add a new one for that.

[solaar -dd]
2013-04-13 20:54:09,804 INFO [MainThread] root: starting desktop notifications
2013-04-13 20:54:09,890 INFO [ReceiverListener] LUR.listener: started with <Receiver(/dev/hidraw1,T12)> (12)
2013-04-13 20:54:09,890 INFO [ReceiverListener] listener: notifications listener has started
2013-04-13 20:54:09,890 DEBUG [ReceiverListener] LUR.base: (12) <= w[10 FF 8000 FFFFFF]
2013-04-13 20:54:09,894 DEBUG [ReceiverListener] LUR.base: (12) => r[10 FF 8000 000000]
2013-04-13 20:54:09,894 INFO [ReceiverListener] LUR.receiver: device notifications enabled
2013-04-13 20:54:09,894 DEBUG [ReceiverListener] LUR.base: (12) <= w[10 FF 8002 020000]
2013-04-13 20:54:09,896 DEBUG [ReceiverListener] LUR.base: (12) => r[10 02 4104 310820]
2013-04-13 20:54:09,896 DEBUG [ReceiverListener] LUR.listener: queueing unhandled Notification(2,41,04,310820)
2013-04-13 20:54:09,898 DEBUG [ReceiverListener] LUR.base: (12) => r[10 03 4104 121A10]
2013-04-13 20:54:09,898 DEBUG [ReceiverListener] LUR.listener: queueing unhandled Notification(3,41,04,121A10)
2013-04-13 20:54:09,900 DEBUG [ReceiverListener] LUR.base: (12) => r[10 FF 8002 000000]
2013-04-13 20:54:09,900 DEBUG [ReceiverListener] listener: status_changed <Receiver(/dev/hidraw1,T12)>: active No devices found. (1)
2013-04-13 20:54:09,900 DEBUG [ReceiverListener] LUR.base: (12) <= w[10 FF 83B5 210000]
2013-04-13 20:54:09,902 DEBUG [ReceiverListener] LUR.base: (12) => r[11 FF 83B5 21081420080400010700000000000000]
2013-04-13 20:54:09,902 INFO [ReceiverListener] LUR.receiver: found device 2 (2008)
2013-04-13 20:54:09,902 DEBUG [ReceiverListener] LUR.base: (12) pinging device 2
2013-04-13 20:54:09,902 DEBUG [ReceiverListener] LUR.base: (12) <= w[10 02 0019 000094]
2013-04-13 20:54:10,294 DEBUG [ReceiverListener] LUR.base: (12) => r[10 02 8F00 190100]
2013-04-13 20:54:10,294 DEBUG [ReceiverListener] LUR.base: (12) <= w[10 FF 83B5 410000]
2013-04-13 20:54:10,296 DEBUG [ReceiverListener] LUR.base: (12) => r[11 FF 83B5 41054D4B373030000000000000000000]
2013-04-13 20:54:10,296 DEBUG [ReceiverListener] listener: status_changed <Receiver(/dev/hidraw1,T12)>: active 1 device found. (0)
2013-04-13 20:54:10,296 DEBUG [ReceiverListener] LUR.status: <PairedDevice(2,MK700)>: connection notification: software=True, encrypted=True, link=True, payload=False
2013-04-13 20:54:10,296 DEBUG [ReceiverListener] listener: status_changed <PairedDevice(2,MK700)>: active (1)
2013-04-13 20:54:10,296 DEBUG [ReceiverListener] LUR.base: (12) <= w[10 FF 83B5 220000]
2013-04-13 20:54:10,300 DEBUG [ReceiverListener] LUR.base: (12) => r[11 FF 83B5 220908101A0400020600000000000000]
2013-04-13 20:54:10,300 INFO [ReceiverListener] LUR.receiver: found device 3 (101A)
2013-04-13 20:54:10,300 DEBUG [ReceiverListener] LUR.base: (12) pinging device 3
2013-04-13 20:54:10,300 DEBUG [ReceiverListener] LUR.base: (12) <= w[10 03 001C 00008E]
2013-04-13 20:54:10,877 INFO [MainThread] root: size-chagend None <Window object at 0x14a7230 (GtkWindow at 0x14c90d0)>
2013-04-13 20:54:11,128 INFO [MainThread] root: check_systray True True
2013-04-13 20:54:11,948 DEBUG [ReceiverListener] LUR.base: (12) => r[10 03 8F00 1C0100]
2013-04-13 20:54:11,948 DEBUG [ReceiverListener] LUR.base: (12) <= w[10 FF 83B5 420000]
2013-04-13 20:54:11,950 DEBUG [ReceiverListener] LUR.base: (12) => r[11 FF 83B5 420E506572666F726D616E6365204D58]
2013-04-13 20:54:11,950 DEBUG [ReceiverListener] listener: status_changed <Receiver(/dev/hidraw1,T12)>: active 2 devices found. (0)
2013-04-13 20:54:11,950 DEBUG [ReceiverListener] LUR.status: <PairedDevice(3,Performance MX)>: connection notification: software=True, encrypted=False, link=True, payload=False
2013-04-13 20:54:11,950 DEBUG [ReceiverListener] listener: status_changed <PairedDevice(3,Performance MX)>: active (1)
2013-04-13 20:54:13,953 DEBUG [ReceiverListener] LUR.base: (12) <= w[10 FF 83B5 200000]
2013-04-13 20:54:13,956 DEBUG [ReceiverListener] LUR.base: (12) => r[10 FF 8F83 B50300]
2013-04-13 20:54:13,956 DEBUG [ReceiverListener] LUR.base: (12) device 0xFF error on request {83B5}: 3 = invalid value
2013-04-13 20:54:13,956 DEBUG [ReceiverListener] LUR.base: (12) <= w[10 FF 83B5 230000]
2013-04-13 20:54:13,958 DEBUG [ReceiverListener] LUR.base: (12) => r[10 FF 8F83 B50300]
2013-04-13 20:54:13,958 DEBUG [ReceiverListener] LUR.base: (12) device 0xFF error on request {83B5}: 3 = invalid value
2013-04-13 20:54:13,958 DEBUG [ReceiverListener] LUR.base: (12) <= w[10 FF 83B5 240000]
2013-04-13 20:54:13,960 DEBUG [ReceiverListener] LUR.base: (12) => r[10 FF 8F83 B50300]
2013-04-13 20:54:13,960 DEBUG [ReceiverListener] LUR.base: (12) device 0xFF error on request {83B5}: 3 = invalid value
2013-04-13 20:54:13,960 DEBUG [ReceiverListener] LUR.base: (12) <= w[10 FF 83B5 250000]
2013-04-13 20:54:13,962 DEBUG [ReceiverListener] LUR.base: (12) => r[10 FF 8F83 B50300]
2013-04-13 20:54:13,962 DEBUG [ReceiverListener] LUR.base: (12) device 0xFF error on request {83B5}: 3 = invalid value
2013-04-13 20:54:13,962 DEBUG [ReceiverListener] listener: polling status: <Receiver(/dev/hidraw1,T12)> [<PairedDevice(2,MK700)>, <PairedDevice(3,Performance MX)>]
2013-04-13 20:54:13,962 DEBUG [ReceiverListener] LUR.base: (12) <= w[10 FF 83B5 030000]
2013-04-13 20:54:13,966 DEBUG [ReceiverListener] LUR.base: (12) => r[11 FF 83B5 03998C9E670106090000000000000000]
2013-04-13 20:54:13,966 DEBUG [ReceiverListener] LUR.base: (12) <= w[10 FF 81F1 010000]
2013-04-13 20:54:13,968 DEBUG [ReceiverListener] LUR.base: (12) => r[10 FF 81F1 012400]
2013-04-13 20:54:13,968 DEBUG [ReceiverListener] LUR.base: (12) <= w[10 FF 81F1 020000]
2013-04-13 20:54:13,970 DEBUG [ReceiverListener] LUR.base: (12) => r[10 FF 81F1 020018]
2013-04-13 20:54:13,970 DEBUG [ReceiverListener] LUR.base: (12) <= w[10 FF 81F1 040000]
2013-04-13 20:54:13,972 DEBUG [ReceiverListener] LUR.base: (12) => r[10 FF 81F1 040006]
2013-04-13 20:54:13,972 DEBUG [ReceiverListener] LUR.base: (12) <= w[10 FF 83B5 310000]
2013-04-13 20:54:13,974 DEBUG [ReceiverListener] LUR.base: (12) => r[11 FF 83B5 31FCEBB1811A41000003000000000000]
2013-04-13 20:54:13,974 DEBUG [ReceiverListener] LUR.base: (12) <= w[10 02 81F1 010000]
2013-04-13 20:54:14,344 DEBUG [ReceiverListener] LUR.base: (12) => r[10 02 81F1 012500]
2013-04-13 20:54:14,344 DEBUG [ReceiverListener] LUR.base: (12) <= w[10 02 81F1 020000]
2013-04-13 20:54:14,548 DEBUG [ReceiverListener] LUR.base: (12) => r[10 02 81F1 020009]
2013-04-13 20:54:14,548 DEBUG [ReceiverListener] LUR.base: (12) <= w[10 02 81F1 040000]
2013-04-13 20:54:14,748 DEBUG [ReceiverListener] LUR.base: (12) => r[10 02 81F1 040203]
2013-04-13 20:54:14,748 DEBUG [ReceiverListener] LUR.base: (12) <= w[10 02 810D 000000]
2013-04-13 20:54:14,950 DEBUG [ReceiverListener] LUR.base: (12) => r[10 02 8F81 0D0200]
2013-04-13 20:54:14,950 DEBUG [ReceiverListener] LUR.base: (12) device 0x02 error on request {810D}: 2 = invalid address
2013-04-13 20:54:14,950 DEBUG [ReceiverListener] LUR.base: (12) pinging device 2
2013-04-13 20:54:14,950 DEBUG [ReceiverListener] LUR.base: (12) <= w[10 02 001A 000054]
2013-04-13 20:54:15,154 DEBUG [ReceiverListener] LUR.base: (12) => r[10 02 8F00 1A0100]
2013-04-13 20:54:15,154 WARNING [ReceiverListener] LUR.hidpp10: <PairedDevice(2,MK700)>: failed to read 'battery' from default register 0x0D, blacklisting
2013-04-13 20:54:15,154 DEBUG [ReceiverListener] LUR.base: (12) <= w[10 02 8107 000000]
2013-04-13 20:54:15,356 DEBUG [ReceiverListener] LUR.base: (12) => r[10 02 8107 070000]
2013-04-13 20:54:15,356 INFO [ReceiverListener] LUR.hidpp10: <PairedDevice(2,MK700)>: battery status 07
2013-04-13 20:54:15,356 DEBUG [ReceiverListener] LUR.base: (12) <= w[10 FF 83B5 320000]
2013-04-13 20:54:15,360 DEBUG [ReceiverListener] LUR.base: (12) => r[11 FF 83B5 32007423710400000001000000000000]
2013-04-13 20:54:15,360 DEBUG [ReceiverListener] LUR.base: (12) <= w[10 03 81F1 010000]
2013-04-13 20:54:15,372 DEBUG [ReceiverListener] LUR.base: (12) => r[10 03 81F1 011501]
2013-04-13 20:54:15,372 DEBUG [ReceiverListener] LUR.base: (12) <= w[10 03 81F1 020000]
2013-04-13 20:54:15,388 DEBUG [ReceiverListener] LUR.base: (12) => r[10 03 81F1 020062]
2013-04-13 20:54:15,388 DEBUG [ReceiverListener] LUR.base: (12) <= w[10 03 81F1 040000]
2013-04-13 20:54:15,404 DEBUG [ReceiverListener] LUR.base: (12) => r[10 03 81F1 040211]
2013-04-13 20:54:15,404 DEBUG [ReceiverListener] LUR.base: (12) <= w[10 03 810D 000000]
2013-04-13 20:54:15,420 DEBUG [ReceiverListener] LUR.base: (12) => r[10 03 8F81 0D0200]
2013-04-13 20:54:15,420 DEBUG [ReceiverListener] LUR.base: (12) device 0x03 error on request {810D}: 2 = invalid address
2013-04-13 20:54:15,420 DEBUG [ReceiverListener] LUR.base: (12) pinging device 3
2013-04-13 20:54:15,420 DEBUG [ReceiverListener] LUR.base: (12) <= w[10 03 001A 0000EA]
2013-04-13 20:54:15,438 DEBUG [ReceiverListener] LUR.base: (12) => r[10 03 8F00 1A0100]
2013-04-13 20:54:15,438 WARNING [ReceiverListener] LUR.hidpp10: <PairedDevice(3,Performance MX)>: failed to read 'battery' from default register 0x0D, blacklisting
2013-04-13 20:54:15,438 DEBUG [ReceiverListener] LUR.base: (12) <= w[10 03 8107 000000]
2013-04-13 20:54:15,454 DEBUG [ReceiverListener] LUR.base: (12) => r[10 03 8107 050000]
2013-04-13 20:54:15,454 INFO [ReceiverListener] LUR.hidpp10: <PairedDevice(3,Performance MX)>: battery status 05
2013-04-13 20:55:15,529 DEBUG [ReceiverListener] listener: polling status: <Receiver(/dev/hidraw1,T12)> [<PairedDevice(2,MK700)>, <PairedDevice(3,Performance MX)>]
2013-04-13 20:55:15,529 DEBUG [ReceiverListener] LUR.base: (12) <= w[10 02 8107 000000]
2013-04-13 20:55:15,880 DEBUG [ReceiverListener] LUR.base: (12) => r[10 02 8107 070000]
2013-04-13 20:55:15,880 INFO [ReceiverListener] LUR.hidpp10: <PairedDevice(2,MK700)>: battery status 07
2013-04-13 20:55:15,880 DEBUG [ReceiverListener] LUR.base: (12) <= w[10 03 8107 000000]
2013-04-13 20:55:15,976 DEBUG [ReceiverListener] LUR.base: (12) => r[10 03 8107 050000]
2013-04-13 20:55:15,976 INFO [ReceiverListener] LUR.hidpp10: <PairedDevice(3,Performance MX)>: battery status 05
2013-04-13 20:55:52,523 INFO [ReceiverListener] listener: notifications listener has stopped
2013-04-13 20:55:52,523 DEBUG [ReceiverListener] LUR.base: (12) <= w[10 FF 8000 000000]
2013-04-13 20:55:52,525 DEBUG [ReceiverListener] LUR.base: (12) => r[10 FF 8000 000000]
2013-04-13 20:55:52,525 INFO [ReceiverListener] LUR.receiver: device notifications disabled
2013-04-13 20:55:52,525 DEBUG [ReceiverListener] LUR.listener: <ThreadedHandle(/dev/hidraw1)> closing [11, 12]
2013-04-13 20:55:52,525 DEBUG [ReceiverListener] listener: status_changed None: None None (1)
2013-04-13 20:55:52,525 INFO [MainThread] root: stopping desktop notifications
[/solaar -dd]

Support for Nano Receiver and M215 (Logitech Connection Utility)

My Logitech M215 works well with Solaar and some other old nanoreceiver periphericals (like my Logitech M215) works with Unifyng Receiver but after isn't possible reconnect with nano receiver via Solaar
Under Windows is possible with Logitech Connection Utility...
http://www.logitech.com/en-us/support/articles/3516
Under Linux is possible with lomoco using lomoco_reconnect.c :
http://blog.cryptomilk.org/2011/02/22/logitech-linux-mouse-support/
Please support Nano Receiver using lomoco

Support reprogrammable keys

As requested in http://superuser.com/q/466253/47108.

The keyboards seem to allow changing the functionality of Fn + Fx keys, instead of "Email", another event is generated (I haven't checked whether this is a regular keymapping that is sent to the input layer or only a HID++ notification).

I will probably start working on this next week.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.