mirror of
https://github.com/ByteWelder/Tactility.git
synced 2026-04-20 18:35:05 +00:00
Create hal-device module, fix GPIO, fix tests, fix TactilityC (#471)
* **New Features** * Added a HAL device module providing device enumeration, type queries and a HAL↔kernel bridge. * **Improvements** * Integrated HAL module into startup; standardized module names, includes and lifecycle logging; safer file append behavior; broader build support. * **API Changes** * Driver lifecycle now uses explicit add/remove semantics; C and HAL device type/lookup APIs clarified. * **Chores** * Added module README and Apache‑2.0 license; updated build configuration to include the new module. * **Fixes** * Updated tests and object file handling to behave correctly.
This commit is contained in:
parent
5993ceb232
commit
3fe1dc0312
@ -32,6 +32,7 @@ if (DEFINED ENV{ESP_IDF_VERSION})
|
|||||||
"Firmware"
|
"Firmware"
|
||||||
"Devices/${TACTILITY_DEVICE_PROJECT}"
|
"Devices/${TACTILITY_DEVICE_PROJECT}"
|
||||||
"Drivers"
|
"Drivers"
|
||||||
|
"Modules"
|
||||||
"Platforms/PlatformEsp32"
|
"Platforms/PlatformEsp32"
|
||||||
"TactilityKernel"
|
"TactilityKernel"
|
||||||
"Tactility"
|
"Tactility"
|
||||||
@ -84,6 +85,7 @@ if (NOT DEFINED ENV{ESP_IDF_VERSION})
|
|||||||
add_subdirectory(Libraries/QRCode)
|
add_subdirectory(Libraries/QRCode)
|
||||||
add_subdirectory(Libraries/minitar)
|
add_subdirectory(Libraries/minitar)
|
||||||
add_subdirectory(Libraries/minmea)
|
add_subdirectory(Libraries/minmea)
|
||||||
|
add_subdirectory(Modules/hal-device)
|
||||||
|
|
||||||
# FreeRTOS
|
# FreeRTOS
|
||||||
set(FREERTOS_CONFIG_FILE_DIRECTORY ${PROJECT_SOURCE_DIR}/Devices/simulator/Source CACHE STRING "")
|
set(FREERTOS_CONFIG_FILE_DIRECTORY ${PROJECT_SOURCE_DIR}/Devices/simulator/Source CACHE STRING "")
|
||||||
|
|||||||
@ -36,7 +36,7 @@ static bool initBoot() {
|
|||||||
|
|
||||||
using namespace tt::hal;
|
using namespace tt::hal;
|
||||||
|
|
||||||
static std::vector<std::shared_ptr<Device>> createDevices() {
|
static std::vector<std::shared_ptr<tt::hal::Device>> createDevices() {
|
||||||
return {
|
return {
|
||||||
createPower(),
|
createPower(),
|
||||||
ButtonControl::createOneButtonControl(0),
|
ButtonControl::createOneButtonControl(0),
|
||||||
|
|||||||
@ -12,7 +12,7 @@ bool initBoot();
|
|||||||
|
|
||||||
using namespace tt::hal;
|
using namespace tt::hal;
|
||||||
|
|
||||||
static std::vector<std::shared_ptr<Device>> createDevices() {
|
static std::vector<std::shared_ptr<tt::hal::Device>> createDevices() {
|
||||||
return {
|
return {
|
||||||
createPower(),
|
createPower(),
|
||||||
createDisplay(),
|
createDisplay(),
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Tactility/hal/Device.h>
|
#include <tactility/hal/Device.h>
|
||||||
#include <Tactility/TactilityCore.h>
|
#include <Tactility/TactilityCore.h>
|
||||||
|
|
||||||
class KeyboardBacklightDevice final : public tt::hal::Device {
|
class KeyboardBacklightDevice final : public tt::hal::Device {
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
#include <Tactility/settings/KeyboardSettings.h>
|
#include <Tactility/settings/KeyboardSettings.h>
|
||||||
#include <Tactility/settings/DisplaySettings.h>
|
#include <Tactility/settings/DisplaySettings.h>
|
||||||
#include <Tactility/hal/display/DisplayDevice.h>
|
#include <Tactility/hal/display/DisplayDevice.h>
|
||||||
#include <Tactility/hal/Device.h>
|
#include <tactility/hal/Device.h>
|
||||||
#include <Tactility/Logger.h>
|
#include <Tactility/Logger.h>
|
||||||
#include <KeyboardBacklight/KeyboardBacklight.h>
|
#include <KeyboardBacklight/KeyboardBacklight.h>
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Tactility/hal/Device.h>
|
#include <tactility/hal/Device.h>
|
||||||
#include <lvgl.h>
|
#include <lvgl.h>
|
||||||
|
|
||||||
class TrackballDevice : public tt::hal::Device {
|
class TrackballDevice : public tt::hal::Device {
|
||||||
|
|||||||
@ -9,7 +9,7 @@ bool initBoot();
|
|||||||
|
|
||||||
using namespace tt::hal;
|
using namespace tt::hal;
|
||||||
|
|
||||||
static std::vector<std::shared_ptr<Device>> createDevices() {
|
static std::vector<std::shared_ptr<tt::hal::Device>> createDevices() {
|
||||||
return {
|
return {
|
||||||
createPower(),
|
createPower(),
|
||||||
createDisplay(),
|
createDisplay(),
|
||||||
|
|||||||
@ -11,7 +11,7 @@ static bool initBoot() {
|
|||||||
return driver::pwmbacklight::init(LCD_PIN_BACKLIGHT);
|
return driver::pwmbacklight::init(LCD_PIN_BACKLIGHT);
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<std::shared_ptr<Device>> createDevices() {
|
static std::vector<std::shared_ptr<tt::hal::Device>> createDevices() {
|
||||||
return {
|
return {
|
||||||
createDisplay(),
|
createDisplay(),
|
||||||
ButtonControl::createTwoButtonControl(35, 0)
|
ButtonControl::createTwoButtonControl(35, 0)
|
||||||
|
|||||||
@ -10,7 +10,7 @@ bool initBoot();
|
|||||||
|
|
||||||
using namespace tt::hal;
|
using namespace tt::hal;
|
||||||
|
|
||||||
static std::vector<std::shared_ptr<Device>> createDevices() {
|
static std::vector<std::shared_ptr<tt::hal::Device>> createDevices() {
|
||||||
return {
|
return {
|
||||||
createDisplay(),
|
createDisplay(),
|
||||||
createSdCard()
|
createSdCard()
|
||||||
|
|||||||
@ -22,7 +22,7 @@ static DeviceVector createDevices() {
|
|||||||
auto tca8418 = std::make_shared<Tca8418>(I2C_NUM_0);
|
auto tca8418 = std::make_shared<Tca8418>(I2C_NUM_0);
|
||||||
auto keyboard = std::make_shared<TpagerKeyboard>(tca8418);
|
auto keyboard = std::make_shared<TpagerKeyboard>(tca8418);
|
||||||
|
|
||||||
return std::vector<std::shared_ptr<Device>> {
|
return std::vector<std::shared_ptr<tt::hal::Device>> {
|
||||||
tca8418,
|
tca8418,
|
||||||
std::make_shared<Bq25896>(I2C_NUM_0),
|
std::make_shared<Bq25896>(I2C_NUM_0),
|
||||||
bq27220,
|
bq27220,
|
||||||
|
|||||||
@ -9,14 +9,14 @@ extern Driver tlora_pager_driver;
|
|||||||
static error_t start() {
|
static error_t start() {
|
||||||
/* We crash when construct fails, because if a single driver fails to construct,
|
/* We crash when construct fails, because if a single driver fails to construct,
|
||||||
* there is no guarantee that the previously constructed drivers can be destroyed */
|
* there is no guarantee that the previously constructed drivers can be destroyed */
|
||||||
check(driver_construct(&tlora_pager_driver) == ERROR_NONE);
|
check(driver_construct_add(&tlora_pager_driver) == ERROR_NONE);
|
||||||
return ERROR_NONE;
|
return ERROR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static error_t stop() {
|
static error_t stop() {
|
||||||
/* We crash when destruct fails, because if a single driver fails to destruct,
|
/* We crash when destruct fails, because if a single driver fails to destruct,
|
||||||
* there is no guarantee that the previously destroyed drivers can be recovered */
|
* there is no guarantee that the previously destroyed drivers can be recovered */
|
||||||
check(driver_destruct(&tlora_pager_driver) == ERROR_NONE);
|
check(driver_remove_destruct(&tlora_pager_driver) == ERROR_NONE);
|
||||||
return ERROR_NONE;
|
return ERROR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -28,7 +28,7 @@ static void deinitPower() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<std::shared_ptr<Device>> createDevices() {
|
static std::vector<std::shared_ptr<tt::hal::Device>> createDevices() {
|
||||||
return {
|
return {
|
||||||
std::make_shared<SdlDisplay>(),
|
std::make_shared<SdlDisplay>(),
|
||||||
std::make_shared<SdlKeyboard>(),
|
std::make_shared<SdlKeyboard>(),
|
||||||
|
|||||||
@ -10,7 +10,7 @@ bool initBoot();
|
|||||||
|
|
||||||
using namespace tt::hal;
|
using namespace tt::hal;
|
||||||
|
|
||||||
static std::vector<std::shared_ptr<Device>> createDevices() {
|
static std::vector<std::shared_ptr<tt::hal::Device>> createDevices() {
|
||||||
return {
|
return {
|
||||||
createDisplay(),
|
createDisplay(),
|
||||||
createSdCard()
|
createSdCard()
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
#include "Xpt2046Touch.h"
|
#include "Xpt2046Touch.h"
|
||||||
|
|
||||||
#include <Tactility/Logger.h>
|
#include <Tactility/Logger.h>
|
||||||
#include <Tactility/hal/Device.h>
|
#include <tactility/hal/Device.h>
|
||||||
|
|
||||||
static const auto LOGGER = tt::Logger("Xpt2046Power");
|
static const auto LOGGER = tt::Logger("Xpt2046Power");
|
||||||
|
|
||||||
|
|||||||
@ -36,6 +36,7 @@ else ()
|
|||||||
TactilityCore
|
TactilityCore
|
||||||
TactilityFreeRtos
|
TactilityFreeRtos
|
||||||
TactilityKernel
|
TactilityKernel
|
||||||
|
hal-device
|
||||||
Simulator
|
Simulator
|
||||||
PlatformPosix
|
PlatformPosix
|
||||||
SDL2::SDL2-static SDL2-static
|
SDL2::SDL2-static SDL2-static
|
||||||
|
|||||||
46
Modules/hal-device/CMakeLists.txt
Normal file
46
Modules/hal-device/CMakeLists.txt
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.20)
|
||||||
|
|
||||||
|
if (DEFINED ENV{ESP_IDF_VERSION})
|
||||||
|
file(GLOB_RECURSE SOURCE_FILES Source/*.c*)
|
||||||
|
|
||||||
|
list(APPEND REQUIRES_LIST
|
||||||
|
TactilityKernel
|
||||||
|
TactilityCore
|
||||||
|
TactilityFreeRtos
|
||||||
|
)
|
||||||
|
|
||||||
|
idf_component_register(
|
||||||
|
SRCS ${SOURCE_FILES}
|
||||||
|
INCLUDE_DIRS "Include/"
|
||||||
|
REQUIRES ${REQUIRES_LIST}
|
||||||
|
)
|
||||||
|
|
||||||
|
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||||
|
target_compile_options(${COMPONENT_LIB} PUBLIC -Wno-unused-variable)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
else ()
|
||||||
|
|
||||||
|
file(GLOB_RECURSE SOURCES "Source/*.c*")
|
||||||
|
|
||||||
|
add_library(hal-device OBJECT)
|
||||||
|
|
||||||
|
target_sources(hal-device PRIVATE ${SOURCES})
|
||||||
|
|
||||||
|
target_include_directories(hal-device
|
||||||
|
PRIVATE Private/
|
||||||
|
PUBLIC Include/
|
||||||
|
)
|
||||||
|
|
||||||
|
add_definitions(-D_Nullable=)
|
||||||
|
add_definitions(-D_Nonnull=)
|
||||||
|
|
||||||
|
target_link_libraries(hal-device PUBLIC
|
||||||
|
TactilityFreeRtos
|
||||||
|
TactilityCore
|
||||||
|
TactilityKernel
|
||||||
|
freertos_kernel
|
||||||
|
)
|
||||||
|
|
||||||
|
endif ()
|
||||||
|
|
||||||
28
Modules/hal-device/Include/tactility/drivers/hal_device.h
Normal file
28
Modules/hal-device/Include/tactility/drivers/hal_device.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum class HalDeviceType {
|
||||||
|
HAL_DEVICE_TYPE_I2C,
|
||||||
|
HAL_DEVICE_TYPE_DISPLAY,
|
||||||
|
HAL_DEVICE_TYPE_TOUCH,
|
||||||
|
HAL_DEVICE_TYPE_SDCARD,
|
||||||
|
HAL_DEVICE_TYPE_KEYBOARD,
|
||||||
|
HAL_DEVICE_TYPE_ENCODER,
|
||||||
|
HAL_DEVICE_TYPE_POWER,
|
||||||
|
HAL_DEVICE_TYPE_GPS,
|
||||||
|
HAL_DEVICE_TYPE_OTHER
|
||||||
|
};
|
||||||
|
|
||||||
|
HalDeviceType hal_device_get_type(struct Device* device);
|
||||||
|
|
||||||
|
void hal_device_for_each_of_type(HalDeviceType type, void* context, bool(*onDevice)(struct Device* device, void* context));
|
||||||
|
|
||||||
|
extern const struct DeviceType HAL_DEVICE_TYPE;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
21
Modules/hal-device/Include/tactility/drivers/hal_device.hpp
Normal file
21
Modules/hal-device/Include/tactility/drivers/hal_device.hpp
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "hal_device.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <tactility/hal/Device.h>
|
||||||
|
|
||||||
|
namespace tt::hal {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get a tt::hal::Device object from a Kernel device.
|
||||||
|
* @warning The input device must be of type HAL_DEVICE_TYPE
|
||||||
|
* @param kernelDevice The kernel device
|
||||||
|
* @return std::shared_ptr<Device>
|
||||||
|
*/
|
||||||
|
std::shared_ptr<Device> hal_device_get_device(::Device* kernelDevice);
|
||||||
|
|
||||||
|
void hal_device_set_device(::Device* kernelDevice, std::shared_ptr<Device> halDevice);
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,3 +1,4 @@
|
|||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
@ -7,6 +8,10 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
|
#include <tactility/device.h>
|
||||||
|
|
||||||
|
typedef ::Device KernelDevice;
|
||||||
|
|
||||||
namespace tt::hal {
|
namespace tt::hal {
|
||||||
/** Base class for HAL-related devices. */
|
/** Base class for HAL-related devices. */
|
||||||
class Device {
|
class Device {
|
||||||
@ -27,9 +32,19 @@ public:
|
|||||||
|
|
||||||
typedef uint32_t Id;
|
typedef uint32_t Id;
|
||||||
|
|
||||||
|
struct KernelDeviceHolder {
|
||||||
|
const std::string name;
|
||||||
|
std::shared_ptr<KernelDevice> device = std::make_shared<KernelDevice>();
|
||||||
|
|
||||||
|
explicit KernelDeviceHolder(std::string name) : name(name) {
|
||||||
|
device->name = this->name.c_str();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Id id;
|
Id id;
|
||||||
|
std::shared_ptr<KernelDeviceHolder> kernelDeviceHolder;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -49,6 +64,10 @@ public:
|
|||||||
* e.g. "USB charging controller with I2C interface."
|
* e.g. "USB charging controller with I2C interface."
|
||||||
*/
|
*/
|
||||||
virtual std::string getDescription() const = 0;
|
virtual std::string getDescription() const = 0;
|
||||||
|
|
||||||
|
void setKernelDeviceHolder(std::shared_ptr<KernelDeviceHolder> kernelDeviceHolder) { this->kernelDeviceHolder = kernelDeviceHolder; }
|
||||||
|
|
||||||
|
std::shared_ptr<KernelDeviceHolder> getKernelDeviceHolder() const { return kernelDeviceHolder; }
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -92,7 +111,7 @@ std::vector<std::shared_ptr<DeviceType>> findDevices(Device::Type type) {
|
|||||||
assert(target_device != nullptr);
|
assert(target_device != nullptr);
|
||||||
result.push_back(target_device);
|
result.push_back(target_device);
|
||||||
}
|
}
|
||||||
return std::move(result);
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
12
Modules/hal-device/Include/tactility/hal_device_module.h
Normal file
12
Modules/hal-device/Include/tactility/hal_device_module.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern struct Module hal_device_module;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
195
Modules/hal-device/LICENSE-Apache-2.0.md
Normal file
195
Modules/hal-device/LICENSE-Apache-2.0.md
Normal file
@ -0,0 +1,195 @@
|
|||||||
|
Apache License
|
||||||
|
==============
|
||||||
|
|
||||||
|
_Version 2.0, January 2004_
|
||||||
|
_<<http://www.apache.org/licenses/>>_
|
||||||
|
|
||||||
|
### Terms and Conditions for use, reproduction, and distribution
|
||||||
|
|
||||||
|
#### 1. Definitions
|
||||||
|
|
||||||
|
“License” shall mean the terms and conditions for use, reproduction, and
|
||||||
|
distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
“Licensor” shall mean the copyright owner or entity authorized by the copyright
|
||||||
|
owner that is granting the License.
|
||||||
|
|
||||||
|
“Legal Entity” shall mean the union of the acting entity and all other entities
|
||||||
|
that control, are controlled by, or are under common control with that entity.
|
||||||
|
For the purposes of this definition, “control” means **(i)** the power, direct or
|
||||||
|
indirect, to cause the direction or management of such entity, whether by
|
||||||
|
contract or otherwise, or **(ii)** ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or **(iii)** beneficial ownership of such entity.
|
||||||
|
|
||||||
|
“You” (or “Your”) shall mean an individual or Legal Entity exercising
|
||||||
|
permissions granted by this License.
|
||||||
|
|
||||||
|
“Source” form shall mean the preferred form for making modifications, including
|
||||||
|
but not limited to software source code, documentation source, and configuration
|
||||||
|
files.
|
||||||
|
|
||||||
|
“Object” form shall mean any form resulting from mechanical transformation or
|
||||||
|
translation of a Source form, including but not limited to compiled object code,
|
||||||
|
generated documentation, and conversions to other media types.
|
||||||
|
|
||||||
|
“Work” shall mean the work of authorship, whether in Source or Object form, made
|
||||||
|
available under the License, as indicated by a copyright notice that is included
|
||||||
|
in or attached to the work (an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
“Derivative Works” shall mean any work, whether in Source or Object form, that
|
||||||
|
is based on (or derived from) the Work and for which the editorial revisions,
|
||||||
|
annotations, elaborations, or other modifications represent, as a whole, an
|
||||||
|
original work of authorship. For the purposes of this License, Derivative Works
|
||||||
|
shall not include works that remain separable from, or merely link (or bind by
|
||||||
|
name) to the interfaces of, the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
“Contribution” shall mean any work of authorship, including the original version
|
||||||
|
of the Work and any modifications or additions to that Work or Derivative Works
|
||||||
|
thereof, that is intentionally submitted to Licensor for inclusion in the Work
|
||||||
|
by the copyright owner or by an individual or Legal Entity authorized to submit
|
||||||
|
on behalf of the copyright owner. For the purposes of this definition,
|
||||||
|
“submitted” means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems, and
|
||||||
|
issue tracking systems that are managed by, or on behalf of, the Licensor for
|
||||||
|
the purpose of discussing and improving the Work, but excluding communication
|
||||||
|
that is conspicuously marked or otherwise designated in writing by the copyright
|
||||||
|
owner as “Not a Contribution.”
|
||||||
|
|
||||||
|
“Contributor” shall mean Licensor and any individual or Legal Entity on behalf
|
||||||
|
of whom a Contribution has been received by Licensor and subsequently
|
||||||
|
incorporated within the Work.
|
||||||
|
|
||||||
|
#### 2. Grant of Copyright License
|
||||||
|
|
||||||
|
Subject to the terms and conditions of this License, each Contributor hereby
|
||||||
|
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
|
||||||
|
irrevocable copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the Work and such
|
||||||
|
Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
#### 3. Grant of Patent License
|
||||||
|
|
||||||
|
Subject to the terms and conditions of this License, each Contributor hereby
|
||||||
|
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
|
||||||
|
irrevocable (except as stated in this section) patent license to make, have
|
||||||
|
made, use, offer to sell, sell, import, and otherwise transfer the Work, where
|
||||||
|
such license applies only to those patent claims licensable by such Contributor
|
||||||
|
that are necessarily infringed by their Contribution(s) alone or by combination
|
||||||
|
of their Contribution(s) with the Work to which such Contribution(s) was
|
||||||
|
submitted. If You institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work or a
|
||||||
|
Contribution incorporated within the Work constitutes direct or contributory
|
||||||
|
patent infringement, then any patent licenses granted to You under this License
|
||||||
|
for that Work shall terminate as of the date such litigation is filed.
|
||||||
|
|
||||||
|
#### 4. Redistribution
|
||||||
|
|
||||||
|
You may reproduce and distribute copies of the Work or Derivative Works thereof
|
||||||
|
in any medium, with or without modifications, and in Source or Object form,
|
||||||
|
provided that You meet the following conditions:
|
||||||
|
|
||||||
|
* **(a)** You must give any other recipients of the Work or Derivative Works a copy of
|
||||||
|
this License; and
|
||||||
|
* **(b)** You must cause any modified files to carry prominent notices stating that You
|
||||||
|
changed the files; and
|
||||||
|
* **(c)** You must retain, in the Source form of any Derivative Works that You distribute,
|
||||||
|
all copyright, patent, trademark, and attribution notices from the Source form
|
||||||
|
of the Work, excluding those notices that do not pertain to any part of the
|
||||||
|
Derivative Works; and
|
||||||
|
* **(d)** If the Work includes a “NOTICE” text file as part of its distribution, then any
|
||||||
|
Derivative Works that You distribute must include a readable copy of the
|
||||||
|
attribution notices contained within such NOTICE file, excluding those notices
|
||||||
|
that do not pertain to any part of the Derivative Works, in at least one of the
|
||||||
|
following places: within a NOTICE text file distributed as part of the
|
||||||
|
Derivative Works; within the Source form or documentation, if provided along
|
||||||
|
with the Derivative Works; or, within a display generated by the Derivative
|
||||||
|
Works, if and wherever such third-party notices normally appear. The contents of
|
||||||
|
the NOTICE file are for informational purposes only and do not modify the
|
||||||
|
License. You may add Your own attribution notices within Derivative Works that
|
||||||
|
You distribute, alongside or as an addendum to the NOTICE text from the Work,
|
||||||
|
provided that such additional attribution notices cannot be construed as
|
||||||
|
modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and may provide
|
||||||
|
additional or different license terms and conditions for use, reproduction, or
|
||||||
|
distribution of Your modifications, or for any such Derivative Works as a whole,
|
||||||
|
provided Your use, reproduction, and distribution of the Work otherwise complies
|
||||||
|
with the conditions stated in this License.
|
||||||
|
|
||||||
|
#### 5. Submission of Contributions
|
||||||
|
|
||||||
|
Unless You explicitly state otherwise, any Contribution intentionally submitted
|
||||||
|
for inclusion in the Work by You to the Licensor shall be under the terms and
|
||||||
|
conditions of this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify the terms of
|
||||||
|
any separate license agreement you may have executed with Licensor regarding
|
||||||
|
such Contributions.
|
||||||
|
|
||||||
|
#### 6. Trademarks
|
||||||
|
|
||||||
|
This License does not grant permission to use the trade names, trademarks,
|
||||||
|
service marks, or product names of the Licensor, except as required for
|
||||||
|
reasonable and customary use in describing the origin of the Work and
|
||||||
|
reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
#### 7. Disclaimer of Warranty
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, Licensor provides the
|
||||||
|
Work (and each Contributor provides its Contributions) on an “AS IS” BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
|
||||||
|
including, without limitation, any warranties or conditions of TITLE,
|
||||||
|
NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
|
||||||
|
solely responsible for determining the appropriateness of using or
|
||||||
|
redistributing the Work and assume any risks associated with Your exercise of
|
||||||
|
permissions under this License.
|
||||||
|
|
||||||
|
#### 8. Limitation of Liability
|
||||||
|
|
||||||
|
In no event and under no legal theory, whether in tort (including negligence),
|
||||||
|
contract, or otherwise, unless required by applicable law (such as deliberate
|
||||||
|
and grossly negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special, incidental,
|
||||||
|
or consequential damages of any character arising as a result of this License or
|
||||||
|
out of the use or inability to use the Work (including but not limited to
|
||||||
|
damages for loss of goodwill, work stoppage, computer failure or malfunction, or
|
||||||
|
any and all other commercial damages or losses), even if such Contributor has
|
||||||
|
been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
#### 9. Accepting Warranty or Additional Liability
|
||||||
|
|
||||||
|
While redistributing the Work or Derivative Works thereof, You may choose to
|
||||||
|
offer, and charge a fee for, acceptance of support, warranty, indemnity, or
|
||||||
|
other liability obligations and/or rights consistent with this License. However,
|
||||||
|
in accepting such obligations, You may act only on Your own behalf and on Your
|
||||||
|
sole responsibility, not on behalf of any other Contributor, and only if You
|
||||||
|
agree to indemnify, defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason of your
|
||||||
|
accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
_END OF TERMS AND CONDITIONS_
|
||||||
|
|
||||||
|
### APPENDIX: How to apply the Apache License to your work
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following boilerplate
|
||||||
|
notice, with the fields enclosed by brackets `[]` replaced with your own
|
||||||
|
identifying information. (Don't include the brackets!) The text should be
|
||||||
|
enclosed in the appropriate comment syntax for the file format. We also
|
||||||
|
recommend that a file or class name and description of purpose be included on
|
||||||
|
the same “printed page” as the copyright notice for easier identification within
|
||||||
|
third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
8
Modules/hal-device/README.md
Normal file
8
Modules/hal-device/README.md
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
**WARNING: This module contains deprecated code**
|
||||||
|
|
||||||
|
This module is the basis for the old Tactility HAL.
|
||||||
|
This HAL existed before TactilityKernel.
|
||||||
|
|
||||||
|
The C++ `tt::hal::Device` class is replaced by `struct Device` from TactilityKernel.
|
||||||
|
|
||||||
|
License: Apache v2.0
|
||||||
126
Modules/hal-device/Source/drivers/hal_device.cpp
Normal file
126
Modules/hal-device/Source/drivers/hal_device.cpp
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
#include <tactility/drivers/hal_device.h>
|
||||||
|
#include <tactility/device.h>
|
||||||
|
#include <tactility/driver.h>
|
||||||
|
|
||||||
|
#include <tactility/log.h>
|
||||||
|
#include <tactility/hal/Device.h>
|
||||||
|
#include <memory>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#define TAG LOG_TAG(HalDevice)
|
||||||
|
|
||||||
|
struct HalDevicePrivate {
|
||||||
|
std::shared_ptr<tt::hal::Device> halDevice;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define GET_DATA(device) ((struct HalDevicePrivate*)device->internal.driver_data)
|
||||||
|
|
||||||
|
static enum HalDeviceType getHalDeviceType(tt::hal::Device::Type type) {
|
||||||
|
switch (type) {
|
||||||
|
case tt::hal::Device::Type::I2c:
|
||||||
|
return HalDeviceType::HAL_DEVICE_TYPE_I2C;
|
||||||
|
case tt::hal::Device::Type::Display:
|
||||||
|
return HalDeviceType::HAL_DEVICE_TYPE_DISPLAY;
|
||||||
|
case tt::hal::Device::Type::Touch:
|
||||||
|
return HalDeviceType::HAL_DEVICE_TYPE_TOUCH;
|
||||||
|
case tt::hal::Device::Type::SdCard:
|
||||||
|
return HalDeviceType::HAL_DEVICE_TYPE_SDCARD;
|
||||||
|
case tt::hal::Device::Type::Keyboard:
|
||||||
|
return HalDeviceType::HAL_DEVICE_TYPE_KEYBOARD;
|
||||||
|
case tt::hal::Device::Type::Encoder:
|
||||||
|
return HalDeviceType::HAL_DEVICE_TYPE_ENCODER;
|
||||||
|
case tt::hal::Device::Type::Power:
|
||||||
|
return HalDeviceType::HAL_DEVICE_TYPE_POWER;
|
||||||
|
case tt::hal::Device::Type::Gps:
|
||||||
|
return HalDeviceType::HAL_DEVICE_TYPE_GPS;
|
||||||
|
case tt::hal::Device::Type::Other:
|
||||||
|
return HalDeviceType::HAL_DEVICE_TYPE_OTHER;
|
||||||
|
default:
|
||||||
|
LOG_W(TAG, "Device type %d is not implemented", static_cast<int>(type));
|
||||||
|
return HalDeviceType::HAL_DEVICE_TYPE_OTHER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
HalDeviceType hal_device_get_type(struct Device* device) {
|
||||||
|
auto type = GET_DATA(device)->halDevice->getType();
|
||||||
|
return getHalDeviceType(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
void hal_device_for_each_of_type(HalDeviceType type, void* context, bool(*onDevice)(struct Device* device, void* context)) {
|
||||||
|
struct InternalContext {
|
||||||
|
HalDeviceType typeParam;
|
||||||
|
void* contextParam;
|
||||||
|
bool(*onDeviceParam)(struct Device* device, void* context);
|
||||||
|
};
|
||||||
|
|
||||||
|
InternalContext internal_context = {
|
||||||
|
.typeParam = type,
|
||||||
|
.contextParam = context,
|
||||||
|
.onDeviceParam = onDevice
|
||||||
|
};
|
||||||
|
|
||||||
|
for_each_device_of_type(&HAL_DEVICE_TYPE, &internal_context, [](Device* device, void* context){
|
||||||
|
auto* hal_device_private = GET_DATA(device);
|
||||||
|
auto* internal_context = static_cast<InternalContext*>(context);
|
||||||
|
auto hal_device_type = getHalDeviceType(hal_device_private->halDevice->getType());
|
||||||
|
if (hal_device_type == internal_context->typeParam) {
|
||||||
|
if (!internal_context->onDeviceParam(device, internal_context->contextParam)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace tt::hal {
|
||||||
|
|
||||||
|
std::shared_ptr<Device> hal_device_get_device(::Device* device) {
|
||||||
|
auto* hal_device_private = GET_DATA(device);
|
||||||
|
return hal_device_private->halDevice;
|
||||||
|
}
|
||||||
|
|
||||||
|
void hal_device_set_device(::Device* kernelDevice, std::shared_ptr<Device> halDevice) {
|
||||||
|
GET_DATA(kernelDevice)->halDevice = std::move(halDevice);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma region Lifecycle
|
||||||
|
|
||||||
|
static error_t start(Device* device) {
|
||||||
|
LOG_I(TAG, "start %s", device->name);
|
||||||
|
device->internal.driver_data = new HalDevicePrivate();
|
||||||
|
return ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static error_t stop(Device* device) {
|
||||||
|
LOG_I(TAG, "stop %s", device->name);
|
||||||
|
delete GET_DATA(device);
|
||||||
|
return ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
const struct DeviceType HAL_DEVICE_TYPE {0};
|
||||||
|
|
||||||
|
extern struct Module hal_device_module;
|
||||||
|
|
||||||
|
Driver hal_device_driver = {
|
||||||
|
.name = "hal-device",
|
||||||
|
.compatible = (const char*[]) {"hal-device", nullptr},
|
||||||
|
.startDevice = start,
|
||||||
|
.stopDevice = stop,
|
||||||
|
.api = nullptr,
|
||||||
|
.deviceType = &HAL_DEVICE_TYPE,
|
||||||
|
.owner = &hal_device_module,
|
||||||
|
.driver_private = nullptr
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
143
Modules/hal-device/Source/hal/Device.cpp
Normal file
143
Modules/hal-device/Source/hal/Device.cpp
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
#include <tactility/hal/Device.h>
|
||||||
|
#include <tactility/driver.h>
|
||||||
|
#include <tactility/drivers/hal_device.hpp>
|
||||||
|
|
||||||
|
#include <Tactility/Logger.h>
|
||||||
|
#include <Tactility/RecursiveMutex.h>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace tt::hal {
|
||||||
|
|
||||||
|
RecursiveMutex mutex;
|
||||||
|
static Device::Id nextId = 0;
|
||||||
|
|
||||||
|
static const auto LOGGER = Logger("Devices");
|
||||||
|
|
||||||
|
Device::Device() : id(nextId++) {}
|
||||||
|
|
||||||
|
static std::shared_ptr<Device::KernelDeviceHolder> createKernelDeviceHolder(const std::shared_ptr<Device>& device) {
|
||||||
|
auto kernel_device_name = std::format("hal-device-{}", device->getId());
|
||||||
|
LOGGER.info("Registering {} with id {} as kernel device {}", device->getName(), device->getId(), kernel_device_name);
|
||||||
|
auto kernel_device_holder = std::make_shared<Device::KernelDeviceHolder>(kernel_device_name);
|
||||||
|
auto* kernel_device = kernel_device_holder->device.get();
|
||||||
|
check(device_construct(kernel_device) == ERROR_NONE);
|
||||||
|
check(device_add(kernel_device) == ERROR_NONE);
|
||||||
|
auto* driver = driver_find_compatible("hal-device");
|
||||||
|
check(driver);
|
||||||
|
device_set_driver(kernel_device, driver);
|
||||||
|
check(device_start(kernel_device) == ERROR_NONE);
|
||||||
|
hal_device_set_device(kernel_device, device);
|
||||||
|
return kernel_device_holder;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void destroyKernelDeviceHolder(std::shared_ptr<Device::KernelDeviceHolder>& holder) {
|
||||||
|
auto kernel_device = holder->device.get();
|
||||||
|
hal_device_set_device(kernel_device, nullptr);
|
||||||
|
check(device_stop(kernel_device) == ERROR_NONE);
|
||||||
|
check(device_remove(kernel_device) == ERROR_NONE);
|
||||||
|
check(device_destruct(kernel_device) == ERROR_NONE);
|
||||||
|
holder->device = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void registerDevice(const std::shared_ptr<Device>& device) {
|
||||||
|
auto scoped_mutex = mutex.asScopedLock();
|
||||||
|
scoped_mutex.lock();
|
||||||
|
|
||||||
|
if (device->getKernelDeviceHolder() == nullptr) {
|
||||||
|
// Kernel device
|
||||||
|
auto kernel_device_holder = createKernelDeviceHolder(device);
|
||||||
|
device->setKernelDeviceHolder(kernel_device_holder);
|
||||||
|
} else {
|
||||||
|
LOGGER.warn("Device {} with id {} was already registered", device->getName(), device->getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void deregisterDevice(const std::shared_ptr<Device>& device) {
|
||||||
|
auto scoped_mutex = mutex.asScopedLock();
|
||||||
|
scoped_mutex.lock();
|
||||||
|
|
||||||
|
// Kernel device
|
||||||
|
auto kernel_device_holder = device->getKernelDeviceHolder();
|
||||||
|
if (kernel_device_holder) {
|
||||||
|
destroyKernelDeviceHolder(kernel_device_holder);
|
||||||
|
device->setKernelDeviceHolder(nullptr);
|
||||||
|
} else {
|
||||||
|
LOGGER.warn("Device {} with id {} was not registered", device->getName(), device->getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename R>
|
||||||
|
auto toVector(R&& range) {
|
||||||
|
using T = std::ranges::range_value_t<R>;
|
||||||
|
std::vector<T> result;
|
||||||
|
if constexpr (std::ranges::common_range<R>) {
|
||||||
|
result.reserve(std::ranges::distance(range));
|
||||||
|
}
|
||||||
|
std::ranges::copy(range, std::back_inserter(result));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::shared_ptr<Device>> findDevices(const std::function<bool(const std::shared_ptr<Device>&)>& filterFunction) {
|
||||||
|
auto scoped_mutex = mutex.asScopedLock();
|
||||||
|
scoped_mutex.lock();
|
||||||
|
|
||||||
|
auto devices_view = getDevices() | std::views::filter([&filterFunction](auto& device) {
|
||||||
|
return filterFunction(device);
|
||||||
|
});
|
||||||
|
return toVector(devices_view);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Device> _Nullable findDevice(const std::function<bool(const std::shared_ptr<Device>&)>& filterFunction) {
|
||||||
|
auto scoped_mutex = mutex.asScopedLock();
|
||||||
|
scoped_mutex.lock();
|
||||||
|
|
||||||
|
auto result_set = getDevices() | std::views::filter([&filterFunction](auto& device) {
|
||||||
|
return filterFunction(device);
|
||||||
|
});
|
||||||
|
if (!result_set.empty()) {
|
||||||
|
return result_set.front();
|
||||||
|
} else {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Device> _Nullable findDevice(std::string name) {
|
||||||
|
return findDevice([&name](auto& device){
|
||||||
|
return device->getName() == name;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Device> _Nullable findDevice(Device::Id id) {
|
||||||
|
return findDevice([id](auto& device){
|
||||||
|
return device->getId() == id;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::shared_ptr<Device>> findDevices(Device::Type type) {
|
||||||
|
return findDevices([type](auto& device) {
|
||||||
|
return device->getType() == type;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::shared_ptr<Device>> getDevices() {
|
||||||
|
std::vector<std::shared_ptr<Device>> devices;
|
||||||
|
for_each_device_of_type(&HAL_DEVICE_TYPE, &devices ,[](auto* kernelDevice, auto* context) {
|
||||||
|
auto devices_ptr = static_cast<std::vector<std::shared_ptr<Device>>*>(context);
|
||||||
|
auto hal_device = hal_device_get_device(kernelDevice);
|
||||||
|
(*devices_ptr).push_back(hal_device);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
return devices;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hasDevice(Device::Type type) {
|
||||||
|
auto scoped_mutex = mutex.asScopedLock();
|
||||||
|
scoped_mutex.lock();
|
||||||
|
auto result_set = getDevices() | std::views::filter([&type](auto& device) {
|
||||||
|
return device->getType() == type;
|
||||||
|
});
|
||||||
|
return !result_set.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
31
Modules/hal-device/Source/module.cpp
Normal file
31
Modules/hal-device/Source/module.cpp
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
#include <tactility/check.h>
|
||||||
|
#include <tactility/driver.h>
|
||||||
|
#include <tactility/module.h>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
extern Driver hal_device_driver;
|
||||||
|
|
||||||
|
static error_t start() {
|
||||||
|
/* We crash when construct fails, because if a single driver fails to construct,
|
||||||
|
* there is no guarantee that the previously constructed drivers can be destroyed */
|
||||||
|
check(driver_construct_add(&hal_device_driver) == ERROR_NONE);
|
||||||
|
return ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static error_t stop() {
|
||||||
|
/* We crash when destruct fails, because if a single driver fails to destruct,
|
||||||
|
* there is no guarantee that the previously destroyed drivers can be recovered */
|
||||||
|
check(driver_remove(&hal_device_driver) == ERROR_NONE);
|
||||||
|
check(driver_destruct(&hal_device_driver) == ERROR_NONE);
|
||||||
|
return ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Module hal_device_module = {
|
||||||
|
.name = "hal-device",
|
||||||
|
.start = start,
|
||||||
|
.stop = stop
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
#define TAG LOG_TAG(esp32_gpio)
|
#define TAG LOG_TAG(esp32_gpio)
|
||||||
|
|
||||||
#define GET_CONFIG(device) ((struct Esp32GpioConfig*)device->internal.driver_data)
|
#define GET_CONFIG(device) ((struct Esp32GpioConfig*)device->config)
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
|
|||||||
@ -10,22 +10,22 @@ extern Driver esp32_i2c_driver;
|
|||||||
static error_t start() {
|
static error_t start() {
|
||||||
/* We crash when construct fails, because if a single driver fails to construct,
|
/* We crash when construct fails, because if a single driver fails to construct,
|
||||||
* there is no guarantee that the previously constructed drivers can be destroyed */
|
* there is no guarantee that the previously constructed drivers can be destroyed */
|
||||||
check(driver_construct(&esp32_gpio_driver) == ERROR_NONE);
|
check(driver_construct_add(&esp32_gpio_driver) == ERROR_NONE);
|
||||||
check(driver_construct(&esp32_i2c_driver) == ERROR_NONE);
|
check(driver_construct_add(&esp32_i2c_driver) == ERROR_NONE);
|
||||||
return ERROR_NONE;
|
return ERROR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static error_t stop() {
|
static error_t stop() {
|
||||||
/* We crash when destruct fails, because if a single driver fails to destruct,
|
/* We crash when destruct fails, because if a single driver fails to destruct,
|
||||||
* there is no guarantee that the previously destroyed drivers can be recovered */
|
* there is no guarantee that the previously destroyed drivers can be recovered */
|
||||||
check(driver_destruct(&esp32_gpio_driver) == ERROR_NONE);
|
check(driver_remove_destruct(&esp32_gpio_driver) == ERROR_NONE);
|
||||||
check(driver_destruct(&esp32_i2c_driver) == ERROR_NONE);
|
check(driver_remove_destruct(&esp32_i2c_driver) == ERROR_NONE);
|
||||||
return ERROR_NONE;
|
return ERROR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The name must be exactly "platform_module"
|
// The name must be exactly "platform_module"
|
||||||
struct Module platform_module = {
|
struct Module platform_module = {
|
||||||
.name = "ESP32 Platform",
|
.name = "platform-esp32",
|
||||||
.start = start,
|
.start = start,
|
||||||
.stop = stop
|
.stop = stop
|
||||||
};
|
};
|
||||||
|
|||||||
@ -14,7 +14,7 @@ static error_t stop() {
|
|||||||
|
|
||||||
// The name must be exactly "platform_module"
|
// The name must be exactly "platform_module"
|
||||||
struct Module platform_module = {
|
struct Module platform_module = {
|
||||||
.name = "POSIX Platform",
|
.name = "platform-posix",
|
||||||
.start = start,
|
.start = start,
|
||||||
.stop = stop
|
.stop = stop
|
||||||
};
|
};
|
||||||
|
|||||||
@ -8,6 +8,7 @@ if (DEFINED ENV{ESP_IDF_VERSION})
|
|||||||
PlatformEsp32
|
PlatformEsp32
|
||||||
TactilityCore
|
TactilityCore
|
||||||
TactilityFreeRtos
|
TactilityFreeRtos
|
||||||
|
hal-device
|
||||||
lvgl
|
lvgl
|
||||||
driver
|
driver
|
||||||
elf_loader
|
elf_loader
|
||||||
@ -71,6 +72,7 @@ else()
|
|||||||
TactilityCore
|
TactilityCore
|
||||||
TactilityKernel
|
TactilityKernel
|
||||||
PlatformPosix
|
PlatformPosix
|
||||||
|
hal-device
|
||||||
freertos_kernel
|
freertos_kernel
|
||||||
lvgl
|
lvgl
|
||||||
lv_screenshot
|
lv_screenshot
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../Device.h"
|
#include <tactility/hal/Device.h>
|
||||||
|
|
||||||
#include <lvgl.h>
|
#include <lvgl.h>
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../Device.h"
|
#include <tactility/hal/Device.h>
|
||||||
|
|
||||||
#include <lvgl.h>
|
#include <lvgl.h>
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../Device.h"
|
#include <tactility/hal/Device.h>
|
||||||
#include "GpsConfiguration.h"
|
#include "GpsConfiguration.h"
|
||||||
#include "Satellites.h"
|
#include "Satellites.h"
|
||||||
|
|
||||||
@ -110,7 +110,7 @@ public:
|
|||||||
return lastRmcSubscriptionId;
|
return lastRmcSubscriptionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
void unsubscribeRmc(GgaSubscriptionId subscriptionId) {
|
void unsubscribeRmc(RmcSubscriptionId subscriptionId) {
|
||||||
auto lock = mutex.asScopedLock();
|
auto lock = mutex.asScopedLock();
|
||||||
lock.lock();
|
lock.lock();
|
||||||
std::erase_if(rmcSubscriptions, [subscriptionId](auto& subscription) { return subscription.id == subscriptionId; });
|
std::erase_if(rmcSubscriptions, [subscriptionId](auto& subscription) { return subscription.id == subscriptionId; });
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../Device.h"
|
#include <tactility/hal/Device.h>
|
||||||
#include "I2c.h"
|
#include "I2c.h"
|
||||||
|
|
||||||
namespace tt::hal::i2c {
|
namespace tt::hal::i2c {
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../Device.h"
|
#include <tactility/hal/Device.h>
|
||||||
|
|
||||||
#include <lvgl.h>
|
#include <lvgl.h>
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../Device.h"
|
#include <tactility/hal/Device.h>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
namespace tt::hal::power {
|
namespace tt::hal::power {
|
||||||
@ -44,4 +44,4 @@ public:
|
|||||||
virtual void powerOff() { /* NO-OP*/ }
|
virtual void powerOff() { /* NO-OP*/ }
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace tt
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../Device.h"
|
#include <tactility/hal/Device.h>
|
||||||
|
|
||||||
#include <Tactility/TactilityCore.h>
|
#include <Tactility/TactilityCore.h>
|
||||||
#include <Tactility/Lock.h>
|
#include <Tactility/Lock.h>
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
#include "SdCardDevice.h"
|
#include "SdCardDevice.h"
|
||||||
|
|
||||||
#include <Tactility/RecursiveMutex.h>
|
#include <Tactility/RecursiveMutex.h>
|
||||||
#include <Tactility/hal/Device.h>
|
#include <tactility/hal/Device.h>
|
||||||
#include <Tactility/hal/spi/Spi.h>
|
#include <Tactility/hal/spi/Spi.h>
|
||||||
#include <sd_protocol_types.h>
|
#include <sd_protocol_types.h>
|
||||||
#include <soc/gpio_num.h>
|
#include <soc/gpio_num.h>
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../Device.h"
|
#include <tactility/hal/Device.h>
|
||||||
#include "TouchDriver.h"
|
#include "TouchDriver.h"
|
||||||
|
|
||||||
#include <lvgl.h>
|
#include <lvgl.h>
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
#include "Tactility/MountPoints.h"
|
#include "Tactility/MountPoints.h"
|
||||||
|
|
||||||
#include "Tactility/TactilityConfig.h"
|
#include "Tactility/TactilityConfig.h"
|
||||||
#include "Tactility/hal/Device.h"
|
#include <tactility/hal/Device.h>
|
||||||
#include "Tactility/hal/sdcard/SdCardDevice.h"
|
#include "Tactility/hal/sdcard/SdCardDevice.h"
|
||||||
|
|
||||||
#include <Tactility/file/File.h>
|
#include <Tactility/file/File.h>
|
||||||
|
|||||||
@ -23,6 +23,7 @@
|
|||||||
#include <Tactility/settings/TimePrivate.h>
|
#include <Tactility/settings/TimePrivate.h>
|
||||||
|
|
||||||
#include <tactility/kernel_init.h>
|
#include <tactility/kernel_init.h>
|
||||||
|
#include <tactility/hal_device_module.h>
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <format>
|
#include <format>
|
||||||
@ -38,6 +39,11 @@ static auto LOGGER = Logger("Tactility");
|
|||||||
static const Configuration* config_instance = nullptr;
|
static const Configuration* config_instance = nullptr;
|
||||||
static Dispatcher mainDispatcher;
|
static Dispatcher mainDispatcher;
|
||||||
|
|
||||||
|
struct ModuleParent tactility_module_parent {
|
||||||
|
"tactility",
|
||||||
|
nullptr
|
||||||
|
};
|
||||||
|
|
||||||
// region Default services
|
// region Default services
|
||||||
namespace service {
|
namespace service {
|
||||||
// Primary
|
// Primary
|
||||||
@ -330,6 +336,11 @@ void run(const Configuration& config, Module* platformModule, Module* deviceModu
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HAL compatibility module: it creates kernel driver wrappers for tt::hal::Device
|
||||||
|
check(module_parent_construct(&tactility_module_parent) == ERROR_NONE);
|
||||||
|
check(module_set_parent(&hal_device_module, &tactility_module_parent) == ERROR_NONE);
|
||||||
|
check(module_start(&hal_device_module) == ERROR_NONE);
|
||||||
|
|
||||||
const hal::Configuration& hardware = *config.hardware;
|
const hal::Configuration& hardware = *config.hardware;
|
||||||
|
|
||||||
// Assign early so starting services can use it
|
// Assign early so starting services can use it
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
#include <Tactility/file/File.h>
|
#include <Tactility/file/File.h>
|
||||||
#include <Tactility/file/FileLock.h>
|
#include <Tactility/file/FileLock.h>
|
||||||
#include <Tactility/file/PropertiesFile.h>
|
#include <Tactility/file/PropertiesFile.h>
|
||||||
#include <Tactility/hal/Device.h>
|
#include <tactility/hal/Device.h>
|
||||||
#include <Tactility/Logger.h>
|
#include <Tactility/Logger.h>
|
||||||
#include <Tactility/Paths.h>
|
#include <Tactility/Paths.h>
|
||||||
|
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
#include <Tactility/app/crashdiagnostics/QrHelpers.h>
|
#include <Tactility/app/crashdiagnostics/QrHelpers.h>
|
||||||
#include <Tactility/app/crashdiagnostics/QrUrl.h>
|
#include <Tactility/app/crashdiagnostics/QrUrl.h>
|
||||||
#include <Tactility/app/launcher/Launcher.h>
|
#include <Tactility/app/launcher/Launcher.h>
|
||||||
#include <Tactility/hal/Device.h>
|
#include <tactility/hal/Device.h>
|
||||||
#include <Tactility/Logger.h>
|
#include <Tactility/Logger.h>
|
||||||
#include <Tactility/lvgl/Statusbar.h>
|
#include <Tactility/lvgl/Statusbar.h>
|
||||||
#include <Tactility/service/loader/Loader.h>
|
#include <Tactility/service/loader/Loader.h>
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
#include <Tactility/hal/power/PowerDevice.h>
|
#include <Tactility/hal/power/PowerDevice.h>
|
||||||
#include <Tactility/Timer.h>
|
#include <Tactility/Timer.h>
|
||||||
#include <Tactility/Assets.h>
|
#include <Tactility/Assets.h>
|
||||||
#include <Tactility/hal/Device.h>
|
#include <tactility/hal/Device.h>
|
||||||
|
|
||||||
#include <lvgl.h>
|
#include <lvgl.h>
|
||||||
|
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
#include <Tactility/lvgl/LvglSync.h>
|
#include <Tactility/lvgl/LvglSync.h>
|
||||||
|
|
||||||
#include <Tactility/Assets.h>
|
#include <Tactility/Assets.h>
|
||||||
#include <Tactility/hal/Device.h>
|
#include <tactility/hal/Device.h>
|
||||||
#include <Tactility/Tactility.h>
|
#include <Tactility/Tactility.h>
|
||||||
#include <Tactility/Timer.h>
|
#include <Tactility/Timer.h>
|
||||||
|
|
||||||
|
|||||||
@ -16,7 +16,7 @@ bool ObjectFileWriter::open() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Edit existing or create a new file
|
// Edit existing or create a new file
|
||||||
auto opening_file = std::unique_ptr<FILE, FileCloser>(std::fopen(filePath.c_str(), "wb"));
|
auto opening_file = std::unique_ptr<FILE, FileCloser>(std::fopen(filePath.c_str(), edit_existing ? "rb+" : "wb"));
|
||||||
if (opening_file == nullptr) {
|
if (opening_file == nullptr) {
|
||||||
LOGGER.error("Failed to open file {}", filePath);
|
LOGGER.error("Failed to open file {}", filePath);
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@ -1,106 +0,0 @@
|
|||||||
#include <Tactility/hal/Device.h>
|
|
||||||
|
|
||||||
#include <Tactility/Logger.h>
|
|
||||||
#include <Tactility/RecursiveMutex.h>
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
namespace tt::hal {
|
|
||||||
|
|
||||||
std::vector<std::shared_ptr<Device>> devices;
|
|
||||||
RecursiveMutex mutex;
|
|
||||||
static Device::Id nextId = 0;
|
|
||||||
|
|
||||||
static const auto LOGGER = Logger("Devices");
|
|
||||||
|
|
||||||
Device::Device() : id(nextId++) {}
|
|
||||||
|
|
||||||
template <std::ranges::range RangeType>
|
|
||||||
auto toVector(RangeType&& range) {
|
|
||||||
auto view = range | std::views::common;
|
|
||||||
return std::vector(view.begin(), view.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
void registerDevice(const std::shared_ptr<Device>& device) {
|
|
||||||
auto scoped_mutex = mutex.asScopedLock();
|
|
||||||
scoped_mutex.lock();
|
|
||||||
|
|
||||||
if (findDevice(device->getId()) == nullptr) {
|
|
||||||
devices.push_back(device);
|
|
||||||
LOGGER.info("Registered {} with id {}", device->getName(), device->getId());
|
|
||||||
} else {
|
|
||||||
LOGGER.warn("Device {} with id {} was already registered", device->getName(), device->getId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void deregisterDevice(const std::shared_ptr<Device>& device) {
|
|
||||||
auto scoped_mutex = mutex.asScopedLock();
|
|
||||||
scoped_mutex.lock();
|
|
||||||
|
|
||||||
auto id_to_remove = device->getId();
|
|
||||||
auto remove_iterator = std::remove_if(devices.begin(), devices.end(), [id_to_remove](const auto& device) {
|
|
||||||
return device->getId() == id_to_remove;
|
|
||||||
});
|
|
||||||
if (remove_iterator != devices.end()) {
|
|
||||||
LOGGER.info("Deregistering {} with id {}", device->getName(), device->getId());
|
|
||||||
devices.erase(remove_iterator);
|
|
||||||
} else {
|
|
||||||
LOGGER.warn("Deregistering {} with id {} failed: not found", device->getName(), device->getId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::shared_ptr<Device>> findDevices(const std::function<bool(const std::shared_ptr<Device>&)>& filterFunction) {
|
|
||||||
auto scoped_mutex = mutex.asScopedLock();
|
|
||||||
scoped_mutex.lock();
|
|
||||||
|
|
||||||
auto devices_view = devices | std::views::filter([&filterFunction](auto& device) {
|
|
||||||
return filterFunction(device);
|
|
||||||
});
|
|
||||||
return toVector(devices_view);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<Device> _Nullable findDevice(const std::function<bool(const std::shared_ptr<Device>&)>& filterFunction) {
|
|
||||||
auto scoped_mutex = mutex.asScopedLock();
|
|
||||||
scoped_mutex.lock();
|
|
||||||
|
|
||||||
auto result_set = devices | std::views::filter([&filterFunction](auto& device) {
|
|
||||||
return filterFunction(device);
|
|
||||||
});
|
|
||||||
if (!result_set.empty()) {
|
|
||||||
return result_set.front();
|
|
||||||
} else {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<Device> _Nullable findDevice(std::string name) {
|
|
||||||
return findDevice([&name](auto& device){
|
|
||||||
return device->getName() == name;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<Device> _Nullable findDevice(Device::Id id) {
|
|
||||||
return findDevice([id](auto& device){
|
|
||||||
return device->getId() == id;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::shared_ptr<Device>> findDevices(Device::Type type) {
|
|
||||||
return findDevices([type](auto& device) {
|
|
||||||
return device->getType() == type;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::shared_ptr<Device>> getDevices() {
|
|
||||||
return devices;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool hasDevice(Device::Type type) {
|
|
||||||
auto scoped_mutex = mutex.asScopedLock();
|
|
||||||
scoped_mutex.lock();
|
|
||||||
auto result_set = devices | std::views::filter([&type](auto& device) {
|
|
||||||
return device->getType() == type;
|
|
||||||
});
|
|
||||||
return !result_set.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -2,7 +2,7 @@
|
|||||||
#include <Tactility/Tactility.h>
|
#include <Tactility/Tactility.h>
|
||||||
#include <tactility/check.h>
|
#include <tactility/check.h>
|
||||||
#include <Tactility/hal/Configuration.h>
|
#include <Tactility/hal/Configuration.h>
|
||||||
#include <Tactility/hal/Device.h>
|
#include <tactility/hal/Device.h>
|
||||||
#include <Tactility/hal/power/PowerDevice.h>
|
#include <Tactility/hal/power/PowerDevice.h>
|
||||||
#include <Tactility/hal/spi/SpiInit.h>
|
#include <Tactility/hal/spi/SpiInit.h>
|
||||||
#include <Tactility/hal/uart/UartInit.h>
|
#include <Tactility/hal/uart/UartInit.h>
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
#include "Tactility/hal/Device.h"
|
#include <tactility/hal/Device.h>
|
||||||
#include "Tactility/hal/sdcard/SdCardDevice.h"
|
#include "Tactility/hal/sdcard/SdCardDevice.h"
|
||||||
|
|
||||||
namespace tt::hal::sdcard {
|
namespace tt::hal::sdcard {
|
||||||
|
|||||||
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
#include <Tactility/Tactility.h>
|
#include <Tactility/Tactility.h>
|
||||||
#include <Tactility/TactilityConfig.h>
|
#include <Tactility/TactilityConfig.h>
|
||||||
#include <Tactility/hal/Device.h>
|
#include <tactility/hal/Device.h>
|
||||||
#include <Tactility/app/AppRegistration.h>
|
#include <Tactility/app/AppRegistration.h>
|
||||||
#include <Tactility/app/AppManifest.h>
|
#include <Tactility/app/AppManifest.h>
|
||||||
#include <Tactility/app/App.h>
|
#include <Tactility/app/App.h>
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
#include <Tactility/settings/DisplaySettings.h>
|
#include <Tactility/settings/DisplaySettings.h>
|
||||||
|
|
||||||
#include <Tactility/file/PropertiesFile.h>
|
#include <Tactility/file/PropertiesFile.h>
|
||||||
#include <Tactility/hal/Device.h>
|
#include <tactility/hal/Device.h>
|
||||||
#include <Tactility/hal/display/DisplayDevice.h>
|
#include <Tactility/hal/display/DisplayDevice.h>
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|||||||
@ -15,7 +15,7 @@ typedef enum {
|
|||||||
DEVICE_TYPE_KEYBOARD,
|
DEVICE_TYPE_KEYBOARD,
|
||||||
DEVICE_TYPE_POWER,
|
DEVICE_TYPE_POWER,
|
||||||
DEVICE_TYPE_GPS
|
DEVICE_TYPE_GPS
|
||||||
} DeviceType;
|
} TtDeviceType;
|
||||||
|
|
||||||
typedef uint32_t DeviceId;
|
typedef uint32_t DeviceId;
|
||||||
|
|
||||||
@ -27,7 +27,7 @@ typedef uint32_t DeviceId;
|
|||||||
* @param[in] maxCount the maximum number of items that the "deviceIds" output can contain (minimum value is 1)
|
* @param[in] maxCount the maximum number of items that the "deviceIds" output can contain (minimum value is 1)
|
||||||
* @return true if one or more devices were found
|
* @return true if one or more devices were found
|
||||||
*/
|
*/
|
||||||
bool tt_hal_device_find(DeviceType type, DeviceId* deviceIds, uint16_t* count, uint16_t maxCount);
|
bool tt_hal_device_find(TtDeviceType type, DeviceId* deviceIds, uint16_t* count, uint16_t maxCount);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
#include <tactility/check.h>
|
#include <tactility/check.h>
|
||||||
|
|
||||||
#include <Tactility/hal/Device.h>
|
#include <tactility/hal/Device.h>
|
||||||
|
|
||||||
static tt::hal::Device::Type toTactilityDeviceType(DeviceType type) {
|
static tt::hal::Device::Type toTactilityDeviceType(TtDeviceType type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case DEVICE_TYPE_I2C:
|
case DEVICE_TYPE_I2C:
|
||||||
return tt::hal::Device::Type::I2c;
|
return tt::hal::Device::Type::I2c;
|
||||||
@ -27,7 +27,7 @@ static tt::hal::Device::Type toTactilityDeviceType(DeviceType type) {
|
|||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
bool tt_hal_device_find(DeviceType type, DeviceId* deviceIds, uint16_t* count, uint16_t maxCount) {
|
bool tt_hal_device_find(TtDeviceType type, DeviceId* deviceIds, uint16_t* count, uint16_t maxCount) {
|
||||||
assert(maxCount > 0);
|
assert(maxCount > 0);
|
||||||
|
|
||||||
int16_t currentIndex = -1;
|
int16_t currentIndex = -1;
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include <tactility/check.h>
|
#include <tactility/check.h>
|
||||||
|
|
||||||
#include <Tactility/hal/Device.h>
|
#include <tactility/hal/Device.h>
|
||||||
#include <Tactility/hal/display/DisplayDevice.h>
|
#include <Tactility/hal/display/DisplayDevice.h>
|
||||||
#include <Tactility/hal/display/DisplayDriver.h>
|
#include <Tactility/hal/display/DisplayDriver.h>
|
||||||
|
|
||||||
|
|||||||
@ -24,7 +24,7 @@ bool tt_hal_gpio_get_level(GpioPin pin) {
|
|||||||
Device* device_result = find_first_gpio_controller();
|
Device* device_result = find_first_gpio_controller();
|
||||||
if (device_result == nullptr) return false;
|
if (device_result == nullptr) return false;
|
||||||
bool pin_state = false;
|
bool pin_state = false;
|
||||||
if (!gpio_controller_get_level(device_result, pin, &pin_state)) return false;
|
if (gpio_controller_get_level(device_result, pin, &pin_state) != ERROR_NONE) return false;
|
||||||
return pin_state;
|
return pin_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,7 +32,7 @@ int tt_hal_gpio_get_pin_count() {
|
|||||||
Device* device_result = find_first_gpio_controller();
|
Device* device_result = find_first_gpio_controller();
|
||||||
if (device_result == nullptr) return 0;
|
if (device_result == nullptr) return 0;
|
||||||
uint32_t pin_count = 0;
|
uint32_t pin_count = 0;
|
||||||
if (!gpio_controller_get_pin_count(device_result, &pin_count)) return 0;
|
if (gpio_controller_get_pin_count(device_result, &pin_count) != ERROR_NONE) return 0;
|
||||||
return (int)pin_count;
|
return (int)pin_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
#include "tt_hal_touch.h"
|
#include "tt_hal_touch.h"
|
||||||
|
|
||||||
#include "Tactility/hal/Device.h"
|
#include <tactility/hal/Device.h>
|
||||||
#include "Tactility/hal/touch/TouchDevice.h"
|
#include "Tactility/hal/touch/TouchDevice.h"
|
||||||
#include "Tactility/hal/touch/TouchDriver.h"
|
#include "Tactility/hal/touch/TouchDriver.h"
|
||||||
|
|
||||||
|
|||||||
@ -4,5 +4,10 @@
|
|||||||
#include "RTOS.h"
|
#include "RTOS.h"
|
||||||
|
|
||||||
#ifndef ESP_PLATFORM
|
#ifndef ESP_PLATFORM
|
||||||
#define xPortInIsrContext(x) (false)
|
|
||||||
|
// TactilityKernel co-existence check
|
||||||
|
#ifndef xPortInIsrContext
|
||||||
|
#define xPortInIsrContext() (false)
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -37,6 +37,14 @@ error_t driver_construct(struct Driver* driver);
|
|||||||
|
|
||||||
error_t driver_destruct(struct Driver* driver);
|
error_t driver_destruct(struct Driver* driver);
|
||||||
|
|
||||||
|
error_t driver_add(struct Driver* driver);
|
||||||
|
|
||||||
|
error_t driver_remove(struct Driver* driver);
|
||||||
|
|
||||||
|
error_t driver_construct_add(struct Driver* driver);
|
||||||
|
|
||||||
|
error_t driver_remove_destruct(struct Driver* driver);
|
||||||
|
|
||||||
error_t driver_bind(struct Driver* driver, struct Device* device);
|
error_t driver_bind(struct Driver* driver, struct Device* device);
|
||||||
|
|
||||||
error_t driver_unbind(struct Driver* driver, struct Device* device);
|
error_t driver_unbind(struct Driver* driver, struct Device* device);
|
||||||
|
|||||||
@ -5,6 +5,15 @@
|
|||||||
#include "freertos.h"
|
#include "freertos.h"
|
||||||
|
|
||||||
#ifndef ESP_PLATFORM
|
#ifndef ESP_PLATFORM
|
||||||
|
|
||||||
|
// TactilityFreeRTOS co-existence check
|
||||||
|
#ifndef xPortInIsrContext
|
||||||
#define xPortInIsrContext() (pdFALSE)
|
#define xPortInIsrContext() (pdFALSE)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// TactilityFreeRTOS co-existence check
|
||||||
|
#ifndef vPortAssertIfInISR
|
||||||
#define vPortAssertIfInISR()
|
#define vPortAssertIfInISR()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|||||||
@ -11,8 +11,8 @@ extern "C" {
|
|||||||
/**
|
/**
|
||||||
* Initialize the kernel with platform and device modules, and a device tree.
|
* Initialize the kernel with platform and device modules, and a device tree.
|
||||||
* @param platform_module The platform module to start. This module should not be constructed yet.
|
* @param platform_module The platform module to start. This module should not be constructed yet.
|
||||||
* @param device_module The device module to start. This module should not be constructed yet.
|
* @param device_module The device module to start. This module should not be constructed yet. This parameter can be NULL.
|
||||||
* @param devicetree_devices The list of generated devices from the devicetree. The array must be terminated by an entry { NULL, NULL }
|
* @param devicetree_devices The list of generated devices from the devicetree. The array must be terminated by an entry { NULL, NULL }. This parameter can be NULL.
|
||||||
* @return ERROR_NONE on success, otherwise an error code
|
* @return ERROR_NONE on success, otherwise an error code
|
||||||
*/
|
*/
|
||||||
error_t kernel_init(struct Module* platform_module, struct Module* device_module, struct CompatibleDevice devicetree_devices[]);
|
error_t kernel_init(struct Module* platform_module, struct Module* device_module, struct CompatibleDevice devicetree_devices[]);
|
||||||
|
|||||||
@ -17,6 +17,8 @@ struct Module {
|
|||||||
/**
|
/**
|
||||||
* The name of the module, for logging/debugging purposes
|
* The name of the module, for logging/debugging purposes
|
||||||
* Should never be NULL.
|
* Should never be NULL.
|
||||||
|
* Characters allowed: a-z A-Z 0-9 - _ .
|
||||||
|
* Desirable format "platform-esp32", "lilygo-tdeck", etc.
|
||||||
*/
|
*/
|
||||||
const char* name;
|
const char* name;
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
#include <cstdlib>
|
||||||
#include <tactility/freertos/task.h>
|
#include <tactility/freertos/task.h>
|
||||||
#include <tactility/log.h>
|
#include <tactility/log.h>
|
||||||
|
|
||||||
@ -31,7 +32,7 @@ __attribute__((noreturn)) void __crash(void) {
|
|||||||
#ifdef ESP_PLATFORM
|
#ifdef ESP_PLATFORM
|
||||||
esp_system_abort("System halted. Connect debugger for more info.");
|
esp_system_abort("System halted. Connect debugger for more info.");
|
||||||
#else
|
#else
|
||||||
while (true) { /* Indefinite lock-up */ }
|
exit(1);
|
||||||
#endif
|
#endif
|
||||||
__builtin_unreachable();
|
__builtin_unreachable();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -49,7 +49,7 @@ error_t device_construct(Device* device) {
|
|||||||
if (device->internal.device_private == nullptr) {
|
if (device->internal.device_private == nullptr) {
|
||||||
return ERROR_OUT_OF_MEMORY;
|
return ERROR_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
LOG_I(TAG, "construct %s", device->name);
|
LOG_D(TAG, "construct %s", device->name);
|
||||||
mutex_construct(&device->internal.mutex);
|
mutex_construct(&device->internal.mutex);
|
||||||
return ERROR_NONE;
|
return ERROR_NONE;
|
||||||
}
|
}
|
||||||
@ -61,7 +61,7 @@ error_t device_destruct(Device* device) {
|
|||||||
if (!get_device_private(device)->children.empty()) {
|
if (!get_device_private(device)->children.empty()) {
|
||||||
return ERROR_INVALID_STATE;
|
return ERROR_INVALID_STATE;
|
||||||
}
|
}
|
||||||
LOG_I(TAG, "destruct %s", device->name);
|
LOG_D(TAG, "destruct %s", device->name);
|
||||||
mutex_destruct(&device->internal.mutex);
|
mutex_destruct(&device->internal.mutex);
|
||||||
delete get_device_private(device);
|
delete get_device_private(device);
|
||||||
device->internal.device_private = nullptr;
|
device->internal.device_private = nullptr;
|
||||||
@ -88,7 +88,7 @@ static void device_remove_child(struct Device* device, struct Device* child) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
error_t device_add(Device* device) {
|
error_t device_add(Device* device) {
|
||||||
LOG_I(TAG, "add %s", device->name);
|
LOG_D(TAG, "add %s", device->name);
|
||||||
|
|
||||||
// Already added
|
// Already added
|
||||||
if (device->internal.state.started || device->internal.state.added) {
|
if (device->internal.state.started || device->internal.state.added) {
|
||||||
@ -111,7 +111,7 @@ error_t device_add(Device* device) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
error_t device_remove(Device* device) {
|
error_t device_remove(Device* device) {
|
||||||
LOG_I(TAG, "remove %s", device->name);
|
LOG_D(TAG, "remove %s", device->name);
|
||||||
|
|
||||||
if (device->internal.state.started || !device->internal.state.added) {
|
if (device->internal.state.started || !device->internal.state.added) {
|
||||||
return ERROR_INVALID_STATE;
|
return ERROR_INVALID_STATE;
|
||||||
|
|||||||
@ -58,28 +58,6 @@ static DriverLedger& get_ledger() {
|
|||||||
#define driver_lock(driver) mutex_lock(&get_driver_private(driver)->mutex);
|
#define driver_lock(driver) mutex_lock(&get_driver_private(driver)->mutex);
|
||||||
#define driver_unlock(driver) mutex_unlock(&get_driver_private(driver)->mutex);
|
#define driver_unlock(driver) mutex_unlock(&get_driver_private(driver)->mutex);
|
||||||
|
|
||||||
static void driver_add(Driver* driver) {
|
|
||||||
LOG_I(TAG, "add %s", driver->name);
|
|
||||||
ledger.lock();
|
|
||||||
ledger.drivers.push_back(driver);
|
|
||||||
ledger.unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
static error_t driver_remove(Driver* driver) {
|
|
||||||
LOG_I(TAG, "remove %s", driver->name);
|
|
||||||
|
|
||||||
ledger.lock();
|
|
||||||
const auto iterator = std::ranges::find(ledger.drivers, driver);
|
|
||||||
if (iterator == ledger.drivers.end()) {
|
|
||||||
ledger.unlock();
|
|
||||||
return ERROR_NOT_FOUND;
|
|
||||||
}
|
|
||||||
ledger.drivers.erase(iterator);
|
|
||||||
ledger.unlock();
|
|
||||||
|
|
||||||
return ERROR_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
error_t driver_construct(Driver* driver) {
|
error_t driver_construct(Driver* driver) {
|
||||||
@ -87,7 +65,6 @@ error_t driver_construct(Driver* driver) {
|
|||||||
if (driver->driver_private == nullptr) {
|
if (driver->driver_private == nullptr) {
|
||||||
return ERROR_OUT_OF_MEMORY;
|
return ERROR_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
driver_add(driver);
|
|
||||||
return ERROR_NONE;
|
return ERROR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,10 +81,6 @@ error_t driver_destruct(Driver* driver) {
|
|||||||
}
|
}
|
||||||
get_driver_private(driver)->destroying = true;
|
get_driver_private(driver)->destroying = true;
|
||||||
|
|
||||||
if (driver_remove(driver) != ERROR_NONE) {
|
|
||||||
LOG_W(TAG, "Failed to remove driver from ledger: %s", driver->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
driver_unlock(driver);
|
driver_unlock(driver);
|
||||||
delete get_driver_private(driver);
|
delete get_driver_private(driver);
|
||||||
driver->driver_private = nullptr;
|
driver->driver_private = nullptr;
|
||||||
@ -115,6 +88,41 @@ error_t driver_destruct(Driver* driver) {
|
|||||||
return ERROR_NONE;
|
return ERROR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
error_t driver_add(Driver* driver) {
|
||||||
|
LOG_I(TAG, "add %s", driver->name);
|
||||||
|
ledger.lock();
|
||||||
|
ledger.drivers.push_back(driver);
|
||||||
|
ledger.unlock();
|
||||||
|
return ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
error_t driver_remove(Driver* driver) {
|
||||||
|
LOG_I(TAG, "remove %s", driver->name);
|
||||||
|
|
||||||
|
ledger.lock();
|
||||||
|
const auto iterator = std::ranges::find(ledger.drivers, driver);
|
||||||
|
if (iterator == ledger.drivers.end()) {
|
||||||
|
ledger.unlock();
|
||||||
|
return ERROR_NOT_FOUND;
|
||||||
|
}
|
||||||
|
ledger.drivers.erase(iterator);
|
||||||
|
ledger.unlock();
|
||||||
|
|
||||||
|
return ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
error_t driver_construct_add(struct Driver* driver) {
|
||||||
|
if (driver_construct(driver) != ERROR_NONE) return ERROR_RESOURCE;
|
||||||
|
if (driver_add(driver) != ERROR_NONE) return ERROR_RESOURCE;
|
||||||
|
return ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
error_t driver_remove_destruct(struct Driver* driver) {
|
||||||
|
if (driver_remove(driver) != ERROR_NONE) return ERROR_RESOURCE;
|
||||||
|
if (driver_destruct(driver) != ERROR_NONE) return ERROR_RESOURCE;
|
||||||
|
return ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
bool driver_is_compatible(Driver* driver, const char* compatible) {
|
bool driver_is_compatible(Driver* driver, const char* compatible) {
|
||||||
if (compatible == nullptr || driver->compatible == nullptr) {
|
if (compatible == nullptr || driver->compatible == nullptr) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@ -14,7 +14,7 @@ struct ModuleParent kernel_module_parent = {
|
|||||||
|
|
||||||
static error_t init_kernel_drivers() {
|
static error_t init_kernel_drivers() {
|
||||||
extern Driver root_driver;
|
extern Driver root_driver;
|
||||||
if (driver_construct(&root_driver) != ERROR_NONE) return ERROR_RESOURCE;
|
if (driver_construct_add(&root_driver) != ERROR_NONE) return ERROR_RESOURCE;
|
||||||
return ERROR_NONE;
|
return ERROR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,19 +37,23 @@ error_t kernel_init(struct Module* platform_module, struct Module* device_module
|
|||||||
return ERROR_RESOURCE;
|
return ERROR_RESOURCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
module_set_parent(device_module, &kernel_module_parent);
|
if (device_module != nullptr) {
|
||||||
if (module_start(device_module) != ERROR_NONE) {
|
module_set_parent(device_module, &kernel_module_parent);
|
||||||
LOG_E(TAG, "init failed to start device module");
|
if (module_start(device_module) != ERROR_NONE) {
|
||||||
return ERROR_RESOURCE;
|
LOG_E(TAG, "init failed to start device module");
|
||||||
}
|
|
||||||
|
|
||||||
CompatibleDevice* compatible_device = devicetree_devices;
|
|
||||||
while (compatible_device->device != nullptr) {
|
|
||||||
if (device_construct_add_start(compatible_device->device, compatible_device->compatible) != ERROR_NONE) {
|
|
||||||
LOG_E(TAG, "kernel_init failed to construct device: %s (%s)", compatible_device->device->name, compatible_device->compatible);
|
|
||||||
return ERROR_RESOURCE;
|
return ERROR_RESOURCE;
|
||||||
}
|
}
|
||||||
compatible_device++;
|
}
|
||||||
|
|
||||||
|
if (devicetree_devices) {
|
||||||
|
CompatibleDevice* compatible_device = devicetree_devices;
|
||||||
|
while (compatible_device->device != nullptr) {
|
||||||
|
if (device_construct_add_start(compatible_device->device, compatible_device->compatible) != ERROR_NONE) {
|
||||||
|
LOG_E(TAG, "kernel_init failed to construct device: %s (%s)", compatible_device->device->name, compatible_device->compatible);
|
||||||
|
return ERROR_RESOURCE;
|
||||||
|
}
|
||||||
|
compatible_device++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_I(TAG, "init done");
|
LOG_I(TAG, "init done");
|
||||||
|
|||||||
@ -3,6 +3,8 @@
|
|||||||
#include <tactility/concurrent/mutex.h>
|
#include <tactility/concurrent/mutex.h>
|
||||||
#include <tactility/module.h>
|
#include <tactility/module.h>
|
||||||
|
|
||||||
|
#define TAG LOG_TAG(module)
|
||||||
|
|
||||||
struct ModuleParentPrivate {
|
struct ModuleParentPrivate {
|
||||||
std::vector<struct Module*> modules;
|
std::vector<struct Module*> modules;
|
||||||
struct Mutex mutex = { 0 };
|
struct Mutex mutex = { 0 };
|
||||||
@ -72,6 +74,8 @@ error_t module_set_parent(struct Module* module, struct ModuleParent* parent) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
error_t module_start(struct Module* module) {
|
error_t module_start(struct Module* module) {
|
||||||
|
LOG_I(TAG, "start %s", module->name);
|
||||||
|
|
||||||
if (module->internal.started) return ERROR_NONE;
|
if (module->internal.started) return ERROR_NONE;
|
||||||
if (!module->internal.parent) return ERROR_INVALID_STATE;
|
if (!module->internal.parent) return ERROR_INVALID_STATE;
|
||||||
|
|
||||||
@ -85,6 +89,8 @@ bool module_is_started(struct Module* module) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
error_t module_stop(struct Module* module) {
|
error_t module_stop(struct Module* module) {
|
||||||
|
LOG_I(TAG, "stop %s", module->name);
|
||||||
|
|
||||||
if (!module->internal.started) return ERROR_NONE;
|
if (!module->internal.started) return ERROR_NONE;
|
||||||
|
|
||||||
error_t error = module->stop();
|
error_t error = module->stop();
|
||||||
|
|||||||
@ -22,6 +22,8 @@ target_link_libraries(TactilityTests PRIVATE
|
|||||||
Tactility
|
Tactility
|
||||||
TactilityCore
|
TactilityCore
|
||||||
TactilityKernel
|
TactilityKernel
|
||||||
|
PlatformPosix
|
||||||
|
hal-device
|
||||||
Simulator
|
Simulator
|
||||||
SDL2::SDL2-static SDL2-static
|
SDL2::SDL2-static SDL2-static
|
||||||
)
|
)
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#include "doctest.h"
|
#include "doctest.h"
|
||||||
#include <Tactility/hal/Device.h>
|
#include <tactility/hal/Device.h>
|
||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
|||||||
@ -5,12 +5,27 @@
|
|||||||
#include "FreeRTOS.h"
|
#include "FreeRTOS.h"
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
|
|
||||||
|
#include <tactility/kernel_init.h>
|
||||||
|
#include <tactility/hal_device_module.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int argc;
|
int argc;
|
||||||
char** argv;
|
char** argv;
|
||||||
int result;
|
int result;
|
||||||
} TestTaskData;
|
} TestTaskData;
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
// From the relevant platform
|
||||||
|
extern struct Module platform_module;
|
||||||
|
// From the relevant device
|
||||||
|
extern struct Module device_module;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ModuleParent tactility_tests_module_parent {
|
||||||
|
"tactility-tests",
|
||||||
|
nullptr
|
||||||
|
};
|
||||||
|
|
||||||
void test_task(void* parameter) {
|
void test_task(void* parameter) {
|
||||||
auto* data = (TestTaskData*)parameter;
|
auto* data = (TestTaskData*)parameter;
|
||||||
|
|
||||||
@ -21,6 +36,12 @@ void test_task(void* parameter) {
|
|||||||
// overrides
|
// overrides
|
||||||
context.setOption("no-breaks", true); // don't break in the debugger when assertions fail
|
context.setOption("no-breaks", true); // don't break in the debugger when assertions fail
|
||||||
|
|
||||||
|
check(kernel_init(&platform_module, &device_module, nullptr) == ERROR_NONE);
|
||||||
|
// HAL compatibility module: it creates kernel driver wrappers for tt::hal::Device
|
||||||
|
check(module_parent_construct(&tactility_tests_module_parent) == ERROR_NONE);
|
||||||
|
check(module_set_parent(&hal_device_module, &tactility_tests_module_parent) == ERROR_NONE);
|
||||||
|
check(module_start(&hal_device_module) == ERROR_NONE);
|
||||||
|
|
||||||
data->result = context.run();
|
data->result = context.run();
|
||||||
|
|
||||||
vTaskEndScheduler();
|
vTaskEndScheduler();
|
||||||
@ -46,4 +67,6 @@ int main(int argc, char** argv) {
|
|||||||
assert(task_result == pdPASS);
|
assert(task_result == pdPASS);
|
||||||
|
|
||||||
vTaskStartScheduler();
|
vTaskStartScheduler();
|
||||||
|
|
||||||
|
return data.result;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -56,8 +56,10 @@ TEST_CASE("Appending records to a file") {
|
|||||||
CHECK_EQ(reader.open(), true);
|
CHECK_EQ(reader.open(), true);
|
||||||
CHECK_EQ(reader.hasNext(), true);
|
CHECK_EQ(reader.hasNext(), true);
|
||||||
CHECK_EQ(reader.readNext(&record_in), true);
|
CHECK_EQ(reader.readNext(&record_in), true);
|
||||||
|
CHECK_EQ(record_in.value, 0xAAAAAAAA);
|
||||||
CHECK_EQ(reader.hasNext(), true);
|
CHECK_EQ(reader.hasNext(), true);
|
||||||
CHECK_EQ(reader.readNext(&record_in), true);
|
CHECK_EQ(reader.readNext(&record_in), true);
|
||||||
|
CHECK_EQ(record_in.value, 0xBBBBBBBB);
|
||||||
CHECK_EQ(reader.hasNext(), false);
|
CHECK_EQ(reader.hasNext(), false);
|
||||||
reader.close();
|
reader.close();
|
||||||
|
|
||||||
|
|||||||
@ -11,4 +11,8 @@ target_include_directories(TactilityKernelTests PRIVATE ${DOCTESTINC})
|
|||||||
|
|
||||||
add_test(NAME TactilityKernelTests COMMAND TactilityKernelTests)
|
add_test(NAME TactilityKernelTests COMMAND TactilityKernelTests)
|
||||||
|
|
||||||
target_link_libraries(TactilityKernelTests PUBLIC TactilityKernel)
|
target_link_libraries(TactilityKernelTests PUBLIC
|
||||||
|
TactilityKernel
|
||||||
|
PlatformPosix
|
||||||
|
hal-device
|
||||||
|
)
|
||||||
|
|||||||
@ -177,7 +177,7 @@ TEST_CASE("device_is_ready should return true only when it is started") {
|
|||||||
|
|
||||||
Device device = { 0 };
|
Device device = { 0 };
|
||||||
|
|
||||||
CHECK_EQ(driver_construct(&driver), ERROR_NONE);
|
CHECK_EQ(driver_construct_add(&driver), ERROR_NONE);
|
||||||
CHECK_EQ(device_construct(&device), ERROR_NONE);
|
CHECK_EQ(device_construct(&device), ERROR_NONE);
|
||||||
|
|
||||||
CHECK_EQ(device.internal.state.started, false);
|
CHECK_EQ(device.internal.state.started, false);
|
||||||
@ -192,6 +192,6 @@ TEST_CASE("device_is_ready should return true only when it is started") {
|
|||||||
CHECK_EQ(device_remove(&device), ERROR_NONE);
|
CHECK_EQ(device_remove(&device), ERROR_NONE);
|
||||||
CHECK_EQ(device.internal.state.started, false);
|
CHECK_EQ(device.internal.state.started, false);
|
||||||
|
|
||||||
CHECK_EQ(driver_destruct(&driver), ERROR_NONE);
|
|
||||||
CHECK_EQ(device_destruct(&device), ERROR_NONE);
|
CHECK_EQ(device_destruct(&device), ERROR_NONE);
|
||||||
|
CHECK_EQ(driver_remove_destruct(&driver), ERROR_NONE);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -55,7 +55,7 @@ TEST_CASE("driver with with start success and stop success should start and stop
|
|||||||
.parent = nullptr,
|
.parent = nullptr,
|
||||||
};
|
};
|
||||||
|
|
||||||
CHECK_EQ(driver_construct(&integration_driver), ERROR_NONE);
|
CHECK_EQ(driver_construct_add(&integration_driver), ERROR_NONE);
|
||||||
|
|
||||||
CHECK_EQ(device_construct(&integration_device), ERROR_NONE);
|
CHECK_EQ(device_construct(&integration_device), ERROR_NONE);
|
||||||
device_add(&integration_device);
|
device_add(&integration_device);
|
||||||
@ -68,5 +68,5 @@ TEST_CASE("driver with with start success and stop success should start and stop
|
|||||||
CHECK_EQ(device_remove(&integration_device), ERROR_NONE);
|
CHECK_EQ(device_remove(&integration_device), ERROR_NONE);
|
||||||
CHECK_EQ(device_destruct(&integration_device), ERROR_NONE);
|
CHECK_EQ(device_destruct(&integration_device), ERROR_NONE);
|
||||||
|
|
||||||
CHECK_EQ(driver_destruct(&integration_driver), ERROR_NONE);
|
CHECK_EQ(driver_remove_destruct(&integration_driver), ERROR_NONE);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,7 +14,9 @@ TEST_CASE("driver_construct and driver_destruct should set and unset the correct
|
|||||||
driver.owner = &module;
|
driver.owner = &module;
|
||||||
|
|
||||||
CHECK_EQ(driver_construct(&driver), ERROR_NONE);
|
CHECK_EQ(driver_construct(&driver), ERROR_NONE);
|
||||||
|
CHECK_EQ(driver_add(&driver), ERROR_NONE);
|
||||||
CHECK_NE(driver.driver_private, nullptr);
|
CHECK_NE(driver.driver_private, nullptr);
|
||||||
|
CHECK_EQ(driver_remove(&driver), ERROR_NONE);
|
||||||
CHECK_EQ(driver_destruct(&driver), ERROR_NONE);
|
CHECK_EQ(driver_destruct(&driver), ERROR_NONE);
|
||||||
CHECK_EQ(driver.driver_private, nullptr);
|
CHECK_EQ(driver.driver_private, nullptr);
|
||||||
}
|
}
|
||||||
@ -62,10 +64,12 @@ TEST_CASE("driver_find should only find a compatible driver when the driver was
|
|||||||
CHECK_EQ(found_driver, nullptr);
|
CHECK_EQ(found_driver, nullptr);
|
||||||
|
|
||||||
CHECK_EQ(driver_construct(&driver), ERROR_NONE);
|
CHECK_EQ(driver_construct(&driver), ERROR_NONE);
|
||||||
|
CHECK_EQ(driver_add(&driver), ERROR_NONE);
|
||||||
|
|
||||||
found_driver = driver_find_compatible("test_compatible");
|
found_driver = driver_find_compatible("test_compatible");
|
||||||
CHECK_EQ(found_driver, &driver);
|
CHECK_EQ(found_driver, &driver);
|
||||||
|
|
||||||
|
CHECK_EQ(driver_remove(&driver), ERROR_NONE);
|
||||||
CHECK_EQ(driver_destruct(&driver), ERROR_NONE);
|
CHECK_EQ(driver_destruct(&driver), ERROR_NONE);
|
||||||
|
|
||||||
found_driver = driver_find_compatible("test_compatible");
|
found_driver = driver_find_compatible("test_compatible");
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
#include <tactility/freertos/task.h>
|
#include <tactility/freertos/task.h>
|
||||||
|
#include <tactility/kernel_init.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int argc;
|
int argc;
|
||||||
@ -10,6 +11,11 @@ typedef struct {
|
|||||||
int result;
|
int result;
|
||||||
} TestTaskData;
|
} TestTaskData;
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
// From the relevant platform
|
||||||
|
extern struct Module platform_module;
|
||||||
|
}
|
||||||
|
|
||||||
void test_task(void* parameter) {
|
void test_task(void* parameter) {
|
||||||
auto* data = (TestTaskData*)parameter;
|
auto* data = (TestTaskData*)parameter;
|
||||||
|
|
||||||
@ -20,6 +26,8 @@ void test_task(void* parameter) {
|
|||||||
// overrides
|
// overrides
|
||||||
context.setOption("no-breaks", true); // don't break in the debugger when assertions fail
|
context.setOption("no-breaks", true); // don't break in the debugger when assertions fail
|
||||||
|
|
||||||
|
check(kernel_init(&platform_module, nullptr, nullptr) == ERROR_NONE);
|
||||||
|
|
||||||
data->result = context.run();
|
data->result = context.run();
|
||||||
|
|
||||||
vTaskEndScheduler();
|
vTaskEndScheduler();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user