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

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/)

 

 

 

 

你可能感兴趣的:(android)