1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
|
# Copyright 2015-present Facebook. All rights reserved.
#
# This program file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program in a file named COPYING; if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301 USA
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
import logging
import os
import string
_gpio_shadow = '/tmp/gpionames'
def setup_shadow(shadow=None):
global _gpio_shadow
if shadow is not None:
_gpio_shadow = shadow
if not os.path.exists(_gpio_shadow):
os.makedirs(_gpio_shadow)
def gpio_name2value(name):
name = str(name).lower()
if name.startswith('gpio'):
name = name[4:]
try:
return int(name)
except:
# it is not just value, try treat it as name like 'A0'
pass
val = 0
try:
if len(name) != 2 and len(name) != 3:
raise
for idx in range(0, len(name)):
ch = name[idx]
if ch in string.ascii_lowercase:
# letter cannot be the last character
if idx == len(name) - 1:
raise
tmp = ord(ch) - ord('a') + 1
val = val * 26 + tmp
elif ch in string.digits:
# digit must be the last character
if idx != len(name) - 1:
raise
# the digit must be 0-7
tmp = ord(ch) - ord('0')
if tmp > 7:
raise
# 'A4' is value 4
if val > 0:
val -= 1
val = val * 8 + tmp
else:
raise
except:
logging.exception('Invalid GPIO name "%s"' % name)
return val
def gpio_dir(name, check_shadow=True):
GPIODIR_FMT = '/sys/class/gpio/gpio{gpio}'
if check_shadow:
shadowdir = os.path.join(_gpio_shadow, name)
if os.path.isdir(shadowdir):
return shadowdir
val = gpio_name2value(name)
return GPIODIR_FMT.format(gpio=val)
def gpio_get_shadow(name):
path = gpio_dir(name, check_shadow=False)
for child in os.listdir(_gpio_shadow):
try:
child = os.path.join(_gpio_shadow, child)
if os.readlink(child) == path:
return child
except:
pass
return None
def gpio_export(name, shadow=None):
GPIOEXPORT = '/sys/class/gpio/export'
if shadow is not None or shadow != '':
shadowdir = os.path.join(_gpio_shadow, shadow)
if os.path.exists(shadowdir):
raise Exception('Shadow "%s" exists already' % shadowdir)
old_shadow = gpio_get_shadow(name)
if old_shadow is not None:
raise Exception('Shadow "%s" already exists for %s'
% (old_shadow, name))
val = gpio_name2value(name)
try:
with open(GPIOEXPORT, 'w') as f:
f.write('%d\n' % val)
except:
# in case the GPIO has been exported already
pass
if shadow is not None:
gpiodir = gpio_dir(val, check_shadow=False)
os.symlink(gpiodir, shadowdir)
def gpio_get(name, change_direction=True):
path = gpio_dir(name)
if change_direction:
with open(os.path.join(path, 'direction'), 'w') as f:
f.write('in\n')
with open(os.path.join(path, 'value'), 'r') as f:
val = int(f.read().rstrip('\n'))
return val
def gpio_set(name, value, change_direction=True):
path = gpio_dir(name)
with open(os.path.join(path, 'value'), 'w') as f:
f.write('%d\n' % (1 if value else 0))
if change_direction:
with open(os.path.join(path, 'direction'), 'w') as f:
f.write('out\n')
def gpio_info(name):
res = {}
# first check if name is shadow
path = None
shadow = os.path.join(_gpio_shadow, name)
if os.path.exists(shadow):
if not os.path.islink(shadow) or not os.path.isdir(shadow):
raise Exception('Path "%s" is not a valid shadow path' % shadow)
path = os.readlink(shadow)
else:
path = gpio_dir(name, check_shadow=False)
shadow = gpio_get_shadow(name)
res['path'] = path
res['shadow'] = shadow
if os.path.isdir(path):
with open(os.path.join(path, 'direction'), 'r') as f:
res['direction'] = f.read().rstrip('\n')
with open(os.path.join(path, 'value'), 'r') as f:
res['value'] = int(f.read().rstrip('\n'))
else:
res['direction'] = None
res['value'] = None
return res
|