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