一切再次回到原点,一切都又开始了正常的路线,上班,下班。每每一个人回到那小小的屋子,觉得什么也不是。想离开,又不知道要去哪。日子还是一天天过去,地球不因任何人改变它的转速,月亮也不会为了谁而改变她的形状。平静,也许就是一种幸福。
上周由于其他部门需要用我们的芯片,得模拟个input设备,用以mcu按键传递过来后的处理。所以只能屁颠屁颠地去实现了,还好以前做过类似的驱动,于是很快就实现了这个功能。但是一直对于android长按键功能和短按键功能表示不解。网上也很少讲到驱动时怎么取实现的。一直以为那个
input_report_key(btn_dev, KEY_POWER, 0); input_report_key(btn_dev, KEY_POWER, 1);
这句话是表示按键的按下和抬起,其实错了,是value值为1的时候表示是按键按下,而value值是0的时候才是表示按键的抬起,而每次都需要发送一个
input_sync(btn_dev);
这样才表示是整个过程,才可以实现按键的长按和短按的功能。也就是下面的方式:
input_report_key(btn_dev, KEY_POWER, 1); input_sync(btn_dev);
这个表示的是按键被按下了。
input_report_key(btn_dev, KEY_POWER, 0); input_sync(btn_dev);
这个表示按键被抬起了。
这两个之间是表示按键按下的时间长度,android上层就是通过这个来实现按键的短按和长按的功能的。
下面用简单的驱动和简单的应用才实现android的按键的功能,无需真实的按键就可以测试了。
下面的驱动和我的那篇input子系统实例的驱动很类似
#include <linux/slab.h> #include <linux/irq.h> #include <linux/interrupt.h> #include <linux/poll.h> #include <asm/io.h> #include <linux/delay.h> #include <linux/module.h> #include <linux/time.h> #include <linux/gpio.h> #include <linux/wait.h> #include <linux/input.h> #include <linux/init.h> #define CODENUM 3 struct input_dev *btn_dev; //input设备的结构体,这里定义了btn_dev static keycode[] = { KEY_POWER, KEY_VOLUMEUP, KEY_VOLUMEDOWN }; static int __init button_init(void) { int error; //分配input设备 btn_dev = input_allocate_device(); if(!btn_dev) { printk(KERN_ERR "button: not enough memory\n"); error = -ENOMEM; return error; } //把相应的按键给置上 btn_dev->evbit[0] = BIT_MASK(EV_KEY); for(i = 0; i < CODENUM; i++) btn_dev->keybit[BIT_WORK(keycode[i])] |= BIT_MASK(keycode[i]); //注册input设备 error = input_register_device(btn_dev); if(error) { printk(KERN_ERR "button: failed to register device\n"); return error; } return 0; } static void __exit button_exit(void) { input_free_device(btn_dev); } module_init(button_init); module_exit(button_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("eastmoon");
上面的驱动其实主要就是注册一个input设备,然后再注册要用到的按键的code而已,下面就是要用的应用程序来实现那个长按和短按的功能了。
#include <stdio.h> #include <sys/ioctl.h> #include <unistd.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/select.h> #include <sys/time.h> #include <linux/input.h> #include <stdlib.h> #define DEVICE "/dev/input/event0" //这个根据自己的平台来的,不一定是event0的 int main(int argc, char *argv[]) { struct input_event btn; int fd, rev; unsigned short type; unsigned short code; int value; int longbt = 1; int delay = 0; fd = open(DEVICE, O_RDWR); if(fd < 0) { printf("Open file %s failed!\n", DEVICE); return -1; } if(argv[2] == NULL) { Longbt = 0; //命令行如果输入2个参数的话那么就默认的短按了 } else { longbt = atoi(argv[2]); if(longbt >= 10 || longbt < 0) { Printf(“Please input the longbt 0------9”); return 0; } delay = longbt *100000; //longbt表示长按的时间,步进100ms。 } btn.type = EV_KEY; //表示按键按下了 btn.code = atoi(argv[1]); btn.value = 1; rev = write(fd, &btn, sizeof(struct input_event)); if(rev > 0) { printf(“ok1\n”); } btn.type = EV_SYN; //上报表示这个过程 btn.code = SYN_REPORT; btn.value = 0; rev = write(fd, &btn, sizeof(struct input_event)); if(rev > 0) { printf(“ok3\n”); } usleep(delay); //按键按的时间 btn.type = EV_KEY; //表示按键抬起了 btn.code = atoi(argv[1]); btn.value = 0; rev = write(fd, &btn, sizeof(struct input_event)); if(rev > 0) { printf(“ok2\n”); } btn.type = EV_SYN; //上报表示这个过程好了 btn.code = SYN_REPORT; btn.value = 0; rev = write(fd, &btn, sizeof(struct input_event)); if(rev > 0) { printf(“ok3\n”); } close(fd); return 0; }
至于怎么在android下编译一个应用程序的话,网上也讲得很多了,这里也还是讲讲吧。
首先在android的external/下新建个input_app目录,然后在下面建个.c文件就是上面这段代码,命名为vitual.c好了。然后建一个Android.mk文件
内容如下:
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILE := \ virtual.c LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) LOCAL_MODULE_TAGS := eng LOCAL_MODULE := virtual include $(BUILD_EXECUTABLE)
然后在input_app下mm后就可以得到一个vitual的bin文件了,再把这个可执行文件拷贝到system/bin下就可以了。
然后就可以执行
virtual 116 //这个表示短按会锁屏或者解锁,其中116就是那个电源键的code了 virtual 116 6 //这个就可以表示长按了,然后会出来一个选择框,让你选择是否要关机了。
至此,关于android的按键功能就实现了,其短按、长按的功能也得以实现了。