Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions doc/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -610,9 +610,11 @@ A :any:`SysfsGPIO` resource describes a GPIO line.

SysfsGPIO:
index: 12
invert: False

Arguments:
- index (int): index of the GPIO line
- invert (bool, default=False): optional, whether the logic level is inverted(active-low)

Used by:
- `GpioDigitalOutputDriver`_
Expand All @@ -636,6 +638,7 @@ USB based gpiochips.
'@SUBSYSTEM': 'usb'
'@ID_SERIAL_SHORT': 'D38EJ8LF'
pin: 0
invert: False

The example would search for a USB gpiochip with the key `ID_SERIAL_SHORT`
and the value `D38EJ8LF` and use the pin 0 of this device.
Expand All @@ -644,6 +647,7 @@ The `ID_SERIAL_SHORT` property is set by the usb_id builtin helper program.
Arguments:
- match (dict): key and value pairs for a udev match, see `udev Matching`_
- pin (int): gpio pin number within the matched gpiochip.
- invert (bool, default=False): optional, whether the logic level is inverted (active-low)

Used by:
- `GpioDigitalOutputDriver`_
Expand Down
3 changes: 2 additions & 1 deletion examples/sysfsgpio/export-gpio.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
desk:
GpioDigitalOutputDriver:
SysfsGPIO:
index: 60
invert: False
2 changes: 0 additions & 2 deletions examples/sysfsgpio/import-gpio.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,3 @@ targets:
name: gpio
drivers:
GpioDigitalOutputDriver: {}
options:
coordinator_address: 'labgrid:20408'
3 changes: 2 additions & 1 deletion examples/sysfsgpio/sysfsgpio.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@
StepLogger.start()

t = Target("main")
r = SysfsGPIO(t, name=None, index=60)
r = SysfsGPIO(t, name=None, index=60, invert=True)
d = GpioDigitalOutputDriver(t, name=None)

p = t.get_driver("DigitalOutputProtocol")
print(t.resources)
print("Testing IO")
p.set(True)
print(p.get())
time.sleep(2)
Expand Down
1 change: 1 addition & 0 deletions examples/sysfsgpio/sysfsgpio_remote.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

p = t.get_driver("DigitalOutputProtocol")
print(t.resources)
print("Testing IO")
p.set(True)
print(p.get())
time.sleep(2)
Expand Down
4 changes: 2 additions & 2 deletions labgrid/driver/gpiodriver.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ def on_deactivate(self):
@Driver.check_active
@step(args=['status'])
def set(self, status):
self.proxy.set(self.gpio.index, status)
self.proxy.set(self.gpio.index, self.gpio.invert, status)

@Driver.check_active
@step(result=True)
def get(self):
return self.proxy.get(self.gpio.index)
return self.proxy.get(self.gpio.index, self.gpio.invert)
3 changes: 3 additions & 0 deletions labgrid/remote/exporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -642,16 +642,19 @@ def _get_params(self):
return {
"host": self.host,
"index": self.local.index,
"invert": self.local.invert,
}

def _get_start_params(self):
return {
"index": self.local.index,
"invert": self.local.invert,
}

def _start(self, start_params):
"""Start a GPIO export to userspace"""
index = start_params["index"]
invert = start_params["invert"] # pylint: disable=unused-variable

if self.export_path.exists():
self.system_exported = True
Expand Down
4 changes: 3 additions & 1 deletion labgrid/resource/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,7 @@ class SysfsGPIO(Resource):
"""The basic SysfsGPIO contains an index

Args:
index (int): index of target gpio line."""
index (int): index of target gpio line.
invert (bool) : optional, whether the logic level is inverted (active-low)"""
index = attr.ib(default=None, validator=attr.validators.instance_of(int))
invert = attr.ib(default=False, validator=attr.validators.instance_of(bool))
1 change: 1 addition & 0 deletions labgrid/resource/remote.py
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,7 @@ class NetworkSysfsGPIO(NetworkResource, ManagedResource):

"""The NetworkSysfsGPIO describes a remotely accessible gpio line"""
index = attr.ib(validator=attr.validators.optional(attr.validators.instance_of(int)))
invert = attr.ib(default=False, validator=attr.validators.instance_of(bool))
def __attrs_post_init__(self):
self.timeout = 10.0
super().__attrs_post_init__()
Expand Down
4 changes: 3 additions & 1 deletion labgrid/resource/udev.py
Original file line number Diff line number Diff line change
Expand Up @@ -778,8 +778,10 @@ class MatchedSysfsGPIO(USBResource):
"""The MatchedSysfsGPIO described a SysfsGPIO matched by Udev

Args:
pin (int): gpio pin number within the matched gpiochip."""
pin (int): gpio pin number within the matched gpiochip.
invert (bool): optional, whether the logic level is inverted (active-low)"""
pin = attr.ib(default=None, validator=attr.validators.instance_of(int))
invert = attr.ib(default=False, validator=attr.validators.instance_of(bool))
index = None

def __attrs_post_init__(self):
Expand Down
21 changes: 12 additions & 9 deletions labgrid/util/agents/sysfsgpio.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
This module implements switching GPIOs via sysfs GPIO kernel interface.

Takes an integer property 'index' which refers to the already exported GPIO device.
Takes a boolean property 'invert' which inverts logical values if set to True (active-low)

"""
import logging
Expand All @@ -23,7 +24,7 @@ def _assert_gpio_line_is_exported(index):
if not os.path.exists(gpio_sysfs_path):
raise ValueError("Device not found")

def __init__(self, index):
def __init__(self, index, invert):
self.gpio_sysfs_value_fd = None
self._logger = logging.getLogger("Device: ")
GpioDigitalOutput._assert_gpio_line_is_exported(index)
Expand All @@ -41,6 +42,10 @@ def __init__(self, index):
gpio_sysfs_value_path = os.path.join(gpio_sysfs_path, 'value')
self.gpio_sysfs_value_fd = os.open(gpio_sysfs_value_path, flags=(os.O_RDWR | os.O_SYNC))

gpio_sysfs_active_low_path = os.path.join(gpio_sysfs_path, 'active_low')
with open(gpio_sysfs_active_low_path, 'w') as active_low_fd:
active_low_fd.write(str(int(invert)))

def __del__(self):
if self.gpio_sysfs_value_fd:
os.close(self.gpio_sysfs_value_fd)
Expand Down Expand Up @@ -68,24 +73,22 @@ def set(self, status):

os.write(self.gpio_sysfs_value_fd, binary_value)


_gpios = {}

def _get_gpio_line(index):
def _get_gpio_line(index, invert):
if index not in _gpios:
_gpios[index] = GpioDigitalOutput(index=index)
_gpios[index] = GpioDigitalOutput(index=index, invert=invert)
return _gpios[index]

def handle_set(index, status):
gpio_line = _get_gpio_line(index)
def handle_set(index, invert, status):
gpio_line = _get_gpio_line(index, invert)
gpio_line.set(status)


def handle_get(index):
gpio_line = _get_gpio_line(index)
def handle_get(index, invert):
gpio_line = _get_gpio_line(index, invert)
return gpio_line.get()


methods = {
'set': handle_set,
'get': handle_get,
Expand Down
4 changes: 2 additions & 2 deletions tests/test_sysfsgpioagent.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@ def set(self, val):
super().set(val)

def test_instantiation(self):
gpio_line = TestGpioAgent.GpioDigitalOutputMock(index=13)
gpio_line = TestGpioAgent.GpioDigitalOutputMock(index=13, invert=False)
assert isinstance(gpio_line, GpioDigitalOutput)

def test_set(self):
gpio_line = TestGpioAgent.GpioDigitalOutputMock(index=13)
gpio_line = TestGpioAgent.GpioDigitalOutputMock(index=13, invert=False)
for val in [True, False, True, False]:
gpio_line.set(val)
assert gpio_line.get() == val