需求分解:
主要需求:屏亮无操作,按键灯5s 后自动熄灭
实现场景:
1)按下按键后检测到按键中断,在中断函数中点亮按键灯并且启动定时器定时五秒,时间到关闭按键灯。
2)当点亮屏幕后,点亮按键灯并且启动定时器定时五秒,时间到关闭按键灯。
@ \kernel\drivers\input\keyboard\aw9523.c
#include //jiffies调用头文件
#include //timer_list结构体
u32 bl_level_bakup = 0; // 备份bl_level (当前屏幕背光的亮度值),用于点亮按键灯的亮度,bl_level是一个局部变量
static bool is_btn_leds_timer_onoff = false; // 定时器开 flag
static struct timer_list btn_leds_ms_timer; //定义timer_list结构体
static void btn_leds_ms_timer_func_handler(void); //声时定时器函数
void aw9523_buttonleds_set_timer_on(u32 bl_level); //*********************
void aw9523_key_work()
{
// 在按键处理函数中 调用封装好的代码
//*********************
aw9523_buttonleds_set_timer_on(bl_level_bakup) //同理,panel.c 中也直接调用这个
}
@ 点亮按键灯并且启动定时器定时五秒,时间到关闭按键灯。
void aw9523_buttonleds_set_timer_on(u32 bl_level)
{
if(bl_level == 0){ //*********************
// 判断当前定时器是否开启了
if (is_btn_leds_timer_onoff == true){
del_timer(&btn_leds_ms_timer); // 移除定时器
}
//如果是灭屏,则不启动定时器,直接关灯
aw9523_buttonleds_set(bl_level);
}else{
// 如果是亮屏状态
//cancel timer 如果定时器已经开启过了,说明此时按键灯已经是开启状态,则清除定时器
if (is_btn_leds_timer_onoff == true)
{
printk("hyl_timer [%s][%d] --start to restart timer-- ----- 333333-----\n",__func__,__LINE__);
//如果之前已经有按过,则删定时器,并重新启动定时器
mod_timer(&btn_leds_ms_timer, jiffies+msecs_to_jiffies(1000 * 5));
}
else
{
printk("hyl_timer [%s][%d] --start timer------- 222222----- \n",__func__,__LINE__);
// 如果定时器没有开启过,则说明按键灯没有开启过,则开启按键背光
// light up button leds hyl_leds +++
// ------------此处先注释,看看log--------log 正常 后开启
// 定义定时器中断时间: 5s 后进入中断
btn_leds_ms_timer.expires = jiffies + msecs_to_jiffies(1000 * 5);
// 绑定定时器的计时到达时候的操作函数
btn_leds_ms_timer.function = btn_leds_ms_timer_func_handler;
// 启动定时器
add_timer(&btn_leds_ms_timer); //增加注册定时器,使定时器生效
}
aw9523_buttonleds_set(bl_level); //*********************
is_btn_leds_timer_onoff = true;
}
}
// 定时器函数代码,定义定时器处理函数
static void btn_leds_ms_timer_func_handler(void)
{
printk("hyl_timer [%s][%d] --timer end ,start turn off leds ----- 4444------- \n",__func__,__LINE__);
// close button leds
// ------------此处先注释,看看log--------log 正常 后开启
//aw9523_buttonleds_set(0);
// 清楚定时器开关标志位
is_btn_leds_timer_onoff = false;
}
static int aw9523_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
// 初始化定时器
init_timer(&btn_leds_ms_timer);
// 定义定时器中断时间: 5s 后进入中断
btn_leds_ms_timer.expires = jiffies + msecs_to_jiffies(1000 * 5);
// 绑定定时器的计时到达时候的操作函数
btn_leds_ms_timer.function = btn_leds_ms_timer_func_handler;
printk("hyl_timer [%s][%d] add timer success ----- 111111-----\n",__func__,__LINE__);
// 此时不启动定时器
// add_timer(&btn_leds_ms_timer); //增加注册定时器,使定时器生效
}
static int aw9523_release(struct i2c_client *client, const struct i2c_device_id *id)
{
// 删除化定时器
del_timer(&btn_leds_ms_timer);
}
增加工作队列:
#include
// 工作队列定义
static struct work_struct leds_work;
//---> 把这个函数的代码还原
void aw9523_buttonleds_set_timer_on(void)
{
if(btn_leds_timer_onoff == true)
{
printk("---hyl---timer[%s][%d]--33333-start to restart timer\n",__func__,__LINE__);
mod_timer(&btn_leds_ms_timer,jiffies+msecs_to_jiffies(1000*5));
}
else
{
printk("---hyl---timer[%s][%d]--------22222----------start timer\n",__func__,__LINE__);
aw9523_buttonleds_set(0);
btn_leds_ms_timer.expires = jiffies + msecs_to_jiffies(1000*5);
btn_leds_ms_timer.function = btn_leds_ms_timer_func_handler;
add_timer(&btn_leds_ms_timer);
}
btn_leds_timer_onoff = true;
}
// 工作队列运行函数 ,将之前定时器函数中的工作 ,全搬过来,在工作队列中, 关闭灯
static void leds_work_handler(struct work_struct *data)
{
printk("hyl_timer [%s][%d] --timer end ,start turn off leds ----- 5555------- \n",__func__,__LINE__);
aw9523_buttonleds_set(0); // close button leds
// 清除定时器开关标志位
is_btn_leds_timer_onoff = false;
}
// 定义定时器处理函数 , 定时器时间到达后只负表 让CPU调度leds_work_handler()
static void btn_leds_ms_timer_func_handler(void)
{
printk("hyl_timer [%s][%d] --timer end ,start turn off leds ----- 4444------- \n",__func__,__LINE__);
schedule_work(&leds_work); // 让CPU 调度工作队列, cpu 会创建线程执行leds_work_handler()这个函数
}
void probe (){
// 这个代码,在初始化定时器后面增加
INIT_WORK(&leds_work, leds_work_handler); //初始化工作队列,绑定 leds_work_handler() 这个函数
}
增加proc 调试节点:
#include
void xxxxx_aaa(void)
{
printk("hyl_timer [%s][%d] ---- \n",__func__,__LINE__);
//打开背光
//启动 5s 定时器
ms_timer.expires=jiffies+msecs_to_jiffies(1000 * 5);
ms_timer.function=ms_timer_handler;
add_timer(&ms_timer);
}
static ssize_t igh_gfar_proc_write(struct file *file, const char __user *buffer, size_t count, loff_t *f_pos)
{
xxxxx_aaa(); // 此处加上 ,打开背光,启动 5s 定时器
return count;
}
struct proc_dir_entry *leds_proc_dir = NULL;
static int32_t xxx_probe(void)
{
struct proc_dir_entry* leds_file;
leds_proc_dir = proc_mkdir("leds_back", NULL);
leds_file = proc_create("leds_onoff", 0777, leds_proc_dir, &leds_proc_fops);
}
static xxxx_release(void){
del_timer(&ms_timer);
remove_proc_entry("leds_onoff", leds_proc_dir);
remove_proc_entry("leds_back", NULL);
}