From 024203b0f98e5e8c3ca0f3d680ff092b435d1802 Mon Sep 17 00:00:00 2001
From: guowenxue <guowenxue@gmail.com>
Date: Sat, 27 Aug 2022 13:45:24 +0800
Subject: [PATCH] Update fbtest.c, can support show BMP file
---
/dev/null | 154 ---------------
bsp/uapi/test/fbtest.c | 395 +++++++++++++++++++++++++++++++++++++++
2 files changed, 395 insertions(+), 154 deletions(-)
diff --git a/bsp/uapi/test/fbtest.c b/bsp/uapi/test/fbtest.c
new file mode 100644
index 0000000..91b9d55
--- /dev/null
+++ b/bsp/uapi/test/fbtest.c
@@ -0,0 +1,395 @@
+/********************************************************************************
+ * Copyright: (C) 2021 Guo Wenxue<Email:guowenxue@gmail.com QQ:281143292>
+ * All rights reserved.
+ *
+ * Filename: fbtest.c
+ * Description: This program used to:
+ * 1, Show framebuffer device information
+ * 2, Show RGB color on LCD full screen
+ * 3, Show BMP file on LCD;
+ *
+ * Version: 1.0.0(08/26/22)
+ * Author: Guo Wenxue <wenxue.guo@avnet.com>
+ * ChangeLog: 1, Release initial version on "08/26/22 12:56:31"
+ *
+ ********************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <libgen.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <linux/fb.h>
+#include <sys/mman.h>
+
+#define PROG_VERSION "1.0.0"
+
+enum
+{
+ CMD_SHOW_INFO, /* show LCD info */
+ CMD_SHOW_RGB, /* show RGB color */
+ CMD_SHOW_BMP, /* show BMP file */
+};
+
+typedef struct fb_ctx_s
+{
+ int fd; /* framebuffer file descriptor */
+ char dev[64]; /* framebuffer device name */
+ long fb_size; /* framebuffer size */
+ int pix_size; /* lcd screen pix size */
+ struct fb_var_screeninfo vinfo; /* framebuffer var information */
+ char *fbp; /* framebuffer mmap() address */
+} fb_ctx_t;
+
+
+int fb_init(fb_ctx_t *fb_ctx);
+int fb_term(fb_ctx_t *fb_ctx);
+int show_rgb(fb_ctx_t *fb_ctx, int times);
+int show_bmp(fb_ctx_t *fb_ctx, char *bmp_file);
+
+static void program_usage(char *progname)
+{
+ printf("Usage: %s [OPTION]...\n", progname);
+ printf(" %s is a program to show RGB color or BMP file on LCD screen\n", progname);
+
+ printf("\nMandatory arguments to long options are mandatory for short options too:\n");
+ printf(" -d[device ] Specify framebuffer device, such as: /dev/fb0\n");
+ printf(" -c[color ] Display RGB corlor on LCD screen for some times, such as: -c 3\n");
+ printf(" -b[bmp ] Display BMP file, such as: -b bg.bmp\n");
+ printf(" -h[help ] Display this help information\n");
+ printf(" -v[version ] Display the program version\n");
+
+ printf("\n%s version %s\n", progname, PROG_VERSION);
+ return;
+}
+
+int main (int argc, char **argv)
+{
+ fb_ctx_t fb_ctx;
+ char *progname=NULL;
+ char *bmp_file=NULL;
+ char *fb_dev="/dev/fb0";
+ int cmd = CMD_SHOW_INFO;
+ int opt, times;
+
+ struct option long_options[] = {
+ {"device", required_argument, NULL, 'd'},
+ {"color", required_argument, NULL, 'c'},
+ {"bmp", required_argument, NULL, 'b'},
+ {"version", no_argument, NULL, 'v'},
+ {"help", no_argument, NULL, 'h'},
+ {NULL, 0, NULL, 0}
+ };
+
+ progname = (char *)basename(argv[0]);
+
+ /* Parser the command line parameters */
+ while ((opt = getopt_long(argc, argv, "d:c:b:vh", long_options, NULL)) != -1)
+ {
+ switch (opt)
+ {
+ case 'd': /* Set framebuffer device */
+ fb_dev = optarg;
+ break;
+
+ case 'b': /* Set BMP file */
+ bmp_file = optarg;
+ cmd = CMD_SHOW_BMP;
+ break;
+
+ case 'c': /* Show RGB color */
+ times = atoi(optarg);
+ cmd = CMD_SHOW_RGB;
+ break;
+
+ case 'v': /* Get software version */
+ printf("%s version %s\n", progname, PROG_VERSION);
+ return 0;
+
+ case 'h': /* Get help information */
+ program_usage(progname);
+ return 0;
+
+ default:
+ break;
+ }
+
+ }
+
+ memset(&fb_ctx, 0, sizeof(fb_ctx));
+ strncpy(fb_ctx.dev, fb_dev, sizeof(fb_ctx.dev));
+
+ if( fb_init(&fb_ctx) < 0 )
+ {
+ printf("ERROR: Initial framebuffer device '%s' failure.\n", fb_ctx.dev);
+ return 1;
+ }
+
+ switch( cmd )
+ {
+ case CMD_SHOW_RGB:
+ show_rgb(&fb_ctx, times);
+ break;
+
+ case CMD_SHOW_BMP:
+ show_bmp(&fb_ctx, bmp_file);
+ break;
+
+ default:
+ break;
+ }
+
+ fb_term(&fb_ctx);
+
+ return 0;
+}
+
+
+int fb_get_var_screeninfo(int fd, struct fb_var_screeninfo *vinfo)
+{
+ if( fd<0 || !vinfo )
+ {
+ printf("ERROR: Invalid input arguments\n");
+ return -1;
+ }
+
+ if(ioctl(fd, FBIOGET_VSCREENINFO, vinfo))
+ {
+ printf("ERROR: ioctl() get variable info failure: %s\n", strerror(errno));
+ return -2;
+ }
+
+ printf("LCD information : %dx%d, bpp:%d rgba:%d/%d,%d/%d,%d/%d,%d/%d\n", vinfo->xres, vinfo->yres, vinfo->bits_per_pixel,
+ vinfo->red.length, vinfo->red.offset, vinfo->green.length, vinfo->green.offset,
+ vinfo->blue.length,vinfo->blue.offset, vinfo->transp.length, vinfo->transp.offset);
+
+ return 0;
+}
+
+int fb_init(fb_ctx_t *fb_ctx)
+{
+ struct fb_var_screeninfo *vinfo;
+
+ if( !fb_ctx || !strlen(fb_ctx->dev) )
+ {
+ printf("ERROR: Invalid input arguments\n");
+ return -1;
+ }
+
+ if( (fb_ctx->fd=open(fb_ctx->dev, O_RDWR)) < 0 )
+ {
+ printf("ERROR: Open framebuffer device '%s' failure: %s\n", fb_ctx->dev, strerror(errno));
+ return -2;
+ }
+
+ fb_get_var_screeninfo(fb_ctx->fd, &fb_ctx->vinfo);
+
+ vinfo = &fb_ctx->vinfo;
+ fb_ctx->fb_size = vinfo->xres * vinfo->yres * vinfo->bits_per_pixel / 8;
+ fb_ctx->pix_size = vinfo->xres * vinfo->yres;
+
+ fb_ctx->fbp =(char *)mmap(0, fb_ctx->fb_size, PROT_READ | PROT_WRITE, MAP_SHARED, fb_ctx->fd ,0);
+ if ( !fb_ctx->fbp )
+ {
+ printf ("ERROR: Framebuffer mmap() failure: %s\n", strerror(errno));
+ return -2;
+ }
+
+ vinfo->xoffset = 0;
+ vinfo->yoffset = 0;
+
+ return 0;
+}
+
+int fb_term(fb_ctx_t *fb_ctx)
+{
+ if( !fb_ctx )
+ {
+ printf("ERROR: Invalid input arguments\n");
+ return -1;
+ }
+
+ munmap(fb_ctx->fbp, fb_ctx->fb_size);
+ close (fb_ctx->fd);
+
+ return 0;
+}
+
+int show_rgb_screen(fb_ctx_t *fb_ctx)
+{
+ struct fb_var_screeninfo *vinfo;
+ char *fb_addr;
+ int interval = 1;
+ int i, color;
+ int bpp_bytes;
+
+ if( !fb_ctx )
+ {
+ printf("ERROR: Invalid input arguments\n");
+ return -1;
+ }
+
+ vinfo = &fb_ctx->vinfo;
+ bpp_bytes = vinfo->bits_per_pixel / 8;
+
+ printf("show full screen on red\n");
+ color = (1<<vinfo->red.length-1) << vinfo->red.offset;
+ fb_addr = fb_ctx->fbp;
+ for(i=0; i<fb_ctx->pix_size; i++)
+ {
+ memcpy(fb_addr, &color, bpp_bytes);
+ fb_addr += bpp_bytes;
+ }
+ sleep(interval);
+
+ printf("show full screen on green\n");
+ color = (1<<vinfo->green.length-1) << vinfo->green.offset;
+ fb_addr = fb_ctx->fbp;
+ for(i=0; i<fb_ctx->pix_size; i++)
+ {
+ memcpy(fb_addr, &color, bpp_bytes);
+ fb_addr += bpp_bytes;
+ }
+ sleep(interval);
+
+ printf("show full screen on blue\n");
+ color = (1<<vinfo->blue.length-1) << vinfo->blue.offset;
+ fb_addr = fb_ctx->fbp;
+ for(i=0; i<fb_ctx->pix_size; i++)
+ {
+ memcpy(fb_addr, &color, bpp_bytes);
+ fb_addr += bpp_bytes;
+ }
+ sleep(interval);
+
+ return 0;
+}
+
+int show_rgb(fb_ctx_t *fb_ctx, int times)
+{
+ int i;
+
+ if( !fb_ctx )
+ {
+ printf("ERROR: Invalid input arguments\n");
+ return -1;
+ }
+
+ for(i=0; i<times; i++)
+ {
+ show_rgb_screen(fb_ctx);
+ }
+
+ return 0;
+}
+
+
+/* BMP format: https://blog.csdn.net/weixin_39756273/article/details/110585675 */
+typedef struct bmp_file_head_s
+{
+ uint8_t bfType[2]; /* BMP file type: "BM" */
+ int32_t bfSize; /* BMP file size */
+ int32_t bfReserved; /* reserved */
+ int32_t bfoffBits; /* image data offset */
+}__attribute__((packed)) bmp_file_head_t;
+
+
+typedef struct bmp_bitmap_info_s
+{
+ int32_t biSize; /* this struture size */
+ int32_t biWidth; /* image width in pix */
+ int32_t biHeight; /* image height in pix */
+ uint16_t biPlanes; /* display planes, always be 1 */
+ uint16_t biBitCount; /* bpp: 1,4,8,16,24,32 */
+ int32_t biCompress; /* compress type */
+ int32_t biSizeImage; /* image size in byte */
+ int32_t biXPelsPerMeter; /* x-res in pix/m */
+ int32_t biYPelsPerMeter; /* y-res in pix/m */
+ int32_t biClrUsed;
+ int32_t biClrImportant;
+}__attribute__((packed)) bmp_bitmap_info_t;
+
+/*
+ * BMP image file format:
+ * +----------------+------------------+--------------------+---------------+
+ * | File Head(14B) | Bitmap Info(40B) | color palette(OPT) | bitmap data |
+ * +----------------+------------------+--------------------+---------------+
+ */
+int show_bmp(fb_ctx_t *fb_ctx, char *bmp_file)
+{
+ struct fb_var_screeninfo *vinfo;
+ char *fb_addr;
+ bmp_file_head_t *file_head;
+ bmp_bitmap_info_t *bitmap_info;
+ struct stat statbuf;
+ char *f_addr;
+ char *d_addr;
+ char *p_addr;
+ int fd;
+ int bpp_bytes;
+ int i, j;
+ int width, height;
+
+ if( !fb_ctx || !bmp_file )
+ {
+ printf("ERROR: Invalid input arguments\n");
+ return -1;
+ }
+
+ if( (fd=open(bmp_file, O_RDONLY)) < 0 )
+ {
+ printf("ERROR: Open file '%s' failure: %s\n", bmp_file, strerror(errno));
+ return -2;
+ }
+
+ fstat(fd, &statbuf);
+ f_addr =(char *)mmap(0, statbuf.st_size, PROT_READ, MAP_SHARED, fd ,0);
+ if ( !f_addr )
+ {
+ printf ("ERROR: BMP file mmap() failure: %s\n", strerror(errno));
+ return -2;
+ }
+
+ /* BMP file header */
+ file_head = (bmp_file_head_t *)f_addr;
+ if( memcmp(file_head->bfType, "BM", 2) != 0)
+ {
+ printf("ERROR: It's not a BMP file\n");
+ return -3;
+ }
+
+ /* BMP bitmap information header */
+ bitmap_info = (bmp_bitmap_info_t *)(f_addr+sizeof(bmp_file_head_t));
+
+ /* BMP bitmap data */
+ d_addr = f_addr + file_head->bfoffBits;
+
+ vinfo = &fb_ctx->vinfo;
+ fb_addr = fb_ctx->fbp;
+ bpp_bytes = vinfo->bits_per_pixel / 8;
+
+ width = bitmap_info->biWidth>vinfo->xres ? vinfo->xres : bitmap_info->biWidth;
+ height = bitmap_info->biHeight>vinfo->yres ? vinfo->yres : bitmap_info->biHeight;
+
+ printf("BMP file '%s': %dx%d and display %dx%d\n", bmp_file, bitmap_info->biWidth, bitmap_info->biHeight, width, height);
+
+ /* if biHeight is positive, the bitmap is a bottom-up DIB */
+ for(i=0; i<height; i++)
+ {
+ p_addr=d_addr+(height-1-i)*bitmap_info->biWidth*bpp_bytes;
+ memcpy(fb_addr, p_addr, bpp_bytes*width);
+ fb_addr += bpp_bytes * vinfo->xres;
+ }
+
+ munmap(f_addr, statbuf.st_size);
+ close (fd);
+
+ return 0;
+}
+
diff --git a/bsp/uapi/test/test_fb.c b/bsp/uapi/test/test_fb.c
deleted file mode 100644
index 2010d23..0000000
--- a/bsp/uapi/test/test_fb.c
+++ /dev/null
@@ -1,154 +0,0 @@
-
-/*********************************************************************************
- * Copyright: (C) 2021 Guo Wenxue<Email:guowenxue@gmail.com QQ:281143292>
- * All rights reserved.
- *
- * Filename: test_key.c
- * Description: This file used to test GPIO button driver builtin Linux kernel on ARM board
- *
- * Version: 1.0.0(11/17/2021~)
- * Author: Guo Wenxue <guowenxue@gmail.com>
- * ChangeLog: 1, Release initial version on "11/17/2021 02:46:18 PM"
- *
- * Linux Clear LCD screen command :
- *
- * dd if=/dev/zero of=/dev/fb0 bs=320 count=720 [ 240*(24bpp/8)=720 ]
- *
- ********************************************************************************/
-
-#include <unistd.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <linux/fb.h>
-#include <sys/mman.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/ioctl.h>
-
-
-#define CONFIG_RGB565
-
-#ifdef CONFIG_RGB565 /* RRRR RGGG GGGB BBBB */
-#define RED 0xF800
-#define GREEN 0x07E0
-#define BLUE 0x001F
-#define YELLOW 0xFFE0
-#define WHITE 0xFFFF
-#endif
-
-
-void fill_color16(short *fb_addr, short bit_map, int psize)
-{
- int i;
- for(i=0; i<psize; i++) {
- *fb_addr = bit_map;
- fb_addr++;
- }
-}
-
-int main ()
-{
- int fp=0;
- struct fb_var_screeninfo vinfo;
- struct fb_fix_screeninfo finfo;
- long screensize=0;
- char *fbp = NULL, *test_fbp=NULL;
- int x = 0, y = 0;
- long location = 0;
- int i;
- int num = 5;
- int pix_size=0;
-
- fp = open("/dev/fb0", O_RDWR);
-
- if(fp < 0) {
- printf("Error : Can not open framebuffer device/n");
- exit(1);
- }
-
- if(ioctl(fp, FBIOGET_FSCREENINFO, &finfo)){
- printf("Error reading fixed information/n");
- exit(2);
- }
-
- if(ioctl(fp, FBIOGET_VSCREENINFO, &vinfo)){
- printf("Error reading variable information/n");
- exit(3);
- }
-
- screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
-
- printf("The phy mem = 0x%x, total size = %d(byte)\n", finfo.smem_start, finfo.smem_len);
- printf("xres = %d, yres = %d, bits_per_pixel = %d\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel);
- printf("So the screensize = %d(byte), using %d frame\n", screensize, finfo.smem_len/screensize);
- printf("vinfo.xoffset = %d, vinfo.yoffset = %d\n", vinfo.xoffset, vinfo.yoffset);
- printf("vinfo.vmode is :%d\n", vinfo.vmode);
- printf("finfo.ypanstep is :%d\n", finfo.ypanstep);
- printf("vinfo.red.offset=0x%x\n", vinfo.red.offset);
- printf("vinfo.red.length=0x%x\n", vinfo.red.length);
- printf("vinfo.green.offset=0x%x\n", vinfo.green.offset);
- printf("vinfo.green.length=0x%x\n", vinfo.green.length);
- printf("vinfo.blue.offset=0x%x\n", vinfo.blue.offset);
- printf("vinfo.blue.length=0x%x\n", vinfo.blue.length);
- printf("vinfo.transp.offset=0x%x\n", vinfo.transp.offset);
- printf("vinfo.transp.length=0x%x\n", vinfo.transp.length);
-
-
- fbp =(char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fp,0);
- if ((int)fbp == -1)
- {
- printf ("Error: failed to map framebuffer device to memory./n");
- exit (4);
- }
- printf("Get virt mem = %p\n", fbp);
-
-
- pix_size = vinfo.xres * vinfo.yres;
- /* using first frame, for FBIOPAN_DISPLAY
- * 当刷新需要调用FBIOPAN_DISPLAY, 要告知驱动刷哪块帧, 用到下面两个参数
- * 如果使用第二帧buffer -> vinfo.xoffset = 0; vinfo.yoffset = vinfo.yres;
- */
- vinfo.xoffset = 0;
- vinfo.yoffset = 0;
-
- /* show color loop */
- while(num--) {
- printf("\ndrawing red ...\n");
- fill_color16((short *)fbp, RED, pix_size);
- //ioctl(fp, FBIOPAN_DISPLAY, &vinfo);
- sleep(3);
-
- printf("\ndrawing green ...\n");
- fill_color16((short *)fbp, GREEN, pix_size);
- //ioctl(fp, FBIOPAN_DISPLAY, &vinfo);
- sleep(3);
-
- printf("\ndrawing blue ...\n");
- fill_color16((short *)fbp, BLUE, pix_size);
- //ioctl(fp, FBIOPAN_DISPLAY, &vinfo);
- sleep(3);
-
- printf("\ndrawing yellow ...\n");
- fill_color16((short *)fbp, YELLOW, pix_size);
- //ioctl(fp, FBIOPAN_DISPLAY, &vinfo);
- sleep(3);
-
- }
-#if 1
- /*这是你想画的点的位置坐标,(0,0)点在屏幕左上角*/
- x = 10;
- y = 10;
- location = x * (vinfo.bits_per_pixel / 8) + y * finfo.line_length;
- test_fbp = fbp + location;
- printf("draw line.......\n");
- for(i = 0; i < (vinfo.xres - x); i++)
- *test_fbp++ = i+30;
-
- //ioctl(fp, FBIOPAN_DISPLAY, &vinfo);
-#endif
-
- munmap(fbp, screensize); /*解除映射*/
-
- close (fp);
- return 0;
-}
--
Gitblit v1.9.1