导航

elan的触控屏驱动在android下的整合

Posted on 2013-10-10 02:32  xhawk18  阅读(1150)  评论(2编辑  收藏  举报

xhawk整合过很多触控屏的驱动,这是最紧张的一次。

以前碰到的触控屏,无非就是将驱动代码放到linux kernel下面,加下i2c设备,

然后再看看屏幕是否旋转,大小是否对,三下五除二,效果就出来了。

这次的elan屏,有两种接口,usb口和i2c口的。

先说usb口触控屏,它是 “免驱” 的,插上windows直接可以使用。

我肋个去~~ android/linux素好源码,恶 “免驱”。

 

何不一试?也许运气不错!将屏幕连接到系统一看,有戏!

/dev/input下面成功的出现了新的event2和mouse2设备。

再到安卓界面上试试看,咦,没反应?

再 cat /dev/input/event2,发现触摸屏幕时,的确有数据输出的。

看来,情况很明显 -- 这个屏幕输出的数据,不被android所认可。

于是,结论也很明显 -- 要么屏的厂家能提供一份android驱动,要么我们自己写。

而厂家明确说,他们没有android/linux驱动。。。

 

现在,真的挑战来了。

离项目拿给客户做演示还有两天的时间,而我们要在没有数据手册的情况下,

为第三方产品开发一个驱动。。这都是苦命啊!

 

但是人还是要向前看,要充满英雄主义的自信感,事情总是会解决的。

 

每当这么悲催又必须自信的时候,我都不免想起大学挂科的经历。

挂科,然后补考。

补考出来,极为惆怅;同考的一个妹子,幽幽的跟俺说,同时天涯沦落人。。

我肋个去~~ 谁跟你沦落人,不就一辅修课吗,老子还有大好前程呢。这种鸟女人无需理会。

于是我大踏步走开,悲催又略显自信,任由妹子在风中。。

数年后,咱一贯的悲催又自信。岂止悲催,简直悲痛。用时下流行语,简直是喔草,屌丝,活该撸一被子。。。

 

扯远,言归正传。

xhawk不想写驱动,于是去试验用另一个i2c接口的屏幕,希望能取代此usb接口屏。

直接后果是,又浪费了一天。

此时,离截止时间还有半天。俗话说,压力之下必有激情,总之,咱找到办法了--

用uinput,用户层输入接口。写一个用户层应用程序即可,

这样程序修改调试是很快速的,不会把系统搞死,也无需重烧系统。

总之,比写kernel层的驱动经济有效的多。

现在,只要一个程序,从原usb的设备文件event2中读到数据,

将它用uinput包装成安卓可辨识的设备数据,就大功告成了。

 

事后证明,此法相当靠谱,写应用层驱动果然很方便,几个小时就完成了。

此次演示涉险过关。

 

贴上部分代码,很简单的。就是对原有hid数据转换一下而已。

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <linux/input.h>
#include <android/log.h>
#include <linux/uinput.h>
#include <sys/select.h>

#define SCREEN_W 4000
#define SCREEN_H 2250
#define SCREEN_RORATE

int input_init(int fd) {
	int i;
	struct uinput_user_dev uidev;
	struct input_absinfo absX, absY;

	int ufd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
	if(ufd < 0) return ufd;

	memset(&uidev, 0, sizeof(uidev));
	snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, "uinput-convert");

	uidev.absmax[ABS_X] = SCREEN_W;
	uidev.absmin[ABS_X] = 0;
	uidev.absmax[ABS_Y] = SCREEN_H;
	uidev.absmin[ABS_Y] = 0;

	ioctl(ufd, UI_SET_EVBIT, EV_SYN);
	ioctl(ufd, UI_SET_EVBIT, EV_KEY);
	ioctl(ufd, UI_SET_EVBIT, EV_ABS);
	//ioctl(ufd, UI_SET_EVBIT, EV_MSC);
	ioctl(ufd, UI_SET_ABSBIT, ABS_X);
	ioctl(ufd, UI_SET_ABSBIT, ABS_Y);
	ioctl(ufd, UI_SET_KEYBIT, BTN_TOUCH);

	write(ufd, &uidev, sizeof(uidev));

	ioctl(ufd, UI_DEV_CREATE);

	return ufd;
}


void input_report(int ufd, struct input_event *ev) {
	write(ufd, ev, sizeof(*ev));
}

void input_close(int ufd) {
	if(ufd < 0) return;
	ioctl(ufd, UI_DEV_DESTROY);
	close(ufd);
}


void convert_data(int ufd, int fd) {
	int i = 0;
	struct input_event ie;
	int last_key_down = 0;
	struct timeval tv_key0 = {0, 0};
	struct timeval tv = {0, 0};
	fd_set set;
	
	FD_ZERO(&set);
	while(1) {
		int j;
		int rt;
		ssize_t len;

		if(!FD_ISSET(fd, &set))
			FD_SET(fd, &set);
		tv.tv_sec = 0;
		tv.tv_usec = 10000;
		rt = select(fd+1, &set, NULL, NULL, &tv);
		if(rt < 0) continue;
		
		if(rt == 0) {
			if(last_key_down) {
				last_key_down = 0;
				memset(&ie, 0, sizeof(ie));
				ie.type = EV_KEY;
				ie.code = BTN_TOUCH;
				ie.value = 0;
				input_report(ufd, &ie);
			}
			continue;
		}

		if(!FD_ISSET(fd, &set)) continue;

		len = read(fd, &ie, sizeof(ie));
		if(len < 0) break;
		
		switch(ie.type) {
			case EV_SYN:
				input_report(ufd, &ie);
				break;
			case EV_KEY:
				if(ie.code == BTN_TOUCH) {
					struct timeval interval;
					timersub(&ie.time, &tv_key0, &interval);
					tv_key0 = ie.time;
					if(interval.tv_sec == 0 && interval.tv_usec >= 0 && interval.tv_usec < 5000) 
						;	//ignore
					else {
						last_key_down = ie.value;
						input_report(ufd, &ie);
					}
				}
				break;
			case EV_ABS:
				if(ie.code == 0x0) {
#ifdef SCREEN_RORATE
					ie.value = (SCREEN_W > ie.value ? SCREEN_W - ie.value - 1 : 0);
#endif
					input_report(ufd, &ie);
				}
				else if(ie.code == 0x2) {
					ie.code = ABS_Y;
#ifdef SCREEN_RORATE
					ie.value = (SCREEN_H > ie.value ? SCREEN_H - ie.value - 1 : 0);
#endif
					input_report(ufd, &ie);
				}
				break;
			default:;
		}
	}
}

int main(int argc, char **argv) {

	int fd;
	int ufd;

	if(argc != 2) {
		fprintf(stderr, "Usage: %s <touch_device_path>\n", argv[0]);
		return 1;
	}

	fd = open(argv[1], O_RDONLY);
	if(fd < 0) {
		fprintf(stderr, "Can not open device: %s\n", argv[1]);
		return 1;
	}

	ufd = input_init(fd);
	if(ufd < 0) {
		close(fd);
		fprintf(stderr, "Can not create uinput device\n");
		return 1;
	}

	convert_data(ufd, fd);

	close(ufd);
	close(fd);
	return 0;
}

  

 

(转载请标明:http://www.cnblogs.com/xhawk18/)