韦东山-电子量产工具项目:输入单元

news2024/9/21 0:27:46

所有代码都已通过测试跑通,其中代码结构如下:

 一、include文件夹

 1.1 input_manager.h

#ifndef _INPUT_MANAGER_H //防止头文件重复包含,只要右边的出现过,就不会再往下编译
#define _INPUT_MANAGER_H
#include <sys/time.h>

#define INPUT_TYPE_TOUCH 1
#define INPUT_TYPE_NET 2
/* 上报的数据格式 */
typedef struct InputEvent
{
    struct timeval tTime; //加入时间管理
 
    int iType;      //网络事件或者触摸事件类型
    int iX;         //触摸事件x坐标
    int iY;         //触摸事件y坐标
    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;



#endif

 1.2 tslib.h(注意:该文件由tslib-1.21.tar.bz2通过交叉编译得来,如何交叉编译及移植到开发板上将在文章最后介绍,也可参考韦东山老师的视频)

#ifndef _TSLIB_H_
#define _TSLIB_H_
/*
 *  tslib/src/tslib.h
 *
 *  Copyright (C) 2016 Martin Kepplinger <martink@posteo.de>
 *  Copyright (C) 2001 Russell King.
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
 *  USA
 *
 * SPDX-License-Identifier: LGPL-2.1
 *
 *
 * Touch screen library interface definitions.
 */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#include <stdarg.h>
#include <sys/time.h>

#ifdef WIN32
  #define TSIMPORT __declspec(dllimport)
  #define TSEXPORT __declspec(dllexport)
  #define TSLOCAL
#else
  #define TSIMPORT
  #ifdef GCC_HASCLASSVISIBILITY
    #define TSEXPORT __attribute__ ((visibility("default")))
    #define TSLOCAL __attribute__ ((visibility("hidden")))
  #else
    #define TSEXPORT
    #define TSLOCAL
  #endif
#endif

#ifdef TSLIB_INTERNAL
  #define TSAPI TSEXPORT
#else
  #define TSAPI TSIMPORT
#endif /* TSLIB_INTERNAL */

struct tsdev;

struct ts_sample {
	int		x;
	int		y;
	unsigned int	pressure;
	struct timeval	tv;
};

struct ts_sample_mt {
	/* ABS_MT_* event codes. linux/include/uapi/linux/input-event-codes.h
	 * has the definitions.
	 */
	int		x;
	int		y;
	unsigned int	pressure;
	int		slot;
	int		tracking_id;

	int		tool_type;
	int		tool_x;
	int		tool_y;
	unsigned int	touch_major;
	unsigned int	width_major;
	unsigned int	touch_minor;
	unsigned int	width_minor;
	int		orientation;
	int		distance;
	int		blob_id;

	struct timeval	tv;

	/* BTN_TOUCH state */
	short		pen_down;

	/* valid is set != 0 if this sample
	 * contains new data; see below for the
	 * bits that get set.
	 * valid is set to 0 otherwise
	 */
	short		valid;
};

#define TSLIB_MT_VALID			(1 << 0)	/* any new data */
#define TSLIB_MT_VALID_TOOL		(1 << 1)	/* new tool_x or tool_y data */

struct ts_lib_version_data {
	const char	*package_version;
	int		version_num;
	unsigned int	features; /* bitmask, see below */
};

#define TSLIB_VERSION_MT		(1 << 0)	/* multitouch support */
#define TSLIB_VERSION_OPEN_RESTRICTED	(1 << 1)	/* ts_open_restricted() */
#define TSLIB_VERSION_EVENTPATH		(1 << 2)	/* ts_get_eventpath() */
#define TSLIB_VERSION_VERSION		(1 << 3)	/* tslib_version() */

enum ts_param {
	TS_SCREEN_RES = 0,		/* 2 integer args, x and y */
	TS_SCREEN_ROT			/* 1 integer arg, 1 = rotate */
};

struct ts_module_conf {
	char *name;
	char *params;
	int raw;
	int nr;

	struct ts_module_conf *next;
	struct ts_module_conf *prev;
};

/*
 * Close the touchscreen device, free all resources.
 */
TSAPI int ts_close(struct tsdev *);

/*
 * Reloads all modules - useful to reload calibration data.
 */
TSAPI int ts_reconfig(struct tsdev *);

/*
 * Configure the touchscreen device.
 */
TSAPI int ts_config(struct tsdev *);

/*
 * Changes a setting.
 */
TSAPI int ts_option(struct tsdev *, enum ts_param, ...);

/*
 * Change this hook to point to your custom error handling function.
 */
extern TSAPI int (*ts_error_fn)(const char *fmt, va_list ap);

/*
 * Implement this to override open() for the input device and return the fd.
 */
extern TSAPI int (*ts_open_restricted)(const char *path, int flags, void *user_data);

/*
 * Implement this to override close().
 */
extern TSAPI void (*ts_close_restricted)(int fd, void *user_data);

/*
 * Returns the file descriptor in use for the touchscreen device.
 */
TSAPI int ts_fd(struct tsdev *);

/*
 * Load a filter/scaling module
 */
TSAPI int ts_load_module(struct tsdev *, const char *mod, const char *params);

/*
 * Open the touchscreen device.
 */
TSAPI struct tsdev *ts_open(const char *dev_name, int nonblock);

/*
 * Find, open and configure the touchscreen device.
 */
TSAPI struct tsdev *ts_setup(const char *dev_name, int nonblock);

/*
 * Return a scaled touchscreen sample.
 */
TSAPI int ts_read(struct tsdev *, struct ts_sample *, int);

/*
 * Returns a raw, unscaled sample from the touchscreen.
 */
TSAPI int ts_read_raw(struct tsdev *, struct ts_sample *, int);

/*
 * Return a scaled touchscreen multitouch sample.
 */
TSAPI int ts_read_mt(struct tsdev *, struct ts_sample_mt **, int slots, int nr);

/*
 * Return a raw, unscaled touchscreen multitouch sample.
 */
TSAPI int ts_read_raw_mt(struct tsdev *, struct ts_sample_mt **, int slots, int nr);

/*
 * This function returns a pointer to a static copy of the version info struct.
 */
TSAPI struct ts_lib_version_data *ts_libversion(void);

/*
 * Get the list of (commented-in) ts.conf module lines (as structs)
 */
TSAPI struct ts_module_conf *ts_conf_get(struct tsdev *ts);

/*
 * Write the list of modules to ts.conf
 */
TSAPI int ts_conf_set(struct ts_module_conf *conf);

/*
 * This function returns the path to the opened touchscreen input device file.
 */
TSAPI char *ts_get_eventpath(struct tsdev *tsdev);

/*
 * This simply returns tslib's version string
 */
TSAPI char *tslib_version(void);

/*
 * This prints tslib's logo to stdout, with pos preceding spaces
 */
TSAPI void ts_print_ascii_logo(unsigned int pos);

#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* _TSLIB_H_ */

二、input文件夹

2.1 input_manager.c

#include "input_manager.h"
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <semaphore.h>
#include <string.h>
static pthread_mutex_t g_tMutex  = PTHREAD_MUTEX_INITIALIZER; 
static pthread_cond_t  g_tConVar = PTHREAD_COND_INITIALIZER;
static PInputDevice g_InputDevs = NULL;


/************环形缓冲区开******************/
#define BUFFER_LEN 20         /*环形缓冲区长度*/
static int g_iRead  = 0;      /*读指针*/
static int g_iWrite = 0;       /*写指针*/
static InputEvent g_atInputEvents[BUFFER_LEN];   /*环形缓冲区*/
/*判断环形缓冲区是否为满*/
static int isInputBufferFull(void)
{
	return (g_iRead == ((g_iWrite + 1) % BUFFER_LEN));
}
/*判断环形缓冲区是否为空*/
static int isInputBufferEmpty(void)
{
	return (g_iRead == g_iWrite);
}
/************环形缓冲区关******************/

//缓冲区事件存储函数
static void PutInputEventToBuffer(PInputEvent ptInputEvent)
{
	if (!isInputBufferFull())
	{
		g_atInputEvents[g_iWrite] = *ptInputEvent;
		g_iWrite = (g_iWrite + 1) % BUFFER_LEN;
	}
}
//缓冲区事件获取函数
static int GetInputEventFromBuffer(PInputEvent ptInputEvent)
{
	if (!isInputBufferEmpty())
	{
		*ptInputEvent = g_atInputEvents[g_iRead];
		g_iRead = (g_iRead + 1) % BUFFER_LEN;
		return 1;
	}
	else
	{
		return 0;
	}
}
// 事件获取函数
int GetInputEvent(PInputEvent ptInputEvent)
{
	InputEvent tEvent;
	int ret;
	/* 无数据则休眠 */
	pthread_mutex_lock(&g_tMutex);  /*互斥锁*/
	if (GetInputEventFromBuffer(&tEvent))
	{
		*ptInputEvent = tEvent;
		pthread_mutex_unlock(&g_tMutex);/*释放互斥锁*/
		return 0;
	}
	else
	{
		/* 休眠等待 */
		pthread_cond_wait(&g_tConVar, &g_tMutex);	
		if (GetInputEventFromBuffer(&tEvent))
		{
			*ptInputEvent = tEvent;
			ret = 0;
		}
		else
		{
			ret = -1;
		}
		pthread_mutex_unlock(&g_tMutex);  /*释放互斥锁*/		
	}
	return ret;
}
//线程函数
static void *input_recv_thread_func (void *data)
{
	PInputDevice ptInputDev = (PInputDevice)data;
	InputEvent tEvent;
	int ret;	
	while (1)
	{
		/* 读数据 */
		ret = ptInputDev->GetInputEvent(&tEvent);
		if (!ret)
		{	
			/* 保存数据 */
			pthread_mutex_lock(&g_tMutex);
			PutInputEventToBuffer(&tEvent);
			/* 唤醒等待数据的线程 */
			pthread_cond_signal(&g_tConVar); /* 通知接收线程 */
			pthread_mutex_unlock(&g_tMutex);
		}
	}
	return NULL;
}


 
void RegisterInputDevice(PInputDevice ptInputDev)
{
    ptInputDev->ptNext = g_InputDevs;//指向链表头
    g_InputDevs = ptInputDev;
}
  
 
void InputInit(void)
{
    /* 注册按键输入 */
    extern void TouchscreenRegister(void);
    TouchscreenRegister();//在touchscreen.c中
 
    /* 注册网络输入 */
    extern void NetInputRegister(void);
    NetInputRegister();//在netinput.c中
}
 

void InputDeviceInit(void)
{
    int ret;
    pthread_t tid;
    /* for each device ,init,pthread_create */
    PInputDevice ptTmp = g_InputDevs;
    while (ptTmp)
    {
        ret = ptTmp->DeviceInit();
        if (!ret)
        {
 
            ret = pthread_create(&tid, NULL, input_recv_thread_func, ptTmp);
        }
 
        ptTmp = ptTmp->ptNext;
    }
}
 

2.2 netinput.c 

#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>
#include "input_manager.h"
 
#define SERVER_PORT 8888
 
static int g_iSocketServer;
 
static int NetinputGetInputEvent(PInputEvent ptInputEvent)
{
    char ucRecvBuf[1000];
    int iRecvLen;
    struct sockaddr_in tSocketClientAddr;
 
    unsigned int iAddrLen = sizeof(struct sockaddr);
    /* 接收客户端数据报文,返回的为接收到的字节数 */
    iRecvLen = recvfrom(g_iSocketServer, ucRecvBuf, sizeof(ucRecvBuf), 0, (struct sockaddr *)&tSocketClientAddr, &iAddrLen);
    if (iRecvLen > 0)
    {
 
        ucRecvBuf[iRecvLen] = '\0';
        //printf("Get Msg from %s : %s\n", inet_ntoa(socket_client_addr.sin_addr), buf);
        ptInputEvent->iType = INPUT_TYPE_NET;
        gettimeofday(&ptInputEvent->tTime, NULL);
        strncpy(ptInputEvent->str, ucRecvBuf, 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 (g_iSocketServer == -1)
    {
        printf("socket error");
        return -1;
    }
 
    /* 服务器端填充 sockaddr_in结构 */
    tSocketServerAddr.sin_family = AF_INET;
    tSocketServerAddr.sin_port = htons(SERVER_PORT);
    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 (iRet == -1)
    {
        printf("bind error!\n");
        return -1;
    }
    return 0;
}
 
static int NetinputDeviceExit(void)
{
    close(g_iSocketServer);
    return 0;
}
 
static InputDevice g_tNetinputDev = {
 
    .name = "netinput",
    .GetInputEvent = NetinputGetInputEvent,
    .DeviceInit = NetinputDeviceInit,
    .DeviceExit = NetinputDeviceExit,
 
};
void NetInputRegister(void)
{
	RegisterInputDevice(&g_tNetinputDev);
}
#if 0
 
int main(int argc, char **argv)
{
    InputEvent event;
    int ret;
    g_tNetinputDev.DeviceInit();
    while (1)
    {
        ret = g_tNetinputDev.GetInputEvent(&event);
        if (ret)
        {
            printf("GetInputEvent err\r\n");
            return -1;
        }
        else
        {
            printf("iType       =%d\r\n", event.iType);
            printf("str         =%s\r\n", event.str);
        }
    }
    return 0;
}
 
#endif

2.3 touchscreen.c

#include "input_manager.h"
#include <tslib.h>
#include <stdio.h>

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);
}

#if 0
 
int main(int argc, char **argv)
{
    InputEvent event;
    int ret;
    g_tTouchscreenDev.DeviceInit();
    while (1)
    {
        ret = g_tTouchscreenDev.GetInputEvent(&event);
        if (ret)
        {
            printf("GetInputEvent err\r\n");
            return -1;
        }
        else
        {
            printf("iType       =%d\r\n", event.iType);
            printf("iX          =%d\r\n", event.iX);
            printf("iY          =%d\r\n", event.iY);
            printf("iPressure   =%d\r\n", event.iPressure);
        }
    }
    return 0;
}
 
#endif

2.4 Makefile

EXTRA_CFLAGS  :=
CFLAGS_file.o :=
obj-y +=netinput.o  
obj-y +=touchscreen.o
obj-y +=input_manager.o

三、uiontest文件夹

3.1 test.c

#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 <input_manager.h>

int main(int argc, char **argv)
{
	int ret;
	InputEvent event;
	
	InputInit();
	InputDeviceInit();

	while (1)
	{
		printf("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
		ret = GetInputEvent(&event);

		printf("%s %s %d, ret = %d\n", __FILE__, __FUNCTION__, __LINE__, ret);
		if (ret) {
			printf("GetInputEvent err!\n");
			return -1;
		}
		else
		{
			printf("%s %s %d, event.iType = %d\n", __FILE__, __FUNCTION__, __LINE__, event.iType );
			if (event.iType == INPUT_TYPE_TOUCH)
			{
				printf("Type      : %d\n", event.iType);
				printf("iX        : %d\n", event.iX);
				printf("iY        : %d\n", event.iY);
				printf("iPressure : %d\n", event.iPressure);
			}
			else if (event.iType == INPUT_TYPE_NET)
			{
				printf("Type      : %d\n", event.iType);
				printf("str       : %s\n", event.str);
			}
		}
	}
	return 0;	
}

3.2 client.c

        注意:该代码不通过makefile编译,而是直接通过arm-linux-gnueabihf-gcc client.c -o all_client命令编译

#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>
 
#define SERVER_PORT 8888
 
int main(int argc, char **argv)
{
	int iSocketClient;
	struct sockaddr_in tSocketServerAddr;
 
	int iRet;
	int iSendLen;
	int iAddrLen;
 
	if (argc != 3)
	{
		printf("Usage:\n");
		printf("%s <server_ip> <str>\n", argv[0]);
		return -1;
	}
 
	iSocketClient = socket(AF_INET, SOCK_DGRAM, 0);
 
	tSocketServerAddr.sin_family = AF_INET;
	tSocketServerAddr.sin_port = htons(SERVER_PORT); /* host to net, short */
	//tSocketServerAddr.sin_addr.s_addr = INADDR_ANY;
	if (0 == inet_aton(argv[1], &tSocketServerAddr.sin_addr))
	{
		printf("invalid server_ip\n");
		return -1;
	}
	memset(tSocketServerAddr.sin_zero, 0, 8);
 
#if 0
	iRet = connect(iSocketClient, (const struct sockaddr *)&tSocketServerAddr, sizeof(struct sockaddr));	
	if (-1 == iRet)
	{
		printf("connect error!\n");
		return -1;
	}
#endif
 
	iAddrLen = sizeof(struct sockaddr);
	iSendLen = sendto(iSocketClient, argv[2], strlen(argv[2]), 0,(const struct sockaddr *)&tSocketServerAddr, iAddrLen);
 
	close(iSocketClient);
 
	return 0;
}

3.3 Makefile

      这里很明显可以看到只编译test.c

EXTRA_CFLAGS  :=
CFLAGS_file.o :=
obj-y +=test.o  

四、顶层Makefile及Makefile.build

4.1 Makefile

注意LDFLAGS 设置链接库,需要线程库和触摸屏库支持,其中-lts要求在指定路径下寻找,我的tslib交叉编译在/home/alexius/Downloads/tslib-1.21/install文件夹下。故LDFLAGS设置如下:

                  LDFLAGS := -L/home/alexius/Downloads/tslib-1.21/install/lib -lts -lpthread

#指定交叉编译工具链
COSS_COMPLE ?=arm-linux-gnueabihf-
AS	= $(COSS_COMPLE)as
LD	= $(COSS_COMPLE)ld
CC	= $(COSS_COMPLE)gcc
CPP = $(CC) -E
AR = $(CROSS_COMPILE)ar
NM = $(CROSS_COMPILE)nm



STRIP = $(CROSS_COMPILE)strip
OBJCOPY = $(CROSS_COMPILE)objcopy
OBJDUMP = $(CROSS_COMPILE)objdump

# export导出的变量是给子目录下的Makefile使用的
export AS LD CC CPP AR NM 
export STRIP OBJCOPY OBJDUMP

# 编译器在编译时的参数设置
CFLAGS := -Wall -O2 -g -DDEBUG
# 添加头文件路径,不添加的话include目录下的头文件编译时找不到
CFLAGS += -I $(shell pwd)/include 

# 链接器的链接参数设置,链接库
LDFLAGS := -L/home/alexius/Downloads/tslib-1.21/install/lib -lts -lpthread#触摸屏库链接

export CFLAGS LDFLAGS

TOPDIR := $(shell pwd)
export TOPDIR

# 定义将来编译生成的可执行程序的名字
TARGET := all_test

# 添加项目中所有用到的源文件,有顶层目录下的.c文件,和子文件夹
# 添加顶层目录下的.c文件
#obj-y += main.o

# 添加顶层目录下的子文件夹(注意目录名后面加一个/)
#obj-y += main.o
obj-y += input/
obj-y += uiontest/



# 第一个目标
all : start_recursive_build $(TARGET)
	@echo $(TARGET) has been built!
    
# 处理第一个依赖,**转到 Makefile.build 执行**
start_recursive_build:
	make -C ./ -f $(TOPDIR)/Makefile.build
    
# 处理最终目标,把前期处理得出的 built-in.o 用上
$(TARGET) : built-in.o
	$(CC) -o $(TARGET) built-in.o $(LDFLAGS)
    
# 清理
clean:
	rm -f $(shell find -name "*.o")
	rm -f $(TARGET)
    
# 彻底清理
distclean:
	rm -f $(shell find -name "*.o")
	rm -f $(shell find -name "*.d")
	rm -f $(TARGET)

4.2 Makefile.build


# 将__build定义为伪目标
PHONY := __build
__build:

# 这里初值为空,下面引入Makefile文件后会被覆盖
obj-y :=
subdir-y :=

# 包含同级目录的Makefile
include Makefile

# 从obj-y变量中,将"/"结尾的字符串提取出来,也就是包含的子文件夹目录
__subdir-y	:= $(patsubst %/,%,$(filter %/, $(obj-y)))
subdir-y	+= $(__subdir-y)

# 将subdir-y变量中的字符串依次赋值给f变量,形成新的$(f)/built-in.o字符串
subdir_objs := $(foreach f,$(subdir-y),$(f)/built-in.o)

# 筛选出obj-y中不以"/"结尾的字符串,也就是普通文件,一般是.o结尾
cur_objs := $(filter-out %/, $(obj-y))

# 为每个.o文件生成.d文件
# 注意.$(f).d是隐藏文件,需要ls -a查看
dep_files := $(foreach f,$(cur_objs),.$(f).d)
dep_files := $(wildcard $(dep_files))

# 如果.d文件不是空,则将.d文件都包含进来
ifneq ($(dep_files),)
  include $(dep_files)
endif


PHONY += $(subdir-y)

# __build是Makefile的目标

__build : $(subdir-y) built-in.o

# 依次跳转到子目录中,执行Makefile.build文件
$(subdir-y):
	make -C $@ -f $(TOPDIR)/Makefile.build

# 生成当前目录的built-in.o,依赖当前目录的.o文件和子目录下的built-in.o文件
built-in.o : $(cur_objs) $(subdir_objs)
	$(LD) -r -o $@ $^

# dep_file变量是用来生成.d文件的
dep_file = .$@.d

# Makefile中的规则,把.c文件编译成.o文件
%.o : %.c
	$(CC) $(CFLAGS) -Wp,-MD,$(dep_file) -c -o $@ $<

# 重新定义 .PHONY的依赖
.PHONY : $(PHONY)

五、编译及运行

  5.1 编译    

此时编译client.c

 5.2 运行

 先查开发板ip

运行测试程序

再运行clien程序

 此时滑动屏幕,显示如下:

六、tslib库移植到开发板上

      6.1 交叉编译步骤 

        采用tslib-1.21.tar.bz2,步骤如下:

#ubuntu 工具安装
sudo apt-get install autoconf
sudo apt-get install automake
sudo apt-get install libtool
#git下载
git clone https://github.com/libts/tslib
#加入文件夹
cd tslib/
mkdir install
./autogen.sh
./configure --host=arm-linux-gnueabihf --prefix=$(pwd)/install  
make //编译
sudo make install //安装

 交叉编译后的文件如下:

     6.2 移植开发板

       将install文件夹拷贝到IMX6ull开发板上,并重命名为arm-tslib。这里不建议向正点一样直接将lib下文件拷贝到开发板lib下,因为做其他类似移植时,存在使用同一个库但不同版本的问题。如移植wpa_supplicant和mqtt时候存在两个openssl库冲突问题,故移植直接打包过去就好,省时还清晰明了。

      6.3 开发板配置tslib的相关文件

        由于是整个打包到开发板,所以直接在开发板上把包里的库和可执行程序告诉profile环境就行,执行 vi /etc/profile ,添加如下:

#tslib
export TSLIB_CONSOLEDEVICE=none
export TSLIB_FBDEVICE=/dev/fb0
export TSLIB_TSDEVICE=/dev/input/event1
export TSLIB_ROOT=/arm-tslib
export TSLIB_CONFFILE=$TSLIB_ROOT/etc/ts.conf
export TSLIB_PLUGINDIR=$TSLIB_ROOT/lib/ts
export TSLIB_CALIBFILE=/etc/pointercal #TSLIB_CALIBFILE指定了触摸屏的校准文件路径
#export LD_PRELOAD=$TSLIB_ROOT/lib/libts.so
export PATH=$PATH:$TSLIB_ROOT/bin
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$TSLIB_ROOT/lib

#再次激活环境
source /etc/profile

6.4 移植测试 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/888439.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

springboot艰难版本升级之路!! springboot 2.3.x版本升级到2.7.x版本

文章目录 1.缘起1.1 升级到版本2.7.12启动失败,而且没有报错信息1.2 application-dev.yml 配置加载问题1.3 openfeign依赖问题汇总1.4 datasource报错1.5 MySQL驱动升级1.6 循环依赖报错临时总结1.缘起 由于服务需要搭建链路追踪, 需要把springboot版本升级到2.7.12. 目前服务是…

爬虫借助代理会让网速快点吗?

亲爱的程序员朋友们&#xff0c;你曾经遇到过爬虫网速慢的情况吗&#xff1f;别着急&#xff01;今天我将和你一起探讨一下使用代理是否可以加速爬虫&#xff0c;让我们一起进入这个轻松又专业的知识分享。 一、原因和机制的解析 1.IP限制 某些网站为了保护资源和防止爬虫行…

大模型基础03:Embedding 实战本地知识问答

大模型基础:Embedding 实战本地知识问答 Embedding 概述 知识在计算机内的表示是人工智能的核心问题。从数据库、互联网到大模型时代,知识的储存方式也发生了变化。在数据库中,知识以结构化的数据形式储存在数据库中,需要机器语言(如SQL)才能调用这些信息。互联网时代,…

ZKRF-08、ZKRF-10、ZKBLF-04压力补偿节流阀

ZKFC-08、ZKFC-10单向节流阀、ZKNV2-08、ZKNV2-10节流阀、ZKRF-08、ZKRF-10、ZKBLF-04压力补偿节流阀。 螺纹插装式单向节流阀&#xff0c;节流阀流量大小可通过调节螺杆来实现。②到①节流&#xff0c; ①到②开启。 手动节流阀&#xff0c;节流阀流量大小或关闭可通过调节螺…

系统性能调优之绑定cpu

支持超线程的numa架构 物理硬件视角&#xff0c; 将多个CPU封装在一起&#xff0c;这个封装被称为插槽Socket&#xff1b;Core是socket上独立的硬件单元&#xff1b;通过intel的超线程HT技术进一步提升CPU的处理能力&#xff0c;OS看到的逻辑上的核Processor的数量。 每个硬…

Studio One6最新音乐歌曲编曲伴奏软件

Studio One也是一款受众面积十分广泛的编曲软件&#xff0c;它集混音、编曲、乐曲制作为一体&#xff0c;是一款一站式工作的音乐制作软件。它支持用户添加乐器轨道&#xff0c;在轨道中使用内部乐器进行编辑输入&#xff0c;以实现编曲操作。 和FL Studio类似&#xff0c;Stu…

相关搜索引擎常用搜索语法(Google hacking语法和FOFA语法)

一&#xff1a;Google Hack语法 Google Hacking原指利用Google搜索引擎搜索信息来进行入侵的技术和行为&#xff0c;现指利用各种搜索引擎并使用一些高级的搜索语法来搜索信息。既利用搜索引擎强大的搜索功能&#xff0c;在在浩瀚的互联网中搜索到我们需要的信息。 &#xff0…

Jetpack Compose:探索声明式UI开发的未来

Jetpack Compose&#xff1a;探索声明式UI开发的未来 1. 引言 在移动应用开发领域&#xff0c;用户界面&#xff08;UI&#xff09;开发一直是开发过程中的关键挑战之一。传统的UI开发方式往往涉及大量繁琐的布局代码、手动管理状态和事件处理&#xff0c;不仅容易引发错误&a…

微信小程序 授权登录时不得默认强制用户同意隐私政策协议

今天提交微信小程序审核时&#xff0c;官方提示“隐私政策不合规&#xff0c;默认自动同意《用户服务协议》及《隐私政策》&#xff0c;应当由用户自主阅读后自行选择是否同意隐私政策协议&#xff0c;不得默认强制用户同意。” 需要在微信授权登录时先判断用户是否勾了隐私选…

ESP8266串口WiFi模块的四大创新型应用领域分析

ESP8266串口WiFi模块顾名思义&#xff0c;这是一款基于ESP8266方案的串口WiFi模块&#xff0c;可将用户的物理设备连接到WiFi无线网络上&#xff0c;进行互联网或局域网通信&#xff0c;实现联网功能。ESP8266串口WiFi模块是一种适用性强、应用范围广泛的WiFi模块。 ESP8266串口…

tsconfig.json和jsconfig.json配置

{// 编译选项"compilerOptions": {// 生成代码的语言版本&#xff1a;将我们写的 TS 代码编译成哪个版本的 JS 代码// 命令行&#xff1a; tsc --target es5 11-测试TS配置文件.ts"target": "es5",// 指定要包含在编译中的 library"lib&quo…

掌握指针进阶:探索字符指针、数组指针和指针数组的妙用

&#x1f341;博客主页&#xff1a;江池俊的博客 &#x1f4ab;收录专栏&#xff1a;C语言—探索高效编程的基石 &#x1f4a1;代码仓库&#xff1a;江池俊的代码仓库 &#x1f3aa;我的社区&#xff1a;GeekHub &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐…

Springboot 整合MQ实现延时队列入门

延时队列 添加依赖配置文件队列TTL代码架构图交换机、队列、绑定配置文件代码生产者代码消费者代码延时队列优化添加普通队列配置代码生产者发送消息是进行设置消息的ttl 通过MQ 插件实现延时队列代码架构图配置交换机生产者代码消费者代码测试发送 添加依赖 <!-- rabbitMQ …

2023国赛数学建模思路 - 复盘:校园消费行为分析

文章目录 0 赛题思路1 赛题背景2 分析目标3 数据说明4 数据预处理5 数据分析5.1 食堂就餐行为分析5.2 学生消费行为分析 建模资料 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 赛题背景 校园一卡通是集…

Unity如何控制声音大小(包括静音功能)

一&#xff1a;UGUI制作 1. 首先在【层级】下面创建UI里面的Slider组件。设置好它对应的宽度和高度。 2.调整Slider滑动条的填充颜色。一般声音颜色我黄色&#xff0c;所以我们也调成黄色。 我们尝试滑动Slider里面的value。 a.滑动前。 b.滑动一半。 c.滑动完。 从以上滑动va…

Cat(2):下载与安装

1 github源码下载 要安装CAT&#xff0c;首先需要从github上下载最新版本的源码。 官方给出的建议如下&#xff1a; 注意cat的3.0代码分支更新都发布在master上&#xff0c;包括最新文档也都是这个分支注意文档请用最新master里面的代码文档作为标准&#xff0c;一些开源网站…

8月14-15日上课内容 LVS负载均衡的群集

知识点&#xff1a; 本章结构: 企业群集概述 集群的含义&#xff1a; 1、群集的含义 ①、Cluster、集群、群集 ②、由多台主机构成&#xff0c;但对外只表现为一个整体&#xff0c;只提供一个访问入口&#xff08;域名与IP地址&#xff09;&#xff0c;相当于一台大型计算机。…

TypeScript相关面试题

typeScript 1.什么是TypeScript?是什么&#xff1f;特性&#xff1f;区别&#xff1f; 2.TypeScript数据类型&#xff1f;3.说说你对 TypeScript 中枚举类型的理解&#xff1f;应用场景&#xff1f;4.说说你对 TypeScript 中接口的理解&#xff1f;应用场景&#xff1f;使用方…

面试题. 分割链表

给你一个链表的头节点 head 和一个特定值 x &#xff0c;请你对链表进行分隔&#xff0c;使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。 你不需要 保留 每个分区中各节点的初始相对位置。 示例 1&#xff1a; 输入&#xff1a;head [1,4,3,2,5,2], x 3 输出&a…

C#学习....

1.基础 //引用命名空间using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;//项目名或者命名空间 namespace _01_MY_First_Demo {//Program类class Program{//程序的主入口或者Main函数static void Main(S…