Remove old HAL components and refactored GPS-related code (#583)
- Added generic GPS/GNSS support with device detection, configuration, and persistent settings. - Improved device and module lifecycle management. - Added flexible filesystem locking support for displays and storage. - Improved display-idle and keyboard backlight handling. - Updated architecture, driver, module, testing, and licensing documentation. - Removed old HAL device and related code.
This commit is contained in:
committed by
GitHub
parent
29e80cfd65
commit
2a2558b29a
@@ -1,6 +1,5 @@
|
||||
#include "Main.h"
|
||||
#include <Tactility/Thread.h>
|
||||
#include <Tactility/TactilityCore.h>
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
#include "hal/SdlDisplay.h"
|
||||
#include "hal/SdlKeyboard.h"
|
||||
#include "hal/SimulatorPower.h"
|
||||
|
||||
#include <Tactility/hal/Configuration.h>
|
||||
|
||||
#define TAG "hardware"
|
||||
|
||||
using namespace tt::hal;
|
||||
|
||||
static std::vector<std::shared_ptr<tt::hal::Device>> createDevices() {
|
||||
return {
|
||||
std::make_shared<SdlDisplay>(),
|
||||
std::make_shared<SdlKeyboard>(),
|
||||
std::make_shared<SimulatorPower>(),
|
||||
};
|
||||
}
|
||||
|
||||
extern const Configuration hardwareConfiguration = {
|
||||
.initBoot = nullptr,
|
||||
.createDevices = createDevices
|
||||
};
|
||||
@@ -0,0 +1,160 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
#include "sdl_display.h"
|
||||
|
||||
#include <tactility/device.h>
|
||||
#include <tactility/driver.h>
|
||||
#include <tactility/drivers/display.h>
|
||||
#include <tactility/log.h>
|
||||
#include <tactility/module.h>
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
constexpr auto* TAG = "SdlDisplay";
|
||||
#define GET_CONFIG(device) (static_cast<const SdlDisplayConfig*>((device)->config))
|
||||
|
||||
struct SdlDisplayInternal {
|
||||
SDL_Window* window;
|
||||
SDL_Renderer* renderer;
|
||||
SDL_Texture* texture;
|
||||
};
|
||||
|
||||
// region Driver lifecycle
|
||||
|
||||
static error_t start(Device* device) {
|
||||
const auto* config = GET_CONFIG(device);
|
||||
|
||||
auto* internal = static_cast<SdlDisplayInternal*>(malloc(sizeof(SdlDisplayInternal)));
|
||||
if (internal == nullptr) {
|
||||
return ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
if (SDL_InitSubSystem(SDL_INIT_VIDEO) != 0) {
|
||||
LOG_E(TAG, "SDL_InitSubSystem failed: %s", SDL_GetError());
|
||||
free(internal);
|
||||
return ERROR_RESOURCE;
|
||||
}
|
||||
|
||||
internal->window = SDL_CreateWindow(
|
||||
"Tactility",
|
||||
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
|
||||
config->horizontal_resolution, config->vertical_resolution,
|
||||
SDL_WINDOW_SHOWN
|
||||
);
|
||||
internal->renderer = internal->window != nullptr
|
||||
? SDL_CreateRenderer(internal->window, -1, SDL_RENDERER_ACCELERATED)
|
||||
: nullptr;
|
||||
internal->texture = internal->renderer != nullptr
|
||||
? SDL_CreateTexture(internal->renderer, SDL_PIXELFORMAT_RGB565, SDL_TEXTUREACCESS_STREAMING,
|
||||
config->horizontal_resolution, config->vertical_resolution)
|
||||
: nullptr;
|
||||
|
||||
if (internal->window == nullptr || internal->renderer == nullptr || internal->texture == nullptr) {
|
||||
LOG_E(TAG, "Failed to create SDL window: %s", SDL_GetError());
|
||||
if (internal->texture != nullptr) SDL_DestroyTexture(internal->texture);
|
||||
if (internal->renderer != nullptr) SDL_DestroyRenderer(internal->renderer);
|
||||
if (internal->window != nullptr) SDL_DestroyWindow(internal->window);
|
||||
SDL_QuitSubSystem(SDL_INIT_VIDEO);
|
||||
free(internal);
|
||||
return ERROR_RESOURCE;
|
||||
}
|
||||
|
||||
device_set_driver_data(device, internal);
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
static error_t stop(Device* device) {
|
||||
auto* internal = static_cast<SdlDisplayInternal*>(device_get_driver_data(device));
|
||||
|
||||
SDL_DestroyTexture(internal->texture);
|
||||
SDL_DestroyRenderer(internal->renderer);
|
||||
SDL_DestroyWindow(internal->window);
|
||||
SDL_QuitSubSystem(SDL_INIT_VIDEO);
|
||||
|
||||
free(internal);
|
||||
device_set_driver_data(device, nullptr);
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region DisplayApi
|
||||
|
||||
static error_t sdl_display_reset(Device*) { return ERROR_NONE; }
|
||||
static error_t sdl_display_init(Device*) { return ERROR_NONE; }
|
||||
|
||||
static error_t sdl_display_draw_bitmap(Device* device, int32_t x_start, int32_t y_start, int32_t x_end, int32_t y_end, const void* color_data) {
|
||||
auto* internal = static_cast<SdlDisplayInternal*>(device_get_driver_data(device));
|
||||
|
||||
SDL_Rect rect = { x_start, y_start, x_end - x_start, y_end - y_start };
|
||||
// RGB565 = 2 bytes/pixel.
|
||||
if (SDL_UpdateTexture(internal->texture, &rect, color_data, (x_end - x_start) * 2) != 0) {
|
||||
return ERROR_RESOURCE;
|
||||
}
|
||||
|
||||
SDL_RenderClear(internal->renderer);
|
||||
SDL_RenderCopy(internal->renderer, internal->texture, nullptr, nullptr);
|
||||
SDL_RenderPresent(internal->renderer);
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
static enum DisplayColorFormat sdl_display_get_color_format(Device*) {
|
||||
return DISPLAY_COLOR_FORMAT_RGB565;
|
||||
}
|
||||
|
||||
static uint16_t sdl_display_get_resolution_x(Device* device) {
|
||||
return GET_CONFIG(device)->horizontal_resolution;
|
||||
}
|
||||
|
||||
static uint16_t sdl_display_get_resolution_y(Device* device) {
|
||||
return GET_CONFIG(device)->vertical_resolution;
|
||||
}
|
||||
|
||||
static void sdl_display_get_frame_buffer(Device*, uint8_t, void** out_buffer) {
|
||||
*out_buffer = nullptr;
|
||||
}
|
||||
|
||||
static uint8_t sdl_display_get_frame_buffer_count(Device*) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
static const DisplayApi sdl_display_api = {
|
||||
.capabilities = 0,
|
||||
.reset = sdl_display_reset,
|
||||
.init = sdl_display_init,
|
||||
.draw_bitmap = sdl_display_draw_bitmap,
|
||||
.mirror = nullptr,
|
||||
.swap_xy = nullptr,
|
||||
.get_swap_xy = nullptr,
|
||||
.get_mirror_x = nullptr,
|
||||
.get_mirror_y = nullptr,
|
||||
.set_gap = nullptr,
|
||||
.get_gap_x = nullptr,
|
||||
.get_gap_y = nullptr,
|
||||
.invert_color = nullptr,
|
||||
.disp_on_off = nullptr,
|
||||
.disp_sleep = nullptr,
|
||||
.get_color_format = sdl_display_get_color_format,
|
||||
.get_resolution_x = sdl_display_get_resolution_x,
|
||||
.get_resolution_y = sdl_display_get_resolution_y,
|
||||
.get_frame_buffer = sdl_display_get_frame_buffer,
|
||||
.get_frame_buffer_count = sdl_display_get_frame_buffer_count,
|
||||
.get_backlight = nullptr,
|
||||
.has_capability = nullptr,
|
||||
};
|
||||
|
||||
extern Module simulator_module;
|
||||
|
||||
Driver sdl_display_driver = {
|
||||
.name = "sdl-display",
|
||||
.compatible = (const char*[]) { "tactility,sdl-display", nullptr },
|
||||
.start_device = start,
|
||||
.stop_device = stop,
|
||||
.api = &sdl_display_api,
|
||||
.device_type = &DISPLAY_TYPE,
|
||||
.owner = &simulator_module,
|
||||
.internal = nullptr
|
||||
};
|
||||
@@ -0,0 +1,17 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct SdlDisplayConfig {
|
||||
uint16_t horizontal_resolution;
|
||||
uint16_t vertical_resolution;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,108 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
#include "sdl_input.h"
|
||||
|
||||
#include <lvgl.h>
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr size_t KEY_QUEUE_CAPACITY = 32;
|
||||
|
||||
SdlPointerState pointer_state = { 0, 0, false };
|
||||
|
||||
uint32_t key_queue[KEY_QUEUE_CAPACITY];
|
||||
size_t key_queue_head = 0;
|
||||
size_t key_queue_count = 0;
|
||||
|
||||
bool text_input_started = false;
|
||||
|
||||
void push_key(uint32_t key) {
|
||||
if (key == 0 || key_queue_count >= KEY_QUEUE_CAPACITY) {
|
||||
return;
|
||||
}
|
||||
key_queue[(key_queue_head + key_queue_count) % KEY_QUEUE_CAPACITY] = key;
|
||||
key_queue_count++;
|
||||
}
|
||||
|
||||
// Mirrors LVGL's own lv_sdl_keyboard.c keycode_to_ctrl_key(): maps navigation/control keys to
|
||||
// LV_KEY_* constants. Printable characters arrive separately via SDL_TEXTINPUT.
|
||||
uint32_t keycode_to_key(SDL_Keycode sdl_key) {
|
||||
switch (sdl_key) {
|
||||
case SDLK_RIGHT: return LV_KEY_RIGHT;
|
||||
case SDLK_LEFT: return LV_KEY_LEFT;
|
||||
case SDLK_UP: return LV_KEY_UP;
|
||||
case SDLK_DOWN: return LV_KEY_DOWN;
|
||||
case SDLK_ESCAPE: return LV_KEY_ESC;
|
||||
case SDLK_BACKSPACE: return LV_KEY_BACKSPACE;
|
||||
case SDLK_DELETE: return LV_KEY_DEL;
|
||||
case SDLK_RETURN:
|
||||
case SDLK_KP_ENTER: return LV_KEY_ENTER;
|
||||
case SDLK_TAB: return LV_KEY_NEXT;
|
||||
case SDLK_HOME: return LV_KEY_HOME;
|
||||
case SDLK_END: return LV_KEY_END;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void sdl_input_pump() {
|
||||
if (!text_input_started) {
|
||||
SDL_StartTextInput();
|
||||
text_input_started = true;
|
||||
}
|
||||
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event)) {
|
||||
switch (event.type) {
|
||||
case SDL_MOUSEMOTION:
|
||||
pointer_state.x = event.motion.x;
|
||||
pointer_state.y = event.motion.y;
|
||||
break;
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
if (event.button.button == SDL_BUTTON_LEFT) {
|
||||
pointer_state.x = event.button.x;
|
||||
pointer_state.y = event.button.y;
|
||||
pointer_state.pressed = true;
|
||||
}
|
||||
break;
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
if (event.button.button == SDL_BUTTON_LEFT) {
|
||||
pointer_state.pressed = false;
|
||||
}
|
||||
break;
|
||||
case SDL_KEYDOWN:
|
||||
push_key(keycode_to_key(event.key.keysym.sym));
|
||||
break;
|
||||
case SDL_TEXTINPUT:
|
||||
// ASCII only (first byte of event.text.text) - sufficient for a simulator keyboard.
|
||||
push_key(static_cast<uint8_t>(event.text.text[0]));
|
||||
break;
|
||||
case SDL_QUIT:
|
||||
exit(0);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sdl_input_get_pointer_state(SdlPointerState* out_state) {
|
||||
*out_state = pointer_state;
|
||||
}
|
||||
|
||||
bool sdl_input_pop_key(uint32_t* out_key) {
|
||||
if (key_queue_count == 0) {
|
||||
return false;
|
||||
}
|
||||
*out_key = key_queue[key_queue_head];
|
||||
key_queue_head = (key_queue_head + 1) % KEY_QUEUE_CAPACITY;
|
||||
key_queue_count--;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool sdl_input_has_queued_key() {
|
||||
return key_queue_count > 0;
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* @brief Latest pointer (mouse) state as tracked by sdl_input_pump().
|
||||
*/
|
||||
struct SdlPointerState {
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
bool pressed;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Drains all pending SDL events exactly once, updating the pointer state and key queue
|
||||
* below. Safe to call from both the sdl-pointer and sdl-keyboard drivers' polling functions:
|
||||
* SDL_PollEvent() drains a single global queue, so whichever driver is polled first on a given
|
||||
* LVGL indev tick pumps events for both.
|
||||
*/
|
||||
void sdl_input_pump(void);
|
||||
|
||||
/**
|
||||
* @brief Gets the pointer state as of the most recent sdl_input_pump() call.
|
||||
*/
|
||||
void sdl_input_get_pointer_state(struct SdlPointerState* out_state);
|
||||
|
||||
/**
|
||||
* @brief Pops the next queued key event (produced by SDL_KEYDOWN/SDL_TEXTINPUT during
|
||||
* sdl_input_pump()).
|
||||
* @retval false when no key event is pending
|
||||
*/
|
||||
bool sdl_input_pop_key(uint32_t* out_key);
|
||||
|
||||
/**
|
||||
* @brief Returns true if another key event is queued after the one just popped.
|
||||
*/
|
||||
bool sdl_input_has_queued_key(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,53 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
#include "sdl_input.h"
|
||||
|
||||
#include <tactility/device.h>
|
||||
#include <tactility/driver.h>
|
||||
#include <tactility/drivers/keyboard.h>
|
||||
#include <tactility/module.h>
|
||||
|
||||
// region Driver lifecycle
|
||||
|
||||
static error_t start(Device*) { return ERROR_NONE; }
|
||||
static error_t stop(Device*) { return ERROR_NONE; }
|
||||
|
||||
// endregion
|
||||
|
||||
// region KeyboardApi
|
||||
|
||||
static error_t sdl_keyboard_read_key(Device*, KeyboardKeyData* data) {
|
||||
sdl_input_pump();
|
||||
|
||||
uint32_t key = 0;
|
||||
if (sdl_input_pop_key(&key)) {
|
||||
data->key = key;
|
||||
data->pressed = true;
|
||||
data->continue_reading = sdl_input_has_queued_key();
|
||||
} else {
|
||||
data->key = 0;
|
||||
data->pressed = false;
|
||||
data->continue_reading = false;
|
||||
}
|
||||
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
static const KeyboardApi sdl_keyboard_api = {
|
||||
.read_key = sdl_keyboard_read_key,
|
||||
.get_backlight = nullptr,
|
||||
};
|
||||
|
||||
extern Module simulator_module;
|
||||
|
||||
Driver sdl_keyboard_driver = {
|
||||
.name = "sdl-keyboard",
|
||||
.compatible = (const char*[]) { "tactility,sdl-keyboard", nullptr },
|
||||
.start_device = start,
|
||||
.stop_device = stop,
|
||||
.api = &sdl_keyboard_api,
|
||||
.device_type = &KEYBOARD_TYPE,
|
||||
.owner = &simulator_module,
|
||||
.internal = nullptr
|
||||
};
|
||||
@@ -0,0 +1,67 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
#include "sdl_input.h"
|
||||
|
||||
#include <tactility/device.h>
|
||||
#include <tactility/driver.h>
|
||||
#include <tactility/drivers/pointer.h>
|
||||
#include <tactility/module.h>
|
||||
|
||||
// region Driver lifecycle
|
||||
|
||||
static error_t start(Device*) { return ERROR_NONE; }
|
||||
static error_t stop(Device*) { return ERROR_NONE; }
|
||||
|
||||
// endregion
|
||||
|
||||
// region PointerApi
|
||||
|
||||
static error_t sdl_pointer_read_data(Device*, TickType_t) {
|
||||
sdl_input_pump();
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
static bool sdl_pointer_get_touched_points(Device*, uint16_t* x, uint16_t* y, uint16_t* strength, uint8_t* point_count, uint8_t max_point_count) {
|
||||
SdlPointerState state;
|
||||
sdl_input_get_pointer_state(&state);
|
||||
|
||||
if (!state.pressed || max_point_count == 0) {
|
||||
*point_count = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
x[0] = static_cast<uint16_t>(state.x);
|
||||
y[0] = static_cast<uint16_t>(state.y);
|
||||
if (strength != nullptr) {
|
||||
strength[0] = 0xFFFF;
|
||||
}
|
||||
*point_count = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
static const PointerApi sdl_pointer_api = {
|
||||
.enter_sleep = nullptr,
|
||||
.exit_sleep = nullptr,
|
||||
.read_data = sdl_pointer_read_data,
|
||||
.get_touched_points = sdl_pointer_get_touched_points,
|
||||
.set_swap_xy = nullptr,
|
||||
.get_swap_xy = nullptr,
|
||||
.set_mirror_x = nullptr,
|
||||
.get_mirror_x = nullptr,
|
||||
.set_mirror_y = nullptr,
|
||||
.get_mirror_y = nullptr,
|
||||
};
|
||||
|
||||
extern Module simulator_module;
|
||||
|
||||
Driver sdl_pointer_driver = {
|
||||
.name = "sdl-pointer",
|
||||
.compatible = (const char*[]) { "tactility,sdl-pointer", nullptr },
|
||||
.start_device = start,
|
||||
.stop_device = stop,
|
||||
.api = &sdl_pointer_api,
|
||||
.device_type = &POINTER_TYPE,
|
||||
.owner = &simulator_module,
|
||||
.internal = nullptr
|
||||
};
|
||||
@@ -1,42 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "SdlTouch.h"
|
||||
#include <tactility/check.h>
|
||||
#include <Tactility/hal/display/DisplayDevice.h>
|
||||
|
||||
class SdlDisplay final : public tt::hal::display::DisplayDevice {
|
||||
|
||||
lv_disp_t* displayHandle = nullptr;
|
||||
|
||||
public:
|
||||
|
||||
std::string getName() const override { return "SDL Display"; }
|
||||
std::string getDescription() const override { return ""; }
|
||||
|
||||
bool start() override { return true; }
|
||||
|
||||
bool stop() override { return true; }
|
||||
|
||||
bool supportsLvgl() const override { return true; }
|
||||
|
||||
bool startLvgl() override {
|
||||
if (displayHandle) return true; // already started
|
||||
displayHandle = lv_sdl_window_create(320, 240);
|
||||
lv_sdl_window_set_title(displayHandle, "Tactility");
|
||||
return displayHandle != nullptr;
|
||||
}
|
||||
|
||||
bool stopLvgl() override {
|
||||
if (!displayHandle) return true;
|
||||
lv_display_delete(displayHandle);
|
||||
displayHandle = nullptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
lv_display_t* getLvglDisplay() const override { return displayHandle; }
|
||||
|
||||
std::shared_ptr<tt::hal::touch::TouchDevice> getTouchDevice() override { return std::make_shared<SdlTouch>(); }
|
||||
|
||||
bool supportsDisplayDriver() const override { return false; }
|
||||
std::shared_ptr<tt::hal::display::DisplayDriver> getDisplayDriver() override { return nullptr; }
|
||||
};
|
||||
@@ -1,26 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <Tactility/TactilityCore.h>
|
||||
#include <tactility/check.h>
|
||||
#include <Tactility/hal/keyboard/KeyboardDevice.h>
|
||||
|
||||
class SdlKeyboard final : public tt::hal::keyboard::KeyboardDevice {
|
||||
|
||||
lv_indev_t* handle = nullptr;
|
||||
|
||||
public:
|
||||
|
||||
std::string getName() const override { return "SDL Keyboard"; }
|
||||
std::string getDescription() const override { return "SDL keyboard device"; }
|
||||
|
||||
bool startLvgl(lv_display_t* display) override {
|
||||
handle = lv_sdl_keyboard_create();
|
||||
return handle != nullptr;
|
||||
}
|
||||
|
||||
bool stopLvgl() override { check(false, "Not supported"); }
|
||||
|
||||
bool isAttached() const override { return true; }
|
||||
|
||||
lv_indev_t* getLvglIndev() override { return handle; }
|
||||
};
|
||||
@@ -1,36 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "Tactility/hal/touch/TouchDevice.h"
|
||||
#include <Tactility/TactilityCore.h>
|
||||
#include <tactility/check.h>
|
||||
|
||||
class SdlTouch final : public tt::hal::touch::TouchDevice {
|
||||
|
||||
lv_indev_t* handle = nullptr;
|
||||
|
||||
public:
|
||||
|
||||
std::string getName() const override { return "SDL Mouse"; }
|
||||
|
||||
std::string getDescription() const override { return "SDL mouse/touch pointer device"; }
|
||||
|
||||
bool start() override { return true; }
|
||||
|
||||
bool stop() override { check(false, "Not supported"); }
|
||||
|
||||
bool supportsLvgl() const override { return true; }
|
||||
|
||||
bool startLvgl(lv_display_t* display) override {
|
||||
handle = lv_sdl_mouse_create();
|
||||
return handle != nullptr;
|
||||
}
|
||||
|
||||
bool stopLvgl() override { check(false, "Not supported"); }
|
||||
|
||||
lv_indev_t* getLvglIndev() override { return handle; }
|
||||
|
||||
bool supportsTouchDriver() override { return false; }
|
||||
|
||||
std::shared_ptr<tt::hal::touch::TouchDriver> getTouchDriver() override { return nullptr; };
|
||||
};
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
#include "SimulatorPower.h"
|
||||
|
||||
constexpr auto* TAG = "SimulatorPower";
|
||||
|
||||
bool SimulatorPower::supportsMetric(MetricType type) const {
|
||||
switch (type) {
|
||||
using enum MetricType;
|
||||
case IsCharging:
|
||||
case Current:
|
||||
case BatteryVoltage:
|
||||
case ChargeLevel:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false; // Safety guard for when new enum values are introduced
|
||||
}
|
||||
|
||||
bool SimulatorPower::getMetric(MetricType type, MetricData& data) {
|
||||
switch (type) {
|
||||
using enum MetricType;
|
||||
case IsCharging:
|
||||
data.valueAsBool = true;
|
||||
return true;
|
||||
case Current:
|
||||
data.valueAsInt32 = 42;
|
||||
return true;
|
||||
case BatteryVoltage:
|
||||
data.valueAsUint32 = 4032;
|
||||
return true;
|
||||
case ChargeLevel:
|
||||
data.valueAsUint8 = 100;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false; // Safety guard for when new enum values are introduced
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <Tactility/hal/power/PowerDevice.h>
|
||||
#include <memory>
|
||||
|
||||
using tt::hal::power::PowerDevice;
|
||||
|
||||
class SimulatorPower final : public PowerDevice {
|
||||
|
||||
bool allowedToCharge = false;
|
||||
|
||||
public:
|
||||
|
||||
SimulatorPower() = default;
|
||||
~SimulatorPower() override = default;
|
||||
|
||||
std::string getName() const override { return "Power Mock"; }
|
||||
std::string getDescription() const override { return ""; }
|
||||
|
||||
bool supportsMetric(MetricType type) const override;
|
||||
bool getMetric(MetricType type, MetricData& data) override;
|
||||
|
||||
bool supportsChargeControl() const override { return true; }
|
||||
bool isAllowedToCharge() const override { return allowedToCharge; }
|
||||
void setAllowedToCharge(bool canCharge) override { allowedToCharge = canCharge; }
|
||||
};
|
||||
@@ -1,23 +1,108 @@
|
||||
#include "drivers/sdl_display.h"
|
||||
|
||||
#include <tactility/device.h>
|
||||
#include <tactility/device_listener.h>
|
||||
#include <tactility/driver.h>
|
||||
#include <tactility/error.h>
|
||||
#include <tactility/log.h>
|
||||
#include <tactility/module.h>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
constexpr auto* TAG = "Simulator";
|
||||
|
||||
extern "C" {
|
||||
|
||||
extern Driver sdl_display_driver;
|
||||
extern Driver sdl_pointer_driver;
|
||||
extern Driver sdl_keyboard_driver;
|
||||
|
||||
static Driver* const simulator_drivers[] = {
|
||||
&sdl_display_driver,
|
||||
&sdl_pointer_driver,
|
||||
&sdl_keyboard_driver,
|
||||
nullptr
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
// These devices have no real bus to attach to (SDL has no notion of one), but every non-root
|
||||
// device is still expected to have a parent (see Device::parent) - they're parented to root once
|
||||
// it's available below.
|
||||
static const SdlDisplayConfig sdl_display_config = { 320, 240 };
|
||||
static Device sdl_display_device {};
|
||||
static Device sdl_pointer_device {};
|
||||
static Device sdl_keyboard_device {};
|
||||
|
||||
static bool construct_add_start(Device* device, Device* parent, const char* name, const void* config, const char* compatible) {
|
||||
device->address = 0;
|
||||
device->name = name;
|
||||
device->config = config;
|
||||
device->parent = nullptr;
|
||||
device->internal = nullptr;
|
||||
|
||||
error_t error = device_construct(device);
|
||||
if (error != ERROR_NONE) {
|
||||
LOG_E(TAG, "Failed to construct %s: %s", name, error_to_string(error));
|
||||
return false;
|
||||
}
|
||||
|
||||
device_set_parent(device, parent);
|
||||
|
||||
Driver* driver = driver_find_compatible(compatible);
|
||||
if (driver == nullptr) {
|
||||
LOG_E(TAG, "No driver registered for %s", compatible);
|
||||
device_destruct(device);
|
||||
return false;
|
||||
}
|
||||
device_set_driver(device, driver);
|
||||
|
||||
if (device_add(device) != ERROR_NONE) {
|
||||
LOG_E(TAG, "Failed to add %s", name);
|
||||
device_destruct(device);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (device_start(device) != ERROR_NONE) {
|
||||
LOG_E(TAG, "Failed to start %s", name);
|
||||
device_remove(device);
|
||||
device_destruct(device);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Root is only constructed/added/started after all dts_modules (including this one) have already
|
||||
// started (see kernel_init()), so it can't be looked up by name from this module's own start() -
|
||||
// wait for its DEVICE_EVENT_STARTED instead, same as e.g. m5stack-tab5's display/keyboard detection.
|
||||
static void on_root_started(Device* device, DeviceEvent event, void* context) {
|
||||
if (event != DEVICE_EVENT_STARTED || strcmp(device->name, "/") != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
construct_add_start(&sdl_display_device, device, "display0", &sdl_display_config, "tactility,sdl-display");
|
||||
construct_add_start(&sdl_pointer_device, device, "pointer0", nullptr, "tactility,sdl-pointer");
|
||||
construct_add_start(&sdl_keyboard_device, device, "keyboard0", nullptr, "tactility,sdl-keyboard");
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
static error_t start() {
|
||||
// Empty for now
|
||||
device_listener_add(on_root_started, nullptr);
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
static error_t stop() {
|
||||
// Empty for now
|
||||
device_listener_remove(on_root_started);
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
struct Module simulator_module = {
|
||||
Module simulator_module = {
|
||||
.name = "simulator",
|
||||
.start = start,
|
||||
.stop = stop,
|
||||
.symbols = nullptr,
|
||||
.internal = nullptr
|
||||
.drivers = simulator_drivers
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user