03.从app分析lcd_drv.c驱动程序

本文详细解析了Linux系统中帧缓冲设备的打开过程和ioctl操作。通过fb_open函数打开/dev/fb0,获取设备信息。接着,利用ioctl获取屏幕的可变参数和固定信息,如分辨率、像素深度等。最后,通过mmap映射显存,以便应用程序直接访问。整个流程涉及内核fbmem.c和lcd_drv.c中的驱动程序交互。
摘要由CSDN通过智能技术生成

1、open过程分析

 

fb_test.c
main.c
    //默认打开/dev/fb0
	fb_open(req_fb, &fb_info/*打开的信息保存在这里*/);
	    //传入的是0,所以打开的是/dev/fb0
		sprintf(str, "/dev/fb%d", fb_num);
		//根据主设备号29找到驱动程序,根据次设备号0,这个驱动程序的哪一个设备
		fd = open(str, O_RDWR);//主设备号: 29, 次设备号: 0
--------------------------------------------------------------
kernel:
/********************fbmem.c*********************************/
	.open =		fb_open,
	/*根据/dev/fb0得到这个设备节点的次设备号*/
	int fbidx = iminor(inode);//fbidx=0
	//跟硬件相关的结构体
	struct fb_info *info;
	//根据这个设备节点的次设备号fbidx获得一个struct fb_info结构体
	info = get_fb_info(fbidx);
		//次设备号为:fbidx = 0
		//取出registered_fb“以次设备号为0”的一项:registered_fb[0]
		fb_info = registered_fb[idx];
	//如果这个info = register_fd[0]的fbops有fb_open函数时就调用fb_open
	if (info->fbops->fb_open)
		res = info->fbops->fb_open(info,1);
--------------------------------------------------------------
/*********************lcd_drv.c*****************************/
fb_info分析注册过程
//1.3 注册fb_info结构体,向fbmem.c注册fb_info结构体
register_framebuffer(myfb_info);
	//调用fbmem.c的do_register_framebuffer
	ret = do_register_framebuffer(fb_info);
	//这里+1
	num_registered_fb++;
	for (i = 0 ; i < FB_MAX; i++)
	    //如果第i项没有设置就跳出来,这样就找出一个空项,后边就这是这一个
		if (!registered_fb[i])
			break;
	fb_info->node = i;//此时i = 0
	//执行到这里的时候,代表有真正的硬件设备了,
    //于是在类下创建设备,使用mdev或者udev自动创建设备节点
	fb_info->dev = device_create(fb_class, fb_info->device, MKDEV(FB_MAJOR, i), NULL, "fb%d", i);
	//根据上边找到的空项,将传进来的fb_info结构体,就是lcd—drv.c static struct fb_info *myfb_info;
	//registered_fb[0] = lcd—drv.c 的[struct fb_info *myfb_info;]
	registered_fb[i] = fb_info;

2、ioctl分析

fb_test.c
main.c
    //默认打开/dev/fb0
	fb_open(req_fb, &fb_info/*打开的信息保存在这里*/);
	    //传入的是0,所以打开的是/dev/fb0
		sprintf(str, "/dev/fb%d", fb_num);
		//根据主设备号29找到驱动程序,根据次设备号0,这个驱动程序的哪一个设备
		fd = open(str, O_RDWR);//主设备号: 29, 次设备号: 0
		//通过ioctl获得可变参数和固定参数
		IOCTL1(fd, FBIOGET_VSCREENINFO, &fb_info->var);
		IOCTL1(fd, FBIOGET_FSCREENINFO, &fb_info->fix);
---------------------------kernel:start-----------------------------------
kernel:
/********************fbmem.c*********************************/
static long fb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
	//根据文件句柄获得fb_info
	struct fb_info *info = file_fb_info(file);
	return do_fb_ioctl(info, cmd, arg);
	case FBIOGET_VSCREENINFO://可变的屏幕参数
		if (!lock_fb_info(info))
			return -ENODEV;
		var = info->var;//保存可变信息
		unlock_fb_info(info);
        //将var复制到用户空间
		ret = copy_to_user(argp, &var, sizeof(var)) ? -EFAULT : 0;
		break;
	case FBIOGET_FSCREENINFO://固定的屏幕信息
		if (!lock_fb_info(info))
			return -ENODEV;
		fix = info->fix;//保存固定信息
		unlock_fb_info(info);
		//将fix复制到用户空间
		ret = copy_to_user(argp, &fix, sizeof(fix)) ? -EFAULT : 0;
		break;
------------------------------kernel:end--------------------------------
//通过ioctl就可以获取驱动程序设置fb_info结构体
	printf("fb res %dx%d virtual %dx%d, line_len %d, bpp %d\n",
			fb_info->var.xres, fb_info->var.yres,
			fb_info->var.xres_virtual, fb_info->var.yres_virtual,
			fb_info->fix.line_length, fb_info->var.bits_per_pixel);
			
//映射显存,应用程序读写显存要是到它的地址,最终导致驱动程序的mmp被调用
	void *ptr = mmap(0,
			fb_info->var.yres_virtual * fb_info->fix.line_length,
			PROT_WRITE | PROT_READ,
			MAP_SHARED, fd, 0);

---------------------------kernel:start-----------------------------------
fb_mem.c :mmpd导致fb_mmap调用
int fb_mmap(struct file *file, struct vm_area_struct * vma)
	//设置固定参数的时候start和len全部都设置了
	start = info->fix.smem_start;
	len = info->fix.smem_len;
	//将显存的物理起始地址和长度映射给应用程序,如何映射的不需要关系
	return vm_iomap_memory(vma, start, len);
------------------------------kernel:end--------------------------------
    //这里是应用程序自己的显存地址,后边就可以用这个显存的虚拟地址进行绘制
	fb_info->ptr = ptr;

#include <rtthread.h> #include <rtdevice.h> #include "ft6236.h" #include "touch.h" #include "drv_common.h" #include <rttlogo.h> #include "drv_spi_ili9488.h" #define DBG_TAG "ft6236_example" #define DBG_LVL DBG_LOG #include <rtdbg.h> rt_thread_t ft6236_thread; rt_device_t touch; void ft6236_thread_entry(void *parameter) { struct rt_touch_data *read_data; rt_uint16_t touch_x,touch_y; rt_uint8_t i; read_data = (struct rt_touch_data *)rt_calloc(1, sizeof(struct rt_touch_data)); while(1) { rt_device_read(touch, 0, read_data, 1); if (read_data->event == RT_TOUCH_EVENT_DOWN) { rt_kprintf("down x: %03d y: %03d", read_data->x_coordinate, read_data->y_coordinate); rt_kprintf(" t: %d\n", read_data->timestamp); for(i=0;i<13;i++)//计算落子的x坐标 { if(abs((read_data->y_coordinate)-(16+24*i))<12) { touch_x=16+24*i; break; } } for(i=0;i<13;i++)//计算落子的y坐标 { if(abs((320-(read_data->x_coordinate))-(16+24*i))<12) { touch_y=16+24*i; break; } } //落子 lcd_show_image(touch_x-12, touch_y-12, 24, 24, acwhite); } if (read_data->event == RT_TOUCH_EVENT_MOVE) { rt_kprintf("move x: %03d y: %03d", read_data->x_coordinate, read_data->y_coordinate); rt_kprintf(" t: %d\n", read_data->timestamp); } if (read_data->event == RT_TOUCH_EVENT_UP) { rt_kprintf("up x: %03d y: %03d", read_data->x_coordinate, read_data->y_coordinate); rt_kprintf(" t: %d\n\n", read_data->timestamp); } rt_thread_delay(10); } } #define REST_PIN GET_PIN(D, 3) int ft6236_example(void) { struct rt_touch_config cfg; cfg.dev_name = "i2c2"; rt_hw_ft6236_init("touch", &cfg, REST_PIN); touch = rt_device_find("touch"); rt_device_open(touch, RT_DEVICE_FLAG_RDONLY); struct rt_touch_info info; rt_device_control(touch, RT_TOUCH_CTRL_GET_INFO, &info); LOG_I("type :%d", info.type); LOG_I("vendor :%d", info.vendor); LOG_I("point_num :%d", info.point_num); LOG_I("range_x :%d", info.range_x); LOG_I("range_y :%d", info.range_y); ft6236_thread = rt_thread_create("touch", ft6236_thread_entry, RT_NULL, 800, 10, 20); if (ft6236_thread == RT_NULL) { LOG_D("create ft6236 thread err"); return -RT_ENOMEM; } rt_thread_startup(ft6236_thread); return RT_EOK; } INIT_APP_EXPORT(ft6236_example);
06-01
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值