MT6755 平台手机皮套驱动实现

是自己写注册一个input device,模仿keypad,在对应的中断处理函数中上报power key的键值。 具体实现代码如下:

alps/kernel-3.10/drivers/misc/mediatek/keypad/kpd.c文件,添加:
 

#include <linux/slab.h>

#define KPD_HAS_HALL_FUN

#ifdef KPD_HAS_HALL_FUN //#define HALL_KEY 0 #include <linux/irqchip/mt-eic.h>

#define HALL_EINT_NUM     11

#define HALL_EINT_PIN     (GPIO11|0x80000000)

static void kpd_flip_handler(unsigned long data);

static DECLARE_TASKLET(kpd_flip_tasklet, kpd_flip_handler, 0);

static bool kpd_flip_state = true;

#define HALL_CLASS_NAME  "hall_class"

#define HALL_DEVICE_NAME  "hall_device"

static struct class *hall_class;

static struct device *hall_device;

static unsigned int hall_irq_num;

/* static ssize_t hall_state_store(struct device *dev,  struct device_attribute *attr, const char *buf, size_t count) {  return 0; } */

static ssize_t hall_state_show(struct device *dev,  struct device_attribute *attr, char *buf)

{       int hall_state=0;    

   hall_state  = kpd_flip_state+2;   

    return sprintf(buf, "%d\n", hall_state); }

static DEVICE_ATTR(hall_state, S_IRUGO | S_IWUSR, hall_state_show, NULL);

static struct device_attribute *hall_dev_attributes[] = {  &dev_attr_hall_state, };

#endif

 

#ifdef KPD_HAS_HALL_FUN

static irqreturn_t kpd_flip_eint_handler(int irq, void *dev_id) {    tasklet_schedule(&kpd_flip_tasklet); }

static void kpd_flip_handler(unsigned long data) {     bool old_state = kpd_flip_state;      int Mhall_key_level;     int ret = 0;

    kpd_flip_state = !kpd_flip_state;

 Mhall_key_level = mt_get_gpio_in(HALL_EINT_PIN);  

    pr_warn("\n chenhaibing kpd_flip_handler report   ");   #if 1     if (kpd_flip_state)     {       input_report_switch(kpd_input_dev, SW_LID, 0);       pr_warn("\n glove is close! report kpd_flip_state=%d, flip state= %d\n", kpd_flip_state,old_state);     }     else     {       input_report_switch(kpd_input_dev, SW_LID, 1);       pr_warn("\n glove is open!report kpd_flip_state=%d, flip state= %d\n", kpd_flip_state,old_state);     } #endif

    input_sync(kpd_input_dev);     pr_warn("chenhaibing hall_key_level = %d", Mhall_key_level);     pr_warn("chenhaibing hall flip key handler:%d,%d\n",old_state,kpd_flip_state); #ifdef BIRD_HALL_CHANGE_TP_PARAM //gtp_change_param(Mhall_key_level); #endif

    if (old_state){      //mt_eint_registration(HALL_EINT_NUM, CUST_EINTF_TRIGGER_HIGH, kpd_flip_eint_handler, false);      ret = request_irq(hall_irq_num, (irq_handler_t)kpd_flip_eint_handler, CUST_EINTF_TRIGGER_HIGH, "hall-eint", NULL);      if (ret > 0)       pr_err("HALL-EINT IRQ LINE NOT AVAILABLE!!\n");     }else{      //mt_eint_registration(HALL_EINT_NUM, CUST_EINTF_TRIGGER_LOW, kpd_flip_eint_handler, false);         ret = request_irq(hall_irq_num, (irq_handler_t)kpd_flip_eint_handler, CUST_EINTF_TRIGGER_LOW, "hall-eint", NULL);         if (ret > 0)       pr_err("HALL-EINT IRQ LINE NOT AVAILABLE!!\n");     }      mt_eint_unmask(HALL_EINT_NUM);     }

#endif

 

static int kpd_pdrv_probe(struct platform_device *pdev)

{

  #ifdef KPD_HAS_HALL_FUN
 __set_bit(EV_SW , kpd_input_dev->evbit);
 __set_bit(SW_LID , kpd_input_dev->swbit);
#endif

 

 

 

#ifdef KPD_HAS_HALL_FUN  mt_set_gpio_mode(HALL_EINT_PIN, GPIO_MODE_00);  mt_set_gpio_dir(HALL_EINT_PIN, GPIO_DIR_IN);  mt_set_gpio_pull_enable(HALL_EINT_PIN, GPIO_PULL_ENABLE);  mt_set_gpio_pull_select(HALL_EINT_PIN, GPIO_PULL_UP);  mt_eint_set_hw_debounce(HALL_EINT_NUM, 0);     //mt_eint_registration(HALL_EINT_NUM, CUST_EINTF_TRIGGER_LOW, kpd_flip_eint_handler, false);     hall_irq_num = mt_gpio_to_irq(HALL_EINT_NUM);     ret = request_irq(hall_irq_num, (irq_handler_t)kpd_flip_eint_handler, CUST_EINTF_TRIGGER_LOW, "hall-eint", NULL);     pr_warn("liuyang:request_irq ret = %d,hall_irq = %d\n!", ret, hall_irq_num);     if (ret > 0)      pr_err("HALL-EINT IRQ LINE NOT AVAILABLE!!\n");  mt_eint_unmask(HALL_EINT_NUM);  pr_warn("hall_sensor probe success!"); #endif #ifdef KPD_HAS_HALL_FUN  int j;  int result;         //create a class to avoid event drop by uevent_ops->filter function (dev_uevent_filter())     hall_class = class_create(THIS_MODULE, HALL_CLASS_NAME);     if (IS_ERR(hall_class)) {         printk("cannot create hall class\n");        //  goto exit_class_create_failed;     }

    #if 0  hall_device = device_create(hall_class, NULL,     MKDEV(MISC_MAJOR, MISC_DYNAMIC_MINOR), NULL,     HALL_DEVICE_NAME);  if (IS_ERR(hall_device)) {         printk("cannot create hall  device\n");        //  goto exit_inv_device_create_failed;  }     #endif

 hall_device = kzalloc(sizeof(struct device), GFP_KERNEL);  if (!hall_device) {         printk("HZF cannot allocate hall device\n");          goto exit_device_register_failed;     }        hall_device->init_name = HALL_DEVICE_NAME;     hall_device->class = hall_class;     hall_device->release = (void (*)(struct device *))kfree;     result = device_register(hall_device);  if (result) {          printk("HZF cannot register hall device\n");             goto exit_device_register_failed;  }            result = 0;  for (j = 0; j < ARRAY_SIZE(hall_dev_attributes); j++) {   result = device_create_file(hall_device,hall_dev_attributes[j]);   if (result)               break;  }  if (result) {         while (--j >= 0)             device_remove_file(hall_device, hall_dev_attributes[j]);          printk("cannot create hall attr.\n");                 goto exit_create_file_failed;  }     return 0;     exit_create_file_failed:     device_unregister(hall_device);     exit_device_register_failed:     class_destroy(hall_class); 

#endif  return err;

 

}

 

完整alps/kernel-3.10/drivers/misc/mediatek/keypad/kpd.c如下:

 

#include <linux/kpd.h> #ifdef CONFIG_HAS_WAKELOCK #include <linux/wakelock.h> #else #include <linux/pm_wakeup.h> #endif #ifdef CONFIG_OF #include <linux/of.h> #include <linux/of_address.h> #include <linux/of_irq.h> #endif

#define KPD_NAME "mtk-kpd" #define MTK_KP_WAKESOURCE /* this is for auto set wake up source */

//huangzifan #include <linux/slab.h>

#define KPD_HAS_HALL_FUN

#ifdef KPD_HAS_HALL_FUN //#define HALL_KEY 0 #include <linux/irqchip/mt-eic.h>

#define HALL_EINT_NUM     11 #define HALL_EINT_PIN     (GPIO11|0x80000000) static void kpd_flip_handler(unsigned long data); static DECLARE_TASKLET(kpd_flip_tasklet, kpd_flip_handler, 0); static bool kpd_flip_state = true;

#define HALL_CLASS_NAME  "hall_class" #define HALL_DEVICE_NAME  "hall_device"

static struct class *hall_class; static struct device *hall_device; static unsigned int hall_irq_num; /* static ssize_t hall_state_store(struct device *dev,  struct device_attribute *attr, const char *buf, size_t count) {  return 0; } */ static ssize_t hall_state_show(struct device *dev,  struct device_attribute *attr, char *buf) {       int hall_state=0;       hall_state  = kpd_flip_state+2;       return sprintf(buf, "%d\n", hall_state); }

static DEVICE_ATTR(hall_state, S_IRUGO | S_IWUSR, hall_state_show, NULL);

static struct device_attribute *hall_dev_attributes[] = {  &dev_attr_hall_state, }; #endif #ifdef CONFIG_OF void __iomem *kp_base; static unsigned int kp_irqnr; #endif struct input_dev *kpd_input_dev; static bool kpd_suspend; static int kpd_show_hw_keycode = 1; static int kpd_show_register = 1; static volatile int call_status; #ifdef CONFIG_HAS_WAKELOCK struct wake_lock kpd_suspend_lock; /* For suspend usage */ #else struct wakeup_source kpd_suspend_lock; #endif

/*for kpd_memory_setting() function*/ static u16 kpd_keymap[KPD_NUM_KEYS]; static u16 kpd_keymap_state[KPD_NUM_MEMS]; /***********************************/

/* for slide QWERTY */ #if KPD_HAS_SLIDE_QWERTY static void kpd_slide_handler(unsigned long data); static DECLARE_TASKLET(kpd_slide_tasklet, kpd_slide_handler, 0); static u8 kpd_slide_state = !KPD_SLIDE_POLARITY; #endif #if !defined(CONFIG_MTK_LEGACY) struct keypad_dts_data kpd_dts_data; #endif /* for Power key using EINT */ #if KPD_PWRKEY_USE_EINT static void kpd_pwrkey_handler(unsigned long data); static DECLARE_TASKLET(kpd_pwrkey_tasklet, kpd_pwrkey_handler, 0); #endif

/* for keymap handling */ static void kpd_keymap_handler(unsigned long data); static DECLARE_TASKLET(kpd_keymap_tasklet, kpd_keymap_handler, 0);

/*********************************************************************/ static void kpd_memory_setting(void);

/*********************************************************************/ static int kpd_pdrv_probe(struct platform_device *pdev); static int kpd_pdrv_remove(struct platform_device *pdev); static int kpd_pdrv_suspend(struct platform_device *pdev, pm_message_t state); static int kpd_pdrv_resume(struct platform_device *pdev);

#ifdef CONFIG_OF static const struct of_device_id kpd_of_match[] = {  {.compatible = "mediatek,KP",},  {.compatible = "mediatek,mt6755-keypad",},  {}, }; #endif

static struct platform_driver kpd_pdrv = {  .probe = kpd_pdrv_probe,  .remove = kpd_pdrv_remove,  .suspend = kpd_pdrv_suspend,  .resume = kpd_pdrv_resume,  .driver = {      .name = KPD_NAME,      .owner = THIS_MODULE, #ifdef CONFIG_OF      .of_match_table = kpd_of_match, #endif      }, };

/********************************************************************/ static void kpd_memory_setting(void) {  kpd_init_keymap(kpd_keymap);  kpd_init_keymap_state(kpd_keymap_state);  return; }

/*****************for kpd auto set wake up source*************************/

static ssize_t kpd_store_call_state(struct device_driver *ddri, const char *buf, size_t count) {  if (sscanf(buf, "%u", &call_status) != 1) {   kpd_print("kpd call state: Invalid values\n");   return -EINVAL;  }

 switch (call_status) {  case 1:   kpd_print("kpd call state: Idle state!\n");   break;  case 2:   kpd_print("kpd call state: ringing state!\n");   break;  case 3:   kpd_print("kpd call state: active or hold state!\n");   break;

 default:   kpd_print("kpd call state: Invalid values\n");   break;  }  return count; }

static ssize_t kpd_show_call_state(struct device_driver *ddri, char *buf) {  ssize_t res;  res = snprintf(buf, PAGE_SIZE, "%d\n", call_status);  return res; }

static DRIVER_ATTR(kpd_call_state, S_IWUSR | S_IRUGO, kpd_show_call_state, kpd_store_call_state);

static struct driver_attribute *kpd_attr_list[] = {  &driver_attr_kpd_call_state, };

/*----------------------------------------------------------------------------*/ static int kpd_create_attr(struct device_driver *driver) {  int idx, err = 0;  int num = (int)(sizeof(kpd_attr_list) / sizeof(kpd_attr_list[0]));  if (driver == NULL)   return -EINVAL;

 for (idx = 0; idx < num; idx++) {   err = driver_create_file(driver, kpd_attr_list[idx]);   if (err) {    kpd_info("driver_create_file (%s) = %d\n", kpd_attr_list[idx]->attr.name, err);    break;   }  }  return err; }

/*----------------------------------------------------------------------------*/ static int kpd_delete_attr(struct device_driver *driver) {  int idx, err = 0;  int num = (int)(sizeof(kpd_attr_list) / sizeof(kpd_attr_list[0]));

 if (!driver)   return -EINVAL;

 for (idx = 0; idx < num; idx++)   driver_remove_file(driver, kpd_attr_list[idx]);

 return err; }

/*----------------------------------------------------------------------------*/ /********************************************************************************************/ /************************************************************************************************************************************************/ /* for autotest */ #if KPD_AUTOTEST static const u16 kpd_auto_keymap[] = {  KEY_MENU,  KEY_HOME, KEY_BACK,  KEY_CALL, KEY_ENDCALL,  KEY_VOLUMEUP, KEY_VOLUMEDOWN,  KEY_FOCUS, KEY_CAMERA, }; #endif /* for AEE manual dump */ #define AEE_VOLUMEUP_BIT 0 #define AEE_VOLUMEDOWN_BIT 1 #define AEE_DELAY_TIME  15 /* enable volup + voldown was pressed 5~15 s Trigger aee manual dump */ #define AEE_ENABLE_5_15  1 static struct hrtimer aee_timer; static unsigned long aee_pressed_keys; static bool aee_timer_started;

#if AEE_ENABLE_5_15 #define AEE_DELAY_TIME_5S 5 static struct hrtimer aee_timer_5s; static bool aee_timer_5s_started; static bool flags_5s; #endif

static inline void kpd_update_aee_state(void) {  if (aee_pressed_keys == ((1 << AEE_VOLUMEUP_BIT) | (1 << AEE_VOLUMEDOWN_BIT))) {   /* if volumeup and volumedown was pressed the same time then start the time of ten seconds */   aee_timer_started = true;

#if AEE_ENABLE_5_15   aee_timer_5s_started = true;   hrtimer_start(&aee_timer_5s, ktime_set(AEE_DELAY_TIME_5S, 0), HRTIMER_MODE_REL); #endif   hrtimer_start(&aee_timer, ktime_set(AEE_DELAY_TIME, 0), HRTIMER_MODE_REL);   kpd_print("aee_timer started\n");  } else {   if (aee_timer_started) { /*   * hrtimer_cancel - cancel a timer and wait for the handler to finish.   * Returns:   * 0 when the timer was not active.   * 1 when the timer was active.  */    if (hrtimer_cancel(&aee_timer)) {     kpd_print("try to cancel hrtimer\n"); #if AEE_ENABLE_5_15     if (flags_5s) {      kpd_print("Pressed Volup + Voldown5s~15s then trigger aee manual dump.\n");      aee_kernel_reminding("manual dump", "Trigger Vol Up +Vol Down 5s");     } #endif

   } #if AEE_ENABLE_5_15    flags_5s = false; #endif    aee_timer_started = false;    kpd_print("aee_timer canceled\n");   } #if AEE_ENABLE_5_15   if (aee_timer_5s_started) { /*   * hrtimer_cancel - cancel a timer and wait for the handler to finish.   * Returns:   * 0 when the timer was not active.   * 1 when the timer was active.  */    if (hrtimer_cancel(&aee_timer_5s))     kpd_print("try to cancel hrtimer (5s)\n");    aee_timer_5s_started = false;    kpd_print("aee_timer canceled (5s)\n");   } #endif  } }

static void kpd_aee_handler(u32 keycode, u16 pressed) {  if (pressed) {   if (keycode == KEY_VOLUMEUP)    __set_bit(AEE_VOLUMEUP_BIT, &aee_pressed_keys);   else if (keycode == KEY_VOLUMEDOWN)    __set_bit(AEE_VOLUMEDOWN_BIT, &aee_pressed_keys);   else    return;   kpd_update_aee_state();  } else {   if (keycode == KEY_VOLUMEUP)    __clear_bit(AEE_VOLUMEUP_BIT, &aee_pressed_keys);   else if (keycode == KEY_VOLUMEDOWN)    __clear_bit(AEE_VOLUMEDOWN_BIT, &aee_pressed_keys);   else    return;   kpd_update_aee_state();  } }

static enum hrtimer_restart aee_timer_func(struct hrtimer *timer) {  /* kpd_info("kpd: vol up+vol down AEE manual dump!\n"); */  /* aee_kernel_reminding("manual dump ", "Triggered by press KEY_VOLUMEUP+KEY_VOLUMEDOWN"); */  aee_trigger_kdb();  return HRTIMER_NORESTART; }

#if AEE_ENABLE_5_15 static enum hrtimer_restart aee_timer_5s_func(struct hrtimer *timer) {

 /* kpd_info("kpd: vol up+vol down AEE manual dump timer 5s !\n"); */  flags_5s = true;  return HRTIMER_NORESTART; } #endif

/************************************************************************/

#if KPD_HAS_SLIDE_QWERTY static void kpd_slide_handler(unsigned long data) {  bool slid;  u8 old_state = kpd_slide_state;

 kpd_slide_state = !kpd_slide_state;  slid = (kpd_slide_state == !!KPD_SLIDE_POLARITY);  /* for SW_LID, 1: lid open => slid, 0: lid shut => closed */  input_report_switch(kpd_input_dev, SW_LID, slid);  input_sync(kpd_input_dev);  kpd_print("report QWERTY = %s\n", slid ? "slid" : "closed");

 if (old_state)   mt_set_gpio_pull_select(GPIO_QWERTYSLIDE_EINT_PIN, 0);  else   mt_set_gpio_pull_select(GPIO_QWERTYSLIDE_EINT_PIN, 1);  /* for detecting the return to old_state */  mt65xx_eint_set_polarity(KPD_SLIDE_EINT, old_state);  mt65xx_eint_unmask(KPD_SLIDE_EINT); }

static void kpd_slide_eint_handler(void) {  tasklet_schedule(&kpd_slide_tasklet); } #endif

#if KPD_PWRKEY_USE_EINT static void kpd_pwrkey_handler(unsigned long data) {  kpd_pwrkey_handler_hal(data); }

static void kpd_pwrkey_eint_handler(void) {  tasklet_schedule(&kpd_pwrkey_tasklet); } #endif /*********************************************************************/

/*********************************************************************/ #if KPD_PWRKEY_USE_PMIC void kpd_pwrkey_pmic_handler(unsigned long pressed) {  kpd_print("Power Key generate, pressed=%ld\n", pressed);  if (!kpd_input_dev) {   kpd_print("KPD input device not ready\n");   return;  }  kpd_pmic_pwrkey_hal(pressed); } #endif

void kpd_pmic_rstkey_handler(unsigned long pressed) {  kpd_print("PMIC reset Key generate, pressed=%ld\n", pressed);  if (!kpd_input_dev) {   kpd_print("KPD input device not ready\n");   return;  }  kpd_pmic_rstkey_hal(pressed); #ifdef KPD_PMIC_RSTKEY_MAP  kpd_aee_handler(KPD_PMIC_RSTKEY_MAP, pressed); #endif }

/*********************************************************************/

/*********************************************************************/ static void kpd_keymap_handler(unsigned long data) {  int i, j;  bool pressed;  u16 new_state[KPD_NUM_MEMS], change, mask;  u16 hw_keycode,  linux_keycode;  kpd_get_keymap_state(new_state); #ifdef CONFIG_HAS_WAKELOCK  wake_lock_timeout(&kpd_suspend_lock, HZ / 2); #else  __pm_wakeup_event(&kpd_suspend_lock, 500); #endif

 for (i = 0; i < KPD_NUM_MEMS; i++) {   change = new_state[i] ^ kpd_keymap_state[i];   if (!change)    continue;

  for (j = 0; j < 16; j++) {    mask = 1U << j;    if (!(change & mask))     continue;

   hw_keycode = (i << 4) + j;    /* bit is 1: not pressed, 0: pressed */    pressed = !(new_state[i] & mask);    if (kpd_show_hw_keycode)     kpd_print("(%s) HW keycode = %u\n", pressed ? "pressed" : "released", hw_keycode);    BUG_ON(hw_keycode >= KPD_NUM_KEYS);    linux_keycode = kpd_keymap[hw_keycode];    if (unlikely(linux_keycode == 0)) {     kpd_print("Linux keycode = 0\n");     continue;    }    kpd_aee_handler(linux_keycode, pressed);

   kpd_backlight_handler(pressed, linux_keycode);    input_report_key(kpd_input_dev, linux_keycode, pressed);    input_sync(kpd_input_dev);    kpd_print("report Linux keycode = %u\n", linux_keycode);   }  }

 memcpy(kpd_keymap_state, new_state, sizeof(new_state));  kpd_print("save new keymap state\n"); #ifdef CONFIG_OF  enable_irq(kp_irqnr); #else  enable_irq(MT_KP_IRQ_ID); #endif }

static irqreturn_t kpd_irq_handler(int irq, void *dev_id) {  /* use _nosync to avoid deadlock */ #ifdef CONFIG_OF  disable_irq_nosync(kp_irqnr); #else  disable_irq_nosync(MT_KP_IRQ_ID); #endif  tasklet_schedule(&kpd_keymap_tasklet);  return IRQ_HANDLED; }

/*********************************************************************/

/*****************************************************************************************/ long kpd_dev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) {  /* void __user *uarg = (void __user *)arg; */

 switch (cmd) { #if KPD_AUTOTEST  case PRESS_OK_KEY: /* KPD_AUTOTEST disable auto test setting to resolve CR ALPS00464496 */   if (test_bit(KEY_OK, kpd_input_dev->keybit)) {    kpd_print("[AUTOTEST] PRESS OK KEY!!\n");    input_report_key(kpd_input_dev, KEY_OK, 1);    input_sync(kpd_input_dev);   } else {    kpd_print("[AUTOTEST] Not Support OK KEY!!\n");   }   break;  case RELEASE_OK_KEY:   if (test_bit(KEY_OK, kpd_input_dev->keybit)) {    kpd_print("[AUTOTEST] RELEASE OK KEY!!\n");    input_report_key(kpd_input_dev, KEY_OK, 0);    input_sync(kpd_input_dev);   } else {    kpd_print("[AUTOTEST] Not Support OK KEY!!\n");   }   break;  case PRESS_MENU_KEY:   if (test_bit(KEY_MENU, kpd_input_dev->keybit)) {    kpd_print("[AUTOTEST] PRESS MENU KEY!!\n");    input_report_key(kpd_input_dev, KEY_MENU, 1);    input_sync(kpd_input_dev);   } else {    kpd_print("[AUTOTEST] Not Support MENU KEY!!\n");   }   break;  case RELEASE_MENU_KEY:   if (test_bit(KEY_MENU, kpd_input_dev->keybit)) {    kpd_print("[AUTOTEST] RELEASE MENU KEY!!\n");    input_report_key(kpd_input_dev, KEY_MENU, 0);    input_sync(kpd_input_dev);   } else {    kpd_print("[AUTOTEST] Not Support MENU KEY!!\n");   }

  break;  case PRESS_UP_KEY:   if (test_bit(KEY_UP, kpd_input_dev->keybit)) {    kpd_print("[AUTOTEST] PRESS UP KEY!!\n");    input_report_key(kpd_input_dev, KEY_UP, 1);    input_sync(kpd_input_dev);   } else {    kpd_print("[AUTOTEST] Not Support UP KEY!!\n");   }   break;  case RELEASE_UP_KEY:   if (test_bit(KEY_UP, kpd_input_dev->keybit)) {    kpd_print("[AUTOTEST] RELEASE UP KEY!!\n");    input_report_key(kpd_input_dev, KEY_UP, 0);    input_sync(kpd_input_dev);   } else {    kpd_print("[AUTOTEST] Not Support UP KEY!!\n");   }   break;  case PRESS_DOWN_KEY:   if (test_bit(KEY_DOWN, kpd_input_dev->keybit)) {    kpd_print("[AUTOTEST] PRESS DOWN KEY!!\n");    input_report_key(kpd_input_dev, KEY_DOWN, 1);    input_sync(kpd_input_dev);   } else {    kpd_print("[AUTOTEST] Not Support DOWN KEY!!\n");   }   break;  case RELEASE_DOWN_KEY:   if (test_bit(KEY_DOWN, kpd_input_dev->keybit)) {    kpd_print("[AUTOTEST] RELEASE DOWN KEY!!\n");    input_report_key(kpd_input_dev, KEY_DOWN, 0);    input_sync(kpd_input_dev);   } else {    kpd_print("[AUTOTEST] Not Support DOWN KEY!!\n");   }   break;  case PRESS_LEFT_KEY:   if (test_bit(KEY_LEFT, kpd_input_dev->keybit)) {    kpd_print("[AUTOTEST] PRESS LEFT KEY!!\n");    input_report_key(kpd_input_dev, KEY_LEFT, 1);    input_sync(kpd_input_dev);   } else {    kpd_print("[AUTOTEST] Not Support LEFT KEY!!\n");   }   break;  case RELEASE_LEFT_KEY:   if (test_bit(KEY_LEFT, kpd_input_dev->keybit)) {    kpd_print("[AUTOTEST] RELEASE LEFT KEY!!\n");    input_report_key(kpd_input_dev, KEY_LEFT, 0);    input_sync(kpd_input_dev);   } else {    kpd_print("[AUTOTEST] Not Support LEFT KEY!!\n");   }   break;

 case PRESS_RIGHT_KEY:   if (test_bit(KEY_RIGHT, kpd_input_dev->keybit)) {    kpd_print("[AUTOTEST] PRESS RIGHT KEY!!\n");    input_report_key(kpd_input_dev, KEY_RIGHT, 1);    input_sync(kpd_input_dev);   } else {    kpd_print("[AUTOTEST] Not Support RIGHT KEY!!\n");   }   break;  case RELEASE_RIGHT_KEY:   if (test_bit(KEY_RIGHT, kpd_input_dev->keybit)) {    kpd_print("[AUTOTEST] RELEASE RIGHT KEY!!\n");    input_report_key(kpd_input_dev, KEY_RIGHT, 0);    input_sync(kpd_input_dev);   } else {    kpd_print("[AUTOTEST] Not Support RIGHT KEY!!\n");   }   break;  case PRESS_HOME_KEY:   if (test_bit(KEY_HOME, kpd_input_dev->keybit)) {    kpd_print("[AUTOTEST] PRESS HOME KEY!!\n");    input_report_key(kpd_input_dev, KEY_HOME, 1);    input_sync(kpd_input_dev);   } else {    kpd_print("[AUTOTEST] Not Support HOME KEY!!\n");   }   break;  case RELEASE_HOME_KEY:   if (test_bit(KEY_HOME, kpd_input_dev->keybit)) {    kpd_print("[AUTOTEST] RELEASE HOME KEY!!\n");    input_report_key(kpd_input_dev, KEY_HOME, 0);    input_sync(kpd_input_dev);   } else {    kpd_print("[AUTOTEST] Not Support HOME KEY!!\n");   }   break;  case PRESS_BACK_KEY:   if (test_bit(KEY_BACK, kpd_input_dev->keybit)) {    kpd_print("[AUTOTEST] PRESS BACK KEY!!\n");    input_report_key(kpd_input_dev, KEY_BACK, 1);    input_sync(kpd_input_dev);   } else {    kpd_print("[AUTOTEST] Not Support BACK KEY!!\n");   }   break;  case RELEASE_BACK_KEY:   if (test_bit(KEY_BACK, kpd_input_dev->keybit)) {    kpd_print("[AUTOTEST] RELEASE BACK KEY!!\n");    input_report_key(kpd_input_dev, KEY_BACK, 0);    input_sync(kpd_input_dev);   } else {    kpd_print("[AUTOTEST] Not Support BACK KEY!!\n");   }   break;  case PRESS_CALL_KEY:   if (test_bit(KEY_CALL, kpd_input_dev->keybit)) {    kpd_print("[AUTOTEST] PRESS CALL KEY!!\n");    input_report_key(kpd_input_dev, KEY_CALL, 1);    input_sync(kpd_input_dev);   } else {    kpd_print("[AUTOTEST] Not Support CALL KEY!!\n");   }   break;  case RELEASE_CALL_KEY:   if (test_bit(KEY_CALL, kpd_input_dev->keybit)) {    kpd_print("[AUTOTEST] RELEASE CALL KEY!!\n");    input_report_key(kpd_input_dev, KEY_CALL, 0);    input_sync(kpd_input_dev);   } else {    kpd_print("[AUTOTEST] Not Support CALL KEY!!\n");   }   break;

 case PRESS_ENDCALL_KEY:   if (test_bit(KEY_ENDCALL, kpd_input_dev->keybit)) {    kpd_print("[AUTOTEST] PRESS ENDCALL KEY!!\n");    input_report_key(kpd_input_dev, KEY_ENDCALL, 1);    input_sync(kpd_input_dev);   } else {    kpd_print("[AUTOTEST] Not Support ENDCALL KEY!!\n");   }   break;  case RELEASE_ENDCALL_KEY:   if (test_bit(KEY_ENDCALL, kpd_input_dev->keybit)) {    kpd_print("[AUTOTEST] RELEASE ENDCALL KEY!!\n");    input_report_key(kpd_input_dev, KEY_ENDCALL, 0);    input_sync(kpd_input_dev);   } else {    kpd_print("[AUTOTEST] Not Support ENDCALL KEY!!\n");   }   break;  case PRESS_VLUP_KEY:   if (test_bit(KEY_VOLUMEUP, kpd_input_dev->keybit)) {    kpd_print("[AUTOTEST] PRESS VOLUMEUP KEY!!\n");    input_report_key(kpd_input_dev, KEY_VOLUMEUP, 1);    input_sync(kpd_input_dev);   } else {    kpd_print("[AUTOTEST] Not Support VOLUMEUP KEY!!\n");   }   break;  case RELEASE_VLUP_KEY:   if (test_bit(KEY_VOLUMEUP, kpd_input_dev->keybit)) {    kpd_print("[AUTOTEST] RELEASE VOLUMEUP KEY!!\n");    input_report_key(kpd_input_dev, KEY_VOLUMEUP, 0);    input_sync(kpd_input_dev);   } else {    kpd_print("[AUTOTEST] Not Support VOLUMEUP KEY!!\n");   }   break;  case PRESS_VLDOWN_KEY:   if (test_bit(KEY_VOLUMEDOWN, kpd_input_dev->keybit)) {    kpd_print("[AUTOTEST] PRESS VOLUMEDOWN KEY!!\n");    input_report_key(kpd_input_dev, KEY_VOLUMEDOWN, 1);    input_sync(kpd_input_dev);   } else {    kpd_print("[AUTOTEST] Not Support VOLUMEDOWN KEY!!\n");   }   break;  case RELEASE_VLDOWN_KEY:   if (test_bit(KEY_VOLUMEDOWN, kpd_input_dev->keybit)) {    kpd_print("[AUTOTEST] RELEASE VOLUMEDOWN KEY!!\n");    input_report_key(kpd_input_dev, KEY_VOLUMEDOWN, 0);    input_sync(kpd_input_dev);   } else {    kpd_print("[AUTOTEST] Not Support VOLUMEDOWN KEY!!\n");   }   break;  case PRESS_FOCUS_KEY:   if (test_bit(KEY_FOCUS, kpd_input_dev->keybit)) {    kpd_print("[AUTOTEST] PRESS FOCUS KEY!!\n");    input_report_key(kpd_input_dev, KEY_FOCUS, 1);    input_sync(kpd_input_dev);   } else {    kpd_print("[AUTOTEST] Not Support FOCUS KEY!!\n");   }   break;  case RELEASE_FOCUS_KEY:   if (test_bit(KEY_FOCUS, kpd_input_dev->keybit)) {    kpd_print("[AUTOTEST] RELEASE FOCUS KEY!!\n");    input_report_key(kpd_input_dev, KEY_FOCUS, 0);    input_sync(kpd_input_dev);   } else {    kpd_print("[AUTOTEST] Not Support RELEASE KEY!!\n");   }   break;  case PRESS_CAMERA_KEY:   if (test_bit(KEY_CAMERA, kpd_input_dev->keybit)) {    kpd_print("[AUTOTEST] PRESS CAMERA KEY!!\n");    input_report_key(kpd_input_dev, KEY_CAMERA, 1);    input_sync(kpd_input_dev);   } else {    kpd_print("[AUTOTEST] Not Support CAMERA KEY!!\n");   }   break;  case RELEASE_CAMERA_KEY:   if (test_bit(KEY_CAMERA, kpd_input_dev->keybit)) {    kpd_print("[AUTOTEST] RELEASE CAMERA KEY!!\n");    input_report_key(kpd_input_dev, KEY_CAMERA, 0);    input_sync(kpd_input_dev);   } else {    kpd_print("[AUTOTEST] Not Support CAMERA KEY!!\n");   }   break;  case PRESS_POWER_KEY:   if (test_bit(KEY_POWER, kpd_input_dev->keybit)) {    kpd_print("[AUTOTEST] PRESS POWER KEY!!\n");    input_report_key(kpd_input_dev, KEY_POWER, 1);    input_sync(kpd_input_dev);   } else {    kpd_print("[AUTOTEST] Not Support POWER KEY!!\n");   }   break;  case RELEASE_POWER_KEY:   if (test_bit(KEY_POWER, kpd_input_dev->keybit)) {    kpd_print("[AUTOTEST] RELEASE POWER KEY!!\n");    input_report_key(kpd_input_dev, KEY_POWER, 0);    input_sync(kpd_input_dev);   } else {    kpd_print("[AUTOTEST] Not Support POWER KEY!!\n");   }   break; #endif

 case SET_KPD_KCOL:   kpd_auto_test_for_factorymode(); /* API 3 for kpd factory mode auto-test */   kpd_print("[kpd_auto_test_for_factorymode] test performed!!\n");   break;  default:   return -EINVAL;  }

 return 0; }

int kpd_dev_open(struct inode *inode, struct file *file) {  return 0; }

static const struct file_operations kpd_dev_fops = {  .owner = THIS_MODULE,  .unlocked_ioctl = kpd_dev_ioctl,  .open = kpd_dev_open, };

/*********************************************************************/ static struct miscdevice kpd_dev = {  .minor = MISC_DYNAMIC_MINOR,  .name = KPD_NAME,  .fops = &kpd_dev_fops, };

static int kpd_open(struct input_dev *dev) {  kpd_slide_qwerty_init(); /* API 1 for kpd slide qwerty init settings */  return 0; }

#ifdef KPD_HAS_HALL_FUN

static irqreturn_t kpd_flip_eint_handler(int irq, void *dev_id) {    tasklet_schedule(&kpd_flip_tasklet); }

static void kpd_flip_handler(unsigned long data) {     bool old_state = kpd_flip_state;      int Mhall_key_level;     int ret = 0;

    kpd_flip_state = !kpd_flip_state;

 Mhall_key_level = mt_get_gpio_in(HALL_EINT_PIN);  

    pr_warn("\n chenhaibing kpd_flip_handler report   ");   #if 1     if (kpd_flip_state)     {       input_report_switch(kpd_input_dev, SW_LID, 0);       pr_warn("\n glove is close! report kpd_flip_state=%d, flip state= %d\n", kpd_flip_state,old_state);     }     else     {       input_report_switch(kpd_input_dev, SW_LID, 1);       pr_warn("\n glove is open!report kpd_flip_state=%d, flip state= %d\n", kpd_flip_state,old_state);     } #endif

    input_sync(kpd_input_dev);     pr_warn("chenhaibing hall_key_level = %d", Mhall_key_level);     pr_warn("chenhaibing hall flip key handler:%d,%d\n",old_state,kpd_flip_state); #ifdef BIRD_HALL_CHANGE_TP_PARAM //gtp_change_param(Mhall_key_level); #endif

    if (old_state){      //mt_eint_registration(HALL_EINT_NUM, CUST_EINTF_TRIGGER_HIGH, kpd_flip_eint_handler, false);      ret = request_irq(hall_irq_num, (irq_handler_t)kpd_flip_eint_handler, CUST_EINTF_TRIGGER_HIGH, "hall-eint", NULL);      if (ret > 0)       pr_err("HALL-EINT IRQ LINE NOT AVAILABLE!!\n");     }else{      //mt_eint_registration(HALL_EINT_NUM, CUST_EINTF_TRIGGER_LOW, kpd_flip_eint_handler, false);         ret = request_irq(hall_irq_num, (irq_handler_t)kpd_flip_eint_handler, CUST_EINTF_TRIGGER_LOW, "hall-eint", NULL);         if (ret > 0)       pr_err("HALL-EINT IRQ LINE NOT AVAILABLE!!\n");     }      mt_eint_unmask(HALL_EINT_NUM);     }

#endif

 

#if !defined(CONFIG_MTK_LEGACY) void kpd_get_dts_info(void) {  struct device_node *node;  node = of_find_compatible_node(NULL, NULL, "mediatek, kpd");  if (node) {   of_property_read_u32(node, "kpd-key-debounce", &kpd_dts_data.kpd_key_debounce);   of_property_read_u32(node, "kpd-sw-pwrkey", &kpd_dts_data.kpd_sw_pwrkey);   of_property_read_u32(node, "kpd-hw-pwrkey", &kpd_dts_data.kpd_hw_pwrkey);   of_property_read_u32(node, "kpd-sw-rstkey", &kpd_dts_data.kpd_sw_rstkey);   of_property_read_u32(node, "kpd-hw-rstkey", &kpd_dts_data.kpd_hw_rstkey);   of_property_read_u32(node, "kpd-use-extend-type", &kpd_dts_data.kpd_use_extend_type);   of_property_read_u32(node, "kpd-pwrkey-eint-gpio", &kpd_dts_data.kpd_pwrkey_eint_gpio);   of_property_read_u32(node, "kpd-pwrkey-gpio-din", &kpd_dts_data.kpd_pwrkey_gpio_din);   of_property_read_u32(node, "kpd-hw-dl-key1", &kpd_dts_data.kpd_hw_dl_key1);   of_property_read_u32(node, "kpd-hw-dl-key2", &kpd_dts_data.kpd_hw_dl_key2);   of_property_read_u32(node, "kpd-hw-dl-key3", &kpd_dts_data.kpd_hw_dl_key3);   of_property_read_u32(node, "kpd-hw-recovery-key", &kpd_dts_data.kpd_hw_recovery_key);   of_property_read_u32(node, "kpd-hw-factory-key", &kpd_dts_data.kpd_hw_factory_key);   of_property_read_u32_array(node, "kpd-hw-init-map", kpd_dts_data.kpd_hw_init_map,         ARRAY_SIZE(kpd_dts_data.kpd_hw_init_map));

  kpd_info       ("key-debounce = %d, sw-pwrkey = %d, hw-pwrkey = %d, hw-rstkey = %d, sw-rstkey = %d\n",        kpd_dts_data.kpd_key_debounce, kpd_dts_data.kpd_sw_pwrkey, kpd_dts_data.kpd_hw_pwrkey,        kpd_dts_data.kpd_hw_rstkey, kpd_dts_data.kpd_sw_rstkey);  } else {   kpd_info("[kpd]%s can't find compatible custom node\n", __func__);  } } #endif static int kpd_pdrv_probe(struct platform_device *pdev) {

 int i, r;  int err = 0;  int ret = 0;    kpd_info("Keypad probe start!!!\n"); #ifdef CONFIG_OF  kp_base = of_iomap(pdev->dev.of_node, 0);  if (!kp_base) {   kpd_info("KP iomap failed\n");   return -ENODEV;  };

 kp_irqnr = irq_of_parse_and_map(pdev->dev.of_node, 0);  if (!kp_irqnr) {   kpd_info("KP get irqnr failed\n");   return -ENODEV;  }  kpd_info("kp base: 0x%p, addr:0x%p,  kp irq: %d\n", kp_base, &kp_base, kp_irqnr); #endif #if defined(CONFIG_MTK_LEGACY) /*This not need now */ #ifdef CONFIG_MTK_LDVT  kpd_ldvt_test_init(); /* API 2 for kpd LFVT test enviroment settings */ #endif #endif  /* initialize and register input device (/dev/input/eventX) */  kpd_input_dev = input_allocate_device();  if (!kpd_input_dev)   return -ENOMEM;

 kpd_input_dev->name = KPD_NAME;  kpd_input_dev->id.bustype = BUS_HOST;  kpd_input_dev->id.vendor = 0x2454;  kpd_input_dev->id.product = 0x6500;  kpd_input_dev->id.version = 0x0010;  kpd_input_dev->open = kpd_open; #if !defined(CONFIG_MTK_LEGACY)  kpd_get_dts_info(); #endif  /* fulfill custom settings */  kpd_memory_setting();

 __set_bit(EV_KEY, kpd_input_dev->evbit);

#ifdef KPD_HAS_HALL_FUN  __set_bit(EV_SW , kpd_input_dev->evbit);  __set_bit(SW_LID , kpd_input_dev->swbit); #endif #if (KPD_PWRKEY_USE_EINT || KPD_PWRKEY_USE_PMIC) #if !defined(CONFIG_MTK_LEGACY)  __set_bit(kpd_dts_data.kpd_sw_pwrkey, kpd_input_dev->keybit); #else  __set_bit(KPD_PWRKEY_MAP, kpd_input_dev->keybit); #endif  kpd_keymap[8] = 0; #endif #if !defined(CONFIG_MTK_LEGACY)  if (!kpd_dts_data.kpd_use_extend_type) {   for (i = 17; i < KPD_NUM_KEYS; i += 9) /* only [8] works for Power key */    kpd_keymap[i] = 0;  } #else #if !KPD_USE_EXTEND_TYPE  for (i = 17; i < KPD_NUM_KEYS; i += 9) /* only [8] works for Power key */   kpd_keymap[i] = 0; #endif #endif  for (i = 0; i < KPD_NUM_KEYS; i++) {   if (kpd_keymap[i] != 0)    __set_bit(kpd_keymap[i], kpd_input_dev->keybit);  }

#if KPD_AUTOTEST  for (i = 0; i < ARRAY_SIZE(kpd_auto_keymap); i++)   __set_bit(kpd_auto_keymap[i], kpd_input_dev->keybit); #endif

#if KPD_HAS_SLIDE_QWERTY  __set_bit(EV_SW, kpd_input_dev->evbit);  __set_bit(SW_LID, kpd_input_dev->swbit); #endif #if !defined(CONFIG_MTK_LEGACY)  if (kpd_dts_data.kpd_sw_rstkey)   __set_bit(kpd_dts_data.kpd_sw_rstkey, kpd_input_dev->keybit); #else #ifdef KPD_PMIC_RSTKEY_MAP  __set_bit(KPD_PMIC_RSTKEY_MAP, kpd_input_dev->keybit); #endif #endif #ifdef KPD_KEY_MAP  __set_bit(KPD_KEY_MAP, kpd_input_dev->keybit); #endif

#ifdef CONFIG_MTK_MRDUMP_KEY  __set_bit(KEY_RESTART, kpd_input_dev->keybit); #endif

 kpd_input_dev->dev.parent = &pdev->dev;  r = input_register_device(kpd_input_dev);  if (r) {   kpd_info("register input device failed (%d)\n", r);   input_free_device(kpd_input_dev);   return r;  }

 /* register device (/dev/mt6575-kpd) */  kpd_dev.parent = &pdev->dev;  r = misc_register(&kpd_dev);  if (r) {   kpd_info("register device failed (%d)\n", r);   input_unregister_device(kpd_input_dev);   return r;  } #ifdef CONFIG_HAS_WAKELOCK  wake_lock_init(&kpd_suspend_lock, WAKE_LOCK_SUSPEND, "kpd wakelock"); #else  wakeup_source_init(&kpd_suspend_lock, "kpd wakelock"); #endif

 /* register IRQ and EINT */ #if !defined(CONFIG_MTK_LEGACY)  kpd_set_debounce(kpd_dts_data.kpd_key_debounce); #else  kpd_set_debounce(KPD_KEY_DEBOUNCE); #endif #ifdef CONFIG_OF  r = request_irq(kp_irqnr, kpd_irq_handler, IRQF_TRIGGER_NONE, KPD_NAME, NULL); #else  r = request_irq(MT_KP_IRQ_ID, kpd_irq_handler, IRQF_TRIGGER_FALLING, KPD_NAME, NULL); #endif  if (r) {   kpd_info("register IRQ failed (%d)\n", r);   misc_deregister(&kpd_dev);   input_unregister_device(kpd_input_dev);   return r;  }  mt_eint_register();

#ifndef KPD_EARLY_PORTING /*add for avoid early porting build err the macro is defined in custom file */  long_press_reboot_function_setting(); /* /API 4 for kpd long press reboot function setting */ #endif  hrtimer_init(&aee_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);  aee_timer.function = aee_timer_func;

#if AEE_ENABLE_5_15  hrtimer_init(&aee_timer_5s, CLOCK_MONOTONIC, HRTIMER_MODE_REL);  aee_timer_5s.function = aee_timer_5s_func; #endif  err = kpd_create_attr(&kpd_pdrv.driver);  if (err) {   kpd_info("create attr file fail\n");   kpd_delete_attr(&kpd_pdrv.driver);   return err;  }  kpd_info("%s Done\n", __func__); #ifdef KPD_HAS_HALL_FUN  mt_set_gpio_mode(HALL_EINT_PIN, GPIO_MODE_00);  mt_set_gpio_dir(HALL_EINT_PIN, GPIO_DIR_IN);  mt_set_gpio_pull_enable(HALL_EINT_PIN, GPIO_PULL_ENABLE);  mt_set_gpio_pull_select(HALL_EINT_PIN, GPIO_PULL_UP);  mt_eint_set_hw_debounce(HALL_EINT_NUM, 0);     //mt_eint_registration(HALL_EINT_NUM, CUST_EINTF_TRIGGER_LOW, kpd_flip_eint_handler, false);     hall_irq_num = mt_gpio_to_irq(HALL_EINT_NUM);     ret = request_irq(hall_irq_num, (irq_handler_t)kpd_flip_eint_handler, CUST_EINTF_TRIGGER_LOW, "hall-eint", NULL);     pr_warn("liuyang:request_irq ret = %d,hall_irq = %d\n!", ret, hall_irq_num);     if (ret > 0)      pr_err("HALL-EINT IRQ LINE NOT AVAILABLE!!\n");  mt_eint_unmask(HALL_EINT_NUM);  pr_warn("hall_sensor probe success!"); #endif #ifdef KPD_HAS_HALL_FUN  int j;  int result;         //create a class to avoid event drop by uevent_ops->filter function (dev_uevent_filter())     hall_class = class_create(THIS_MODULE, HALL_CLASS_NAME);     if (IS_ERR(hall_class)) {         printk("cannot create hall class\n");        //  goto exit_class_create_failed;     }

    #if 0  hall_device = device_create(hall_class, NULL,     MKDEV(MISC_MAJOR, MISC_DYNAMIC_MINOR), NULL,     HALL_DEVICE_NAME);  if (IS_ERR(hall_device)) {         printk("cannot create hall  device\n");        //  goto exit_inv_device_create_failed;  }     #endif

 hall_device = kzalloc(sizeof(struct device), GFP_KERNEL);  if (!hall_device) {         printk("HZF cannot allocate hall device\n");          goto exit_device_register_failed;     }        hall_device->init_name = HALL_DEVICE_NAME;     hall_device->class = hall_class;     hall_device->release = (void (*)(struct device *))kfree;     result = device_register(hall_device);  if (result) {          printk("HZF cannot register hall device\n");             goto exit_device_register_failed;  }            result = 0;  for (j = 0; j < ARRAY_SIZE(hall_dev_attributes); j++) {   result = device_create_file(hall_device,hall_dev_attributes[j]);   if (result)               break;  }  if (result) {         while (--j >= 0)             device_remove_file(hall_device, hall_dev_attributes[j]);          printk("cannot create hall attr.\n");                 goto exit_create_file_failed;  }     return 0;     exit_create_file_failed:     device_unregister(hall_device);     exit_device_register_failed:     class_destroy(hall_class); 

#endif  return err; }

/* should never be called */ static int kpd_pdrv_remove(struct platform_device *pdev) {  return 0; }

static int kpd_pdrv_suspend(struct platform_device *pdev, pm_message_t state) {  kpd_suspend = true; #ifdef MTK_KP_WAKESOURCE  if (call_status == 2) {   kpd_print("kpd_pdrv_suspend wake up source enable!! (%d)\n", kpd_suspend);  } else {   kpd_wakeup_src_setting(0);   kpd_print("kpd_pdrv_suspend wake up source disable!! (%d)\n", kpd_suspend);  } #endif  kpd_disable_backlight();  kpd_print("suspend!! (%d)\n", kpd_suspend);  return 0; }

static int kpd_pdrv_resume(struct platform_device *pdev) {  kpd_suspend = false; #ifdef MTK_KP_WAKESOURCE  if (call_status == 2) {   kpd_print("kpd_pdrv_suspend wake up source enable!! (%d)\n", kpd_suspend);  } else {   kpd_print("kpd_pdrv_suspend wake up source resume!! (%d)\n", kpd_suspend);   kpd_wakeup_src_setting(1);  } #endif  kpd_print("resume!! (%d)\n", kpd_suspend);  return 0; }

#ifdef CONFIG_MTK_SMARTBOOK_SUPPORT #ifdef CONFIG_HAS_SBSUSPEND static struct sb_handler kpd_sb_handler_desc = {  .level = SB_LEVEL_DISABLE_KEYPAD,  .plug_in = sb_kpd_enable,  .plug_out = sb_kpd_disable, }; #endif #endif

static int __init kpd_mod_init(void) {  int r;

 r = platform_driver_register(&kpd_pdrv);  if (r) {   kpd_info("register driver failed (%d)\n", r);   return r;  }

#ifdef CONFIG_MTK_SMARTBOOK_SUPPORT #ifdef CONFIG_HAS_SBSUSPEND  register_sb_handler(&kpd_sb_handler_desc); #endif #endif

 return 0; }

/* should never be called */ static void __exit kpd_mod_exit(void) { }

module_init(kpd_mod_init); module_exit(kpd_mod_exit);

module_param(kpd_show_hw_keycode, int, 0644); module_param(kpd_show_register, int, 0644);

MODULE_AUTHOR("yucong.xiong <yucong.xiong@mediatek.com>"); MODULE_DESCRIPTION("MTK Keypad (KPD) Driver v0.4"); MODULE_LICENSE("GPL");

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值