zoukankan      html  css  js  c++  java
  • android2.3 -添加自定义按键:作唤醒功能 .

    最近需要做个唤醒功能,当按键的时候android系统唤醒并点亮屏,在长按键中,系统不能在进入睡眠。

    1. 驱动方面:  
    2. 1:在平台设备文件中添加 一个按键,定义为唤醒源!  
    3. archarmmach-s5pv210  
    4. static struct gpio_keys_button gpio_buttons[] = {  
    5.   
    6.     {  
    7.   .gpio  = S5PV210_GPH1(3),  
    8.    .code  = KEY_F22,  //对应 192    
    9.    .desc  = "F22",  
    10.    .active_low = 1,  
    11.    .wakeup  = 1,  
    12.    .debounce_interval =100, //去抖动   
    13.     },  
    14.   
    15. }  
    16.   
    17.   
    18.   
    19. static struct gpio_keys_platform_data gpio_button_data = {  
    20.  .buttons = gpio_buttons,  
    21.  .nbuttons = ARRAY_SIZE(gpio_buttons),  
    22. };  
    23.   
    24. static struct platform_device s3c_device_gpio_button = {  
    25.  .name  = "gpio-keys",  
    26.  .id  = -1,  
    27.  .num_resources = 0,  
    28.  .dev  = {  
    29.   .platform_data = &gpio_button_data,  
    30.  }  
    31. };  
    32.   
    33. platform_add_devices(smdkc110_devices, ARRAY_SIZE(smdkc110_devices));  
    34.   
    35.   
    36. 2:添加驱动kernel-v.20120620driversinputkeyboards3c-gpio-keys.c  
    37. struct s3c_gpio_key{  
    38.     int pin;  
    39.     int eint;  
    40.     int eintcfg;  
    41.     int inputcfg;  
    42. };  
    43.   
    44. struct s3c_gpio_key s3c_gpio_keys[]=  
    45. {     
    46.         ///*   
    47.       {   
    48.               .pin = S5PV210_GPH1(3), //at base wake up   
    49.               .eintcfg = 0X0f<<12,        
    50.               .inputcfg = 0<<12,  
    51.               .eint = IRQ_EINT11,  
    52.       },  
    53.         
    54.      // */   
    55. };  
    驱动方面:
    1:在平台设备文件中添加 一个按键,定义为唤醒源!
    archarmmach-s5pv210
    static struct gpio_keys_button gpio_buttons[] = {
    
        {
      .gpio  = S5PV210_GPH1(3),
       .code  = KEY_F22,  //对应 192 
       .desc  = "F22",
       .active_low = 1,
       .wakeup  = 1,
       .debounce_interval =100, //去抖动
        },
    
    }
    
    
    
    static struct gpio_keys_platform_data gpio_button_data = {
     .buttons = gpio_buttons,
     .nbuttons = ARRAY_SIZE(gpio_buttons),
    };
    
    static struct platform_device s3c_device_gpio_button = {
     .name  = "gpio-keys",
     .id  = -1,
     .num_resources = 0,
     .dev  = {
      .platform_data = &gpio_button_data,
     }
    };
    
    platform_add_devices(smdkc110_devices, ARRAY_SIZE(smdkc110_devices));
    
    
    2:添加驱动kernel-v.20120620driversinputkeyboards3c-gpio-keys.c
    struct s3c_gpio_key{
    	int pin;
    	int eint;
    	int eintcfg;
    	int inputcfg;
    };
    
    struct s3c_gpio_key s3c_gpio_keys[]=
    {	
            ///*
          { 
                  .pin = S5PV210_GPH1(3), //at base wake up
                  .eintcfg = 0X0f<<12,      
                  .inputcfg = 0<<12,
                  .eint = IRQ_EINT11,
          },
          
         // */
    };
    

    //申请中断为上/下沿出发方式。

    1. error = request_irq(s3c_gpio_keys[i].eint, gpio_keys_isr,  
    2.             IRQF_SAMPLE_RANDOM | IRQF_TRIGGER_RISING |  
    3.             IRQF_TRIGGER_FALLING,  
    4.             button->desc ? button->desc : "gpio_keys",  
    5.             bdata);  
    		error = request_irq(s3c_gpio_keys[i].eint, gpio_keys_isr,
    				    IRQF_SAMPLE_RANDOM | IRQF_TRIGGER_RISING |
    					IRQF_TRIGGER_FALLING,
    				    button->desc ? button->desc : "gpio_keys",
    				    bdata);
    1. static void gpio_keys_report_event(struct gpio_button_data *bdata)  
    2. {  
    3.     struct gpio_keys_button *button = bdata->button;  
    4.     struct input_dev *input = bdata->input;  
    5.     unsigned int type = button->type ?: EV_KEY;  
    6.   
    7.     int state = (gpio_get_value(button->gpio) ? 1 : 0) ^ button->active_low;  
    8.     //add by xiao@2012-0620:for wake up mid when it on base.   
    9.     //上报事件处理下,因会发生系统唤醒后,又马上进入睡眠,造成一种假唤醒状态,所以当按键时,不时上报此事件来唤醒系统   
    10.     if(button->code == 192){  
    11.         if(state)  
    12.            mod_timer(&bdata->timer,  
    13.             jiffies + msecs_to_jiffies(button->debounce_interval + 300));  
    14.     }  
    15.     input_event(input, type, button->code, !!state);  
    16.     input_sync(input);  
    17.     #ifdef key_debug   
    18.     printk("gpio_keys_report_event->code =%d, state = %d ",button->code,state);  
    19.     #endif   
    20. }  
    static void gpio_keys_report_event(struct gpio_button_data *bdata)
    {
    	struct gpio_keys_button *button = bdata->button;
    	struct input_dev *input = bdata->input;
    	unsigned int type = button->type ?: EV_KEY;
    
    	int state = (gpio_get_value(button->gpio) ? 1 : 0) ^ button->active_low;
        //add by xiao@2012-0620:for wake up mid when it on base.
        //上报事件处理下,因会发生系统唤醒后,又马上进入睡眠,造成一种假唤醒状态,所以当按键时,不时上报此事件来唤醒系统
        if(button->code == 192){
            if(state)
               mod_timer(&bdata->timer,
    			jiffies + msecs_to_jiffies(button->debounce_interval + 300));
        }
        input_event(input, type, button->code, !!state);
    	input_sync(input);
    	#ifdef key_debug
    	printk("gpio_keys_report_event->code =%d, state = %d
    ",button->code,state);
    	#endif
    }

    驱动按键添加完成,内核能唤醒,但是android系统屏并不会点亮,所以需要修改源码,让系统服务获取到此按键并作一些处理。


    1:首先看下键值表:out argetproductsmdkv210systemusrkeylayout

    qwerty.kl

    # On an AT keyboard: ESC, F10
    key 1     BACK              WAKE_DROPPED
    key 68    MENU              WAKE_DROPPED

    # on base wake up mid
    key 192     NULL         WAKE_DROPPED   //需要添加的键NULL。WAKE_DROPPED:唤醒并点亮屏。

    第一列:key
    第二列: SCANCODE是一个整数,是驱动里面定义的,在文件./kernel/include/linux/input.h
    第三列: KEYCODE 是一个字串,定义在你描述的布局文件frameworks/base/include/ui/KeycodeLabels.h
    另外可以设置相关的FLAGS:
    SHIFT: 当按下,自动加上SHIFT键值
    ALT:当按下,自动加上ALT
    CAPS:当按下,自动带上CAPS大写
    WAKE:当按下,当设备进入睡眠的时候,按下这个键将唤醒,而且发送消息给应用层。
    WAKE_DROPPED:当按下,且设备正处于睡眠,设备被唤醒,但是不发送消息给应用层。

    2:./frameworks/base/include/ui/keycodeLabels.h

    static const KeycodeLabel KEYCODES[] = {
        { "BUTTON_MODE", 110 },
        { "NULL", 111 }, //在最后添加NULL按键, 键值为111 ,后续android根据键值来映射。    
        // NOTE: If you add a new keycode here you must also add it to several other files.
        //       Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list.

        { NULL, 0 }
    };

    3: ./ frameworks/base/native/include/android/Keycodes.h   

    enum {
        AKEYCODE_BUTTON_MODE     = 110,
        AKEYCODE_NULL     = 111, //     当keyevent处理按键事件时,isSystemKey 判断是否为系统按键才会继续上报上层,所以需要添加进去。
        // NOTE: If you add a new keycode here you must also add it to several other files.
        //       Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list.
    };

    ./frameworks/base/libs/ui/input.java

       同时 isSystemKey() 也要添加:

    bool KeyEvent::isSystemKey(int32_t keyCode) {
        switch (keyCode) {
            case AKEYCODE_FOCUS:
            case AKEYCODE_SEARCH:
      case AKEYCODE_NULL: // add by xiao@2012-06-20
                return true;
        }
       
        return false;
    }

    4: ./frameworks/base/core/java/android/view/KeyEvent.java

      //根据键值 映射 为 KEYCODE_BUTTON_NULL  ,为PhoneWindowManager.java 提供按键目标。
        public static final int KEYCODE_BUTTON_NULL     = 111;

     同时 这也修改:

     private static final int LAST_KEYCODE           = KEYCODE_BUTTON_NULL;

    5:./frameworks/base/core/res/res/values/attrs.xml
            <enum name="KEYCODE_BUTTON_MODE" value="110" />
            <enum name="KEYCODE_BUTTON_NULL" value="111" />

    通过以上的更改,新的键值就添加上去了,由于更改了 KeyEvent,影响到了API, 所以需要make update-api

    这样系统就会获取到这个NULL按键,并能够点亮屏幕了。

    如果对新键值进行处理,可以通过获取相应的keycode,对它进行处理;对于按键事件的处理一般如下文件中
     frameworks/policies/base/phone/com/android/internal/policy/impl/PhoneWindowManager.java

    interceptKeyBeforeQueueing 函数中处理,

    1. public int interceptKeyBeforeQueueing(long whenNanos, int keyCode, boolean down,  
    2.            int policyFlags, boolean isScreenOn) {  
    3.   
    4.   
    5.     //add by xiao@2012-06-20 :wakeup mid when it on base,   
    6.     else if(keyCode == KeyEvent.KEYCODE_BUTTON_NULL){ //获取NULL按键,不让系统进入睡眠状态,释放按键时,进入可睡眠。   
    7.         if(down){  
    8.             if(IS_MID_ONBASE == false)  
    9.             {  
    10.                 IS_MID_ONBASE = true;  
    11.                 mBroadcastWakeLock.acquire();  
    12.                 Log.e(TAG,"MID WAKE UP button: DOwn");  
    13.             }  
    14.         }else{  
    15.             IS_MID_ONBASE = false;  
    16.             mBroadcastWakeLock.release();  
    17.             Log.e(TAG,"MID WAKE UP button: release");  
    18.         }  
    19.     }  
    20.   
    21.      }  
     public int interceptKeyBeforeQueueing(long whenNanos, int keyCode, boolean down,
                int policyFlags, boolean isScreenOn) {
    
    
    		//add by xiao@2012-06-20 :wakeup mid when it on base,
    		else if(keyCode == KeyEvent.KEYCODE_BUTTON_NULL){ //获取NULL按键,不让系统进入睡眠状态,释放按键时,进入可睡眠。
    			if(down){
    				if(IS_MID_ONBASE == false)
    				{
    					IS_MID_ONBASE = true;
    					mBroadcastWakeLock.acquire();
    					Log.e(TAG,"MID WAKE UP button: DOwn");
    				}
    			}else{
    				IS_MID_ONBASE = false;
    				mBroadcastWakeLock.release();
    				Log.e(TAG,"MID WAKE UP button: release");
    			}
    		}
    
          }
  • 相关阅读:
    per-CPU变量
    oom killer
    System.map文件的作用
    Linux电源管理(9)_wakelocks【转】
    Linux内核的冷热缓存
    浅谈TCP IP协议栈(四)IP协议解析
    浅谈TCP IP协议栈(三)路由器简介
    CFS调度器(1)-基本原理
    浅谈TCP IP协议栈(二)IP地址
    (利用DOM)在新打开的页面点击关闭当前浏览器窗口
  • 原文地址:https://www.cnblogs.com/ljf181275034/p/3303706.html
Copyright © 2011-2022 走看看