From 33ff5fd5abb714434acc1f8f3d663fe5b912af86 Mon Sep 17 00:00:00 2001 From: Shawn Nock Date: Fri, 30 Dec 2016 20:58:58 -0500 Subject: [PATCH] Wait for sysfs node to ready before access (API BREAK) --- sysfs/gpio.py | 40 ++++++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/sysfs/gpio.py b/sysfs/gpio.py index 80b2cce..5c9875c 100755 --- a/sysfs/gpio.py +++ b/sysfs/gpio.py @@ -32,7 +32,7 @@ import os import select -from twisted.internet import reactor +from twisted.internet import reactor, defer import logging @@ -57,6 +57,7 @@ SYSFS_GPIO_VALUE_HIGH = '1' EPOLL_TIMEOUT = 1 # second +SYSFS_GPIO_TIMEOUT = 5 # second # Public interface @@ -74,6 +75,22 @@ EDGES = (RISING, FALLING, BOTH) ACTIVE_LOW_MODES = (ACTIVE_LOW_ON, ACTIVE_LOW_OFF) +def wait_for_file(path, timeout=SYSFS_GPIO_TIMEOUT): + d = defer.Deferred() + d.addTimeout(timeout, reactor) + def _exists(di): + if os.path.exists(path): + try: + with open(path, 'r+') as f: + pass + except Exception as e: + pass + else: + di.callback(None) + return + reactor.callLater(0, _exists, di) + _exists(d) + return d class Pin(object): """ @@ -286,9 +303,6 @@ def stop(self): def alloc_pin(self, number, direction, callback=None, edge=None, active_low=0): - Logger.debug('SysfsGPIO: alloc_pin(%d, %s, %s, %s, %s)' - % (number, direction, callback, edge, active_low)) - self._check_pin_validity(number) if direction not in DIRECTIONS: @@ -298,19 +312,25 @@ def alloc_pin(self, number, direction, callback=None, edge=None, active_low=0): if callback and edge not in EDGES: raise Exception("Pin edge %s not in %s" % (edge, EDGES)) + def _init_pin(_): + pin = Pin(number, direction, callback, edge, active_low) + Logger.debug('SysfsGPIO: alloc_pin(%d, %s, %s, %s, %s)' + % (number, direction, callback, edge, active_low)) + if direction is INPUT: + self._poll_queue_register_pin(pin) + self._allocated_pins[number] = pin + return pin + if not self._check_pin_already_exported(number): with open(SYSFS_EXPORT_PATH, 'w') as export: export.write('%d' % number) else: Logger.debug("SysfsGPIO: Pin %d already exported" % number) - pin = Pin(number, direction, callback, edge, active_low) - - if direction is INPUT: - self._poll_queue_register_pin(pin) + d = wait_for_file(SYSFS_GPIO_VALUE_PATH % number) + d.addCallback(_init_pin) - self._allocated_pins[number] = pin - return pin + return d def _poll_queue_register_pin(self, pin): ''' Pin responds to fileno(), so it's pollable. '''