在此已完成对linux驱动的入门,写了个小程序以实践。在此感谢朱有鹏老师,学习了老师的课程才入门驱动。
博客以记录和理解为主,并不以讲解为目的,若有需要此源码,可在博客留下邮箱信息,或联系本人。
项目名称:图片播放器
项目介绍:
小项目支持显示bmp,png,JPEG图片,并通过点击触摸屏左右两端实现上下切换图片的效果。
主要技术:
- linux Framebuffer驱动
- linux input输入子系统
- linux i2c子系统
- 触摸屏驱动
- libjpeg库
- libpng库
主要模块功能:
1.驱动模块
2.目录扫描,图片管理模块
3.图片切换模块
4.图片显示模块
模块介绍与主要代码分析
驱动模块
小项目使用s5pv210开发板,linux平台开发。
在搭建开发板平台,完成对触摸屏,显示屏支持后,驱动模块主要的任务就是进行Framebuffer地址映射。
- linux Framebuffer驱动
参考此文章理解,移植framebufer驱动。 - 触摸屏(gslX680)驱动
参考此文章理解,移植gslX680驱动,内附源码下载。 - 在此显示Framebuffer映射主要代码
int fb_driver(void)
{
int fd = -1, ret = -1;
struct fb_fix_screeninfo finfo = {0};
struct fb_var_screeninfo vinfo = {0};
// 第1步:打开设备
fd = open(FBDEVICE, O_RDWR);
if (fd < 0)
{
perror("open");
return -1;
}
printf("open %s success.\n", FBDEVICE);
// 第2步:获取设备的硬件信息
ret = ioctl(fd, FBIOGET_FSCREENINFO, &finfo);
if (ret < 0)
{
perror("ioctl");
return -1;
}
printf("smem_start = 0x%x, smem_len = %u.\n", finfo.smem_start, finfo.smem_len);//打印信息
ret = ioctl(fd, FBIOGET_VSCREENINFO, &vinfo);
if (ret < 0)
{
perror("ioctl");
return -1;
}
//打印信息
printf("xres = %u, yres = %u.\n", vinfo.xres, vinfo.yres);
printf("xres_virtual = %u, yres_virtual = %u.\n", vinfo.xres_virtual, vinfo.yres_virtual);
printf("bpp = %u.\n", vinfo.bits_per_pixel);
// 第3步:进行mmap
unsigned long len = vinfo.xres_virtual * vinfo.yres_virtual * vinfo.bits_per_pixel / 8;
printf("len = %ld\n", len);
pfb = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (NULL == pfb)
{
perror("mmap");
return -1;
}
printf("pfb = %p.\n", pfb);
close(fd);
return 0;
}
目录扫描,图片管理模块
目录扫描功能采用递归方法,扫描目录的所有文件,经过排除,最后只对普通文件做进一步处理。
图片管理采用数组来组织。经判后初始化数据类型。(预计是用链表实现的,可实际情况并不理想,源码中移植了linux内核链表,已验证可使用。理解可参考博客)
//声明数组节点数据结构
typedef struct picture
{
char name[PATHNAME_MAX];
image_type_e type;
}picture;
/*
*扫描目录,索引图片,并完成图片数据的初始化
*参数:目录的路径
*/
int scan_image(const char *path)
{
// 在本函数中递归检索path文件夹
//,将其中所有图片填充到iamges数组中去
DIR *dir;
struct dirent *ptr;
char base[1000];
struct stat sta;
if ((dir = opendir(path)) == NULL)
{
perror("Open dir error...");
exit(1);
}
// readdir函数每调用一次就会返回opendir打开的basepath目录下的一个文件,直到
// basepath目录下所有文件都被读完之后,就会返回NULL
while ((ptr = readdir(dir)) != NULL)
{
if(strcmp(ptr->d_name, ".")==0 || strcmp(ptr->d_name, "..")==0) ///current dir OR parrent dir
continue;
// 用lstat来读取文件属性并判断文件类型
memset(base,'\0',sizeof(base));
strcpy(base,path);
strcat(base,"/");
strcat(base,ptr->d_name);
lstat(base, &sta);
if (S_ISREG(sta.st_mode))
{
// 如果是普通文件,就要在这里进行处理:
// 处理思路就是 先判定是否属于已知的某种图片格式,如果是则放到images数组中
// 如果都不属于则不理他