Compare commits

...

2 Commits

Author SHA1 Message Date
Ken Van Hoeylandt
25c3f19e5d
Merge develop into main (#494)
* Updated runtime gating to enable LilyGO T-Deck specific apps and services
  * New device compatibility and model-detection APIs
  * Added a buffer-overflow error code and message
  * Updated GitHub Actions checkout to v4
  * Adjusted an LVGL-related library version
  * Device config now emits a T-Deck workaround flag when applicable
  * Removed internal developer comments and minor cleanups
2026-02-09 22:12:03 +01:00
Ken Van Hoeylandt
93efadd5e3
Devicetree DTS and YAML format improvements (#492)
* **DevicetreeCompiler**
  * Binding properties now support default values.
  * Compiler returns meaningful exit codes and reports errors more clearly.
  * Stronger validation of device configurations with unified error handling.
  * Added integration tests and a dedicated Devicetree test workflow.

* **Changes**
  * Platform binding schemas updated: some fields made required, others gained explicit defaults.
  * Many device-tree files simplified by removing unused/placeholder pin and transfer-size entries.

* **Documentation**
  * Removed several outdated TODO items.
2026-02-09 17:38:06 +01:00
74 changed files with 323 additions and 308 deletions

View File

@ -15,7 +15,7 @@ runs:
using: "composite"
steps:
- name: "Checkout repo"
uses: actions/checkout@v2
uses: actions/checkout@v4
with:
submodules: recursive
- name: Install Linux Dependencies for SDL

View File

@ -6,11 +6,11 @@ on:
pull_request:
types: [ opened, synchronize, reopened ]
jobs:
run:
TactilityTests:
runs-on: ubuntu-latest
steps:
- name: "Checkout repo"
uses: actions/checkout@v2
uses: actions/checkout@v4
with:
submodules: recursive
- name: "Configure Project"
@ -27,3 +27,17 @@ jobs:
run: build/Tests/Tactility/TactilityTests
- name: "Run TactilityKernel Tests"
run: build/Tests/TactilityKernel/TactilityKernelTests
DevicetreeTests:
runs-on: ubuntu-latest
steps:
- name: "Checkout repo"
uses: actions/checkout@v4
with:
submodules: recursive
- name: "Install Python Dependencies"
shell: bash
run: pip install lark==1.3.1 pyyaml==6.0.3
- name: "Run Devicetree Tests"
shell: bash
working-directory: Buildscripts/DevicetreeCompiler/tests
run: python test_integration.py

View File

@ -24,5 +24,6 @@ if __name__ == "__main__":
is_verbose = "--verbose" in sys.argv
devicetree_yaml_config = args[0]
output_path = args[1]
main(devicetree_yaml_config, output_path, is_verbose)
result = main(devicetree_yaml_config, output_path, is_verbose)
sys.exit(result)

View File

@ -1,4 +1,5 @@
import os
from .exception import DevicetreeException
def find_bindings(directory_path: str) -> list[str]:
yaml_files = []
@ -14,6 +15,6 @@ def find_all_bindings(directory_paths: list[str]) -> list[str]:
for directory_path in directory_paths:
new_paths = find_bindings(directory_path)
if len(new_paths) == 0:
raise Exception(f"No bindings found in {directory_path}")
raise DevicetreeException(f"No bindings found in {directory_path}")
yaml_files += new_paths
return yaml_files

View File

@ -44,6 +44,7 @@ def parse_binding(file_path: str, binding_dirs: list[str]) -> Binding:
type=details.get('type', 'unknown'),
required=details.get('required', False),
description=details.get('description', '').strip(),
default=details.get('default', None),
)
properties_dict[name] = prop
filename = os.path.basename(file_path)

View File

@ -0,0 +1,2 @@
class DevicetreeException(Exception):
pass

View File

@ -1,7 +1,7 @@
import os.path
from textwrap import dedent
from source.models import *
from .exception import DevicetreeException
def write_include(file, include: IncludeC, verbose: bool):
if verbose:
@ -26,9 +26,9 @@ def get_device_node_name_safe(device: Device):
def get_device_type_name(device: Device, bindings: list[Binding]):
device_binding = find_device_binding(device, bindings)
if device_binding is None:
raise Exception(f"Binding not found for {device.node_name}")
raise DevicetreeException(f"Binding not found for {device.node_name}")
if device_binding.compatible is None:
raise Exception(f"Couldn't find compatible binding for {device.node_name}")
raise DevicetreeException(f"Couldn't find compatible binding for {device.node_name}")
compatible_safe = device_binding.compatible.split(",")[-1]
return compatible_safe.replace("-", "_")
@ -41,7 +41,7 @@ def find_device_property(device: Device, name: str) -> DeviceProperty:
def find_device_binding(device: Device, bindings: list[Binding]) -> Binding:
compatible_property = find_device_property(device, "compatible")
if compatible_property is None:
raise Exception(f"property 'compatible' not found in device {device.node_name}")
raise DevicetreeException(f"property 'compatible' not found in device {device.node_name}")
for binding in bindings:
if binding.compatible == compatible_property.value:
return binding
@ -57,44 +57,69 @@ def find_phandle(devices: list[Device], phandle: str):
for device in devices:
if device.node_name == phandle or device.node_alias == phandle:
return f"&{get_device_node_name_safe(device)}"
raise Exception(f"phandle '{phandle}' not found in device tree")
raise DevicetreeException(f"phandle '{phandle}' not found in device tree")
def property_to_string(property: DeviceProperty, devices: list[Device]) -> str:
type = property.type
if type == "value":
if type == "value" or type == "int":
return property.value
elif type == "boolean":
elif type == "boolean" or type == "bool":
return "true"
elif type == "text":
return f"\"{property.value}\""
elif type == "values":
return "{ " + ",".join(property.value) + " }"
value_list = list()
for item in property.value:
if isinstance(item, PropertyValue):
value_list.append(property_to_string(DeviceProperty(name="", type=item.type, value=item.value), devices))
else:
value_list.append(str(item))
return "{ " + ",".join(value_list) + " }"
elif type == "phandle":
return find_phandle(devices, property.value)
else:
raise Exception(f"property_to_string() has an unsupported type: {type}")
raise DevicetreeException(f"property_to_string() has an unsupported type: {type}")
def resolve_parameters_from_bindings(device: Device, bindings: list[Binding], devices: list[Device]) -> list:
compatible_property = find_device_property(device, "compatible")
if compatible_property is None:
raise Exception(f"Cannot find 'compatible' property for {device.node_name}")
raise DevicetreeException(f"Cannot find 'compatible' property for {device.node_name}")
device_binding = find_binding(compatible_property.value, bindings)
if device_binding is None:
raise Exception(f"Binding not found for {device.node_name} and compatible '{compatible_property.value}'")
raise DevicetreeException(f"Binding not found for {device.node_name} and compatible '{compatible_property.value}'")
# Filter out system properties
binding_properties = []
binding_property_names = set()
for property in device_binding.properties:
if property.name != "compatible":
binding_properties.append(property)
binding_property_names.add(property.name)
# Check for invalid properties in device
for device_property in device.properties:
if device_property.name in ["compatible"]:
continue
if device_property.name not in binding_property_names:
raise DevicetreeException(f"Device '{device.node_name}' has invalid property '{device_property.name}'")
# Allocate total expected configuration arguments
result = [0] * len(binding_properties)
for index, binding_property in enumerate(binding_properties):
device_property = find_device_property(device, binding_property.name)
if device_property is None:
if binding_property.required:
raise Exception(f"device {device.node_name} doesn't have property '{binding_property.name}'")
if binding_property.default is not None:
temp_prop = DeviceProperty(
name=binding_property.name,
type=binding_property.type,
value=binding_property.default
)
result[index] = property_to_string(temp_prop, devices)
elif binding_property.required:
raise DevicetreeException(f"device {device.node_name} doesn't have property '{binding_property.name}'")
elif binding_property.type == "bool":
result[index] = "false"
else:
result[index] = '0'
raise DevicetreeException(f"Device {device.node_name} doesn't have property '{binding_property.name}' and no default value is set")
else:
result[index] = property_to_string(device_property, devices)
return result
@ -121,7 +146,7 @@ def write_device_structs(file, device: Device, parent_device: Device, bindings:
type_name = get_device_type_name(device, bindings)
compatible_property = find_device_property(device, "compatible")
if compatible_property is None:
raise Exception(f"Cannot find 'compatible' property for {device.node_name}")
raise DevicetreeException(f"Cannot find 'compatible' property for {device.node_name}")
node_name = get_device_node_name_safe(device)
config_variable_name = f"{node_name}_config"
if parent_device is not None:
@ -148,7 +173,7 @@ def write_device_init(file, device: Device, bindings: list[Binding], verbose: bo
# Assemble some pre-requisites
compatible_property = find_device_property(device, "compatible")
if compatible_property is None:
raise Exception(f"Cannot find 'compatible' property for {device.node_name}")
raise DevicetreeException(f"Cannot find 'compatible' property for {device.node_name}")
# Type & instance names
node_name = get_device_node_name_safe(device)
device_variable = node_name

View File

@ -9,16 +9,19 @@ from source.generator import *
from source.binding_files import find_all_bindings
from source.binding_parser import parse_binding
from source.config import *
from source.exception import DevicetreeException
def main(config_path: str, output_path: str, verbose: bool):
def main(config_path: str, output_path: str, verbose: bool) -> int:
print(f"Generating devicetree code\n config: {config_path}\n output: {output_path}")
if not os.path.isdir(config_path):
raise Exception(f"Directory not found: {config_path}")
print(f"Directory not found: {config_path}")
return 1
config = parse_config(config_path, os.getcwd())
if verbose:
pprint(config)
try:
project_dir = os.path.dirname(os.path.realpath(__file__))
grammar_path = os.path.join(project_dir, "grammar.lark")
lark_data = read_file(grammar_path)
@ -32,11 +35,11 @@ def main(config_path: str, output_path: str, verbose: bool):
pprint(transformed)
binding_files = find_all_bindings(config.bindings)
if verbose:
print(f"Bindings found:")
print("Bindings found:")
for binding_file in binding_files:
print(f" {binding_file}")
if verbose:
print(f"Parsing bindings")
print("Parsing bindings")
bindings = []
for binding_file in binding_files:
bindings.append(parse_binding(binding_file, config.bindings))
@ -44,3 +47,7 @@ def main(config_path: str, output_path: str, verbose: bool):
for binding in bindings:
pprint(binding)
generate(output_path, transformed, bindings, verbose)
return 0
except DevicetreeException as caught:
print("\033[31mError: ", caught, "\033[0m")
return 1

View File

@ -36,6 +36,7 @@ class BindingProperty:
type: str
required: bool
description: str
default: object = None
@dataclass
class Binding:

View File

@ -4,6 +4,7 @@ from lark import Transformer
from lark import Token
from source.models import *
from dataclasses import dataclass
from .exception import DevicetreeException
def flatten_token_array(tokens: List[Token], name: str):
result_list = list()
@ -23,7 +24,7 @@ class DtsTransformer(Transformer):
def dts_version(self, tokens: List[Token]):
version = tokens[0].value
if version != "dts-v1":
raise Exception(f"Unsupported DTS version: {version}")
raise DevicetreeException(f"Unsupported DTS version: {version}")
return DtsVersion(version)
def device(self, tokens: list):
node_name = None
@ -46,12 +47,12 @@ class DtsTransformer(Transformer):
if (len(objects) == 1) or (objects[1] is None):
return DeviceProperty(name, "boolean", True)
if type(objects[1]) is not PropertyValue:
raise Exception(f"Object was not converted to PropertyValue: {objects[1]}")
raise DevicetreeException(f"Object was not converted to PropertyValue: {objects[1]}")
return DeviceProperty(name, objects[1].type, objects[1].value)
def property_value(self, tokens: List):
token = tokens[0]
if type(token) is Token:
raise Exception(f"Failed to convert token to PropertyValue: {token}")
raise DevicetreeException(f"Failed to convert token to PropertyValue: {token}")
return token
def PHANDLE(self, token: Token):
return PropertyValue(type="phandle", value=token.value[1:])

View File

@ -0,0 +1,14 @@
description: Test device binding
compatible: "test,device"
properties:
reg:
type: int
required: true
status:
type: string
boolean-prop:
type: boolean
int-prop:
type: int
string-prop:
type: string

View File

@ -0,0 +1,5 @@
description: Test root binding
compatible: "test,root"
properties:
model:
type: string

View File

@ -0,0 +1,2 @@
dts: test.dts
bindings: bindings

View File

@ -0,0 +1,17 @@
/dts-v1/;
#include <test_include.h>
/ {
compatible = "test,root";
model = "Test Model";
test_device: test-device@0 {
compatible = "test,device";
reg = <0>;
status = "okay";
boolean-prop;
int-prop = <42>;
string-prop = "hello";
};
};

View File

@ -0,0 +1,102 @@
import os
import subprocess
import shutil
import sys
import tempfile
# Path to the compile.py script
# We assume this script is in Buildscripts/DevicetreeCompiler/tests/
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
PROJECT_ROOT = os.path.abspath(os.path.join(SCRIPT_DIR, ".."))
COMPILE_SCRIPT = os.path.join(PROJECT_ROOT, "compile.py")
TEST_DATA_DIR = os.path.join(SCRIPT_DIR, "data")
def run_compiler(config_path, output_path):
result = subprocess.run(
[sys.executable, COMPILE_SCRIPT, config_path, output_path],
capture_output=True,
text=True,
cwd=PROJECT_ROOT,
timeout=60
)
return result
def test_compile_success():
print("Running test_compile_success...")
with tempfile.TemporaryDirectory() as output_dir:
result = run_compiler(TEST_DATA_DIR, output_dir)
if result.returncode != 0:
print(f"FAILED: Compilation failed: {result.stderr}")
return False
if not os.path.exists(os.path.join(output_dir, "devicetree.c")):
print("FAILED: devicetree.c not generated")
return False
if not os.path.exists(os.path.join(output_dir, "devicetree.h")):
print("FAILED: devicetree.h not generated")
return False
print("PASSED")
return True
def test_compile_invalid_dts():
print("Running test_compile_invalid_dts...")
with tempfile.TemporaryDirectory() as tmp_dir:
bad_data_dir = os.path.join(tmp_dir, "bad_data")
os.makedirs(bad_data_dir)
output_dir = os.path.join(tmp_dir, "output")
os.makedirs(output_dir)
with open(os.path.join(bad_data_dir, "devicetree.yaml"), "w") as f:
f.write("dts: bad.dts\nbindings: bindings")
with open(os.path.join(bad_data_dir, "bad.dts"), "w") as f:
f.write("/dts-v1/;\n / { invalid syntax }")
os.makedirs(os.path.join(bad_data_dir, "bindings"))
result = run_compiler(bad_data_dir, output_dir)
if result.returncode == 0:
print("FAILED: Compilation should have failed but succeeded")
return False
print("PASSED")
return True
def test_compile_missing_config():
print("Running test_compile_missing_config...")
with tempfile.TemporaryDirectory() as output_dir:
result = run_compiler("/non/existent/path", output_dir)
if result.returncode == 0:
print("FAILED: Compilation should have failed for non-existent path")
return False
if "Directory not found" not in result.stdout:
print(f"FAILED: Expected 'Directory not found' error message, got: {result.stdout}")
return False
print("PASSED")
return True
if __name__ == "__main__":
tests = [
test_compile_success,
test_compile_invalid_dts,
test_compile_missing_config
]
failed = 0
for test in tests:
if not test():
failed += 1
if failed > 0:
print(f"\n{failed} tests failed")
sys.exit(1)
else:
print("\nAll tests passed")
sys.exit(0)

View File

@ -28,9 +28,6 @@
pin-mosi = <13>;
pin-miso = <GPIO_PIN_NONE>;
pin-sclk = <14>;
pin-wp = <GPIO_PIN_NONE>;
pin-hd = <GPIO_PIN_NONE>;
max-transfer-size = <0>;
};
sdcard_spi: spi1 {
@ -39,8 +36,5 @@
pin-mosi = <23>;
pin-miso = <19>;
pin-sclk = <18>;
pin-wp = <GPIO_PIN_NONE>;
pin-hd = <GPIO_PIN_NONE>;
max-transfer-size = <0>;
};
};

View File

@ -29,9 +29,6 @@
pin-mosi = <13>;
pin-miso = <12>;
pin-sclk = <14>;
pin-wp = <GPIO_PIN_NONE>;
pin-hd = <GPIO_PIN_NONE>;
max-transfer-size = <0>;
};
sdcard_spi: spi1 {
@ -40,9 +37,6 @@
pin-mosi = <23>;
pin-miso = <19>;
pin-sclk = <18>;
pin-wp = <GPIO_PIN_NONE>;
pin-hd = <GPIO_PIN_NONE>;
max-transfer-size = <0>;
};
uart1 {
@ -50,7 +44,5 @@
port = <UART_NUM_1>;
pin-tx = <3>;
pin-rx = <1>;
pin-cts = <GPIO_PIN_NONE>;
pin-rts = <GPIO_PIN_NONE>;
};
};

View File

@ -29,9 +29,6 @@
pin-mosi = <13>;
pin-miso = <12>;
pin-sclk = <14>;
pin-wp = <GPIO_PIN_NONE>;
pin-hd = <GPIO_PIN_NONE>;
max-transfer-size = <0>;
};
sdcard_spi: spi1 {
@ -40,9 +37,6 @@
pin-mosi = <23>;
pin-miso = <19>;
pin-sclk = <18>;
pin-wp = <GPIO_PIN_NONE>;
pin-hd = <GPIO_PIN_NONE>;
max-transfer-size = <0>;
};
uart1 {
@ -50,7 +44,5 @@
port = <UART_NUM_1>;
pin-tx = <3>;
pin-rx = <1>;
pin-cts = <GPIO_PIN_NONE>;
pin-rts = <GPIO_PIN_NONE>;
};
};

View File

@ -28,9 +28,6 @@
pin-mosi = <13>;
pin-miso = <GPIO_PIN_NONE>;
pin-sclk = <14>;
pin-wp = <GPIO_PIN_NONE>;
pin-hd = <GPIO_PIN_NONE>;
max-transfer-size = <0>;
};
sdcard_spi: spi1 {
@ -39,8 +36,5 @@
pin-mosi = <23>;
pin-miso = <19>;
pin-sclk = <18>;
pin-wp = <GPIO_PIN_NONE>;
pin-hd = <GPIO_PIN_NONE>;
max-transfer-size = <0>;
};
};

View File

@ -28,8 +28,6 @@
pin-mosi = <47>;
pin-miso = <41>;
pin-sclk = <48>;
pin-wp = <GPIO_PIN_NONE>;
pin-hd = <42>;
max-transfer-size = <0>;
};
};

View File

@ -37,9 +37,6 @@
pin-mosi = <11>;
pin-miso = <13>;
pin-sclk = <12>;
pin-wp = <GPIO_PIN_NONE>;
pin-hd = <GPIO_PIN_NONE>;
max-transfer-size = <0>;
};
uart1 {
@ -47,7 +44,5 @@
port = <UART_NUM_1>;
pin-tx = <18>;
pin-rx = <17>;
pin-cts = <GPIO_PIN_NONE>;
pin-rts = <GPIO_PIN_NONE>;
};
};

View File

@ -19,9 +19,6 @@
pin-mosi = <13>;
pin-miso = <12>;
pin-sclk = <14>;
pin-wp = <GPIO_PIN_NONE>;
pin-hd = <GPIO_PIN_NONE>;
max-transfer-size = <0>;
};
sdcard_spi: spi1 {
@ -30,8 +27,5 @@
pin-mosi = <23>;
pin-miso = <19>;
pin-sclk = <18>;
pin-wp = <GPIO_PIN_NONE>;
pin-hd = <GPIO_PIN_NONE>;
max-transfer-size = <0>;
};
};

View File

@ -28,9 +28,6 @@
pin-mosi = <13>;
pin-miso = <12>;
pin-sclk = <14>;
pin-wp = <GPIO_PIN_NONE>;
pin-hd = <GPIO_PIN_NONE>;
max-transfer-size = <0>;
};
sdcard_spi: spi1 {
@ -39,8 +36,5 @@
pin-mosi = <23>;
pin-miso = <19>;
pin-sclk = <18>;
pin-wp = <GPIO_PIN_NONE>;
pin-hd = <GPIO_PIN_NONE>;
max-transfer-size = <0>;
};
};

View File

@ -5,7 +5,6 @@
#include <St7789Display.h>
static std::shared_ptr<tt::hal::touch::TouchDevice> createTouch() {
// Note for future changes: Reset pin is 48 and interrupt pin is 47
auto configuration = std::make_unique<Ft5x06Touch::Configuration>(
I2C_NUM_0,
LCD_HORIZONTAL_RESOLUTION,

View File

@ -27,11 +27,7 @@
compatible = "espressif,esp32-spi";
host = <SPI2_HOST>;
pin-mosi = <39>;
pin-miso = <GPIO_PIN_NONE>;
pin-sclk = <42>;
pin-wp = <GPIO_PIN_NONE>;
pin-hd = <GPIO_PIN_NONE>;
max-transfer-size = <0>;
};
sdcard_spi: spi1 {
@ -40,9 +36,6 @@
pin-mosi = <6>;
pin-miso = <4>;
pin-sclk = <5>;
pin-wp = <GPIO_PIN_NONE>;
pin-hd = <GPIO_PIN_NONE>;
max-transfer-size = <0>;
};
uart0 {
@ -50,8 +43,6 @@
port = <UART_NUM_0>;
pin-tx = <43>;
pin-rx = <44>;
pin-cts = <GPIO_PIN_NONE>;
pin-rts = <GPIO_PIN_NONE>;
};
uart1 {
@ -59,7 +50,5 @@
port = <UART_NUM_1>;
pin-tx = <17>;
pin-rx = <18>;
pin-cts = <GPIO_PIN_NONE>;
pin-rts = <GPIO_PIN_NONE>;
};
};

View File

@ -5,7 +5,6 @@
#include <Ili9488Display.h>
static std::shared_ptr<tt::hal::touch::TouchDevice> createTouch() {
// Note for future changes: Reset pin is 48 and interrupt pin is 47
auto configuration = std::make_unique<Gt911Touch::Configuration>(
I2C_NUM_0,
320,

View File

@ -29,9 +29,6 @@
pin-mosi = <39>;
pin-miso = <GPIO_PIN_NONE>;
pin-sclk = <42>;
pin-wp = <GPIO_PIN_NONE>;
pin-hd = <GPIO_PIN_NONE>;
max-transfer-size = <0>;
};
sdcard_spi: spi1 {
@ -40,9 +37,6 @@
pin-mosi = <6>;
pin-miso = <4>;
pin-sclk = <5>;
pin-wp = <GPIO_PIN_NONE>;
pin-hd = <GPIO_PIN_NONE>;
max-transfer-size = <0>;
};
uart0 {
@ -50,8 +44,6 @@
port = <UART_NUM_0>;
pin-tx = <43>;
pin-rx = <44>;
pin-cts = <GPIO_PIN_NONE>;
pin-rts = <GPIO_PIN_NONE>;
};
uart1 {
@ -59,7 +51,5 @@
port = <UART_NUM_1>;
pin-tx = <17>;
pin-rx = <18>;
pin-cts = <GPIO_PIN_NONE>;
pin-rts = <GPIO_PIN_NONE>;
};
};

View File

@ -29,9 +29,6 @@
pin-mosi = <6>;
pin-miso = <4>;
pin-sclk = <5>;
pin-wp = <GPIO_PIN_NONE>;
pin-hd = <GPIO_PIN_NONE>;
max-transfer-size = <0>;
};
uart0 {
@ -39,8 +36,6 @@
port = <UART_NUM_0>;
pin-tx = <43>;
pin-rx = <44>;
pin-cts = <GPIO_PIN_NONE>;
pin-rts = <GPIO_PIN_NONE>;
};
uart1 {
@ -48,7 +43,5 @@
port = <UART_NUM_1>;
pin-tx = <20>;
pin-rx = <19>;
pin-cts = <GPIO_PIN_NONE>;
pin-rts = <GPIO_PIN_NONE>;
};
};

View File

@ -29,8 +29,6 @@
pin-mosi = <13>;
pin-miso = <12>;
pin-sclk = <14>;
pin-wp = <GPIO_PIN_NONE>;
pin-hd = <GPIO_PIN_NONE>;
max-transfer-size = <65536>;
};
@ -40,9 +38,6 @@
pin-mosi = <23>;
pin-miso = <19>;
pin-sclk = <18>;
pin-wp = <GPIO_PIN_NONE>;
pin-hd = <GPIO_PIN_NONE>;
max-transfer-size = <0>;
};
uart1 {
@ -50,7 +45,5 @@
port = <UART_NUM_1>;
pin-tx = <17>;
pin-rx = <16>;
pin-cts = <GPIO_PIN_NONE>;
pin-rts = <GPIO_PIN_NONE>;
};
};

View File

@ -29,8 +29,6 @@
pin-mosi = <13>;
pin-miso = <33>;
pin-sclk = <14>;
pin-wp = <GPIO_PIN_NONE>;
pin-hd = <GPIO_PIN_NONE>;
max-transfer-size = <65536>;
};
@ -40,9 +38,6 @@
pin-mosi = <23>;
pin-miso = <19>;
pin-sclk = <18>;
pin-wp = <GPIO_PIN_NONE>;
pin-hd = <GPIO_PIN_NONE>;
max-transfer-size = <0>;
};
uart1 {
@ -50,7 +45,5 @@
port = <UART_NUM_1>;
pin-tx = <1>;
pin-rx = <3>;
pin-cts = <GPIO_PIN_NONE>;
pin-rts = <GPIO_PIN_NONE>;
};
};

View File

@ -29,9 +29,6 @@
pin-mosi = <11>;
pin-miso = <13>;
pin-sclk = <12>;
pin-wp = <GPIO_PIN_NONE>;
pin-hd = <GPIO_PIN_NONE>;
max-transfer-size = <0>;
};
uart0 {
@ -39,7 +36,5 @@
port = <UART_NUM_0>;
pin-tx = <43>;
pin-rx = <44>;
pin-cts = <GPIO_PIN_NONE>;
pin-rts = <GPIO_PIN_NONE>;
};
};

View File

@ -36,11 +36,7 @@
compatible = "espressif,esp32-spi";
host = <SPI2_HOST>;
pin-mosi = <13>;
pin-miso = <GPIO_PIN_NONE>;
pin-sclk = <14>;
pin-wp = <GPIO_PIN_NONE>;
pin-hd = <GPIO_PIN_NONE>;
max-transfer-size = <0>;
};
sdcard_spi: spi1 {
@ -49,9 +45,6 @@
pin-mosi = <23>;
pin-miso = <19>;
pin-sclk = <18>;
pin-wp = <GPIO_PIN_NONE>;
pin-hd = <GPIO_PIN_NONE>;
max-transfer-size = <0>;
};
// CN1 header, JST SH 1.25, GND / IO22 / IO21 / 3.3V
@ -60,7 +53,5 @@
port = <UART_NUM_1>;
pin-tx = <22>;
pin-rx = <21>;
pin-cts = <GPIO_PIN_NONE>;
pin-rts = <GPIO_PIN_NONE>;
};
};

View File

@ -39,7 +39,6 @@
pin-sclk = <47>;
pin-wp = <40>;
pin-hd = <39>;
max-transfer-size = <0>;
};
sdcard_spi: spi1 {
@ -48,9 +47,6 @@
pin-mosi = <11>;
pin-miso = <13>;
pin-sclk = <12>;
pin-wp = <GPIO_PIN_NONE>;
pin-hd = <GPIO_PIN_NONE>;
max-transfer-size = <0>;
};
// P1 header
@ -59,7 +55,5 @@
port = <UART_NUM_0>;
pin-tx = <43>;
pin-rx = <44>;
pin-cts = <GPIO_PIN_NONE>;
pin-rts = <GPIO_PIN_NONE>;
};
};

View File

@ -37,9 +37,6 @@
pin-mosi = <11>;
pin-miso = <13>;
pin-sclk = <12>;
pin-wp = <GPIO_PIN_NONE>;
pin-hd = <GPIO_PIN_NONE>;
max-transfer-size = <0>;
};
uart1 {
@ -47,7 +44,5 @@
port = <UART_NUM_1>;
pin-tx = <18>;
pin-rx = <17>;
pin-cts = <GPIO_PIN_NONE>;
pin-rts = <GPIO_PIN_NONE>;
};
};

View File

@ -5,14 +5,15 @@
#include <St7789Display.h>
static std::shared_ptr<tt::hal::touch::TouchDevice> createTouch() {
// Note for future changes: Reset pin is 48 and interrupt pin is 47
auto configuration = std::make_unique<Gt911Touch::Configuration>(
I2C_NUM_0,
240,
320,
true,
true,
false
false,
GPIO_NUM_NC,
GPIO_NUM_16
);
return std::make_shared<Gt911Touch>(std::move(configuration));

View File

@ -39,8 +39,6 @@
pin-bclk = <7>;
pin-ws = <5>;
pin-data-out = <6>;
pin-data-in = <GPIO_PIN_NONE>;
pin-mclk = <GPIO_PIN_NONE>;
};
spi0 {
@ -49,9 +47,6 @@
pin-mosi = <41>;
pin-miso = <38>;
pin-sclk = <40>;
pin-wp = <GPIO_PIN_NONE>;
pin-hd = <GPIO_PIN_NONE>;
max-transfer-size = <0>;
};
uart1 {
@ -59,7 +54,5 @@
port = <UART_NUM_1>;
pin-tx = <43>;
pin-rx = <44>;
pin-cts = <GPIO_PIN_NONE>;
pin-rts = <GPIO_PIN_NONE>;
};
};

View File

@ -18,10 +18,6 @@
compatible = "espressif,esp32-spi";
host = <SPI2_HOST>;
pin-mosi = <7>;
pin-miso = <GPIO_PIN_NONE>;
pin-sclk = <6>;
pin-wp = <GPIO_PIN_NONE>;
pin-hd = <GPIO_PIN_NONE>;
max-transfer-size = <0>;
};
};

View File

@ -18,10 +18,6 @@
compatible = "espressif,esp32-spi";
host = <SPI2_HOST>;
pin-mosi = <19>;
pin-miso = <GPIO_PIN_NONE>;
pin-sclk = <18>;
pin-wp = <GPIO_PIN_NONE>;
pin-hd = <GPIO_PIN_NONE>;
max-transfer-size = <0>;
};
};

View File

@ -27,11 +27,7 @@
compatible = "espressif,esp32-spi";
host = <SPI2_HOST>;
pin-mosi = <3>;
pin-miso = <GPIO_PIN_NONE>;
pin-sclk = <5>;
pin-wp = <GPIO_PIN_NONE>;
pin-hd = <GPIO_PIN_NONE>;
max-transfer-size = <0>;
};
stemma_qt: uart1 {
@ -39,7 +35,5 @@
port = <UART_NUM_1>;
pin-tx = <43>;
pin-rx = <44>;
pin-cts = <GPIO_PIN_NONE>;
pin-rts = <GPIO_PIN_NONE>;
};
};

View File

@ -31,9 +31,6 @@
pin-mosi = <34>;
pin-miso = <33>;
pin-sclk = <35>;
pin-wp = <GPIO_PIN_NONE>;
pin-hd = <GPIO_PIN_NONE>;
max-transfer-size = <0>;
};
// ES8311
@ -53,8 +50,6 @@
port = <UART_NUM_0>;
pin-tx = <12>;
pin-rx = <4>;
pin-cts = <GPIO_PIN_NONE>;
pin-rts = <GPIO_PIN_NONE>;
};
uart_external: uart1 {
@ -62,7 +57,5 @@
port = <UART_NUM_1>;
pin-tx = <43>;
pin-rx = <44>;
pin-cts = <GPIO_PIN_NONE>;
pin-rts = <GPIO_PIN_NONE>;
};
};

View File

@ -37,11 +37,7 @@
compatible = "espressif,esp32-spi";
host = <SPI2_HOST>;
pin-mosi = <35>;
pin-miso = <GPIO_PIN_NONE>;
pin-sclk = <36>;
pin-wp = <GPIO_PIN_NONE>;
pin-hd = <GPIO_PIN_NONE>;
max-transfer-size = <0>;
};
sdcard_spi: spi1 {
@ -50,9 +46,6 @@
pin-mosi = <14>;
pin-miso = <39>;
pin-sclk = <40>;
pin-wp = <GPIO_PIN_NONE>;
pin-hd = <GPIO_PIN_NONE>;
max-transfer-size = <0>;
};
// Speaker and microphone (ES8311)
@ -63,7 +56,6 @@
pin-ws = <43>;
pin-data-out = <42>;
pin-data-in = <46>;
pin-mclk = <GPIO_PIN_NONE>;
};
uart_port_a: uart1 {
@ -71,7 +63,5 @@
port = <UART_NUM_1>;
pin-tx = <1>;
pin-rx = <2>;
pin-cts = <GPIO_PIN_NONE>;
pin-rts = <GPIO_PIN_NONE>;
};
};

View File

@ -29,11 +29,7 @@
compatible = "espressif,esp32-spi";
host = <SPI2_HOST>;
pin-mosi = <35>;
pin-miso = <GPIO_PIN_NONE>;
pin-sclk = <36>;
pin-wp = <GPIO_PIN_NONE>;
pin-hd = <GPIO_PIN_NONE>;
max-transfer-size = <0>;
};
sdcard_spi: spi1 {
@ -42,9 +38,6 @@
pin-mosi = <14>;
pin-miso = <39>;
pin-sclk = <40>;
pin-wp = <GPIO_PIN_NONE>;
pin-hd = <GPIO_PIN_NONE>;
max-transfer-size = <0>;
};
// Speaker and microphone
@ -56,7 +49,6 @@
pin-ws = <43>;
pin-data-out = <42>;
pin-data-in = <46>;
pin-mclk = <GPIO_PIN_NONE>;
};
uart_port_a: uart1 {
@ -64,7 +56,5 @@
port = <UART_NUM_1>;
pin-tx = <1>;
pin-rx = <2>;
pin-cts = <GPIO_PIN_NONE>;
pin-rts = <GPIO_PIN_NONE>;
};
};

View File

@ -39,9 +39,6 @@
pin-mosi = <23>;
pin-miso = <38>;
pin-sclk = <18>;
pin-wp = <GPIO_PIN_NONE>;
pin-hd = <GPIO_PIN_NONE>;
max-transfer-size = <0>;
};
// NS4168: Speaker and microphone
@ -53,7 +50,6 @@
pin-ws = <0>;
pin-data-out = <2>;
pin-data-in = <34>;
pin-mclk = <GPIO_PIN_NONE>;
};
uart_port_a: uart1 {
@ -61,7 +57,5 @@
port = <UART_NUM_1>;
pin-tx = <33>;
pin-rx = <32>;
pin-cts = <GPIO_PIN_NONE>;
pin-rts = <GPIO_PIN_NONE>;
};
};

View File

@ -17,7 +17,6 @@ static void setBacklightDuty(uint8_t backlightDuty) {
}
static std::shared_ptr<tt::hal::touch::TouchDevice> createTouch() {
// Note for future changes: Reset pin is 48 and interrupt pin is 47
auto configuration = std::make_unique<Ft5x06Touch::Configuration>(
I2C_NUM_0,
LCD_HORIZONTAL_RESOLUTION,

View File

@ -55,9 +55,6 @@
pin-mosi = <37>;
pin-miso = <35>;
pin-sclk = <36>;
pin-wp = <GPIO_PIN_NONE>;
pin-hd = <GPIO_PIN_NONE>;
max-transfer-size = <0>;
};
// TODO: Enable speaker via ES7210 I2C: https://github.com/m5stack/M5Unified/blob/a6256725481f1bc366655fa48cf03b6095e30ad1/src/M5Unified.cpp#L417
@ -79,7 +76,5 @@
port = <UART_NUM_1>;
pin-tx = <1>;
pin-rx = <2>;
pin-cts = <GPIO_PIN_NONE>;
pin-rts = <GPIO_PIN_NONE>;
};
};

View File

@ -28,8 +28,6 @@
pin-mosi = <38>;
pin-miso = <40>;
pin-sclk = <39>;
pin-wp = <GPIO_PIN_NONE>;
pin-hd = <GPIO_PIN_NONE>;
max-transfer-size = <4096>;
};
};

View File

@ -35,11 +35,7 @@
compatible = "espressif,esp32-spi";
host = <SPI2_HOST>;
pin-mosi = <15>;
pin-miso = <GPIO_PIN_NONE>;
pin-sclk = <13>;
pin-wp = <GPIO_PIN_NONE>;
pin-hd = <GPIO_PIN_NONE>;
max-transfer-size = <0>;
};
uart_grove: uart1 {
@ -47,7 +43,5 @@
port = <UART_NUM_1>;
pin-tx = <33>;
pin-rx = <32>;
pin-cts = <GPIO_PIN_NONE>;
pin-rts = <GPIO_PIN_NONE>;
};
};

View File

@ -34,11 +34,7 @@
compatible = "espressif,esp32-spi";
host = <SPI2_HOST>;
pin-mosi = <15>;
pin-miso = <GPIO_PIN_NONE>;
pin-sclk = <13>;
pin-wp = <GPIO_PIN_NONE>;
pin-hd = <GPIO_PIN_NONE>;
max-transfer-size = <0>;
};
uart_grove: uart1 {
@ -46,7 +42,5 @@
port = <UART_NUM_1>;
pin-tx = <33>;
pin-rx = <32>;
pin-cts = <GPIO_PIN_NONE>;
pin-rts = <GPIO_PIN_NONE>;
};
};

View File

@ -36,8 +36,5 @@
pin-mosi = <44>;
pin-miso = <39>;
pin-sclk = <43>;
pin-wp = <GPIO_PIN_NONE>;
pin-hd = <GPIO_PIN_NONE>;
max-transfer-size = <0>;
};
};

View File

@ -28,8 +28,6 @@
pin-mosi = <40>;
pin-miso = <41>;
pin-sclk = <39>;
pin-wp = <GPIO_PIN_NONE>;
pin-hd = <GPIO_PIN_NONE>;
max-transfer-size = <65536>;
};
};

View File

@ -27,11 +27,7 @@
compatible = "espressif,esp32-spi";
host = <SPI2_HOST>;
pin-mosi = <11>;
pin-miso = <GPIO_PIN_NONE>;
pin-sclk = <12>;
pin-wp = <GPIO_PIN_NONE>;
pin-hd = <GPIO_PIN_NONE>;
max-transfer-size = <0>;
};
uart0 {
@ -39,7 +35,5 @@
port = <UART_NUM_0>;
pin-tx = <43>;
pin-rx = <44>;
pin-cts = <GPIO_PIN_NONE>;
pin-rts = <GPIO_PIN_NONE>;
};
};

View File

@ -27,11 +27,7 @@
compatible = "espressif,esp32-spi";
host = <SPI2_HOST>;
pin-mosi = <41>;
pin-miso = <GPIO_PIN_NONE>;
pin-sclk = <40>;
pin-wp = <GPIO_PIN_NONE>;
pin-hd = <GPIO_PIN_NONE>;
max-transfer-size = <0>;
};
spi1 {
@ -40,8 +36,5 @@
pin-mosi = <18>;
pin-miso = <16>;
pin-sclk = <21>;
pin-wp = <GPIO_PIN_NONE>;
pin-hd = <GPIO_PIN_NONE>;
max-transfer-size = <0>;
};
};

View File

@ -29,9 +29,6 @@
pin-mosi = <11>;
pin-miso = <12>;
pin-sclk = <10>;
pin-wp = <GPIO_PIN_NONE>;
pin-hd = <GPIO_PIN_NONE>;
max-transfer-size = <0>;
};
sdcard_spi: spi1 {
@ -40,8 +37,5 @@
pin-mosi = <16>;
pin-miso = <15>;
pin-sclk = <17>;
pin-wp = <GPIO_PIN_NONE>;
pin-hd = <GPIO_PIN_NONE>;
max-transfer-size = <0>;
};
};

View File

@ -12,7 +12,6 @@ constexpr auto LCD_VERTICAL_RESOLUTION = 320;
void setBacklightDuty(uint8_t level);
static std::shared_ptr<tt::hal::touch::TouchDevice> createTouch() {
// Note for future changes: Reset pin is 48 and interrupt pin is 47
auto configuration = std::make_unique<Axs5106Touch::Configuration>(
I2C_NUM_0,
172,

View File

@ -29,9 +29,6 @@
pin-mosi = <39>;
pin-miso = <GPIO_PIN_NONE>;
pin-sclk = <38>;
pin-wp = <GPIO_PIN_NONE>;
pin-hd = <GPIO_PIN_NONE>;
max-transfer-size = <0>;
};
sdcard_spi: spi1 {
@ -40,8 +37,5 @@
pin-mosi = <15>;
pin-miso = <17>;
pin-sclk = <16>;
pin-wp = <GPIO_PIN_NONE>;
pin-hd = <GPIO_PIN_NONE>;
max-transfer-size = <0>;
};
};

View File

@ -29,9 +29,6 @@
pin-mosi = <11>;
pin-miso = <13>;
pin-sclk = <12>;
pin-wp = <GPIO_PIN_NONE>;
pin-hd = <GPIO_PIN_NONE>;
max-transfer-size = <0>;
};
uart1 {
@ -39,7 +36,5 @@
port = <UART_NUM_1>;
pin-tx = <43>;
pin-rx = <44>;
pin-cts = <GPIO_PIN_NONE>;
pin-rts = <GPIO_PIN_NONE>;
};
};

View File

@ -28,8 +28,5 @@
pin-mosi = <40>;
pin-miso = <38>;
pin-sclk = <39>;
pin-wp = <GPIO_PIN_NONE>;
pin-hd = <GPIO_PIN_NONE>;
max-transfer-size = <0>;
};
};

View File

@ -12,8 +12,6 @@
## Higher Priority
- Make a root device type so it can be discovered more easily.
- DTS/yaml: Consider support for default values.
- DTS: throw custom exceptions and catch them to show cleaner error messages.
- When device.py selects a new device, it should automatically delete the build dirs (build/, cmake-*/) when it detects that the platform has changed.
- Add font design tokens such as "regular", "title" and "smaller". Perhaps via the LVGL kernel module.
- Add kernel listening mechanism so that the root device init can be notified when a device becomes available:
@ -69,8 +67,6 @@
## Lower Priority
- Rename `Lock::lock()` and `Lock::unlock()` to `Lock::acquire()` and `Lock::release()`?
- Implement system suspend that turns off the screen
- The boot button on some devices can be used as GPIO_NUM_0 at runtime
- Localize all apps
- Support hot-plugging SD card (note: this is not possible if they require the CS pin hack)

View File

@ -51,7 +51,7 @@ add_custom_target(AlwaysRun
add_custom_command(
OUTPUT "${GENERATED_DIR}/devicetree.c"
"${GENERATED_DIR}/devicetree.h"
COMMAND pip install lark pyyaml
COMMAND pip install lark==1.3.1 pyyaml==6.0.3
COMMAND python "${CMAKE_SOURCE_DIR}/Buildscripts/DevicetreeCompiler/compile.py"
"${DEVICETREE_LOCATION}" "${GENERATED_DIR}"
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"

View File

@ -6,6 +6,12 @@ menu "Tactility App"
config TT_DEVICE_ID
string "Device Identifier"
default ""
# T-Deck device-related code was directly referenced from Tactility in a pull request.
# This breaks other devices because the code does not exist in those implementations.
# Until we move it out into a proper driver, we have to have pre-processor definition for that.
config TT_TDECK_WORKAROUND
bool "Temporary work-around until we fix the T-Deck keyboard and trackball settings"
default n
config TT_SPLASH_DURATION
int "Splash Duration (ms)"
default 1000

View File

@ -54,7 +54,7 @@ dependencies:
version: "1.7.6~1"
rules:
- if: "target == esp32s3"
espressif/esp_lvgl_port: "2.7.0"
espressif/esp_lvgl_port: "2.5.0"
lvgl/lvgl: "9.3.0"
FastEPD:
git: https://github.com/bitbank2/FastEPD.git

View File

@ -7,16 +7,20 @@ compatible: "espressif,esp32-i2c"
properties:
port:
type: int
required: true
description: |
The port number, defined by i2c_port_t.
Depending on the hardware, these values are available: I2C_NUM_0, I2C_NUM_1, LP_I2C_NUM_0
clock-frequency:
type: int
required: true
description: Initial clock frequency in Hz
pin-sda:
type: int
required: true
pin-scl:
type: int
required: true
pin-sda-pull-up:
type: bool
description: enable internal pull-up resistor for SDA pin

View File

@ -21,13 +21,14 @@ properties:
description: WS pin
pin-data-out:
type: int
required: true
default: GPIO_PIN_NONE
description: DATA OUT pin
pin-data-in:
type: int
required: true
default: GPIO_PIN_NONE
description: DATA IN pin
pin-mclk:
type: int
required: true
required: false
default: GPIO_PIN_NONE
description: MCLK pin

View File

@ -13,11 +13,11 @@ properties:
Defined by spi_host_device_t (e.g. SPI2_HOST, SPI3_HOST).
pin-mosi:
type: int
required: true
default: GPIO_PIN_NONE
description: MOSI (Data 0) pin
pin-miso:
type: int
required: true
default: GPIO_PIN_NONE
description: MISO (Data 1) pin
pin-sclk:
type: int
@ -25,12 +25,15 @@ properties:
description: Clock pin
pin-wp:
type: int
default: GPIO_PIN_NONE
description: WP (Data 2) pin
pin-hd:
type: int
default: GPIO_PIN_NONE
description: HD (Data 3) pin
max-transfer-size:
type: int
default: 0
description: |
Data transfer size limit in bytes.
0 means the platform decides the limit.

View File

@ -21,7 +21,9 @@ properties:
description: RX pin
pin-cts:
type: int
default: GPIO_PIN_NONE
description: CTS pin
pin-rts:
type: int
default: GPIO_PIN_NONE
description: RTS pin

View File

@ -32,6 +32,7 @@
#include <tactility/lvgl_module.h>
#ifdef ESP_PLATFORM
#include "tactility/drivers/root.h"
#include <Tactility/InitEsp.h>
#endif
@ -61,8 +62,6 @@ namespace service {
namespace statusbar { extern const ServiceManifest manifest; }
#ifdef ESP_PLATFORM
namespace displayidle { extern const ServiceManifest manifest; }
#endif
#if defined(ESP_PLATFORM) && defined(CONFIG_TT_DEVICE_LILYGO_TDECK)
namespace keyboardidle { extern const ServiceManifest manifest; }
#endif
#if TT_FEATURE_SCREENSHOT_ENABLED
@ -112,11 +111,10 @@ namespace app {
#ifdef ESP_PLATFORM
namespace crashdiagnostics { extern const AppManifest manifest; }
namespace webserversettings { extern const AppManifest manifest; }
#if CONFIG_TT_TDECK_WORKAROUND == 1
namespace keyboardsettings { extern const AppManifest manifest; } // T-Deck only for now
namespace trackballsettings { extern const AppManifest manifest; } // T-Deck only for now
#endif
#if defined(ESP_PLATFORM) && defined(CONFIG_TT_DEVICE_LILYGO_TDECK)
namespace keyboardsettings { extern const AppManifest manifest; }
namespace trackballsettings { extern const AppManifest manifest; }
#endif
#if TT_FEATURE_SCREENSHOT_ENABLED
@ -162,12 +160,11 @@ static void registerInternalApps() {
addAppManifest(app::webserversettings::manifest);
addAppManifest(app::crashdiagnostics::manifest);
addAppManifest(app::development::manifest);
#endif
#if defined(ESP_PLATFORM) && defined(CONFIG_TT_DEVICE_LILYGO_TDECK)
#if defined(CONFIG_TT_TDECK_WORKAROUND)
addAppManifest(app::keyboardsettings::manifest);
addAppManifest(app::trackballsettings::manifest);
#endif
#endif
#if defined(CONFIG_TINYUSB_MSC_ENABLED) && CONFIG_TINYUSB_MSC_ENABLED
addAppManifest(app::usbsettings::manifest);
@ -251,13 +248,13 @@ static void registerAndStartSecondaryServices() {
addService(service::loader::manifest);
addService(service::gui::manifest);
addService(service::statusbar::manifest);
#ifdef ESP_PLATFORM
addService(service::memorychecker::manifest);
#if defined(ESP_PLATFORM)
addService(service::displayidle::manifest);
#endif
#if defined(ESP_PLATFORM) && defined(CONFIG_TT_DEVICE_LILYGO_TDECK)
#if defined(CONFIG_TT_TDECK_WORKAROUND)
addService(service::keyboardidle::manifest);
#endif
addService(service::memorychecker::manifest);
#endif
#if TT_FEATURE_SCREENSHOT_ENABLED
addService(service::screenshot::manifest);
#endif

View File

@ -178,6 +178,14 @@ struct Device* device_get_parent(struct Device* device);
*/
bool device_is_ready(const struct Device* device);
/**
* Indicates whether the device is compatible with the given compatible string.
* @param[in] device non-null device pointer
* @param[in] compatible compatible string
* @return true if the device is compatible
*/
bool device_is_compatible(const struct Device* device, const char* compatible);
/**
* Set the driver data for a device.
*

View File

@ -2,6 +2,8 @@
#pragma once
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
@ -10,6 +12,14 @@ struct RootConfig {
const char* model;
};
/**
* Indicates whether the device's model matches the specified model.
* @param[in] device the device to check (non-null)
* @param[in] model the model to check against
* @return true if the device's model matches the specified model
*/
bool root_is_model(const struct Device* device, const char* model);
#ifdef __cplusplus
}
#endif

View File

@ -23,6 +23,7 @@ typedef int error_t;
#define ERROR_OUT_OF_MEMORY 9
#define ERROR_NOT_SUPPORTED 10
#define ERROR_NOT_ALLOWED 11
#define ERROR_BUFFER_OVERFLOW 12
/** Convert an error_t to a human-readable text. Useful for logging. */
const char* error_to_string(error_t error);

View File

@ -277,6 +277,11 @@ bool device_is_ready(const struct Device* device) {
return device->internal->state.started;
}
bool device_is_compatible(const struct Device* device, const char* compatible) {
if (device->internal->driver == nullptr) return false;
return driver_is_compatible(device->internal->driver, compatible);
}
void device_set_driver_data(struct Device* device, void* driver_data) {
device->internal->driver_data = driver_data;
}

View File

@ -1,10 +1,17 @@
// SPDX-License-Identifier: Apache-2.0
#include <tactility/device.h>
#include <tactility/driver.h>
#include <tactility/drivers/root.h>
#include <cstring>
extern "C" {
bool root_is_model(const struct Device* device, const char* buffer) {
auto* config = static_cast<const RootConfig*>(device->config);
return strcmp(config->model, buffer) == 0;
}
Driver root_driver = {
.name = "root",
.compatible = (const char*[]) { "root", nullptr },
@ -12,7 +19,8 @@ Driver root_driver = {
.stop_device = nullptr,
.api = nullptr,
.device_type = nullptr,
.owner = nullptr
.owner = nullptr,
.internal = nullptr
};
}

View File

@ -29,6 +29,8 @@ const char* error_to_string(error_t error) {
return "not supported";
case ERROR_NOT_ALLOWED:
return "not allowed";
case ERROR_BUFFER_OVERFLOW:
return "buffer overflow";
default:
return "unknown";
}

View File

@ -3,6 +3,7 @@
#include <tactility/drivers/gpio_controller.h>
#include <tactility/drivers/i2c_controller.h>
#include <tactility/drivers/i2s_controller.h>
#include <tactility/drivers/root.h>
#include <tactility/drivers/spi_controller.h>
#include <tactility/drivers/uart_controller.h>
#include <tactility/concurrent/dispatcher.h>
@ -36,6 +37,7 @@ const struct ModuleSymbol KERNEL_SYMBOLS[] = {
DEFINE_MODULE_SYMBOL(device_get_driver_data),
DEFINE_MODULE_SYMBOL(device_is_added),
DEFINE_MODULE_SYMBOL(device_is_ready),
DEFINE_MODULE_SYMBOL(device_is_compatible),
DEFINE_MODULE_SYMBOL(device_lock),
DEFINE_MODULE_SYMBOL(device_try_lock),
DEFINE_MODULE_SYMBOL(device_unlock),
@ -79,6 +81,8 @@ const struct ModuleSymbol KERNEL_SYMBOLS[] = {
DEFINE_MODULE_SYMBOL(i2s_controller_get_config),
DEFINE_MODULE_SYMBOL(i2s_controller_reset),
DEFINE_MODULE_SYMBOL(I2S_CONTROLLER_TYPE),
// drivers/root
DEFINE_MODULE_SYMBOL(root_is_model),
// drivers/spi_controller
DEFINE_MODULE_SYMBOL(spi_controller_lock),
DEFINE_MODULE_SYMBOL(spi_controller_try_lock),

View File

@ -105,6 +105,9 @@ def write_tactility_variables(output_file, device_properties: ConfigParser, devi
else:
output_file.write(f"CONFIG_TT_DEVICE_NAME=\"{board_vendor} {board_name}\"\n")
output_file.write(f"CONFIG_TT_DEVICE_ID=\"{device_id}\"\n")
if device_id == "lilygo-tdeck":
output_file.write("CONFIG_TT_TDECK_WORKAROUND=y\n")
def write_core_variables(output_file, device_properties: ConfigParser):
idf_target = get_property_or_exit(device_properties, "hardware", "target").lower()