diff --git a/app/solaar.py b/app/solaar.py index 80930c09..d6f70676 100644 --- a/app/solaar.py +++ b/app/solaar.py @@ -83,7 +83,11 @@ if __name__ == '__main__': global listener, notify_missing if listener is None: - listener = ReceiverListener.open(status_changed) + try: + listener = ReceiverListener.open(status_changed) + except OSError: + ui.show_permissions_warning(window) + if listener is None: pairing.state = None if notify_missing: diff --git a/app/ui/__init__.py b/app/ui/__init__.py index f5bf6f6e..ffdf545a 100644 --- a/app/ui/__init__.py +++ b/app/ui/__init__.py @@ -26,6 +26,16 @@ def icon_file(name): return None +def show_permissions_warning(window): + text = ('Found a possible Unifying Receiver device,\n' + 'but did not have permission to open it.') + + m = Gtk.MessageDialog(window, Gtk.DialogFlags.MODAL, Gtk.MessageType.ERROR, Gtk.ButtonsType.CLOSE, text) + m.set_title('Permissions error') + m.run() + m.destroy() + + def find_children(container, *child_names): assert container is not None diff --git a/lib/hidapi/udev.py b/lib/hidapi/udev.py index 46316cce..0f4f3f57 100644 --- a/lib/hidapi/udev.py +++ b/lib/hidapi/udev.py @@ -120,10 +120,7 @@ def open_path(device_path): :returns: an opaque device handle, or ``None``. """ - try: - return _os.open(device_path, _os.O_RDWR | _os.O_SYNC) - except: - pass + return _os.open(device_path, _os.O_RDWR | _os.O_SYNC) def close(device_handle): diff --git a/lib/logitech/unifying_receiver/api.py b/lib/logitech/unifying_receiver/api.py index 21b71d56..59096505 100644 --- a/lib/logitech/unifying_receiver/api.py +++ b/lib/logitech/unifying_receiver/api.py @@ -4,6 +4,7 @@ from struct import pack as _pack from struct import unpack as _unpack +import errno as _errno from . import base as _base @@ -164,10 +165,22 @@ class Receiver(object): :returns: An open file handle for the found receiver, or ``None``. """ + exception = None + for rawdevice in _base.list_receiver_devices(): - handle = _base.try_open(rawdevice.path) - if handle: - return Receiver(handle, rawdevice.path) + exception = None + try: + handle = _base.try_open(rawdevice.path) + if handle: + return Receiver(handle, rawdevice.path) + except OSError as e: + _log.exception("open %s", rawdevice.path) + if e.errno == _errno.EACCES: + exception = e + + if exception: + # only keep the last exception + raise exception # #