1. 程式人生 > >android5.0輸入系統新增自定義按鍵

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。