ucgui的可移植性很高,只需要做很少的改动就可以移植到各个平台,移植到Linux下也一样。
首先编辑GUIConf.h这个文件:
#ifndef GUICONF_H
#define GUICONF_H
#define GUI_OS (1) /* Compile with multitasking support */
#define GUI_SUPPORT_TOUCH (0) /* Support a touch screen (req. win-manager), for linux */
#define GUI_SUPPORT_UNICODE (1) /* Support mixed ASCII/UNICODE strings, for linux */
#define GUI_DEFAULT_FONT &GUI_Font6x8
#define GUI_ALLOC_SIZE 25*1024 /* Size of dynamic memory */
#define GUI_SUPPORT_CURSOR (1) /* for linux*/
#define GUI_WINSUPPORT 1 /* Window manager package available */
#define GUI_SUPPORT_MEMDEV 1 /* Memory devices available */
#define GUI_SUPPORT_AA 1 /* Anti aliasing available */
#endif /* Avoid multiple inclusion */
接着修改LCDConf.h文件,因为我们直接使用framebuffer设备,所以只需要修改LCDConf.h文件的前面部分即可:
#define LCD_XSIZE (720) /* X-resolution of LCD, Logical coor. for linux */
#define LCD_YSIZE (576) /* Y-resolution of LCD, Logical coor. for linux */
#define LCD_BITSPERPIXEL (16) /* for linux */
#define LCD_SWAP_RB (1) /* for linux, actually 1555 format */
#define LCD_FIXEDPALETTE (555) /* for linux, actually 1555 format */
#define LCD_CONTROLLER (-1) /* for linux */
接下来修改LCDDummy.c,添加对framebuffer的支持:
/* for linux framebuffer */
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
static struct fb_var_screeninfo vinfo;
static struct fb_fix_screeninfo finfo;
static char *pFrameBuffer = NULL;
........................................................
void LCD_L0_SetPixelIndex(int x, int y, int PixelIndex)
{
/* Convert logical into physical coordinates (Dep. on LCDConf.h) */
#if LCD_SWAP_XY | LCD_MIRROR_X| LCD_MIRROR_Y
int xPhys = LOG2PHYS_X(x, y);
int yPhys = LOG2PHYS_Y(x, y);
#else
#define xPhys x
#define yPhys y
#endif
int location = 0;
location = (x + vinfo.xoffset) * (vinfo.bits_per_pixel >> 3) + (y+vinfo.yoffset) * finfo.line_length;
*(short*)(pFrameBuffer + location) = (short)PixelIndex; /* 16bpp */
return;
}
unsigned int LCD_L0_GetPixelIndex(int x, int y)
{
LCD_PIXELINDEX PixelIndex;
/* Convert logical into physical coordinates (Dep. on LCDConf.h) */
#if LCD_SWAP_XY | LCD_MIRROR_X| LCD_MIRROR_Y
int xPhys = LOG2PHYS_X(x, y);
int yPhys = LOG2PHYS_Y(x, y);
#else
#define xPhys x
#define yPhys y
#endif
/* Read from hardware ... Adapt to your system */
{
int location = 0;
location = (x + vinfo.xoffset) * (vinfo.bits_per_pixel >> 3) + (y+vinfo.yoffset) * finfo.line_length;
PixelIndex = *(short*)(pFrameBuffer + location); /* 16bpp */
}
return PixelIndex;
}
....................................................
int LCD_L0_Init(void)
{
int f_fbDev;
int ScreenSize;
static struct fb_bitfield g_r16 = {10, 5, 0};
static struct fb_bitfield g_g16 = {5, 5, 0};
static struct fb_bitfield g_b16 = {0, 5, 0};
static struct fb_bitfield g_a16 = {15, 1, 0};
f_fbDev = open("/dev/fb0", O_RDWR);
if (f_fbDev <= 0)
{
printf("Error: cannot open framebuffer device.\n");
return (-1);
}
if (ioctl(f_fbDev, FBIOGET_VSCREENINFO, &vinfo) < 0)
{
printf("Error reading variable information.\n");
close(f_fbDev);
return (-1);
}
vinfo.xres = vinfo.xres_virtual = 720;
vinfo.yres = 576;
vinfo.yres_virtual = 576*2;
vinfo.transp= g_a16;
vinfo.red = g_r16;
vinfo.green = g_g16;
vinfo.blue = g_b16;
vinfo.bits_per_pixel = 16;
if (ioctl(f_fbDev, FBIOPUT_VSCREENINFO, &vinfo) < 0)
{
printf("Put variable screen info failed!\n");
close(f_fbDev);
return -1;
}
if (ioctl(f_fbDev, FBIOGET_FSCREENINFO, &finfo))
{
printf("Error reading fixed information.\n");
return -1;
}
printf("xres is %d\n, yres is %d\n", vinfo.xres, vinfo.yres);
ScreenSize = vinfo.xres * vinfo.yres * (vinfo.bits_per_pixel >> 3);
pFrameBuffer =(char *)mmap(0, ScreenSize, PROT_READ | PROT_WRITE, MAP_SHARED,f_fbDev, 0);
if ((long)pFrameBuffer == -1)
{
printf("Error: failed to map framebuffer device to memory.\n");
close(f_fbDev);
return (-1);
}
return 0;
}
至此,LCDDummy.c修改完毕。
接下来添加鼠标支持,新建一个GUI_MOUSE_DriverLinux.c代替原来的GUI_MOUSE_DriverPS2.c,这里的思路是用一个线程来读取鼠标设备:
.................................................
void *ThreadReamMouse(void)
{
int ret;
int fd;
fd_set readfs;
int maxfd = 0;
char temp[3];
fd = open ("/dev/mouse0",O_RDWR);
if (fd < 0)
{
printf ("%s open failed\n", "/dev/mouse0");
return NULL;
}
printf("open %s success, fd is %d\n", "/dev/mouse0", fd);
maxfd = fd + 1;
for (; ;)
{
FD_ZERO(&readfs);
FD_SET(fd, &readfs);
ret = select(maxfd, &readfs, NULL, NULL, NULL);
if (ret < 0)
{
printf("select failure!\n");
return NULL;
}
if (FD_ISSET(fd, &readfs))
{
/*
* 读取鼠标
*/
_NumBytesInBuffer = read(fd, _abInBuffer, sizeof(_abInBuffer));
if ((_NumBytesInBuffer == 3) && ((_abInBuffer[0] & 0x0c) == 0x08))
{
_EvaPacket();
//printf("Get mouse data!\n");
}
}
}
}
void GUI_MOUSE_DRIVER_PS2_Init(void)
{
pthread_t pidReadMouse;
_NumBytesInBuffer = 0;
pthread_create(&pidReadMouse, NULL, (void *)ThreadReamMouse, NULL);
printf("Create thread sucess!\n");
}
GUI_MOUSE_DRIVER_PS2_Init()函数需要在哪里调用呢?不调用的话,鼠标没法用啊。增加GUI_X_Linux.c文件:
.............................................................
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
..............................................................
void GUI_X_ExecIdle(void)
{
usleep(1000);
return;
}
int GUI_X_GetTime(void)
{
struct timeval tv;
int tm;
gettimeofday(&tv, NULL);
tm = tv.tv_sec*1024 + tv.tv_usec/1024;
return tm;
}
void GUI_X_Delay(int Period)
{
while(Period--)
{
usleep(1000);
}
return;
}
void GUI_X_Unlock(void)
{
pthread_mutex_unlock(&mutex);
return;
}
void GUI_X_Lock(void)
{
pthread_mutex_lock(&mutex);
return;
}
U32 GUI_X_GetTaskId(void)
{
pthread_t id;
id = pthread_self();
printf("GUI_X_GetTaskId %d \n", (U32)id);
return ((U32)id);
}
void GUI_X_InitOS(void)
{
printf("GUI_X_InitOS\n");
GUI_MOUSE_DRIVER_PS2_Init(); /* create read mouse thread for linux */
return;
}
.....................................................
至此,该修改的文件都修改完毕了,可以开始编译了。但是ucgui的工程一般是在windows下编译的,在Linux下交叉编译需要写Makefile,按照Linux的惯例,在每个文件夹下增加Makefile,如下:
CC = arm-linux-gcc
CFLAGS=-I../Core -I../../Config/ -I../WM/
#all c files at current directory
SRCS:=$(wildcard *.c)
#replace .c to .o in SRCS
OBJS:=$(SRCS:%.c=%.o)
all:$(OBJS)
%.o : %.c
$(CC) $(CFLAGS) -c $< -o $@
.PHONY : clean
clean:
rm *.o
再增加一个编译gui库的Makefile:
SUBDIRS=AntiAlias ConvertMono Font LCDDriver MemDev Widget ConvertColor Core JPEG MultiLayer WM
LIBOBJS=
LIBOBJS+=$(wildcard AntiAlias/*.o)
LIBOBJS+=$(wildcard ConvertMono/*.o)
LIBOBJS+=$(wildcard Font/*.o)
LIBOBJS+=$(wildcard LCDDriver/*.o)
LIBOBJS+=$(wildcard MemDev/*.o)
LIBOBJS+=$(wildcard ConvertColor/*.o)
LIBOBJS+=$(wildcard Core/*.o)
LIBOBJS+=$(wildcard JPEG/*.o)
LIBOBJS+=$(wildcard MultiLayer/*.o)
LIBOBJS+=$(wildcard WM/*.o)
LIBOBJS+=$(wildcard Widget/*.o)
all:
for name in $(SUBDIRS); do (cd $$name && make && cd ../) done
make guilib
.PHONY:guilib
guilib:
arm-linux-ar rv libucgui.a $(LIBOBJS)
.PHONY:clean
clean:
@rm -f libucgui.a
@for name in $(SUBDIRS); do (cd $$name && make clean && cd ../) done