Skip to content

Commit 71dd89d

Browse files
committed
drivers: video: sw_generator: modify video_sw_generator_fill_colorbar()
Add a check for the array size to avoid overwriting unrelated memory when the buffer is too small for the full format. It first check if there is enough buffer for one line, and fill it programmatically. Then, it will try to duplicate that line over the entire buffer, in the limit of the room available. Signed-off-by: Josuah Demangeon <me@josuah.net>
1 parent 541fd56 commit 71dd89d

File tree

1 file changed

+37
-15
lines changed

1 file changed

+37
-15
lines changed

drivers/video/video_sw_generator.c

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <zephyr/drivers/video-controls.h>
1212
#include <zephyr/logging/log.h>
1313
#include <zephyr/sys/util.h>
14+
#include <zephyr/sys/byteorder.h>
1415

1516
#include "video_ctrls.h"
1617
#include "video_device.h"
@@ -116,29 +117,50 @@ uint32_t xrgb32_colorbar_value[] = {
116117
0xFF00FF00, 0xFF00FFFF, 0xFFFFFF00, 0xFFFFFFFF,
117118
};
118119

120+
static inline int video_sw_generator_get_color_idx(uint16_t w, uint16_t width, bool hflip)
121+
{
122+
/* If hflip is on, start from the right instead */
123+
w = (hflip) ? (width - w - 1) : (w);
124+
125+
/* Downscale from w/width to #/8 */
126+
return 8 * w / width;
127+
}
128+
119129
static void video_sw_generator_fill_colorbar(struct video_sw_generator_data *data,
120130
struct video_buffer *vbuf)
121131
{
122132
int bw = data->fmt.width / 8;
123-
int h, w, i = 0;
124-
125-
for (h = 0; h < data->fmt.height; h++) {
126-
for (w = 0; w < data->fmt.width; w++) {
127-
int color_idx = data->ctrls.hflip.val ? 7 - w / bw : w / bw;
128-
if (data->fmt.pixelformat == VIDEO_PIX_FMT_RGB565) {
129-
uint16_t *pixel = (uint16_t *)&vbuf->buffer[i];
130-
*pixel = rgb565_colorbar_value[color_idx];
131-
i += 2;
132-
} else if (data->fmt.pixelformat == VIDEO_PIX_FMT_XRGB32) {
133-
uint32_t *pixel = (uint32_t *)&vbuf->buffer[i];
134-
*pixel = xrgb32_colorbar_value[color_idx];
135-
i += 4;
136-
}
133+
struct video_format *fmt = &data->fmt;
134+
size_t pitch = fmt->width * video_bits_per_pixel(fmt->pixelformat) / BITS_PER_BYTE;
135+
bool hflip = data->ctrls.hflip.val;
136+
137+
vbuf->bytesused = 0;
138+
139+
/* Generate the first line of data */
140+
for (int w = 0, i = 0; w < data->fmt.width; w++) {
141+
int color_idx = video_sw_generator_get_color_idx(w, width, hflip);
142+
143+
if (data->fmt.pixelformat == VIDEO_PIX_FMT_RGB565) {
144+
uint16_t *pixel = (uint16_t *)&vbuf->buffer[i];
145+
*pixel = sys_cpu_to_le16(rgb565_colorbar_value[color_idx]);
146+
} else if (data->fmt.pixelformat == VIDEO_PIX_FMT_XRGB32) {
147+
uint32_t *pixel = (uint32_t *)&vbuf->buffer[i];
148+
*pixel = sys_cpu_to_le32(xrgb32_colorbar_value[color_idx]);
137149
}
150+
i += video_bits_per_pixel(data->fmt.pixelformat) / BITS_PER_BYTE;
151+
}
152+
153+
/* Duplicate the first line all over the buffer */
154+
for (int h = 1; h < data->fmt.height; h++) {
155+
if (vbuf->size < vbuf->bytesused + pitch) {
156+
break;
157+
}
158+
159+
memcpy(vbuf->buffer + h * pitch, vbuf->buffer, pitch);
160+
vbuf->bytesused += pitch;
138161
}
139162

140163
vbuf->timestamp = k_uptime_get_32();
141-
vbuf->bytesused = i;
142164
vbuf->line_offset = 0;
143165
}
144166

0 commit comments

Comments
 (0)