2 alwayszxp Alwayszxp 于 2013.12.07 00:32 提问

android input模块开启等待线程卡死

这几天在写一个input驱动程序,功能是用一个中断读取三个按键的键值并且上报,自己的想法是在模块开启时开启一个等待线程并且睡眠,当中断到来时唤醒它用timer扫描按键值。写好烧进手机后手机一直无法开机,在启动时卡死并且重启。去掉这个等待线程程序就运行正常了,本人对等待线程这一块不是很理解,希望各位大神指导。另外,当读到键值的时候使用input_key_report函数上报的时候没有反应,不知道是不是设备注册有什么问题·····头好痛····
代码如下:

#include "ExternalPanel.h"
#include
//#include
#include
#include
#include

#define EXPANEL_NAME "external_panel"

#define KEY_PRESS_FLAG 1
#define KEY_RELEASE_FLAG 0
//#define KEY_NEXT_FLAG 1
//#define KEY_PAUSE_FLAG 2
#define KEY_PRESS_PAUSE 0
#define KEY_PRESS_UP 1
#define KEY_PRESS_DOWN 2
#define KEY_PRESS_NONE 3
/*

    MD              UP                DW

|---------||-----------||----------|
0V<=MD< =0.2V 0.3V<= UP<=0.6V 0.8<=DW <=1.4V

*/

#define DW_KEY_HIGH_THR (1400) //1400000uv
#define DW_KEY_THR (800) //
#define UP_KEY_HIGH_THR (600) //
#define UP_KEY_THR (300)
#define MD_KEY_HIGH_THR (200)
#define MD_KEY_THR (0)

#define EXPANEL_KEY_ADC_CHANNEL 0
#define KEY_REF_VOLT 1500
static struct input_dev *expanel_input_dev;
struct workquenue_struct *expanel_eint_workquenue;
struct work_struct expanel_enit_work;
struct wake_lock expanel_irq_lock;
static struct hrtimer key_scan_timer;
static wait_queue_head_t scan_queue;
static struct task_struct *scan_kthread;
static int scan_state=0;

//static u8 expanel_state = !KPD_SLIDE_POLARITY;
static int expanel_input_open(struct input_dev dev);
extern void mt65xx_eint_unmask(unsigned int line);
extern void mt65xx_eint_mask(unsigned int line);
extern void mt65xx_eint_set_polarity(kal_uint8 eintno, kal_bool ACT_Polarity);
extern void mt65xx_eint_set_hw_debounce(kal_uint8 eintno, kal_uint32 ms);
extern kal_uint32 mt65xx_eint_set_sens(kal_uint8 eintno, kal_bool sens);
extern void mt65xx_eint_registration(kal_uint8 eintno, kal_bool Dbounce_En,
kal_bool ACT_Polarity, void (EINT_FUNC_PTR)(void),
kal_bool auto_umask);
static void expanel_eint_handler(void);
void expanel_eint_work_callback(struct work_struct *work);
int check_key_type(int b);
int getExPanelVoltage(void);
void report_key_event(int keycode,int flag);
static void expanel_key_detection(void);
//extern int PMIC_IMM_GetOneChannelValue(int dwChannel, int deCount, int trimd);
extern int IMM_GetOneChannelValue(int dwChannel, int data[4], int
rawdata);
void key_scan_hrtimer_init(void);
enum hrtimer_restart key_scan_hrtimer_func(struct hrtimer *timer);
int key_wait_scan_thread(void *x);
int key_get_voltage(void);
static int expanel_probe(struct platform_device *pdev)
{
ExPanel_DEBUG("expanel_input!\n");
expanel_input_dev = input_allocate_device();
if (!expanel_input_dev)
{
ExPanel_DEBUG("expanel_input_device alloc failed!\n");
return 12;
}
//define multi-key keycode
set_bit(EV_KEY, expanel_input_dev->evbit);
//
set_bit(KEY_CALL, expanel_input_dev->keybit);
//__set_bit(KEY_ENDCALL, expanel_input_dev->keybit);
// set_bit(KEY_NEXTSONG, expanel_input_dev->keybit);
// __set_bit(KEY_PREVIOUSSONG, expanel_input_dev->keybit);
__set_bit(KEY_PLAYPAUSE, expanel_input_dev->keybit);
//
set_bit(KEY_STOPCD, expanel_input_dev->keybit);
__set_bit(KEY_VOLUMEDOWN, expanel_input_dev->keybit);
__set_bit(KEY_VOLUMEUP, expanel_input_dev->keybit);

expanel_input_dev->id.bustype = BUS_HOST;
expanel_input_dev->name = "expanel_key";
//expanel_input_dev->open = expanel_input_open;
expanel_input_dev->dev.parent = &pdev->dev;
if(input_register_device(expanel_input_dev))
{
    ExPanel_DEBUG("expanel_input_dev register : fail!\n");
}else
{
    ExPanel_DEBUG("expanel_input_devregister : success!!\n");
} 

 expanel_eint_workquenue = create_singlethread_workqueue("expanel_eint");
  INIT_WORK(&expanel_enit_work, expanel_eint_work_callback);

   wake_lock_init(&expanel_irq_lock, WAKE_LOCK_SUSPEND, "expanel irq wakelock");


   scan_state=0;
  mt65xx_eint_set_sens(CUST_EINT_EXPANEL_NUM , CUST_EINT_EXPANEL_SENSITIVE);
  mt65xx_eint_set_hw_debounce(CUST_EINT_EXPANEL_NUM, 10);
  mt65xx_eint_registration(CUST_EINT_EXPANEL_NUM, true, CUST_EINT_EXPANEL_POLARITY, 
            expanel_eint_handler, false);
mt65xx_eint_unmask(CUST_EINT_EXPANEL_NUM);  
   scan_kthread=kthread_run(key_wait_scan_thread, NULL, "key_wait_scan_thread");


return 0;

}

static int expanel_input_open(struct input_dev dev)
{
/

wake_lock_init(&expanel_irq_lock, WAKE_LOCK_SUSPEND, "expanel irq wakelock");

   scan_state=0;
   init_waitqueue_head(&scan_queue);
  mt65xx_eint_set_sens(CUST_EINT_EXPANEL_NUM , CUST_EINT_EXPANEL_SENSITIVE);
  mt65xx_eint_set_hw_debounce(CUST_EINT_EXPANEL_NUM, 10);
  mt65xx_eint_registration(CUST_EINT_EXPANEL_NUM, true, CUST_EINT_EXPANEL_POLARITY, 
            expanel_eint_handler, false);
mt65xx_eint_unmask(CUST_EINT_EXPANEL_NUM);  
 key_wait_scan_thread();

*/

return 0;

}

void expanel_eint_handler(void)
{

ExPanel_DEBUG( " [ExPanel] expanel_key_handler \n");
/*
//mt65xx_eint_mask(CUST_EINT_EXPANEL_NUM);
scan_state=0;
//wake_up(&scan_queue);

 wake_lock(&expanel_irq_lock);
 // expanel_key_detection();
 if(0==scan_state)
{
ExPanel_DEBUG("[Expanel] key_scan_hrtimer_init scan_state:%d\n",scan_state);
//wake_up_interruptible(&scan_queue);
wake_up(&scan_queue);
}
else
  {
    scan_state=0;
  hrtimer_cancel(&key_scan_timer); 
//mt65xx_eint_mask(CUST_EINT_EXPANEL_NUM);
}

//ExPanel_DEBUG( " [ExPanel]  expanel_key_handler \n");

   wake_unlock(&expanel_irq_lock);
ExPanel_DEBUG("[Expanel] Expanel_eint_handler ret:%d\n");
*/
int ret=0;
ret = queue_work(expanel_eint_workquenue, &expanel_enit_work);  
  if(!ret)
  {
    ExPanel_DEBUG("[Expanel] Expanel_eint_handler ret:%d\n",ret);
  }

}
void expanel_eint_work_callback(struct work_struct *work)
{
//int key_type=0;
mt65xx_eint_mask(CUST_EINT_EXPANEL_NUM);

 wake_lock(&expanel_irq_lock);
// wake_up_interruptible(&scan_queue);
 // expanel_key_detection();
if(0==scan_state)
{
ExPanel_DEBUG("[Expanel] key_scan_hrtimer_init scan_state:%d\n",scan_state);
wake_up_interruptible(&scan_queue);
}
else
  {
    scan_state=0;
  key_scan_hrtimer_init();
//mt65xx_eint_mask(CUST_EINT_EXPANEL_NUM);
}
//ExPanel_DEBUG( " [ExPanel]  expanel_key_dection key_type:%d \n",key_type);

wake_unlock(&expanel_irq_lock);
mt65xx_eint_unmask(CUST_EINT_EXPANEL_NUM);

}

int key_wait_scan_thread(void x)
{
ktime_t ktime;
ktime = ktime_set(0, 100*1000*1000); // 3s, 10
1000 ms
hrtimer_init(&key_scan_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
key_scan_timer.function = key_scan_hrtimer_func;
/* Run on a process content */

// mutex_lock(&adckey_mutex);

// mutex_unlock(&adckey_mutex);
//battery_xlog_printk(BAT_LOG_CRTI, "adckey: wait_evnet \n" );

wait_event_interruptible(scan_queue, (0==scan_state));
scan_state=1;
//wait_event(scan_queue, (0==scan_state));
hrtimer_start(&key_scan_timer, ktime, HRTIMER_MODE_REL);
printk("[DEVICE/EXPANEL]:key_wait_scan_thread wake up!\n");

return 0;

}

void key_scan_hrtimer_init(void)
{
ktime_t ktime;
ktime = ktime_set(0, 100*1000*1000); // 3s, 10* 1000 ms
hrtimer_init(&key_scan_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
key_scan_timer.function = key_scan_hrtimer_func;
ExPanel_DEBUG( "key_scan_hrtimer_init : done\n" );
}

enum hrtimer_restart key_scan_hrtimer_func(struct hrtimer *timer)
{
ktime_t ktime;
ktime = ktime_set(0, 100*1000*1000);

ExPanel_DEBUG( " ExPanel_DEBUG: come in key_check!!\n" );

hrtimer_start(&key_scan_timer, ktime, HRTIMER_MODE_REL);
return HRTIMER_NORESTART;
}
int check_key_type(int b)
{

ExPanel_DEBUG("cExPanel_DEBUG: come in key_check!!\n");
if((b<=DW_KEY_HIGH_THR)&&(b >= DW_KEY_THR)) 
{
    ExPanel_DEBUG("ExPanel_DEBUG adc_data: %d mv\n",b);
    return KEY_PRESS_DOWN;
} 
else if ((b <=UP_KEY_HIGH_THR)&& (b >= UP_KEY_THR))
{
    ExPanel_DEBUG("ExPanel_DEBUG adc_data: %d mv\n",b);
    return KEY_PRESS_UP;
}
else if ((b <= MD_KEY_HIGH_THR) && (b >= MD_KEY_THR))
{
    ExPanel_DEBUG("ExPanel_DEBUG adc_data: %d mv\n",b);
    return KEY_PRESS_PAUSE;
}
ExPanel_DEBUG("ExPanel_DEBUG: leave key_check!!\n");
return KEY_PRESS_NONE;

}

void report_key_event(int keycode,int flag)
{
// if(call_status == 0)
// {
ExPanel_DEBUG(" report_key_event\n");
switch (keycode)

{
case KEY_PRESS_DOWN:
input_report_key(expanel_input_dev, KEY_VOLUMEDOWN, flag);
input_sync(expanel_input_dev);
ExPanel_DEBUG("KEY_NEXTSONG %d\n",flag);
break;

              case KEY_PRESS_UP:
        input_report_key(expanel_input_dev, KEY_VOLUMEUP, flag);
            input_sync(expanel_input_dev);
    ExPanel_DEBUG("KEY_PREVIOUSSONG %d\n",flag);
    case KEY_PRESS_PAUSE:
    input_report_key(expanel_input_dev,KEY_PLAYPAUSE, flag);
            input_sync(expanel_input_dev);
    ExPanel_DEBUG("KEY_PAUSE %d\n",flag);
     break;

            }

}
#if 0
else
{
switch (keycode)
{
case DW_KEY:
input_report_key(expanel_input_dev, KEY_VOLUMEDOWN, flag);
input_sync(expanel_input_dev);
ACCDET_DEBUG("KEY_VOLUMEDOWN %d\n",flag);
break;
case UP_KEY:
input_report_key(expanel_input_dev, KEY_VOLUMEUP, flag);
input_sync(expanel_input_dev);
ACCDET_DEBUG("KEY_VOLUMEUP %d\n",flag);
break;
}
}
#endif
}

static void expanel_key_detection(void)
{
//int current_status = 0;
//int index = 0;
//int count = long_press_time / (KEY_SAMPLE_PERIOD + 40 ); //ADC delay
int m_key = 0;
//int cur_key = 0;
int cali_voltage=0;

   ExPanel_DEBUG("[ExPanel_DEBUG]  expanel_key_detection! \n");
//cali_voltage = getExPanelVoltage();
cali_voltage=key_get_voltage();
ExPanel_DEBUG("[ExPanel_DEBUG]adc cali_voltage1 = %d mv\n", cali_voltage);
//ACCDET_DEBUG("[Accdet]adc cali_voltage final = %d mv\n", cali_voltage);
m_key= check_key_type(cali_voltage);

//
report_key_event(m_key, KEY_PRESS_FLAG);
report_key_event(m_key, KEY_RELEASE_FLAG);

}

int key_get_voltage(void)
{
int i = 0, bat_id_vol = 0, data[4] = {0,0,0,0};

int res =0;

int rawdata=0;

for(i = 0; i < 3; i++)       

{

res = IMM_GetOneChannelValue(EXPANEL_KEY_ADC_CHANNEL,data,&rawdata);
if(res < 0)

{
printk("[DEVICE/EXPANEL]: get data error\n");
break;

}

else

{
printk("[DEVICE/EXPANEL]: channel0[%d]raw =%d\n",i,rawdata);
}

msleep(5);

bat_id_vol += (rawdata * KEY_REF_VOLT / 4096);
printk("DEVICE/EXPANEL: channel0[%d]vol =%d\n",i,rawdata * KEY_REF_VOLT / 4096);
}

if(res < 0) /*get adc value fail*/

return;

bat_id_vol = bat_id_vol/3;

return bat_id_vol;

}

static int expanel_remove(struct platform_device *pdev)
{
//cancel_delayed_work(&accdet_work);
kthread_stop(scan_kthread);
hrtimer_cancel(&key_scan_timer);
destroy_workqueue(expanel_eint_workquenue);
input_unregister_device(expanel_input_dev);
ExPanel_DEBUG("[ExPanel_DEBUG]ExPanel_remove Done!\n");
return 0;
}

static struct platform_device expanel_dev = {
.name = EXPANEL_NAME,
.id = -1,
};

static struct platform_driver expanel_drv = {
.probe = expanel_probe,
.remove = expanel_remove,
.driver = {
.name = EXPANEL_NAME,
.owner= THIS_MODULE,
},
};

static int __init expanel_mod_init(void)
{
ExPanel_DEBUG("expanel_input_device init!\n");
platform_device_register(&expanel_dev );
platform_driver_register(& expanel_drv );

return 0;

}

static void __exit expanel_mod_exit(void)
{
platform_device_unregister(&expanel_dev);
platform_driver_unregister(& expanel_drv );
}

module_init(expanel_mod_init);
module_exit(expanel_mod_exit);
MODULE_LICENSE("GPL");

Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!