mirror of
https://github.com/ByteWelder/Tactility.git
synced 2026-10-17 02:45:05 +00:00
Compare commits
3 Commits
5d2ca3188a
...
026532b1f0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
026532b1f0 | ||
|
|
d9399e3311 | ||
|
|
4cb0882ee7 |
2
.github/actions/build-firmware/action.yml
vendored
2
.github/actions/build-firmware/action.yml
vendored
@ -20,7 +20,7 @@ runs:
|
||||
- name: 'Build'
|
||||
uses: espressif/esp-idf-ci-action@v1
|
||||
with:
|
||||
esp_idf_version: v5.5.2
|
||||
esp_idf_version: v6.1
|
||||
target: ${{ inputs.arch }}
|
||||
path: './'
|
||||
- name: 'Release'
|
||||
|
||||
6
.github/actions/build-sdk/action.yml
vendored
6
.github/actions/build-sdk/action.yml
vendored
@ -21,14 +21,14 @@ runs:
|
||||
uses: espressif/esp-idf-ci-action@v1
|
||||
with:
|
||||
# NOTE: Update with ESP-IDF!
|
||||
esp_idf_version: v5.5.2
|
||||
esp_idf_version: v6.1
|
||||
target: ${{ inputs.arch }}
|
||||
path: './'
|
||||
- name: 'Release'
|
||||
shell: bash
|
||||
env:
|
||||
# NOTE: Update with ESP-IDF!
|
||||
ESP_IDF_VERSION: '5.5.2'
|
||||
ESP_IDF_VERSION: '6.1'
|
||||
run: python Buildscripts/release-sdk-esp32.py release/TactilitySDK
|
||||
- name: 'Test Integration Prep'
|
||||
shell: bash
|
||||
@ -41,7 +41,7 @@ runs:
|
||||
- name: 'Test Integration'
|
||||
uses: espressif/esp-idf-ci-action@v1
|
||||
with:
|
||||
esp_idf_version: v5.5.2
|
||||
esp_idf_version: v6.1
|
||||
target: ${{ inputs.arch }}
|
||||
command: export TACTILITY_SDK_PATH=../../test_sdk && cd Tests/SdkIntegration && python tactility.py build -a ${{ inputs.arch }} --local-sdk
|
||||
- name: 'Upload Artifact'
|
||||
|
||||
@ -2,5 +2,5 @@ file(GLOB_RECURSE SOURCE_FILES source/*.c*)
|
||||
|
||||
idf_component_register(
|
||||
SRCS ${SOURCE_FILES}
|
||||
REQUIRES TactilityKernel driver
|
||||
REQUIRES TactilityKernel driver esp_driver_gpio
|
||||
)
|
||||
|
||||
@ -3,5 +3,5 @@ file(GLOB_RECURSE SOURCE_FILES source/*.c*)
|
||||
idf_component_register(
|
||||
SRCS ${SOURCE_FILES}
|
||||
INCLUDE_DIRS "source"
|
||||
REQUIRES TactilityKernel driver
|
||||
REQUIRES TactilityKernel driver esp_driver_gpio
|
||||
)
|
||||
|
||||
@ -5,7 +5,6 @@
|
||||
#include <tactility/check.h>
|
||||
#include <tactility/device.h>
|
||||
#include <tactility/driver.h>
|
||||
#include <tactility/drivers/esp32_i2c.h>
|
||||
#include <tactility/drivers/esp32_i2c_master.h>
|
||||
#include <tactility/drivers/i2c_controller.h>
|
||||
#include <tactility/drivers/pointer.h>
|
||||
@ -39,14 +38,10 @@ static esp_err_t create_io_handle(Device* parent, esp_lcd_panel_io_handle_t* out
|
||||
esp_lcd_panel_io_i2c_config_t io_config = ESP_LCD_TOUCH_IO_I2C_CST816S_CONFIG();
|
||||
|
||||
auto* parent_driver = device_get_driver(parent);
|
||||
if (driver_is_compatible(parent_driver, "espressif,esp32-i2c")) {
|
||||
auto port = static_cast<const Esp32I2cConfig*>(parent->config)->port;
|
||||
return esp_lcd_new_panel_io_i2c_v1(port, &io_config, out_handle);
|
||||
}
|
||||
if (driver_is_compatible(parent_driver, "espressif,esp32-i2c-master")) {
|
||||
auto bus = esp32_i2c_master_get_bus_handle(parent);
|
||||
io_config.scl_speed_hz = esp32_i2c_master_get_clock_frequency(parent);
|
||||
return esp_lcd_new_panel_io_i2c_v2(bus, &io_config, out_handle);
|
||||
return esp_lcd_new_panel_io_i2c(bus, &io_config, out_handle);
|
||||
}
|
||||
|
||||
LOG_E(TAG, "Unsupported I2C driver");
|
||||
|
||||
@ -5,7 +5,6 @@
|
||||
#include <tactility/check.h>
|
||||
#include <tactility/device.h>
|
||||
#include <tactility/driver.h>
|
||||
#include <tactility/drivers/esp32_i2c.h>
|
||||
#include <tactility/drivers/esp32_i2c_master.h>
|
||||
#include <tactility/drivers/gpio_controller.h>
|
||||
#include <tactility/drivers/i2c_controller.h>
|
||||
@ -71,14 +70,10 @@ static esp_err_t create_io_handle(Device* parent, esp_lcd_panel_io_handle_t* out
|
||||
esp_lcd_panel_io_i2c_config_t io_config = ESP_LCD_TOUCH_IO_I2C_FT5x06_CONFIG();
|
||||
|
||||
auto* parent_driver = device_get_driver(parent);
|
||||
if (driver_is_compatible(parent_driver, "espressif,esp32-i2c")) {
|
||||
auto port = static_cast<const Esp32I2cConfig*>(parent->config)->port;
|
||||
return esp_lcd_new_panel_io_i2c_v1(port, &io_config, out_handle);
|
||||
}
|
||||
if (driver_is_compatible(parent_driver, "espressif,esp32-i2c-master")) {
|
||||
auto bus = esp32_i2c_master_get_bus_handle(parent);
|
||||
io_config.scl_speed_hz = esp32_i2c_master_get_clock_frequency(parent);
|
||||
return esp_lcd_new_panel_io_i2c_v2(bus, &io_config, out_handle);
|
||||
return esp_lcd_new_panel_io_i2c(bus, &io_config, out_handle);
|
||||
}
|
||||
|
||||
LOG_E(TAG, "Unsupported I2C driver");
|
||||
|
||||
@ -6,7 +6,6 @@
|
||||
#include <tactility/check.h>
|
||||
#include <tactility/device.h>
|
||||
#include <tactility/driver.h>
|
||||
#include <tactility/drivers/esp32_i2c.h>
|
||||
#include <tactility/drivers/esp32_i2c_master.h>
|
||||
#include <tactility/drivers/gpio.h>
|
||||
#include <tactility/drivers/gpio_controller.h>
|
||||
@ -73,14 +72,10 @@ static esp_err_t create_io_handle(Device* parent, esp_lcd_panel_io_handle_t* out
|
||||
esp_lcd_panel_io_i2c_config_t io_config = ESP_LCD_TOUCH_IO_I2C_FT6x36_CONFIG();
|
||||
|
||||
auto* parent_driver = device_get_driver(parent);
|
||||
if (driver_is_compatible(parent_driver, "espressif,esp32-i2c")) {
|
||||
auto port = static_cast<const Esp32I2cConfig*>(parent->config)->port;
|
||||
return esp_lcd_new_panel_io_i2c_v1(port, &io_config, out_handle);
|
||||
}
|
||||
if (driver_is_compatible(parent_driver, "espressif,esp32-i2c-master")) {
|
||||
auto bus = esp32_i2c_master_get_bus_handle(parent);
|
||||
io_config.scl_speed_hz = esp32_i2c_master_get_clock_frequency(parent);
|
||||
return esp_lcd_new_panel_io_i2c_v2(bus, &io_config, out_handle);
|
||||
return esp_lcd_new_panel_io_i2c(bus, &io_config, out_handle);
|
||||
}
|
||||
|
||||
LOG_E(TAG, "Unsupported I2C driver");
|
||||
|
||||
@ -72,8 +72,8 @@ static error_t start(Device* device) {
|
||||
}
|
||||
|
||||
esp_lcd_panel_io_spi_config_t io_config = {
|
||||
.cs_gpio_num = pin_or_unused(cs_pin),
|
||||
.dc_gpio_num = pin_or_unused(config->pin_dc),
|
||||
.cs_gpio_num = static_cast<gpio_num_t>(pin_or_unused(cs_pin)),
|
||||
.dc_gpio_num = static_cast<gpio_num_t>(pin_or_unused(config->pin_dc)),
|
||||
.spi_mode = 0,
|
||||
.pclk_hz = config->pixel_clock_hz,
|
||||
.trans_queue_depth = config->transaction_queue_depth,
|
||||
@ -104,13 +104,13 @@ static error_t start(Device* device) {
|
||||
}
|
||||
|
||||
esp_lcd_panel_dev_config_t panel_config = {
|
||||
.reset_gpio_num = pin_or_unused(config->pin_reset),
|
||||
.rgb_ele_order = config->bgr_order ? LCD_RGB_ELEMENT_ORDER_BGR : LCD_RGB_ELEMENT_ORDER_RGB,
|
||||
.data_endian = LCD_RGB_DATA_ENDIAN_LITTLE,
|
||||
.bits_per_pixel = 16,
|
||||
.reset_gpio_num = static_cast<gpio_num_t>(pin_or_unused(config->pin_reset)),
|
||||
.vendor_config = nullptr,
|
||||
// GC9A01's reset line is fixed active-low in hardware.
|
||||
.flags = { .reset_active_high = false },
|
||||
.vendor_config = nullptr,
|
||||
};
|
||||
|
||||
ret = esp_lcd_new_panel_gc9a01(internal->io_handle, &panel_config, &internal->panel_handle);
|
||||
|
||||
@ -129,8 +129,8 @@ static error_t start(Device* device) {
|
||||
}
|
||||
|
||||
esp_lcd_panel_io_spi_config_t io_config = {
|
||||
.cs_gpio_num = pin_or_unused(cs_pin),
|
||||
.dc_gpio_num = pin_or_unused(config->pin_dc),
|
||||
.cs_gpio_num = static_cast<gpio_num_t>(pin_or_unused(cs_pin)),
|
||||
.dc_gpio_num = static_cast<gpio_num_t>(pin_or_unused(config->pin_dc)),
|
||||
.spi_mode = 0,
|
||||
.pclk_hz = config->pixel_clock_hz,
|
||||
.trans_queue_depth = config->transaction_queue_depth,
|
||||
@ -164,14 +164,14 @@ static error_t start(Device* device) {
|
||||
}
|
||||
|
||||
esp_lcd_panel_dev_config_t panel_config = {
|
||||
// Always -1: pulse_reset() handles the physical pin itself (see its comment for why), and
|
||||
// esp_lcd_panel_reset() below falls back to a SWRESET command when this is -1.
|
||||
.reset_gpio_num = -1,
|
||||
.rgb_ele_order = config->bgr_order ? LCD_RGB_ELEMENT_ORDER_BGR : LCD_RGB_ELEMENT_ORDER_RGB,
|
||||
.data_endian = LCD_RGB_DATA_ENDIAN_LITTLE,
|
||||
.bits_per_pixel = config->bits_per_pixel,
|
||||
.flags = { .reset_active_high = config->reset_active_high },
|
||||
// Always NC: pulse_reset() handles the physical pin itself (see its comment for why), and
|
||||
// esp_lcd_panel_reset() below falls back to a SWRESET command when this is NC.
|
||||
.reset_gpio_num = GPIO_NUM_NC,
|
||||
.vendor_config = nullptr,
|
||||
.flags = { .reset_active_high = config->reset_active_high },
|
||||
};
|
||||
|
||||
ret = esp_lcd_new_panel_ili9341(internal->io_handle, &panel_config, &internal->panel_handle);
|
||||
|
||||
@ -77,8 +77,8 @@ static error_t start(Device* device) {
|
||||
}
|
||||
|
||||
esp_lcd_panel_io_spi_config_t io_config = {
|
||||
.cs_gpio_num = pin_or_unused(cs_pin),
|
||||
.dc_gpio_num = pin_or_unused(config->pin_dc),
|
||||
.cs_gpio_num = static_cast<gpio_num_t>(pin_or_unused(cs_pin)),
|
||||
.dc_gpio_num = static_cast<gpio_num_t>(pin_or_unused(config->pin_dc)),
|
||||
.spi_mode = 0,
|
||||
.pclk_hz = config->pixel_clock_hz,
|
||||
.trans_queue_depth = config->transaction_queue_depth,
|
||||
@ -109,13 +109,13 @@ static error_t start(Device* device) {
|
||||
}
|
||||
|
||||
esp_lcd_panel_dev_config_t panel_config = {
|
||||
.reset_gpio_num = pin_or_unused(config->pin_reset),
|
||||
.rgb_ele_order = config->bgr_order ? LCD_RGB_ELEMENT_ORDER_BGR : LCD_RGB_ELEMENT_ORDER_RGB,
|
||||
.data_endian = LCD_RGB_DATA_ENDIAN_LITTLE,
|
||||
.bits_per_pixel = config->bits_per_pixel,
|
||||
.reset_gpio_num = static_cast<gpio_num_t>(pin_or_unused(config->pin_reset)),
|
||||
.vendor_config = nullptr,
|
||||
// ILI9488's reset line is fixed active-low in hardware.
|
||||
.flags = { .reset_active_high = false },
|
||||
.vendor_config = nullptr,
|
||||
};
|
||||
|
||||
// Unlike st7789/ili9341, ili9488 needs an internal conversion buffer: over SPI the
|
||||
|
||||
@ -251,13 +251,13 @@ static error_t start(Device* device) {
|
||||
};
|
||||
|
||||
const esp_lcd_panel_dev_config_t panel_config = {
|
||||
.reset_gpio_num = pin_or_unused(config->pin_reset),
|
||||
.rgb_ele_order = config->bgr_order ? LCD_RGB_ELEMENT_ORDER_BGR : LCD_RGB_ELEMENT_ORDER_RGB,
|
||||
.data_endian = LCD_RGB_DATA_ENDIAN_LITTLE,
|
||||
.bits_per_pixel = config->bits_per_pixel,
|
||||
.reset_gpio_num = static_cast<gpio_num_t>(pin_or_unused(config->pin_reset)),
|
||||
.vendor_config = &vendor_config,
|
||||
// ILI9881C's reset line is fixed active-low in hardware.
|
||||
.flags = { .reset_active_high = false },
|
||||
.vendor_config = &vendor_config,
|
||||
};
|
||||
|
||||
if (esp_lcd_new_panel_ili9881c(internal->io_handle, &panel_config, &internal->panel_handle) != ESP_OK) {
|
||||
@ -355,7 +355,7 @@ static error_t start(Device* device) {
|
||||
xSemaphoreGive(internal->color_trans_done_semaphore);
|
||||
|
||||
esp_lcd_dpi_panel_event_callbacks_t callbacks = {};
|
||||
callbacks.on_refresh_done = on_refresh_done;
|
||||
callbacks.on_frame_buf_complete = on_refresh_done;
|
||||
callbacks.on_color_trans_done = on_color_trans_done;
|
||||
if (esp_lcd_dpi_panel_register_event_callbacks(internal->panel_handle, &callbacks, internal) != ESP_OK) {
|
||||
LOG_E(TAG, "Failed to register panel event callbacks");
|
||||
|
||||
@ -221,13 +221,13 @@ static error_t start(Device* device) {
|
||||
};
|
||||
|
||||
const esp_lcd_panel_dev_config_t panel_config = {
|
||||
.reset_gpio_num = pin_or_unused(config->pin_reset),
|
||||
.rgb_ele_order = config->bgr_order ? LCD_RGB_ELEMENT_ORDER_BGR : LCD_RGB_ELEMENT_ORDER_RGB,
|
||||
.data_endian = LCD_RGB_DATA_ENDIAN_LITTLE,
|
||||
.bits_per_pixel = config->bits_per_pixel,
|
||||
.reset_gpio_num = static_cast<gpio_num_t>(pin_or_unused(config->pin_reset)),
|
||||
.vendor_config = &vendor_config,
|
||||
// JD9165's reset line is fixed active-low in hardware.
|
||||
.flags = { .reset_active_high = false },
|
||||
.vendor_config = &vendor_config,
|
||||
};
|
||||
|
||||
if (esp_lcd_new_panel_jd9165(internal->io_handle, &panel_config, &internal->panel_handle) != ESP_OK) {
|
||||
@ -310,7 +310,7 @@ static error_t start(Device* device) {
|
||||
}
|
||||
|
||||
esp_lcd_dpi_panel_event_callbacks_t callbacks = {};
|
||||
callbacks.on_refresh_done = on_refresh_done;
|
||||
callbacks.on_frame_buf_complete = on_refresh_done;
|
||||
if (esp_lcd_dpi_panel_register_event_callbacks(internal->panel_handle, &callbacks, internal) != ESP_OK) {
|
||||
LOG_E(TAG, "Failed to register panel event callbacks");
|
||||
vSemaphoreDelete(internal->frame_complete_semaphore);
|
||||
|
||||
@ -76,7 +76,7 @@ esp_err_t esp_lcd_new_panel_jd9853(const esp_lcd_panel_io_handle_t io, const esp
|
||||
ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported color space");
|
||||
break;
|
||||
}
|
||||
#else
|
||||
#elif ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(6, 0, 0)
|
||||
switch (panel_dev_config->rgb_endian)
|
||||
{
|
||||
case LCD_RGB_ENDIAN_RGB:
|
||||
@ -89,6 +89,19 @@ esp_err_t esp_lcd_new_panel_jd9853(const esp_lcd_panel_io_handle_t io, const esp
|
||||
ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported rgb endian");
|
||||
break;
|
||||
}
|
||||
#else
|
||||
switch (panel_dev_config->rgb_ele_order)
|
||||
{
|
||||
case LCD_RGB_ELEMENT_ORDER_RGB:
|
||||
jd9853->madctl_val = 0;
|
||||
break;
|
||||
case LCD_RGB_ELEMENT_ORDER_BGR:
|
||||
jd9853->madctl_val |= LCD_CMD_BGR_BIT;
|
||||
break;
|
||||
default:
|
||||
ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported rgb element order");
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (panel_dev_config->bits_per_pixel)
|
||||
|
||||
@ -78,8 +78,8 @@ static error_t start(Device* device) {
|
||||
}
|
||||
|
||||
esp_lcd_panel_io_spi_config_t io_config = {
|
||||
.cs_gpio_num = pin_or_unused(cs_pin),
|
||||
.dc_gpio_num = pin_or_unused(config->pin_dc),
|
||||
.cs_gpio_num = static_cast<gpio_num_t>(pin_or_unused(cs_pin)),
|
||||
.dc_gpio_num = static_cast<gpio_num_t>(pin_or_unused(config->pin_dc)),
|
||||
.spi_mode = 0,
|
||||
.pclk_hz = config->pixel_clock_hz,
|
||||
.trans_queue_depth = config->transaction_queue_depth,
|
||||
@ -115,13 +115,13 @@ static error_t start(Device* device) {
|
||||
};
|
||||
|
||||
esp_lcd_panel_dev_config_t panel_config = {
|
||||
.reset_gpio_num = pin_or_unused(config->pin_reset),
|
||||
.rgb_ele_order = config->bgr_order ? LCD_RGB_ELEMENT_ORDER_BGR : LCD_RGB_ELEMENT_ORDER_RGB,
|
||||
.data_endian = LCD_RGB_DATA_ENDIAN_LITTLE,
|
||||
.bits_per_pixel = 16,
|
||||
.reset_gpio_num = static_cast<gpio_num_t>(pin_or_unused(config->pin_reset)),
|
||||
.vendor_config = &vendor_config,
|
||||
// JD9853's reset line is fixed active-low in hardware.
|
||||
.flags = { .reset_active_high = false },
|
||||
.vendor_config = &vendor_config,
|
||||
};
|
||||
|
||||
ret = esp_lcd_new_panel_jd9853(internal->io_handle, &panel_config, &internal->panel_handle);
|
||||
|
||||
@ -70,6 +70,14 @@ static int pin_or_unused(const GpioPinSpec& pin) {
|
||||
return pin.gpio_controller == nullptr ? -1 : static_cast<int>(pin.pin);
|
||||
}
|
||||
|
||||
static lcd_color_format_t color_format_from_bpp(uint8_t bits_per_pixel) {
|
||||
switch (bits_per_pixel) {
|
||||
case 16: return LCD_COLOR_FMT_RGB565;
|
||||
case 24: return LCD_COLOR_FMT_RGB888;
|
||||
default: return static_cast<lcd_color_format_t>(0);
|
||||
}
|
||||
}
|
||||
|
||||
// Pulses the panel's own driver-IC reset line, if configured. Transient: the descriptor is
|
||||
// released immediately after, since nothing else needs to touch this pin afterward.
|
||||
static error_t perform_hardware_reset(const RgbDisplayConfig* config) {
|
||||
@ -166,33 +174,35 @@ static error_t start(Device* device) {
|
||||
}
|
||||
},
|
||||
.data_width = config->data_width,
|
||||
.bits_per_pixel = config->bits_per_pixel,
|
||||
.in_color_format = color_format_from_bpp(config->bits_per_pixel),
|
||||
.num_fbs = config->num_fbs,
|
||||
.bounce_buffer_size_px = config->bounce_buffer_size_px,
|
||||
.sram_trans_align = config->sram_trans_align,
|
||||
.psram_trans_align = config->psram_trans_align,
|
||||
.hsync_gpio_num = pin_or_unused(config->pin_hsync),
|
||||
.vsync_gpio_num = pin_or_unused(config->pin_vsync),
|
||||
.de_gpio_num = pin_or_unused(config->pin_de),
|
||||
.pclk_gpio_num = pin_or_unused(config->pin_pclk),
|
||||
.disp_gpio_num = pin_or_unused(config->pin_disp),
|
||||
// No device configures sram-trans-align/psram-trans-align differently from their YAML
|
||||
// defaults (8/64), so the single dma_burst_size that replaced both can just take the
|
||||
// larger (PSRAM) alignment - safe for SRAM-only allocations too, just less tightly packed.
|
||||
.dma_burst_size = config->psram_trans_align,
|
||||
.hsync_gpio_num = static_cast<gpio_num_t>(pin_or_unused(config->pin_hsync)),
|
||||
.vsync_gpio_num = static_cast<gpio_num_t>(pin_or_unused(config->pin_vsync)),
|
||||
.de_gpio_num = static_cast<gpio_num_t>(pin_or_unused(config->pin_de)),
|
||||
.pclk_gpio_num = static_cast<gpio_num_t>(pin_or_unused(config->pin_pclk)),
|
||||
.disp_gpio_num = static_cast<gpio_num_t>(pin_or_unused(config->pin_disp)),
|
||||
.data_gpio_nums = {
|
||||
pin_or_unused(config->pin_data0),
|
||||
pin_or_unused(config->pin_data1),
|
||||
pin_or_unused(config->pin_data2),
|
||||
pin_or_unused(config->pin_data3),
|
||||
pin_or_unused(config->pin_data4),
|
||||
pin_or_unused(config->pin_data5),
|
||||
pin_or_unused(config->pin_data6),
|
||||
pin_or_unused(config->pin_data7),
|
||||
pin_or_unused(config->pin_data8),
|
||||
pin_or_unused(config->pin_data9),
|
||||
pin_or_unused(config->pin_data10),
|
||||
pin_or_unused(config->pin_data11),
|
||||
pin_or_unused(config->pin_data12),
|
||||
pin_or_unused(config->pin_data13),
|
||||
pin_or_unused(config->pin_data14),
|
||||
pin_or_unused(config->pin_data15),
|
||||
static_cast<gpio_num_t>(pin_or_unused(config->pin_data0)),
|
||||
static_cast<gpio_num_t>(pin_or_unused(config->pin_data1)),
|
||||
static_cast<gpio_num_t>(pin_or_unused(config->pin_data2)),
|
||||
static_cast<gpio_num_t>(pin_or_unused(config->pin_data3)),
|
||||
static_cast<gpio_num_t>(pin_or_unused(config->pin_data4)),
|
||||
static_cast<gpio_num_t>(pin_or_unused(config->pin_data5)),
|
||||
static_cast<gpio_num_t>(pin_or_unused(config->pin_data6)),
|
||||
static_cast<gpio_num_t>(pin_or_unused(config->pin_data7)),
|
||||
static_cast<gpio_num_t>(pin_or_unused(config->pin_data8)),
|
||||
static_cast<gpio_num_t>(pin_or_unused(config->pin_data9)),
|
||||
static_cast<gpio_num_t>(pin_or_unused(config->pin_data10)),
|
||||
static_cast<gpio_num_t>(pin_or_unused(config->pin_data11)),
|
||||
static_cast<gpio_num_t>(pin_or_unused(config->pin_data12)),
|
||||
static_cast<gpio_num_t>(pin_or_unused(config->pin_data13)),
|
||||
static_cast<gpio_num_t>(pin_or_unused(config->pin_data14)),
|
||||
static_cast<gpio_num_t>(pin_or_unused(config->pin_data15)),
|
||||
},
|
||||
.flags = {
|
||||
.disp_active_low = config->disp_active_low,
|
||||
@ -209,7 +219,7 @@ static error_t start(Device* device) {
|
||||
// marked unused rather than left as the aggregate-init default of 0 (which would look like
|
||||
// "GPIO0 is wired to this line").
|
||||
for (size_t i = 16; i < sizeof(panel_config.data_gpio_nums) / sizeof(panel_config.data_gpio_nums[0]); i++) {
|
||||
panel_config.data_gpio_nums[i] = -1;
|
||||
panel_config.data_gpio_nums[i] = GPIO_NUM_NC;
|
||||
}
|
||||
|
||||
esp_err_t ret = esp_lcd_new_rgb_panel(&panel_config, &internal->panel_handle);
|
||||
|
||||
@ -6,7 +6,6 @@
|
||||
#include <tactility/device.h>
|
||||
#include <tactility/driver.h>
|
||||
#include <tactility/drivers/display.h>
|
||||
#include <tactility/drivers/esp32_i2c.h>
|
||||
#include <tactility/drivers/esp32_i2c_master.h>
|
||||
#include <tactility/drivers/i2c_controller.h>
|
||||
#include <tactility/error.h>
|
||||
@ -52,28 +51,24 @@ static esp_err_t create_io_handle(Device* parent, uint8_t address, esp_lcd_panel
|
||||
// with, unlike the multi-byte-per-command SPI/QSPI panels elsewhere in this repo.
|
||||
esp_lcd_panel_io_i2c_config_t io_config = {
|
||||
.dev_addr = address,
|
||||
.on_color_trans_done = nullptr,
|
||||
.user_ctx = nullptr,
|
||||
.scl_speed_hz = 0,
|
||||
.control_phase_bytes = 1,
|
||||
.dc_bit_offset = 6,
|
||||
.lcd_cmd_bits = 0,
|
||||
.lcd_param_bits = 0,
|
||||
.on_color_trans_done = nullptr,
|
||||
.user_ctx = nullptr,
|
||||
.flags = {
|
||||
.dc_low_on_data = false,
|
||||
.disable_control_phase = false,
|
||||
},
|
||||
.scl_speed_hz = 0,
|
||||
};
|
||||
|
||||
auto* parent_driver = device_get_driver(parent);
|
||||
if (driver_is_compatible(parent_driver, "espressif,esp32-i2c")) {
|
||||
auto port = static_cast<const Esp32I2cConfig*>(parent->config)->port;
|
||||
return esp_lcd_new_panel_io_i2c_v1(port, &io_config, out_handle);
|
||||
}
|
||||
if (driver_is_compatible(parent_driver, "espressif,esp32-i2c-master")) {
|
||||
auto bus = esp32_i2c_master_get_bus_handle(parent);
|
||||
io_config.scl_speed_hz = esp32_i2c_master_get_clock_frequency(parent);
|
||||
return esp_lcd_new_panel_io_i2c_v2(bus, &io_config, out_handle);
|
||||
return esp_lcd_new_panel_io_i2c(bus, &io_config, out_handle);
|
||||
}
|
||||
|
||||
LOG_E(TAG, "Unsupported I2C driver");
|
||||
@ -164,15 +159,14 @@ static error_t start(Device* device) {
|
||||
.height = static_cast<uint8_t>(config->vertical_resolution),
|
||||
};
|
||||
|
||||
// color_space (not rgb_ele_order): this deprecated union member is the only one whose type
|
||||
// can express ESP_LCD_COLOR_SPACE_MONOCHROME - rgb_ele_order's own enum only covers RGB/BGR.
|
||||
// No rgb_ele_order set: the built-in ssd1306 vendor driver is monochrome and never reads it
|
||||
// (only bits_per_pixel, checked to be exactly 1 - see esp_lcd_panel_ssd1306.c).
|
||||
esp_lcd_panel_dev_config_t panel_config = {
|
||||
.reset_gpio_num = -1, // always -1: reset is handled manually above, not by the panel itself
|
||||
.color_space = ESP_LCD_COLOR_SPACE_MONOCHROME,
|
||||
.data_endian = LCD_RGB_DATA_ENDIAN_BIG,
|
||||
.bits_per_pixel = 1,
|
||||
.flags = { .reset_active_high = false },
|
||||
.reset_gpio_num = GPIO_NUM_NC, // reset is handled manually above, not by the panel itself
|
||||
.vendor_config = &ssd1306_config,
|
||||
.flags = { .reset_active_high = false },
|
||||
};
|
||||
|
||||
if (esp_lcd_new_panel_ssd1306(internal->io_handle, &panel_config, &internal->panel_handle) != ESP_OK) {
|
||||
|
||||
@ -250,13 +250,13 @@ static error_t start(Device* device) {
|
||||
};
|
||||
|
||||
const esp_lcd_panel_dev_config_t panel_config = {
|
||||
.reset_gpio_num = pin_or_unused(config->pin_reset),
|
||||
.rgb_ele_order = config->bgr_order ? LCD_RGB_ELEMENT_ORDER_BGR : LCD_RGB_ELEMENT_ORDER_RGB,
|
||||
.data_endian = LCD_RGB_DATA_ENDIAN_LITTLE,
|
||||
.bits_per_pixel = config->bits_per_pixel,
|
||||
.reset_gpio_num = static_cast<gpio_num_t>(pin_or_unused(config->pin_reset)),
|
||||
.vendor_config = &vendor_config,
|
||||
// ST7121's reset line is fixed active-low in hardware.
|
||||
.flags = { .reset_active_high = false },
|
||||
.vendor_config = &vendor_config,
|
||||
};
|
||||
|
||||
if (esp_lcd_new_panel_st7121(internal->io_handle, &panel_config, &internal->panel_handle) != ESP_OK) {
|
||||
@ -354,7 +354,7 @@ static error_t start(Device* device) {
|
||||
xSemaphoreGive(internal->color_trans_done_semaphore);
|
||||
|
||||
esp_lcd_dpi_panel_event_callbacks_t callbacks = {};
|
||||
callbacks.on_refresh_done = on_refresh_done;
|
||||
callbacks.on_frame_buf_complete = on_refresh_done;
|
||||
callbacks.on_color_trans_done = on_color_trans_done;
|
||||
if (esp_lcd_dpi_panel_register_event_callbacks(internal->panel_handle, &callbacks, internal) != ESP_OK) {
|
||||
LOG_E(TAG, "Failed to register panel event callbacks");
|
||||
|
||||
@ -250,13 +250,13 @@ static error_t start(Device* device) {
|
||||
};
|
||||
|
||||
const esp_lcd_panel_dev_config_t panel_config = {
|
||||
.reset_gpio_num = pin_or_unused(config->pin_reset),
|
||||
.rgb_ele_order = config->bgr_order ? LCD_RGB_ELEMENT_ORDER_BGR : LCD_RGB_ELEMENT_ORDER_RGB,
|
||||
.data_endian = LCD_RGB_DATA_ENDIAN_LITTLE,
|
||||
.bits_per_pixel = config->bits_per_pixel,
|
||||
.reset_gpio_num = static_cast<gpio_num_t>(pin_or_unused(config->pin_reset)),
|
||||
.vendor_config = &vendor_config,
|
||||
// ST7123's reset line is fixed active-low in hardware.
|
||||
.flags = { .reset_active_high = false },
|
||||
.vendor_config = &vendor_config,
|
||||
};
|
||||
|
||||
if (esp_lcd_new_panel_st7123(internal->io_handle, &panel_config, &internal->panel_handle) != ESP_OK) {
|
||||
@ -354,7 +354,7 @@ static error_t start(Device* device) {
|
||||
xSemaphoreGive(internal->color_trans_done_semaphore);
|
||||
|
||||
esp_lcd_dpi_panel_event_callbacks_t callbacks = {};
|
||||
callbacks.on_refresh_done = on_refresh_done;
|
||||
callbacks.on_frame_buf_complete = on_refresh_done;
|
||||
callbacks.on_color_trans_done = on_color_trans_done;
|
||||
if (esp_lcd_dpi_panel_register_event_callbacks(internal->panel_handle, &callbacks, internal) != ESP_OK) {
|
||||
LOG_E(TAG, "Failed to register panel event callbacks");
|
||||
|
||||
@ -5,7 +5,6 @@
|
||||
#include <tactility/check.h>
|
||||
#include <tactility/device.h>
|
||||
#include <tactility/driver.h>
|
||||
#include <tactility/drivers/esp32_i2c.h>
|
||||
#include <tactility/drivers/esp32_i2c_master.h>
|
||||
#include <tactility/drivers/i2c_controller.h>
|
||||
#include <tactility/drivers/pointer.h>
|
||||
@ -39,14 +38,10 @@ static esp_err_t create_io_handle(Device* parent, esp_lcd_panel_io_handle_t* out
|
||||
esp_lcd_panel_io_i2c_config_t io_config = ESP_LCD_TOUCH_IO_I2C_ST7123_CONFIG();
|
||||
|
||||
auto* parent_driver = device_get_driver(parent);
|
||||
if (driver_is_compatible(parent_driver, "espressif,esp32-i2c")) {
|
||||
auto port = static_cast<const Esp32I2cConfig*>(parent->config)->port;
|
||||
return esp_lcd_new_panel_io_i2c_v1(port, &io_config, out_handle);
|
||||
}
|
||||
if (driver_is_compatible(parent_driver, "espressif,esp32-i2c-master")) {
|
||||
auto bus = esp32_i2c_master_get_bus_handle(parent);
|
||||
io_config.scl_speed_hz = esp32_i2c_master_get_clock_frequency(parent);
|
||||
return esp_lcd_new_panel_io_i2c_v2(bus, &io_config, out_handle);
|
||||
return esp_lcd_new_panel_io_i2c(bus, &io_config, out_handle);
|
||||
}
|
||||
|
||||
LOG_E(TAG, "Unsupported I2C driver");
|
||||
|
||||
@ -69,6 +69,14 @@ static int pin_or_unused(const GpioPinSpec& pin) {
|
||||
return pin.gpio_controller == nullptr ? -1 : static_cast<int>(pin.pin);
|
||||
}
|
||||
|
||||
static lcd_color_format_t color_format_from_bpp(uint8_t bits_per_pixel) {
|
||||
switch (bits_per_pixel) {
|
||||
case 16: return LCD_COLOR_FMT_RGB565;
|
||||
case 24: return LCD_COLOR_FMT_RGB888;
|
||||
default: return static_cast<lcd_color_format_t>(0);
|
||||
}
|
||||
}
|
||||
|
||||
// Unpacks the devicetree's flat [cmd, data_len, delay_ms, data_len bytes...] encoding (produced
|
||||
// by the devicetree compiler's "array" property type - see init-sequence in
|
||||
// bindings/sitronix,st7701.yaml) into a heap-allocated st7701_lcd_init_cmd_t array. Each entry's
|
||||
@ -177,33 +185,35 @@ static error_t start(Device* device) {
|
||||
}
|
||||
},
|
||||
.data_width = config->data_width,
|
||||
.bits_per_pixel = config->bits_per_pixel,
|
||||
.in_color_format = color_format_from_bpp(config->bits_per_pixel),
|
||||
.num_fbs = config->num_fbs,
|
||||
.bounce_buffer_size_px = config->bounce_buffer_size_px,
|
||||
.sram_trans_align = config->sram_trans_align,
|
||||
.psram_trans_align = config->psram_trans_align,
|
||||
.hsync_gpio_num = pin_or_unused(config->pin_hsync),
|
||||
.vsync_gpio_num = pin_or_unused(config->pin_vsync),
|
||||
.de_gpio_num = pin_or_unused(config->pin_de),
|
||||
.pclk_gpio_num = pin_or_unused(config->pin_pclk),
|
||||
.disp_gpio_num = pin_or_unused(config->pin_disp),
|
||||
// No device configures sram-trans-align/psram-trans-align differently from their YAML
|
||||
// defaults (8/64), so the single dma_burst_size that replaced both can just take the
|
||||
// larger (PSRAM) alignment - safe for SRAM-only allocations too, just less tightly packed.
|
||||
.dma_burst_size = config->psram_trans_align,
|
||||
.hsync_gpio_num = static_cast<gpio_num_t>(pin_or_unused(config->pin_hsync)),
|
||||
.vsync_gpio_num = static_cast<gpio_num_t>(pin_or_unused(config->pin_vsync)),
|
||||
.de_gpio_num = static_cast<gpio_num_t>(pin_or_unused(config->pin_de)),
|
||||
.pclk_gpio_num = static_cast<gpio_num_t>(pin_or_unused(config->pin_pclk)),
|
||||
.disp_gpio_num = static_cast<gpio_num_t>(pin_or_unused(config->pin_disp)),
|
||||
.data_gpio_nums = {
|
||||
pin_or_unused(config->pin_data0),
|
||||
pin_or_unused(config->pin_data1),
|
||||
pin_or_unused(config->pin_data2),
|
||||
pin_or_unused(config->pin_data3),
|
||||
pin_or_unused(config->pin_data4),
|
||||
pin_or_unused(config->pin_data5),
|
||||
pin_or_unused(config->pin_data6),
|
||||
pin_or_unused(config->pin_data7),
|
||||
pin_or_unused(config->pin_data8),
|
||||
pin_or_unused(config->pin_data9),
|
||||
pin_or_unused(config->pin_data10),
|
||||
pin_or_unused(config->pin_data11),
|
||||
pin_or_unused(config->pin_data12),
|
||||
pin_or_unused(config->pin_data13),
|
||||
pin_or_unused(config->pin_data14),
|
||||
pin_or_unused(config->pin_data15),
|
||||
static_cast<gpio_num_t>(pin_or_unused(config->pin_data0)),
|
||||
static_cast<gpio_num_t>(pin_or_unused(config->pin_data1)),
|
||||
static_cast<gpio_num_t>(pin_or_unused(config->pin_data2)),
|
||||
static_cast<gpio_num_t>(pin_or_unused(config->pin_data3)),
|
||||
static_cast<gpio_num_t>(pin_or_unused(config->pin_data4)),
|
||||
static_cast<gpio_num_t>(pin_or_unused(config->pin_data5)),
|
||||
static_cast<gpio_num_t>(pin_or_unused(config->pin_data6)),
|
||||
static_cast<gpio_num_t>(pin_or_unused(config->pin_data7)),
|
||||
static_cast<gpio_num_t>(pin_or_unused(config->pin_data8)),
|
||||
static_cast<gpio_num_t>(pin_or_unused(config->pin_data9)),
|
||||
static_cast<gpio_num_t>(pin_or_unused(config->pin_data10)),
|
||||
static_cast<gpio_num_t>(pin_or_unused(config->pin_data11)),
|
||||
static_cast<gpio_num_t>(pin_or_unused(config->pin_data12)),
|
||||
static_cast<gpio_num_t>(pin_or_unused(config->pin_data13)),
|
||||
static_cast<gpio_num_t>(pin_or_unused(config->pin_data14)),
|
||||
static_cast<gpio_num_t>(pin_or_unused(config->pin_data15)),
|
||||
},
|
||||
.flags = {
|
||||
.disp_active_low = config->disp_active_low,
|
||||
@ -219,7 +229,7 @@ static error_t start(Device* device) {
|
||||
// more data lines than that, the tail of the array must be explicitly marked unused rather
|
||||
// than left as the aggregate-init default of 0 (which would look like "GPIO0 is wired here").
|
||||
for (size_t i = 16; i < sizeof(rgb_config.data_gpio_nums) / sizeof(rgb_config.data_gpio_nums[0]); i++) {
|
||||
rgb_config.data_gpio_nums[i] = -1;
|
||||
rgb_config.data_gpio_nums[i] = GPIO_NUM_NC;
|
||||
}
|
||||
|
||||
st7701_vendor_config_t vendor_config = {
|
||||
@ -234,13 +244,13 @@ static error_t start(Device* device) {
|
||||
};
|
||||
|
||||
esp_lcd_panel_dev_config_t panel_config = {
|
||||
.reset_gpio_num = pin_or_unused(config->pin_reset),
|
||||
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
|
||||
.data_endian = LCD_RGB_DATA_ENDIAN_LITTLE,
|
||||
.bits_per_pixel = config->bits_per_pixel,
|
||||
.reset_gpio_num = static_cast<gpio_num_t>(pin_or_unused(config->pin_reset)),
|
||||
.vendor_config = &vendor_config,
|
||||
// ST7701's reset line is fixed active-low in hardware.
|
||||
.flags = { .reset_active_high = false },
|
||||
.vendor_config = &vendor_config,
|
||||
};
|
||||
|
||||
ret = esp_lcd_new_panel_st7701(internal->io_handle, &panel_config, &internal->panel_handle);
|
||||
|
||||
@ -83,8 +83,8 @@ static error_t start(Device* device) {
|
||||
}
|
||||
|
||||
esp_lcd_panel_io_spi_config_t io_config = {
|
||||
.cs_gpio_num = pin_or_unused(cs_pin),
|
||||
.dc_gpio_num = pin_or_unused(config->pin_dc),
|
||||
.cs_gpio_num = static_cast<gpio_num_t>(pin_or_unused(cs_pin)),
|
||||
.dc_gpio_num = static_cast<gpio_num_t>(pin_or_unused(config->pin_dc)),
|
||||
.spi_mode = 0,
|
||||
.pclk_hz = config->pixel_clock_hz,
|
||||
.trans_queue_depth = config->transaction_queue_depth,
|
||||
@ -115,13 +115,13 @@ static error_t start(Device* device) {
|
||||
}
|
||||
|
||||
esp_lcd_panel_dev_config_t panel_config = {
|
||||
.reset_gpio_num = pin_or_unused(config->pin_reset),
|
||||
.rgb_ele_order = config->bgr_order ? LCD_RGB_ELEMENT_ORDER_BGR : LCD_RGB_ELEMENT_ORDER_RGB,
|
||||
.data_endian = LCD_RGB_DATA_ENDIAN_LITTLE,
|
||||
.bits_per_pixel = config->bits_per_pixel,
|
||||
.reset_gpio_num = static_cast<gpio_num_t>(pin_or_unused(config->pin_reset)),
|
||||
.vendor_config = nullptr,
|
||||
// ST7735's reset line is fixed active-low in hardware.
|
||||
.flags = { .reset_active_high = false },
|
||||
.vendor_config = nullptr,
|
||||
};
|
||||
|
||||
ret = esp_lcd_new_panel_st7735(internal->io_handle, &panel_config, &internal->panel_handle);
|
||||
|
||||
@ -113,7 +113,7 @@ static error_t start(Device* device) {
|
||||
}
|
||||
|
||||
esp_lcd_panel_io_i80_config_t io_config = {
|
||||
.cs_gpio_num = pin_or_unused(cs_pin),
|
||||
.cs_gpio_num = static_cast<gpio_num_t>(pin_or_unused(cs_pin)),
|
||||
.pclk_hz = config->pixel_clock_hz,
|
||||
.trans_queue_depth = config->transaction_queue_depth,
|
||||
.on_color_trans_done = on_color_trans_done,
|
||||
@ -144,13 +144,13 @@ static error_t start(Device* device) {
|
||||
}
|
||||
|
||||
esp_lcd_panel_dev_config_t panel_config = {
|
||||
.reset_gpio_num = pin_or_unused(config->pin_reset),
|
||||
.rgb_ele_order = config->bgr_order ? LCD_RGB_ELEMENT_ORDER_BGR : LCD_RGB_ELEMENT_ORDER_RGB,
|
||||
.data_endian = LCD_RGB_DATA_ENDIAN_LITTLE,
|
||||
.bits_per_pixel = 16,
|
||||
.reset_gpio_num = static_cast<gpio_num_t>(pin_or_unused(config->pin_reset)),
|
||||
.vendor_config = nullptr,
|
||||
// ST7789's reset line is fixed active-low in hardware.
|
||||
.flags = { .reset_active_high = false },
|
||||
.vendor_config = nullptr,
|
||||
};
|
||||
|
||||
ret = esp_lcd_new_panel_st7789(internal->io_handle, &panel_config, &internal->panel_handle);
|
||||
|
||||
@ -81,7 +81,7 @@ static error_t start(Device* device) {
|
||||
}
|
||||
|
||||
esp_lcd_panel_io_i80_config_t io_config = {
|
||||
.cs_gpio_num = pin_or_unused(cs_pin),
|
||||
.cs_gpio_num = static_cast<gpio_num_t>(pin_or_unused(cs_pin)),
|
||||
.pclk_hz = config->pixel_clock_hz,
|
||||
.trans_queue_depth = config->transaction_queue_depth,
|
||||
.on_color_trans_done = on_color_trans_done,
|
||||
@ -112,13 +112,13 @@ static error_t start(Device* device) {
|
||||
}
|
||||
|
||||
esp_lcd_panel_dev_config_t panel_config = {
|
||||
.reset_gpio_num = pin_or_unused(config->pin_reset),
|
||||
.rgb_ele_order = config->bgr_order ? LCD_RGB_ELEMENT_ORDER_BGR : LCD_RGB_ELEMENT_ORDER_RGB,
|
||||
.data_endian = LCD_RGB_DATA_ENDIAN_LITTLE,
|
||||
.bits_per_pixel = 16,
|
||||
.reset_gpio_num = static_cast<gpio_num_t>(pin_or_unused(config->pin_reset)),
|
||||
.vendor_config = nullptr,
|
||||
// ST7796's reset line is fixed active-low in hardware.
|
||||
.flags = { .reset_active_high = false },
|
||||
.vendor_config = nullptr,
|
||||
};
|
||||
|
||||
ret = esp_lcd_new_panel_st7796(internal->io_handle, &panel_config, &internal->panel_handle);
|
||||
|
||||
@ -83,8 +83,8 @@ static error_t start(Device* device) {
|
||||
}
|
||||
|
||||
esp_lcd_panel_io_spi_config_t io_config = {
|
||||
.cs_gpio_num = pin_or_unused(cs_pin),
|
||||
.dc_gpio_num = pin_or_unused(config->pin_dc),
|
||||
.cs_gpio_num = static_cast<gpio_num_t>(pin_or_unused(cs_pin)),
|
||||
.dc_gpio_num = static_cast<gpio_num_t>(pin_or_unused(config->pin_dc)),
|
||||
.spi_mode = 0,
|
||||
.pclk_hz = config->pixel_clock_hz,
|
||||
.trans_queue_depth = config->transaction_queue_depth,
|
||||
@ -115,13 +115,13 @@ static error_t start(Device* device) {
|
||||
}
|
||||
|
||||
esp_lcd_panel_dev_config_t panel_config = {
|
||||
.reset_gpio_num = pin_or_unused(config->pin_reset),
|
||||
.rgb_ele_order = config->bgr_order ? LCD_RGB_ELEMENT_ORDER_BGR : LCD_RGB_ELEMENT_ORDER_RGB,
|
||||
.data_endian = LCD_RGB_DATA_ENDIAN_LITTLE,
|
||||
.bits_per_pixel = config->bits_per_pixel,
|
||||
.reset_gpio_num = static_cast<gpio_num_t>(pin_or_unused(config->pin_reset)),
|
||||
.vendor_config = nullptr,
|
||||
// ST7796's reset line is fixed active-low in hardware.
|
||||
.flags = { .reset_active_high = false },
|
||||
.vendor_config = nullptr,
|
||||
};
|
||||
|
||||
ret = esp_lcd_new_panel_st7796(internal->io_handle, &panel_config, &internal->panel_handle);
|
||||
|
||||
@ -186,25 +186,16 @@ bool writeString(const std::string& filepath, const std::string& content) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool findOrCreateDirectoryInternal(std::string path, mode_t mode) {
|
||||
static bool findOrCreateDirectoryInternal(const std::string& path, mode_t mode) {
|
||||
// Checked before creating, not after: on the SD card's mount root, the FATFS VFS's mkdir()
|
||||
// doesn't fail with EEXIST for an already-mounted root (it returns some other errno), so an
|
||||
// mkdir-first/errno-check approach never recognizes it as already there.
|
||||
struct stat dir_stat;
|
||||
if (mkdir(path.c_str(), mode) == 0) {
|
||||
return true;
|
||||
if (stat(path.c_str(), &dir_stat) == 0) {
|
||||
return S_ISDIR(dir_stat.st_mode);
|
||||
}
|
||||
|
||||
if (errno != EEXIST) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (stat(path.c_str(), &dir_stat) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!S_ISDIR(dir_stat.st_mode)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return mkdir(path.c_str(), mode) == 0;
|
||||
}
|
||||
|
||||
std::string getLastPathSegment(const std::string& path) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user