diff --git a/linuxpy/codegen/spi.py b/linuxpy/codegen/spi.py new file mode 100644 index 0000000..5cd4d56 --- /dev/null +++ b/linuxpy/codegen/spi.py @@ -0,0 +1,69 @@ +# +# This file is part of the linuxpy project +# +# Copyright (c) 2024 Tiago Coutinho +# Distributed under the GPLv3 license. See LICENSE for more info. + +import pathlib + +from linuxpy.codegen.base import CEnum, run + +HEADERS = [ + "/usr/include/linux/spi/spi.h", + "/usr/include/linux/spi/spidev.h", +] + + +TEMPLATE = """\ +# +# This file is part of the linuxpy project +# +# Copyright (c) 2024 Tiago Coutinho +# Distributed under the GPLv3 license. See LICENSE for more info. + +# This file has been generated by {name} +# Date: {date} +# System: {system} +# Release: {release} +# Version: {version} + +import enum + +from linuxpy.ioctl import IOR as _IOR, IOW as _IOW, IOWR as _IOWR +from linuxpy.ctypes import u8, u16, u32, cuint, cint, cchar, culonglong +from linuxpy.ctypes import Struct, Union, POINTER, cvoidp + + +{enums_body} + + +{structs_body} + + +{iocs_body}""" + + +class Mode32(CEnum): + def add_item(self, name, value): + if "_BITUL" in value: + value = value.replace("_BITUL(", "").replace(")", "") + value = f"1 << {value}" + super().add_item(name, value) + + +# macros from #define statements +MACRO_ENUMS = [ + CEnum("IOC", "SPI_IOC_"), + Mode32("Mode32", "SPI_", klass="IntFlag", filter=lambda k, v: "MASK" not in k), +] + + +this_dir = pathlib.Path(__file__).parent + + +def main(output=this_dir.parent / "spi" / "raw.py"): + run(__name__, HEADERS, TEMPLATE, MACRO_ENUMS, output=output) + + +if __name__ == "__main__": + main() diff --git a/linuxpy/spi/__init__.py b/linuxpy/spi/__init__.py new file mode 100644 index 0000000..24bcc0a --- /dev/null +++ b/linuxpy/spi/__init__.py @@ -0,0 +1,5 @@ +# +# This file is part of the linuxpy project +# +# Copyright (c) 2024 Tiago Coutinho +# Distributed under the GPLv3 license. See LICENSE for more info. diff --git a/linuxpy/spi/device.py b/linuxpy/spi/device.py new file mode 100644 index 0000000..0a22c1f --- /dev/null +++ b/linuxpy/spi/device.py @@ -0,0 +1,12 @@ +# +# This file is part of the linuxpy project +# +# Copyright (c) 2024 Tiago Coutinho +# Distributed under the GPLv3 license. See LICENSE for more info. + + +from linuxpy.device import BaseDevice + + +class Device(BaseDevice): + PREFIX = "/dev/spidev" diff --git a/linuxpy/spi/raw.py b/linuxpy/spi/raw.py new file mode 100644 index 0000000..d602c0d --- /dev/null +++ b/linuxpy/spi/raw.py @@ -0,0 +1,74 @@ +# +# This file is part of the linuxpy project +# +# Copyright (c) 2024 Tiago Coutinho +# Distributed under the GPLv3 license. See LICENSE for more info. + +# This file has been generated by __main__ +# Date: 2024-10-10 06:46:12.660131 +# System: Linux +# Release: 6.8.0-45-generic +# Version: #45-Ubuntu SMP PREEMPT_DYNAMIC Fri Aug 30 12:02:04 UTC 2024 + +import enum + +from linuxpy.ctypes import Struct, cuint, culonglong, u8, u16, u32 +from linuxpy.ioctl import IOR as _IOR, IOW as _IOW + + +class Mode32(enum.IntFlag): + CPHA = 1 << 0 # clock phase + CPOL = 1 << 1 # clock polarity + MODE_0 = 0 | 0 # (original MicroWire) + MODE_1 = 0 | CPHA + MODE_2 = CPOL | 0 + MODE_3 = CPOL | CPHA + CS_HIGH = 1 << 2 # chipselect active high? + LSB_FIRST = 1 << 3 # per-word bits-on-wire + _3WIRE = 1 << 4 # SI/SO signals shared + LOOP = 1 << 5 # loopback mode + NO_CS = 1 << 6 # 1 dev/bus, no chipselect + READY = 1 << 7 # slave pulls low to pause + TX_DUAL = 1 << 8 # transmit with 2 wires + TX_QUAD = 1 << 9 # transmit with 4 wires + RX_DUAL = 1 << 10 # receive with 2 wires + RX_QUAD = 1 << 11 # receive with 4 wires + CS_WORD = 1 << 12 # toggle cs after each word + TX_OCTAL = 1 << 13 # transmit with 8 wires + RX_OCTAL = 1 << 14 # receive with 8 wires + _3WIRE_HIZ = 1 << 15 # high impedance turnaround + RX_CPHA_FLIP = 1 << 16 # flip CPHA on Rx only xfer + MOSI_IDLE_LOW = 1 << 17 # leave mosi line low when idle + + +class spi_ioc_transfer(Struct): + pass + + +spi_ioc_transfer._fields_ = [ + ("tx_buf", culonglong), + ("rx_buf", culonglong), + ("len", cuint), + ("speed_hz", cuint), + ("delay_usecs", u16), + ("bits_per_word", u8), + ("cs_change", u8), + ("tx_nbits", u8), + ("rx_nbits", u8), + ("word_delay_usecs", u8), + ("pad", u8), +] + + +class IOC(enum.IntEnum): + MAGIC = "k" + RD_MODE = _IOR(MAGIC, 1, u8) + WR_MODE = _IOW(MAGIC, 1, u8) + RD_LSB_FIRST = _IOR(MAGIC, 2, u8) + WR_LSB_FIRST = _IOW(MAGIC, 2, u8) + RD_BITS_PER_WORD = _IOR(MAGIC, 3, u8) + WR_BITS_PER_WORD = _IOW(MAGIC, 3, u8) + RD_MAX_SPEED_HZ = _IOR(MAGIC, 4, u32) + WR_MAX_SPEED_HZ = _IOW(MAGIC, 4, u32) + RD_MODE32 = _IOR(MAGIC, 5, u32) + WR_MODE32 = _IOW(MAGIC, 5, u32)