In this example, the screen writing function is implemented, that is, the screen is cleared (black). The procedure is roughly as follows: open a framebuffer device; the physical memory space of the video card is mapped to the user space through the MMAP call. The memory is written directly through the ing relationship.
Header file
////////////////////////////////////////
//// // Fbtools. h ////////////////
////////////////////////////////////////
# Ifndef _ fbtools_h _
# DEFINE _ fbtools_h _
# Include <Linux/FB. h>
// A framebuffer device structure;
Typedef struct fbdev
{
Int FB;
Unsigned long fb_mem_offset;
Unsigned long fb_mem;
Struct fb_fix_screeninfo fb_fix;
Struct fb_var_screeninfo fb_var;
Char Dev [20];
} Fbdev, * pfbdev;
// Open & init A Frame Buffer
// To use this function,
// You must set fbdev. Dev = "/dev/fb0"
// Or "/dev/fbx"
// It's your frame buffer.
Int fb_open (pfbdev );
// Close a frame buffer
Int fb_close (pfbdev );
// Get display depth
Int get_display_depth (pfbdev );
// Full screen clear
Void fb_memset (void * ADDR, int C, size_t Len );
# Endif
Test file, in which the comments of deep colors are the results measured on my machine
//////////////////////////////////////// ///
/// // Fbtools. C ///////////////
//////////////////////////////////////// ///
# Include <stdio. h>
# Include <stdlib. h>
# Include <fcntl. h>
# Include <unistd. h>
# Include <string. h>
# Include <sys/IOCTL. h>
# Include <sys/Mman. h>
# Include <ASM/page. h>
# Include "fbtools. H"
# Define true 1
# Define false 0
# Define max (x, y) (x)> (y )? (X) :( y ))
# Define min (x, y) (x) <(y )? (X) :( y ))
// Open & init A Frame Buffer
Int fb_open (pfbdev)
{
Pfbdev-> Fb = open (pfbdev-> Dev, o_rdwr); // pfbdev-> Fb = 3
If (pfbdev-> FB <0)
{
Printf ("error opening % s: % m. Check kernel config
", Pfbdev-> Dev );
Return false;
}
If (-1 = IOCTL (pfbdev-> FB, fbioget_vscreeninfo, & (pfbdev-> fb_var )))
{
Printf ("IOCTL fbioget_vscreeninfo
");
Return false;
}
If (-1 = IOCTL (pfbdev-> FB, fbioget_fscreeninfo, & (pfbdev-> fb_fix )))
{
Printf ("IOCTL fbioget_fscreeninfo
");
Return false;
}
// Map physics address to virtual address
// Pfbdev-> fb_fix.smem_start = f0000000
Pfbdev-> fb_mem_offset = (unsigned long) (pfbdev-> fb_fix.smem_start )&(~ Page_mask );
// Pfbdev-> fb_fix.smem_len = 100 0000 pfbdev-> fb_mem_offset = 0
// Pfbdev-> fb_mem = 0
Pfbdev-> fb_mem = (unsigned long INT) MMAP (null, pfbdev-> fb_fix.smem_len +
Pfbdev-> fb_mem_offset,
Prot_read | prot_write, map_shared, pfbdev-> FB, 0 );
If (-1l = (long) pfbdev-> fb_mem)
{
Printf ("MMAP error! Mem: % d offset: % d
", Pfbdev-> fb_mem,
Pfbdev-> fb_mem_offset );
Return false;
}
Return true;
}
// Close Frame Buffer
Int fb_close (pfbdev)
{
Close (pfbdev-> FB );
Pfbdev-> Fb =-1;
}
// Get display depth
Int get_display_depth (pfbdev );
{
If (pfbdev-> FB <= 0)
{
Printf ("FB device not open, open it first
");
Return false;
}
Return pfbdev-> fb_var.bits_per_pixel;
}
// Full screen clear
Void fb_memset (void * ADDR, int C, size_t Len)
{
Memset (ADDR, C, Len );
}
// Use by test
# Define debug
# Ifdef debug
Main ()
{
Fbdev;
Memset (& fbdev, 0, sizeof (fbdev ));
Strcpy (fbdev. Dev, "/dev/fb0 ");
If (fb_open (& fbdev) = false)
{
Printf ("open frame buffer Error
");
Return;
}
// Note that there is a bug in the following line
Fb_memset (fbdev. fb_mem + fbdev. fb_mem_offset, 0, fbdev. fb_fix.smem_len );
Fb_close (& fbdev );
}
# Endif
Note: If the above Code is directly compiled, it will fail, and a compilation error similar to the following will occur.
# Gcc-O fbtools. c
Fbtools. C: In function 'main'
Fbtools. C: 89: Warning: Passing Arg 1 of 'fb _ memset' makes pointer from integer without a cast
Perform the following operations on the 89th lines of code in the problematic fbtools. C (that is, the bold line with comments) and modify it:
Fb_memset (void *) (fbdev. fb_mem + fbdev. fb_mem_offset), 0, fbdev. fb_fix.smem_len );
Or
Unsigned long temp;
Temp = fbdev. fb_mem + fbdev. fb_mem_offset;
Fb_memset (void *) temp, 0, fbdev. fb_fix.smem_len );
Compilation successful
Problem: The fb0 device cannot be found in the/dev directory.
Solution: for Redhat Linux machines, modify the/boot/GRUB/menu. LST file and add VGA = 0x0317
Then:
# Mknod/dev/fb0 C 29 0
# Mknod/dev/Fb1 C 29 1