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)