Skip to content

Commit 4051ba9

Browse files
committed
Try to open device O_RDONLY open if O_RDWR fails
Methods that require write access are wrapped with the 'needs_write' decorator.
1 parent ba068fd commit 4051ba9

2 files changed

Lines changed: 37 additions & 3 deletions

File tree

doc/changelog.rst

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
11
Changelog
22
=========
33

4-
0.4.7 (Oct 07, 2015)
4+
0.5.0 (Jun 16, 2015)
5+
^^^^^^^^^^^^^^^^^^^^
6+
7+
- Write access to the input device is no longer mandatory. Evdev will
8+
first try to open the device for reading and writing and fallback to
9+
read-only. Methods that require write access (e.g. ``set_led()``)
10+
will raise ``EvdevError`` if the device is open only for reading.
11+
12+
0.4.7 (Oct 07, 2014)
513
^^^^^^^^^^^^^^^^^^^^
614

715
- Fallback to distutils if setuptools is not available.
@@ -13,7 +21,7 @@ Changelog
1321

1422
- Fix install on Python 3.4 (works around issue21121_).
1523

16-
- Fix ioctl() requested buffer size (thanks Jakub Wojciech Klama).
24+
- Fix ``ioctl()`` requested buffer size (thanks Jakub Wojciech Klama).
1725

1826
0.4.5 (Jul 06, 2014)
1927
^^^^^^^^^^^^^^^^^^^^

evdev/device.py

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
11
# encoding: utf-8
22

33
import os
4+
import fcntl
45
from select import select
56
from collections import namedtuple
67

78
from evdev import _input, _uinput, ecodes, util
89
from evdev.events import InputEvent
910

1011

12+
#--------------------------------------------------------------------------
13+
class EvdevError(Exception):
14+
pass
15+
1116
#--------------------------------------------------------------------------
1217
_AbsInfo = namedtuple('AbsInfo', ['value', 'min', 'max', 'fuzz', 'flat', 'resolution'])
1318
_KbdInfo = namedtuple('KbdInfo', ['repeat', 'delay'])
@@ -89,8 +94,15 @@ def __init__(self, dev):
8994
#: Path to input device.
9095
self.fn = dev
9196

97+
# Certain operations are possible only when the device is opened in
98+
# read-write mode.
99+
try:
100+
fd = os.open(dev, os.O_RDWR | os.O_NONBLOCK)
101+
except OSError:
102+
fd = os.open(dev, os.O_RDONLY | os.O_NONBLOCK)
103+
92104
#: A non-blocking file descriptor to the device file.
93-
self.fd = os.open(dev, os.O_RDWR | os.O_NONBLOCK)
105+
self.fd = fd
94106

95107
# Returns (bustype, vendor, product, version, name, phys, capabilities).
96108
info_res = _input.ioctl_devinfo(self.fd)
@@ -177,6 +189,19 @@ def capabilities(self, verbose=False, absinfo=True):
177189
else:
178190
return self._capabilities(absinfo)
179191

192+
def need_write(func):
193+
'''
194+
Decorator that raises EvdevError() if there is no write access to the
195+
input device.
196+
'''
197+
def wrapper(*args):
198+
fd = args[0].fd
199+
if fcntl.fcntl(fd, fcntl.F_GETFL) & os.O_RDWR:
200+
return func(*args)
201+
msg = 'no write access to device "%s"' % args[0].fn
202+
raise EvdevError(msg)
203+
return wrapper
204+
180205
def leds(self, verbose=False):
181206
'''
182207
Return currently set LED keys. For example::
@@ -195,6 +220,7 @@ def leds(self, verbose=False):
195220

196221
return leds
197222

223+
@need_write
198224
def set_led(self, led_num, value):
199225
'''
200226
Set the state of the selected LED. For example::

0 commit comments

Comments
 (0)