You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
89 lines
2.4 KiB
89 lines
2.4 KiB
import os
|
|
import fcntl
|
|
import ctypes
|
|
from functools import cache
|
|
|
|
def gpio_init(pin: int, output: bool) -> None:
|
|
try:
|
|
with open(f"/sys/class/gpio/gpio{pin}/direction", 'wb') as f:
|
|
f.write(b"out" if output else b"in")
|
|
except Exception as e:
|
|
print(f"Failed to set gpio {pin} direction: {e}")
|
|
|
|
def gpio_set(pin: int, high: bool) -> None:
|
|
try:
|
|
with open(f"/sys/class/gpio/gpio{pin}/value", 'wb') as f:
|
|
f.write(b"1" if high else b"0")
|
|
except Exception as e:
|
|
print(f"Failed to set gpio {pin} value: {e}")
|
|
|
|
def gpio_read(pin: int) -> bool | None:
|
|
val = None
|
|
try:
|
|
with open(f"/sys/class/gpio/gpio{pin}/value", 'rb') as f:
|
|
val = bool(int(f.read().strip()))
|
|
except Exception as e:
|
|
print(f"Failed to set gpio {pin} value: {e}")
|
|
|
|
return val
|
|
|
|
def gpio_export(pin: int) -> None:
|
|
if os.path.isdir(f"/sys/class/gpio/gpio{pin}"):
|
|
return
|
|
|
|
try:
|
|
with open("/sys/class/gpio/export", 'w') as f:
|
|
f.write(str(pin))
|
|
except Exception:
|
|
print(f"Failed to export gpio {pin}")
|
|
|
|
@cache
|
|
def get_irq_action(irq: int) -> list[str]:
|
|
try:
|
|
with open(f"/sys/kernel/irq/{irq}/actions") as f:
|
|
actions = f.read().strip().split(',')
|
|
return actions
|
|
except FileNotFoundError:
|
|
return []
|
|
|
|
def get_irqs_for_action(action: str) -> list[str]:
|
|
ret = []
|
|
with open("/proc/interrupts") as f:
|
|
for l in f.readlines():
|
|
irq = l.split(':')[0].strip()
|
|
if irq.isdigit() and action in get_irq_action(irq):
|
|
ret.append(irq)
|
|
return ret
|
|
|
|
# *** gpiochip ***
|
|
|
|
class gpioevent_data(ctypes.Structure):
|
|
_fields_ = [
|
|
("timestamp", ctypes.c_uint64),
|
|
("id", ctypes.c_uint32),
|
|
]
|
|
|
|
class gpioevent_request(ctypes.Structure):
|
|
_fields_ = [
|
|
("lineoffset", ctypes.c_uint32),
|
|
("handleflags", ctypes.c_uint32),
|
|
("eventflags", ctypes.c_uint32),
|
|
("label", ctypes.c_char * 32),
|
|
("fd", ctypes.c_int)
|
|
]
|
|
|
|
def gpiochip_get_ro_value_fd(label: str, gpiochip_id: int, pin: int) -> int:
|
|
GPIOEVENT_REQUEST_BOTH_EDGES = 0x3
|
|
GPIOHANDLE_REQUEST_INPUT = 0x1
|
|
GPIO_GET_LINEEVENT_IOCTL = 0xc030b404
|
|
|
|
rq = gpioevent_request()
|
|
rq.lineoffset = pin
|
|
rq.handleflags = GPIOHANDLE_REQUEST_INPUT
|
|
rq.eventflags = GPIOEVENT_REQUEST_BOTH_EDGES
|
|
rq.label = label.encode('utf-8')[:31] + b'\0'
|
|
|
|
fd = os.open(f"/dev/gpiochip{gpiochip_id}", os.O_RDONLY)
|
|
fcntl.ioctl(fd, GPIO_GET_LINEEVENT_IOCTL, rq)
|
|
os.close(fd)
|
|
return int(rq.fd)
|
|
|