Merge branch 'fix/fix_i2s_i80_color_size_check_v5.2' into 'release/v5.2'

fix(lcd): add color size check for i80 and boundary check for rgb (v5.2)

See merge request espressif/esp-idf!50980
This commit is contained in:
morris
2026-07-31 10:18:45 +08:00
3 changed files with 33 additions and 7 deletions
+26 -4
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -454,6 +454,25 @@ static void i2s_lcd_prepare_param_buffer(lcd_i80_trans_descriptor_t *trans_desc,
#endif
}
static bool i2s_lcd_get_color_buffer_size(const esp_lcd_i80_bus_t *bus, size_t color_size, size_t *buffer_size)
{
#if SOC_I2S_TRANS_SIZE_ALIGN_WORD
size_t input_bytes_per_word = bus->bus_width / 4;
if (color_size % input_bytes_per_word) {
return false;
}
size_t word_num = color_size / input_bytes_per_word;
if (word_num > (size_t) -1 / 4) {
return false;
}
*buffer_size = word_num * 4;
#else
(void)bus;
*buffer_size = color_size;
#endif
return true;
}
static void i2s_lcd_prepare_color_buffer(lcd_i80_trans_descriptor_t *trans_desc, const void *color, size_t color_size)
{
#if SOC_I2S_TRANS_SIZE_ALIGN_WORD
@@ -489,8 +508,8 @@ static esp_err_t panel_io_i80_tx_param(esp_lcd_panel_io_t *io, int lcd_cmd, cons
esp_lcd_i80_bus_t *bus = next_device->bus;
lcd_panel_io_i80_t *cur_device = bus->cur_device;
lcd_i80_trans_descriptor_t *trans_desc = NULL;
assert(param_size <= (bus->num_dma_nodes * DMA_DESCRIPTOR_BUFFER_MAX_SIZE) && "parameter bytes too long, enlarge max_transfer_bytes");
assert(param_size <= CONFIG_LCD_PANEL_IO_FORMAT_BUF_SIZE && "format buffer too small, increase CONFIG_LCD_PANEL_IO_FORMAT_BUF_SIZE");
ESP_RETURN_ON_FALSE(param_size <= (bus->num_dma_nodes * DMA_DESCRIPTOR_BUFFER_MAX_SIZE), ESP_ERR_INVALID_ARG, TAG, "parameter bytes too long, enlarge max_transfer_bytes");
ESP_RETURN_ON_FALSE(param_size <= CONFIG_LCD_PANEL_IO_FORMAT_BUF_SIZE, ESP_ERR_INVALID_ARG, TAG, "format buffer too small, increase CONFIG_LCD_PANEL_IO_FORMAT_BUF_SIZE");
size_t num_trans_inflight = next_device->num_trans_inflight;
// before issue a polling transaction, need to wait queued transactions finished
for (size_t i = 0; i < num_trans_inflight; i++) {
@@ -555,7 +574,10 @@ static esp_err_t panel_io_i80_tx_color(esp_lcd_panel_io_t *io, int lcd_cmd, cons
esp_lcd_i80_bus_t *bus = next_device->bus;
lcd_panel_io_i80_t *cur_device = bus->cur_device;
lcd_i80_trans_descriptor_t *trans_desc = NULL;
assert(color_size <= (bus->num_dma_nodes * DMA_DESCRIPTOR_BUFFER_MAX_SIZE) && "color bytes too long, enlarge max_transfer_bytes");
size_t color_buffer_size = 0;
bool valid_color_buffer_size = i2s_lcd_get_color_buffer_size(bus, color_size, &color_buffer_size);
ESP_RETURN_ON_FALSE(valid_color_buffer_size && color_buffer_size <= bus->num_dma_nodes * DMA_DESCRIPTOR_BUFFER_MAX_SIZE, ESP_ERR_INVALID_ARG, TAG,
"color bytes too long, enlarge max_transfer_bytes");
size_t num_trans_inflight = next_device->num_trans_inflight;
// before issue a polling transaction, need to wait queued transactions finished
for (size_t i = 0; i < num_trans_inflight; i++) {
@@ -413,8 +413,8 @@ static esp_err_t panel_io_i80_tx_param(esp_lcd_panel_io_t *io, int lcd_cmd, cons
esp_lcd_i80_bus_t *bus = next_device->bus;
lcd_panel_io_i80_t *cur_device = bus->cur_device;
lcd_i80_trans_descriptor_t *trans_desc = NULL;
assert(param_size <= (bus->num_dma_nodes * DMA_DESCRIPTOR_BUFFER_MAX_SIZE) && "parameter bytes too long, enlarge max_transfer_bytes");
assert(param_size <= CONFIG_LCD_PANEL_IO_FORMAT_BUF_SIZE && "format buffer too small, increase CONFIG_LCD_PANEL_IO_FORMAT_BUF_SIZE");
ESP_RETURN_ON_FALSE(param_size <= (bus->num_dma_nodes * DMA_DESCRIPTOR_BUFFER_MAX_SIZE), ESP_ERR_INVALID_ARG, TAG, "parameter bytes too long, enlarge max_transfer_bytes");
ESP_RETURN_ON_FALSE(param_size <= CONFIG_LCD_PANEL_IO_FORMAT_BUF_SIZE, ESP_ERR_INVALID_ARG, TAG, "format buffer too small, increase CONFIG_LCD_PANEL_IO_FORMAT_BUF_SIZE");
uint32_t cmd_cycles = next_device->lcd_cmd_bits / bus->bus_width;
// in case bus_width=16 and cmd_bits=8, we still need 1 cmd_cycle
if (cmd_cycles * bus->bus_width < next_device->lcd_cmd_bits) {
@@ -469,7 +469,7 @@ static esp_err_t panel_io_i80_tx_color(esp_lcd_panel_io_t *io, int lcd_cmd, cons
lcd_panel_io_i80_t *i80_device = __containerof(io, lcd_panel_io_i80_t, base);
esp_lcd_i80_bus_t *bus = i80_device->bus;
lcd_i80_trans_descriptor_t *trans_desc = NULL;
assert(color_size <= (bus->num_dma_nodes * DMA_DESCRIPTOR_BUFFER_MAX_SIZE) && "color bytes too long, enlarge max_transfer_bytes");
ESP_RETURN_ON_FALSE(color_size <= (bus->num_dma_nodes * DMA_DESCRIPTOR_BUFFER_MAX_SIZE), ESP_ERR_INVALID_ARG, TAG, "color bytes too long, enlarge max_transfer_bytes");
// in case bus_width=16 and cmd_bits=8, we still need 1 cmd_cycle
uint32_t cmd_cycles = i80_device->lcd_cmd_bits / bus->bus_width;
if (cmd_cycles * bus->bus_width < i80_device->lcd_cmd_bits) {
@@ -727,6 +727,10 @@ static esp_err_t rgb_panel_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int
y_start = MIN(y_start, v_res);
y_end = MIN(y_end, v_res);
}
if (x_start >= x_end || y_start >= y_end) {
// no valid region to draw, skip
return ESP_OK;
}
int bytes_per_pixel = rgb_panel->fb_bits_per_pixel / 8;
int pixels_per_line = rgb_panel->timings.h_res;