一切再次回到原点,一切都又开始了正常的路线,上班,下班。每每一个人回到那小小的屋子,觉得什么也不是。想离开,又不知道要去哪。日子还是一天天过去,地球不因任何人改变它的转速,月亮也不会为了谁而改变她的形状。平静,也许就是一种幸福。
上周由于其他部门需要用我们的芯片,得模拟个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的按键功能就实现了,其短按、长按的功能也得以实现了。