/******************************************************************************** * Copyright: (C) 2023 LingYun IoT System Studio * 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/19/23) * Author: Guo Wenxue * ChangeLog: 1, Release initial version on "08/19/23 12:56:31" * ********************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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<red.length-1) << vinfo->red.offset; fb_addr = fb_ctx->fbp; for(i=0; ipix_size; i++) { memcpy(fb_addr, &color, bpp_bytes); fb_addr += bpp_bytes; } sleep(interval); printf("show full screen on green\n"); color = (1<green.length-1) << vinfo->green.offset; fb_addr = fb_ctx->fbp; for(i=0; ipix_size; i++) { memcpy(fb_addr, &color, bpp_bytes); fb_addr += bpp_bytes; } sleep(interval); printf("show full screen on blue\n"); color = (1<blue.length-1) << vinfo->blue.offset; fb_addr = fb_ctx->fbp; for(i=0; ipix_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; ibfType, "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; ibiWidth*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; }