android5.0输入系统添加自定义按键

申明:本按键添加没有用到全志sys_config.fex配置io。
Board:全志R16
SDK:Android KitKat 4.4.2、Linux-3.4
开发内容:自定义按键名为SOCHIP_EXT1,接在R16开发板的GPIOB7口。
1.先在linux-3.4/inlcude/linux/input.h添加自定义按键#define SOCHIP_EXT1 0x2e8 该键值最好不要跟系统的键值冲突,然后编写linux下的key driver代码。

#include <linux/module.h>
#include <linux/init.h>
#include <linux/input.h>
#include <linux/irq.h>
#include <mach/irqs.h>
#include <linux/interrupt.h>
#include <asm-generic/errno.h>
#include <asm-generic/errno-base.h>
#include <linux/gpio.h>
#include <mach/gpio.h>

#include <linux/slab.h>
#include <linux/timer.h>
#include <linux/param.h>
#include <linux/jiffies.h>

#include <linux/ioport.h>
#include <linux/io.h>

#define KEYDEV_NAME "mykey"
#define MY_KEY      KEY_SOCHIP_EXT1
#define KEY_GPIO GPIOB(7)   

static int key_irq;

static struct timer_list *key_timer = NULL;
static struct input_dev *key_dev = NULL;
static void __iomem *key_reg;


static irqreturn_t isr_key_func(int irq, void *arg)
{
    printk(KERN_EMERG "key intretupt is comming ...\n");

    mod_timer(key_timer, jiffies + (HZ / 5));
    return IRQ_HANDLED; 
}

static void timer_handler(unsigned long arg)
{
    //printk("10ms is comming ... \n");
    unsigned int val;
    val = gpio_get_value(KEY_GPIO);

    printk("val = %d\n", val);
    if(val == 0){
        printk("key up ... \n");
        input_report_key(key_dev, MY_KEY, 0);
        input_sync(key_dev);

    }else if(val == 1){
        printk("key down ...\n");
        input_report_key(key_dev, MY_KEY, 1);
        input_sync(key_dev);
    }
}


static int __init key_init(void)
{
    int ret = 0;
    printk("hello key driver\n");
    //初始化定时器
    key_timer = kzalloc(sizeof(struct timer_list), GFP_KERNEL);
    if(!key_timer){
        printk("kzalloc timer is failed!\n");
        ret = -ENOMEM;
        goto ERR1;
    }
    init_timer(key_timer);
    key_timer->function = timer_handler;//定时服务函数
    key_timer->expires = jiffies + (HZ / 10);//当前时间 + 定时时间 
    add_timer(key_timer);//添加定时器

    //input结构体申请内存
    key_dev = input_allocate_device();
    if(!key_dev){
        printk(KERN_EMERG "key: input_allocate_device failed!\n");
        ret = -ENOMEM;
        goto ERR2;
    }
#if 1
    key_dev->name = KEYDEV_NAME;  //输入设备名字
    key_dev->phys = "input22"; //设备节点名称
    key_dev->id.bustype = BUS_HOST;  //设备标识ID属性     用于与事件处理层进行匹配
    key_dev->id.vendor = 0x0001;
    key_dev->id.product = 0x0001;
    key_dev->id.version = 0x0100;
#endif
    set_bit(EV_KEY, key_dev->evbit);//设置支持的事件类型为key
    set_bit(MY_KEY, key_dev->keybit);//设置设备支持按键类型为MYKEY
    //申请IO资源  第一种方式
    ret = gpio_request(KEY_GPIO, NULL);
    if(ret < 0){
        printk(KERN_EMERG "gpio request failed!\n");
        ret = -EBUSY;
        return ret;
    }
#if 0    //申请IO资源   第二种方式
    if(!request_mem_region(KEY_GPIO, 4, "key")){
        printk("requset_mem_region is failed!\n");
        return -EBUSY;
    }    
#endif
    //映射
    key_reg = ioremap(KEY_GPIO, 4);
    if(!key_reg){
        printk("ioremap is failed!\n");
        return -EIO;
    }
    //配置KEY_GPIO为中断模式
    iowrite32(0x4, key_reg);

    //根据IO获取中断ID
    key_irq = gpio_to_irq(KEY_GPIO);
    if(key_irq == -ENXIO)
    {
        printk(KERN_EMERG "gpio_to_irq failed!\n");
        ret = -ENXIO;
        goto ERR3;
    }
    //2.申请中断
    if(request_irq(key_irq, isr_key_func, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "key", NULL)){
        ret = -EBUSY;
        printk(KERN_EMERG "request irq failed!\n");
        goto ERR4;
    }
    //3.向input子系统注册device
    ret = input_register_device(key_dev);
    if(ret){
        printk(KERN_EMERG "input register device failed!\n");
        goto ERR5;
    }
    return 0;    
ERR5:
    free_irq(key_irq, NULL);
ERR4:
    gpio_free(KEY_GPIO);
ERR3:
    input_free_device(key_dev);
ERR2:
    kfree(key_timer);
ERR1:
    return ret;
}

static void __exit key_exit(void)
{ 
    del_timer(key_timer);  //删除定时器
    kfree(key_timer);//释放内存
    free_irq(key_irq, NULL); //释放中断id
    iounmap(key_reg);//解映射
    gpio_free(KEY_GPIO); //第二种方式释放申请的内存资源
 //   release_mem_region(KEY_GPIO, 4); //第一种方式释放申请的内存资源
    input_unregister_device(key_dev);//解input注册

    printk("goodbye key driver\n");
}
module_init(key_init);
module_exit(key_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("orange");
MODULE_DESCRIPTION("key driver");

2.修改xxx.kl安卓下的按键映射文件,R16平台SDK对应的kl文件在android/device/softwinner/xxx/configs/sunxi-keyboard.kl,也可通过cat /proc/bus/input/devices 可找到相应的驱动名。(其他kl文件可在frameworks//base/data/keyboards/中找到)添加key 744 SOCHIP_EXT1。
3.修改framework层的相关文件,R16平台SDK相关文件对应的路径如下:

=>android/frameworks/native/include/input/KeycodeLabels.h中添加如下对应的代码:

246     { "ASSIST", 219 },
247     { "BRIGHTNESS_DOWN", 220 },
248     { "BRIGHTNESS_UP", 221 },
249     { "MEDIA_AUDIO_TRACK", 222 },
250     { "SOCHIP_EXT1" , 223},  ==>此处添加

=>android/frameworks/native/include/android/keycodes.h中添加如下对应的代码:

265     AKEYCODE_ASSIST          = 219,
266     AKEYCODE_BRIGHTNESS_DOWN = 220,
267     AKEYCODE_BRIGHTNESS_UP   = 221,
268     AKEYCODE_MEDIA_AUDIO_TRACK = 222,
269     AKEYCODE_SOCHIP_EXT1 = 223,   ==>此处添加

=>android/frameworks/base/core/res/res/values/attrs.xml中添加如下对应的代码:

1566         <enum name="KEYCODE_ASSIST" value="219" />
1567         <enum name="KEYCODE_BRIGHTNESS_DOWN" value="220" />
1568         <enum name="KEYCODE_BRIGHTNESS_UP" value="221" />
1569         <enum name="KEYCODE_MEDIA_AUDIO_TRACK" value="222" />
1570         <enum name="KEYCODE_SOCHIP_EXT1" value="223" />  ==>此处添加

=>android/frameworks/base/core/Java/android/view/KeyEvent.java 此文件有两处修改,分别如下:
第一处修改:

631     public static final int KEYCODE_BRIGHTNESS_UP   = 221;
 632     /** Key code constant: Audio Track key
 633      * Switches the audio tracks. */
 634     public static final int KEYCODE_MEDIA_AUDIO_TRACK = 222;
 635 
 636     public static final int KEYCODE_SOCHIP_EXT1 = 223; ==>此处添加
 637 
 638     private static final int LAST_KEYCODE  = KEYCODE_SOCHIP_EXT1;==>此处若LAST_KEYCODE对应的上一行是什么按键就赋值什么。

第二处修改:

879         names.append(KEYCODE_ASSIST, "KEYCODE_ASSIST");
 880         names.append(KEYCODE_BRIGHTNESS_DOWN, "KEYCODE_BRIGHTNESS_DOWN");
 881         names.append(KEYCODE_BRIGHTNESS_UP, "KEYCODE_BRIGHTNESS_UP");
 882         names.append(KEYCODE_MEDIA_AUDIO_TRACK, "KEYCODE_MEDIA_AUDIO_TRACK");
 883         names.append(KEYCODE_SOCHIP_EXT1, "KEYCODE_SOCHIP_EXT1");==>此处添加

=>android/device/softwinner/astar-evb/configs/sunxi-keyboard.kl中添加如下

1 key 102   HOME              WAKE
  2 key 28    BACK              WAKE
  3 key 139   MENU              WAKE_DROPPED
  4 key 114   VOLUME_UP
  5 key 115   VOLUME_DOWN
  6 key 744   SOCHIP_EXT1   ==>此处添加  

=>android/frameworks/native/libs/input/Input.cpp =>修改 bool KeyEvent::isSystemKey(int32_t keyCode) ,添加AKEYCODE_SOCHIP_EXT1 ,如添加了代表此按键为系统按键。

109         case AKEYCODE_SEARCH:
110         case AKEYCODE_BRIGHTNESS_DOWN:
111         case AKEYCODE_BRIGHTNESS_UP:
112         case AKEYCODE_MEDIA_AUDIO_TRACK:
113         case AKEYCODE_SOCHIP_EXT1:

最后切记执行make update-api 把刚刚修改的内容更新,可在frameworks/base/api/current.txt找到更新后添加到里面的按键内容,如本文,我们可以搜索SOCHIP_EXT1,找到的内容如下:

27284     field public static final int KEYCODE_SLASH = 76; // 0x4c
27285     field public static final int KEYCODE_SOCHIP_EXT1 = 223; // 0xdf ==>此处
27286     field public static final int KEYCODE_SOFT_LEFT = 1; // 0x1
27287     field public static final int KEYCODE_SOFT_RIGHT = 2; // 0x2

若没有执行make update-api是找不到你所添加的按键对应的内容,最后编译、打包、烧录,至此添加自定义按键成功,相关解析按键布局的kl文件可在frameworks/base/services/input/EventHub.cpp。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值