On Thu, Jun 23, 2016 at 10:35:34PM -0700, Andrey Smirnov wrote: > Add 'fbtest' - a command to produce test patterns on a screen > > Signed-off-by: Andrey Smirnov <andrew.smirnov@xxxxxxxxx> > Signed-off-by: Andrey Gusakov <andrey.gusakov@xxxxxxxxxxxxxxxxxx> > --- > commands/Kconfig | 9 +++ > commands/Makefile | 1 + > commands/fbtest.c | 201 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 211 insertions(+) > create mode 100644 commands/fbtest.c > > diff --git a/commands/Kconfig b/commands/Kconfig > index 880cd45..cf71289 100644 > --- a/commands/Kconfig > +++ b/commands/Kconfig > @@ -1417,6 +1417,15 @@ config CMD_SPLASH > -b COLOR background color in 0xttrrggbb > -o render offscreen > > +config CMD_FBTEST > + bool > + depends on VIDEO > + select 2D_PRIMITIVES > + prompt "FB test" > + help > + Framebuffer test command that allows to produce a number of > + test patterns on a screen. > + > config CMD_READLINE > tristate > prompt "readline" > diff --git a/commands/Makefile b/commands/Makefile > index b8c07f3..5a899ab 100644 > --- a/commands/Makefile > +++ b/commands/Makefile > @@ -57,6 +57,7 @@ obj-$(CONFIG_CMD_HELP) += help.o > obj-$(CONFIG_CMD_LSMOD) += lsmod.o > obj-$(CONFIG_CMD_INSMOD) += insmod.o > obj-$(CONFIG_CMD_SPLASH) += splash.o > +obj-$(CONFIG_CMD_FBTEST) += fbtest.o > obj-$(CONFIG_USB_GADGET_DFU) += dfu.o > obj-$(CONFIG_USB_GADGET_SERIAL) += usbserial.o > obj-$(CONFIG_CMD_GPIO) += gpio.o > diff --git a/commands/fbtest.c b/commands/fbtest.c > new file mode 100644 > index 0000000..f1569e9 > --- /dev/null > +++ b/commands/fbtest.c > @@ -0,0 +1,201 @@ > +#include <common.h> > +#include <command.h> > +#include <errno.h> > +#include <malloc.h> > +#include <getopt.h> > +#include <fb.h> > +#include <gui/graphic_utils.h> > +#include <gui/2d-primitives.h> > +#include <linux/gcd.h> > +#include <int_sqrt.h> > + > +static void fbtest_pattern_bars(struct screen *sc, u32 unused) > +{ > + int i; > + > + const u32 xres = sc->info->xres; > + const u32 yres = sc->info->yres; > + > + const u32 colors[] = { > + 0xFFFFFF, /* white */ > + 0xFFFF00, /* yellow */ > + 0x00FFFF, /* cyan */ > + 0x00FF00, /* green */ > + 0xFF00FF, /* magenta */ > + 0xFF0000, /* red */ > + 0x0000FF, /* blue */ > + 0x000000, /* black */ > + }; > + > + for (i = 0; i < ARRAY_SIZE(colors); i++) { > + const u8 r = (colors[i] >> 16) & 0xff; > + const u8 g = (colors[i] >> 8) & 0xff; > + const u8 b = (colors[i] >> 0) & 0xff; > + const int dx = xres / ARRAY_SIZE(colors); > + > + gu_fill_rectangle(sc, > + i * dx, 0, (i + 1) * dx - 1, yres - 1, > + r, g, b, 0xff); > + } > +} > + > +static void fbtest_pattern_geometry(struct screen *sc, u32 color) > +{ > + int i; > + > + const u8 r = (color >> 16) & 0xff; > + const u8 g = (color >> 8) & 0xff; > + const u8 b = (color >> 0) & 0xff; > + > + const u32 xres = sc->info->xres; > + const u32 yres = sc->info->yres; > + > + const u8 xcount = xres / gcd(xres, yres); > + const u8 ycount = yres / gcd(xres, yres); > + > + const struct { > + int x1, y1, x2, y2; > + } borders[] = { > + { 0, 0, xres - 1, 0 }, > + { xres - 1, 0, xres - 1, yres - 1 }, > + { 0, yres - 1, xres - 1, yres - 1 }, > + { 0, 0, 0, yres - 1 }, > + }; > + > + const int R1 = min(xres, yres) / 2; > + const int h = xres * xres + yres * yres; > + const int R2 = (int_sqrt(h) / 2 - R1) * 5 / 12; > + > + const struct { > + int x0, y0, radius; > + } circles[] = { > + { xres / 2, yres / 2, R1 - 1 }, > + { R2, R2, R2 - 1 }, > + { xres - R2, R2, R2 - 1 }, > + { xres - R2, yres - R2, R2 - 1 }, > + { R2, yres - R2, R2 - 1 } > + }; > + > + void *buf = gui_screen_render_buffer(sc); > + > + gu_memset_pixel(sc->info, buf, ~color, > + sc->s.width * sc->s.height); > + > + for (i = 0; i < ARRAY_SIZE(borders); i++) > + gu_draw_line(sc, > + borders[i].x1, borders[i].y1, > + borders[i].x2, borders[i].y2, > + r, g, b, 0xff, 10); > + > + for (i = 0; i < ARRAY_SIZE(circles); i++) > + gu_draw_circle(sc, > + circles[i].x0, circles[i].y0, > + circles[i].radius, > + r, g, b, 0xff); > + > + for (i = 1; i < ycount; i++) { > + const int y = (yres - 1) * i / ycount; > + gu_draw_line(sc, > + 0, y, xres - 1, y, > + r, g, b, 0xff, 0); > + } > + > + > + for (i = 1; i < xcount; i++) { > + const int x = (xres - 1) * i / xcount; > + gu_draw_line(sc, > + x, 0, x, yres - 1, > + r, g, b, 0xff, 0); > + } > +} > + > +static int do_fbtest(int argc, char *argv[]) > +{ > + struct screen *sc; > + int opt; > + unsigned int i; > + const char *pattern_name = NULL; > + char *fbdev = "/dev/fb0"; > + void (*pattern) (struct screen *sc, u32 color) = NULL; > + u32 color = 0xffffff; > + > + struct { > + const char *name; > + void (*func) (struct screen *sc, u32 color); > + } patterns[] = { > + { "geometry", fbtest_pattern_geometry }, > + { "bars", fbtest_pattern_bars } > + }; > + > + while((opt = getopt(argc, argv, "d:p:c:")) > 0) { > + switch(opt) { > + case 'd': > + fbdev = optarg; > + break; > + case 'p': > + pattern_name = optarg; > + break; > + case 'c': > + color = simple_strtoul(optarg, NULL, 16); > + break; > + } > + } > + > + if (pattern_name) { > + for (i = 0; i < ARRAY_SIZE(patterns); i++) > + if (!strcmp(pattern_name, patterns[i].name)) > + pattern = patterns[i].func; > + > + if (!pattern) { > + printf("Unknonw pattern: %s\n", pattern_name); s/Unknonw/Unknown/ > + return -EINVAL; > + } > + } > + > + sc = fb_open(fbdev); > + if (IS_ERR(sc)) { > + perror("fd_open"); > + return PTR_ERR(sc); > + } > + > + if (!pattern_name) { > + printf("No pattern selected. Cycling through all of them.\n"); > + printf("Press Ctrl-C to stop\n"); > + > + i = 0; > + for (;;) { > + pattern = patterns[i++ % ARRAY_SIZE(patterns)].func; > + pattern(sc, color); > + gu_screen_blit(sc); > + > + if (ctrlc()) > + break; > + > + mdelay(2000); > + } The user will likely hit ctrl-c during the delay. Then when pressed there will always be the next pattern printed before actually stopping, which is probably not expected. How about this instead? start = get_time_ns(); while (!is_timeout(start, 2 * SECOND)) if (ctrlc()) break; Sascha > + } else { > + pattern(sc, color); > + gu_screen_blit(sc); > + } > + > + fb_close(sc); > + > + return 0; > +} > + > +BAREBOX_CMD_HELP_START(fbtest) > +BAREBOX_CMD_HELP_TEXT("This command displays a test pattern on a screen") > +BAREBOX_CMD_HELP_TEXT("") > +BAREBOX_CMD_HELP_TEXT("Options:") > +BAREBOX_CMD_HELP_OPT ("-d <fbdev>\t", "framebuffer device (default /dev/fb0)") > +BAREBOX_CMD_HELP_OPT ("-c color\t", "color") > +BAREBOX_CMD_HELP_OPT ("-p pattern\t", "pattern name (geometry, bars)") > +BAREBOX_CMD_HELP_END > + > +BAREBOX_CMD_START(fbtest) > + .cmd = do_fbtest, > + BAREBOX_CMD_DESC("display a test pattern") > + BAREBOX_CMD_OPTS("[-dcp]") > + BAREBOX_CMD_GROUP(CMD_GRP_CONSOLE) > + BAREBOX_CMD_HELP(cmd_fbtest_help) > +BAREBOX_CMD_END > -- > 2.5.5 > > > _______________________________________________ > barebox mailing list > barebox@xxxxxxxxxxxxxxxxxxx > http://lists.infradead.org/mailman/listinfo/barebox > -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | _______________________________________________ barebox mailing list barebox@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/barebox