怎样通过framebuffer来传递关屏信息

    本人的项目是一个用oled来显示的android项目;需要在系统睡眠关闭主屏幕的时候,一起把oled屏幕关掉。但这是并没有进入系统睡眠。因此不能使用kernel里的suspend 与resume机制来控制oled的显示和背光。 可以使用framebuffer的功能来从用户态到kernel态来传递命令。

     在用户层,可以使用消息的机制,来获得用户关屏的动作,无论是短按电源键还是时间到关屏,都会有一个消息发布;这是上层hardware从可以获得这个消息,然后通过framebuffer来告知kernel层;本文主要说明这个用户层和kernel之间的通信机制。

一. kernel对framebuffer的注册和使用

    1. probe函数里的变量定义:

	struct fb_info *info;
	u32 vmem_size;
	struct ssd1307fb_par *par;
	u8 *vmem;

    2. 主要变量的初始化:(只有部分)

	info = framebuffer_alloc(sizeof(struct ssd1307fb_par), &client->dev);
	if (!info) {
		dev_err(&client->dev, "Couldn't allocate framebuffer.\n");
		return -ENOMEM;
	}
	vmem_size = par->width * par->height / 8;

	vmem = vmalloc(vmem_size);
	if (!vmem) {
		dev_err(&client->dev, "Couldn't allocate graphical memory.\n");
		ret = -ENOMEM;
		goto fb_alloc_error;
	}

	info->fbops = &ssd1307fb_ops;
	info->fix = ssd1307fb_fix;
	info->fix.line_length = par->width / 8;
	info->fbdefio = &ssd1307fb_defio;

	dev_info(&client->dev, "%s info->fix.line_length=%d\n",
        __func__, info->fix.line_length);

	info->var = ssd1307fb_var;
	info->var.xres = par->width;
	info->var.xres_virtual = par->width;
	info->var.yres = par->height;
	info->var.yres_virtual = par->height;

	info->var.red.length = 1;
	info->var.red.offset = 0;
	info->var.green.length = 1;
	info->var.green.offset = 0;
	info->var.blue.length = 1;
	info->var.blue.offset = 0;

	info->screen_base = (char *)vmem;
	info->fix.smem_start = (unsigned long)vmem;
	info->fix.smem_len = vmem_size;

	fb_deferred_io_init(info);
     3. 注册

	ret = register_framebuffer(info);
	if (ret) {
		dev_err(&client->dev, "Couldn't register the framebuffer\n");
		goto panel_init_error;
	}
     4. 在上面的注册中,还有一些文件节点需要定义:

static struct fb_fix_screeninfo ssd1307fb_fix = {
	.id		= "Solomon SSD1307",
	.type		= FB_TYPE_PACKED_PIXELS,
	.visual		= FB_VISUAL_MONO10,
	.xpanstep	= 0,
	.ypanstep	= 0,
	.ywrapstep	= 0,
	.accel		= FB_ACCEL_NONE,
};

static struct fb_var_screeninfo ssd1307fb_var = {
	.bits_per_pixel	= 1,
};

static struct fb_ops ssd1307fb_ops = {
	.owner		= THIS_MODULE,
	.fb_read	= fb_sys_read,
	.fb_write	= ssd1307fb_write,
	.fb_fillrect	= ssd1307fb_fillrect,
	.fb_copyarea	= ssd1307fb_copyarea,
	.fb_imageblit	= ssd1307fb_imageblit,
	.fb_blank   = ssd1305fb_blank,
};
static void ssd1307fb_deferred_io(struct fb_info *info,
				struct list_head *pagelist)
{
	ssd1305fb_update_display(info->par);
}

static struct fb_deferred_io ssd1307fb_defio = {
	.delay		= HZ,
	.deferred_io	= ssd1307fb_deferred_io,
};

    在上面的注册中, .fb_blank = ssd1305fb_blank,   就是对关屏动作的回调函数的调用。

二、 上层对framebuffer的调用

    int fbfd = 0;
    struct fb_var_screeninfo vinfo;
    struct fb_fix_screeninfo finfo;
    long int screensize = 0;
    char *fbp = 0;

    // Open the file for reading and writing
    fbfd = open("/dev/graphics/fb3", O_RDWR);
    if (fbfd < 0) {
        printf("Error: cannot open framebuffer device.\n");
        exit(1);
    }
    printf("The framebuffer device was opened successfully. fbfd=%x\n", fbfd);

    screensize = 128 * 8;

    printf("the screensize is %d\n", screensize );

    // Map the device to memory
    fbp = (char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED,
                       fbfd, 0);
    if ((int)fbp == -1) {
        printf("Error: failed to map framebuffer device to memory.\n");
        exit(4);
    }
    printf("The framebuffer device was mapped to memory successfully.\n");

    memcpy(fbp, picture5, screensize);

    munmap(fbp, screensize);

	sleep(10);

    printf("start blank OLED\n");
	ioctl(fbfd, FBIOBLANK, 0);  // enable bklight
	ioctl(fbfd, FBIOBLANK, 1);  // disable bkilght

    close(fbfd);

在上面中,ioctl(fbfd, FBIOBLANK,  0) ;   函数就是对底层函数ssd1305fb_blank()的调用。


在Linux上,您可以使用framebuffer来显示字符打印。Framebuffer是一种在内存中维护图形缓冲区的设备,它可以直接访问和控制显示器的像素。 要通过应用程序使用framebuffer显示字符打印,您可以按照以下步骤进行操作: 1. 打开framebuffer设备:使用`open()`函数打开framebuffer设备文件。通常,framebuffer设备文件的路径是`/dev/fb0`。 2. 获取framebuffer信息:使用`ioctl()`函数和`FBIOGET_VSCREENINFO`命令来获取framebuffer信息结构体。您可以使用`struct fb_var_screeninfo`类型的结构体来存储此信息。 3. 设置终端模式:如果您正在从终端登录并且需要在终端模式下显示字符打印,可以使用`ioctl()`函数和`KDSETMODE`命令将终端模式设置为`KD_GRAPHICS`。 4. 映射framebuffer内存:使用`mmap()`函数将framebuffer设备文件映射到内存中。您可以使用`struct fb_fix_screeninfo`类型的结构体来获取framebuffer内存地址和长度。 5. 编写字符打印代码:您可以使用映射的framebuffer内存地址来直接操作像素,从而实现字符打印。您可以选择使用ASCII表中的字符,并将它们绘制到适当的位置上。 6. 刷新屏幕:在完成字符打印后,使用`ioctl()`函数和`FBIO_REFRESH_RATE`命令来刷新屏幕。 7. 关闭framebuffer设备:最后,使用`close()`函数关闭framebuffer设备。 请注意,使用framebuffer直接操作像素是一种底层的方法,需要对图形编程和硬件进行一定的了解。此外,不同的嵌入式系统和显示设备可能有不同的framebuffer实现和操作方式。 以上是一个简单的概述,实际操作中可能需要更多的细节和代码。如果您想了解更多关于使用framebuffer显示字符打印的详细信息,建议查阅相关的文档或参考示例代码。 希望这些信息对您有所帮助!如有任何进一步的问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值