Skip to content
Open
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
40 changes: 30 additions & 10 deletions sysfs/gpio.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
import os
import select

from twisted.internet import reactor
from twisted.internet import reactor, defer

import logging

Expand All @@ -57,6 +57,7 @@
SYSFS_GPIO_VALUE_HIGH = '1'

EPOLL_TIMEOUT = 1 # second
SYSFS_GPIO_TIMEOUT = 5 # second

# Public interface

Expand All @@ -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):
"""
Expand Down Expand Up @@ -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:
Expand All @@ -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. '''
Expand Down