zoukankan      html  css  js  c++  java
  • 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>
    ", argv[0]);
    		return 1;
    	}
    
    	fd = open(argv[1], O_RDONLY);
    	if(fd < 0) {
    		fprintf(stderr, "Can not open device: %s
    ", argv[1]);
    		return 1;
    	}
    
    	ufd = input_init(fd);
    	if(ufd < 0) {
    		close(fd);
    		fprintf(stderr, "Can not create uinput device
    ");
    		return 1;
    	}
    
    	convert_data(ufd, fd);
    
    	close(ufd);
    	close(fd);
    	return 0;
    }
    

      

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

  • 相关阅读:
    SICP习题 1.11 (一个函数的递归与迭代)
    SICP 实例 ExchangeMoney
    SICP 1.2.2 树形递归 与 线性迭代(斐波那契数)
    SICP习题 1.10(Ackermann函数)
    SICP习题 1.9 (递归与迭代初探)
    SICP实例 1.2.1 (阶乘的递归与迭代)
    SICP习题 1.8 (立方根)
    SICP习题 1.7 (求平方根改进)
    SICP习题 1.6 (再探 函数 与 正则序 应用序 关系)
    SICP实例 1.1.7 (求平方根)
  • 原文地址:https://www.cnblogs.com/xhawk18/p/3360455.html
Copyright © 2011-2022 走看看