项目框架
一、显示设备
disp_manager.c
存在着一个链表。链表中存放在底层设备节点的指针,通过这个链表中的指针来控制底层的 设备,里面有很多控制设备节点的函数
frambuffer.c
就是负责创建出底层的设备
mange.h
都是一些dis.c的预定义函数之类的
1-1 数据结构抽象
定义一个显示设备的结构体,程序直接创建出一个结构体就可以代表一个显示设备。通过调用设备结构体中的各种函数实现显示功能
disp_manager.h
#ifndef _DISP_MANAGER_H //防止头文件重复包含,只要右边的出现过,就不会再往下编译
#define _DISP_MANAGER_H
//区域结构体
typedef struct Region {
int iLeftUpX; //区域左上方的坐标
int iLeftUpY; //区域左下方的坐标
int iWidth; //区域宽度
int iHeigh; //区域高度
}Region, *PRegion;
//显示设备结构体(LCD设备或者是web设备),通过调用这个结构体中的函数来实现显示功能
typedef struct DispOpr {
char *name; //设备名
char *GetBuffer(int *pXres, int *pYres, int *pBpp);///用于获取lcd所需的内存空间,return内存空间的首地址
//argument1-lcd屏长度,argument2-lcd屏宽度,argument3-每一个像素点的位数。
int FlushRegion(PRegion ptRegion, char *buffer);//刷新出argum1-按钮区域,argum2-区域数据
struct DispOpr *ptNext;//结构体指针,指向下一个设备机构体
};
#endif
1-2 Framebuffer编程
创建出一个 Framebuffer设备实体,完善里面的各种函数
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <linux/fb.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include "disp_manager.h"
static int fd_fb; //设备节点的文件权柄
static struct fb_var_screeninfo var; /* Current var */
static int screen_size;
static unsigned char *fb_base;//LCD的framebuffer地址
static unsigned int line_width;
static unsigned int pixel_width;
static int DeviceInit(void) //设备初始化函数
{
fd_fb = open("/dev/fb0", O_RDWR);//打开设备节点
if (fd_fb < 0)
{
printf("can't open /dev/fb0\n");
return -1;
}
if (ioctl(fd_fb, FBIOGET_VSCREENINFO, &var))
{
printf("can't get var\n");
return -1;
}
//var.xres x方向的分辨率
line_width = var.xres * var.bits_per_pixel / 8;
pixel_width = var.bits_per_pixel / 8;
screen_size = var.xres * var.yres * var.bits_per_pixel / 8;
fb_base = (unsigned char *)mmap(NULL , screen_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0);//内存映射
if (fb_base == (unsigned char *)-1)
{
printf("can't mmap\n");
return -1;
}
return 0;
}
static int DeviceExit(void) //设备退出函数,释放设备资源
{
munmap(fb_base, screen_size);//取消内存映射
close(fd_fb);
return 0;
}
/* 可以返回LCD的framebuffer, 以后上层APP可以直接操作LCD, 可以不用FbFlushRegion
* 也可以malloc返回一块无关的buffer, 要使用FbFlushRegion
*/
static char *GetBuffer(int *pXres, int *pYres, int *pBpp)//获取内存空间
{
*pXres = var.xres;
*pYres = var.yres;
*pBpp = var.bits_per_pixel;
return fb_base;
}
static int FbFlushRegion(PRegion ptRegion, char *buffer) //刷新函数
{
return 0;
}
static DispOpr g_tFramebuf ferOpr = { // 构建framebuffer设备结构体
.name = "fb", //设备的名字是fb
.DeviceInit = FbDeviceInit, //
.DeviceExit = FbDeviceExit, //
.GetBuffer = FbGetBuffer, //获得buf空间中的数据
.FlushRegion = FbFlushRegion, //刷新
};
输入系统
input_manager.h
在头文件中构建触摸屏和网络线程的数据结构体和设备结构体和结构体中的一些函数的声明
#ifndef _INPUT_MANAGER_H
#define _INPUT_MANAGER_H
#include <sys/time.h>
#ifndef NULL
#define NULL (void *)0
#endif
#define INPUT_TYPE_TOUCH 1
#define INPUT_TYPE_NET 2
//输出数据结构体
typedef struct InputEvent {
struct timeval tTime;
int iType;
int iX;
int iY;
int iPressure;
char str[1024];
}InputEvent, *PInputEvent;
typedef struct InputDevice {
char *name;
int (*GetInputEvent)(PInputEvent ptInputEvent);
int (*DeviceInit)(void);
int (*DeviceExit)(void);
struct InputDevice *ptNext;
}InputDevice, *PInputDevice;
void RegisterInputDevice(PInputDevice ptInputDev);
void InputInit(void);
void IntpuDeviceInit(void);
int GetInputEvent(PInputEvent ptInputEvent);
#endif
touchscreen.c
构建触摸屏线程对应的设备结构体和对应的成员函数
#include <input_manager.h>
#include <tslib.h>
#include <stdio.h>
static struct tsdev *g_ts;
static int TouchscreenGetInputEvent(PInputEvent ptInputEvent)
{
struct ts_sample samp;
int ret;
ret = ts_read(g_ts, &samp, 1);
if (ret != 1)
return -1;
ptInputEvent->iType = INPUT_TYPE_TOUCH;
ptInputEvent->iX = samp.x;
ptInputEvent->iY = samp.y;
ptInputEvent->iPressure = samp.pressure;
ptInputEvent->tTime = samp.tv;
return 0;
}
static int TouchscreenDeviceInit(void)
{
g_ts = ts_setup(NULL, 0);
if (!g_ts)
{
printf("ts_setup err\n");
return -1;
}
return 0;
}
static int TouchscreenDeviceExit(void)
{
ts_close(g_ts);
return 0;
}
//网络输入线程结构体
static InputDevice g_tTouchscreenDev ={
.name = "touchscreen",
.GetInputEvent = TouchscreenGetInputEvent,//接口函数,上层通过调用此函数获得数据,也就是将触摸数据传到输出设备结构体中
.DeviceInit = TouchscreenDeviceInit, //设备初始化函数
.DeviceExit = TouchscreenDeviceExit, //退出函数
};
void TouchscreenRegister(void)//上层应用调用这个函数将设备注册到链表中去管理
{
RegisterInputDevice(&g_tTouchscreenDev);
}
netinput.c
构建网络输入线程对应的设备结构体,并实现对应成员函数
Server端:socket----bind ----recvfrom/sendto----close
#include <input_manager.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
/* socket
* bind
* sendto/recvfrom
*/
#define SERVER_PORT 8888
static int g_iSocketServer;
static int NetinputGetInputEvent(PInputEvent ptInputEvent)
{
struct sockaddr_in tSocketClientAddr;
int iRecvLen;
char aRecvBuf[1000];
unsigned int iAddrLen = sizeof(struct sockaddr);
iRecvLen = recvfrom(g_iSocketServer, aRecvBuf, 999, 0, (struct sockaddr *)&tSocketClientAddr, &iAddrLen);
if (iRecvLen > 0)
{
aRecvBuf[iRecvLen] = '\0';
//printf("Get Msg From %s : %s\n", inet_ntoa(tSocketClientAddr.sin_addr), ucRecvBuf);
ptInputEvent->iType = INPUT_TYPE_NET;
gettimeofday(&ptInputEvent->tTime, NULL);
strncpy(ptInputEvent->str, aRecvBuf, 1000);
ptInputEvent->str[999] = '\0';
return 0;
}
else
return -1;
}
static int NetinputDeviceInit(void)
{
struct sockaddr_in tSocketServerAddr;
int iRet;
g_iSocketServer = socket(AF_INET, SOCK_DGRAM, 0);
if (-1 == g_iSocketServer)
{
printf("socket error!\n");
return -1;
}
tSocketServerAddr.sin_family = AF_INET;
tSocketServerAddr.sin_port = htons(SERVER_PORT); /* host to net, short */
tSocketServerAddr.sin_addr.s_addr = INADDR_ANY;
memset(tSocketServerAddr.sin_zero, 0, 8);
iRet = bind(g_iSocketServer, (const struct sockaddr *)&tSocketServerAddr, sizeof(struct sockaddr));
if (-1 == iRet)
{
printf("bind error!\n");
return -1;
}
return 0;
}
static int NetinputDeviceExit(void)
{
close(g_iSocketServer);
return 0;
}
static InputDevice g_tNetinputDev ={
.name = "touchscreen",
.GetInputEvent = NetinputGetInputEvent,//接口函数,上层通过调用此函数获得数据,也就是将触摸数据传到输出设备结构体中
.DeviceInit = NetinputDeviceInit, //设备初始化函数
.DeviceExit = NetinputDeviceExit, //退出函数
};
void NetInputRegister(void)
{
RegisterInputDevice(&g_tNetinputDev);
}
input_manager.c
1、将设备注册到链表中去,初始化函数
2、从链表中依次取出设备结构体,并为其创建线程,设备初始化函数
3、事件获取函数