tp 雙擊喚醒 最終實現方案 參考

2021-10-24 06:20:42 字數 4587 閱讀 4637

註冊和上報鍵值這裡就不在累贅了,本篇部落格主要要解決以下bug:

1.系統進入睡眠狀態後,如何通過tp喚醒系統。

2.如何解決快速雙擊時喚醒系統,長按時不喚醒系統。

要喚醒進入睡眠狀態的系統,首先要了解以下函式介面:

在了解函式界面前,講一下suspend和resume,

suspend:kernel會依次呼叫你註冊驅動裡的suspend函式,將各種外設都進入節電模式。最後cpu進入power down 模式。

resume:當用rtc或者gpio中的乙個將cpu從power down 模式喚醒。依次也會呼叫各個驅動裡的resume函式將外設喚醒,

進入正常工作狀態。

這些函式核心功能體現在它為底層的裝置驅動提供用於上報wakeup event的介面。

首先要定義乙個可以在睡眠狀態下喚醒cpu的gpio,用enable_irq_wake(irq);和disable_irq_wake(ts->irq);

disable_irq_wake(ts->irq);//禁止中斷喚醒功能

enable_irq_wake(ts->irq);//使能中斷喚醒功能

在進入suspend時,會將irq mask寫入到cpu。也就是告訴cpu哪些irq可以將其從睡眠中喚醒。

device_init_wakeup(&client->dev, 1);

用來設定乙個驅動可以被喚醒,函式中的can_wakeup為1時,表明乙個裝置可以被喚醒, 在裝置初始化的時候呼叫。

//設定dev的can_wakeup標誌,若是enable==1,同時呼叫device_wakeup_enable使能wakeup功能;

int device_init_wakeup(struct device *dev, bool enable)

...}// 裝置模型中的所有裝置都有兩個標誌來控制喚醒事件(可使得裝置或系統退出低功耗狀態)

static inline void device_set_wakeup_capable(struct device *dev, bool capable)

static inline int device_set_wakeup_enable(struct device *dev, bool enable)

can_wakeup為1時表明乙個裝置可以被喚醒,裝置驅動為了支援linux中的電源管理,有責任呼叫device_init_wakeup()來初始化can_wakeup。

而should_wakeup則是在裝置的電源狀態發生變化時被device_may_wakeup()用來測試,測試它該不該變化。

pm_stay_awake(&ts->client->dev);

中斷中,pm_stay_awake可以使的裝置不立即進入休眠,這個響應是非常快的。

當裝置有wakeup event正在處理時,需要呼叫該介面通知電源管理系統。

那處理完成後呢?driver要呼叫pm_relax通知電源管理系統。pm_relax釋放這個「鎖」,讓系統可以重新休眠。

pm_relax和pm_stay_awake成對出現,用於在event處理結束後通知電源管理系統。

以下提供乙個例子:

//想要具備喚醒系統的功能,就要從中斷上下功夫,如下:

#include ...

#include #include struct device * dev;

int ***_isr(int irq, void *dev_id)

int ***_probe(struct platform_device *pdev)

int __init ***_init(void)

module_initcall(***_init);

module_license("gpl");

這段**中對中斷做了兩個特殊的處理,乙個是在申請中斷時加上了irqf_no_suspend, 另乙個是irq_enable_wake(irq); 

這兩個函式都可以賦予irq喚醒系統的能力,前者是在suspend過程中dpm_suspend_noirq()->suspend_devices_irq()時保留irqf_no_suspend型別的中斷響應,

而後者直接跟irq_chip打交道,把喚醒功能的設定交由irq_chip driver處理。從使用角度我覺得,irq_enable_wake()會是乙個更為保險且靈活的方法,

畢竟更為直接而且禁用喚醒功能方便,disable_irq_wake()即可。

需要在源**中新增如下:(改完之後,休眠狀態下測得的電流只是比正常休眠狀態下的電流多了tp的電流)

//suspend中新增

static int gsl_ts_suspend(struct device *dev)

//resume中新增

static int gsl_ts_resume(struct device *dev)

//在中斷上半部關中斷

static irqreturn_t gsl_ts_irq(int irq, void *dev_id)

//中斷執行完畢會開啟中斷

如果有中斷關閉就要在程式執行完畢後開啟中斷,如果邏輯出錯,會報如下錯誤:

warning:at /sda1/yzhao-work-1/qc706eu-s/msm8916_1605_444/kernel/kernel/irq/manage.c:529 irq_set_irq_wake+0x88/0xe8()

[ 8518.783716] —[ end trace 35ae10e4ba3033e2 ]—

一般是申請和釋放資源不匹配。

下面解決第二個bug,快速雙擊喚醒,長按不喚醒,這個可以有不同的邏輯實現,以下是我的邏輯,不正確的地方希望指出:

首先要熟悉上報座標的流程,這裡擷取有用的一段進行分析,中斷的下半部函式為,gsl_ts_xy_worker,其中有process_gslx680_data處理座標點,和上報座標點。

gsl螢幕支援多點觸控,一次按下時把多個點的座標值經過record_point計算成為乙個點,後用report_data上報。

函式中,有三個重要的變數,之前一直忽視了,卻起到了區分快速雙擊和長按的作用:

cinfo.finger_num----->記錄按下的手指數

id_state_old_flag[i]----->記錄上一次按下的狀態,是陣列,按下為1,抬起為0

id_state_flag[i]----->記錄此次按下的狀態,是陣列,沒按為0,按下為1

下面是這個函式的大致**,和加入的**,之後再分析區分思路

static void process_gslx680_data(struct gsl_ts *ts)

break;

case 1: //第二階段

if((cinfo.finger_num == 0) && (id_sign[1] ==0 ))

level = 2; //在level為1的基礎上,cinfo.finger_num == 0說明有手指頭抬起,但是可能沒有按下第二次

break;

case 2://第三階段

if((cinfo.finger_num == 1) && (id_sign[1] <= 8 ))

level = 3; //在level為2的基礎上,cinfo.finger_num再次為1,說明有手指頭又按下,完成一次雙擊觸控

break;

}if(level == 3) //level為3時候,說明完成一次雙擊觸控,可以喚醒系統

}...}

//喚醒系統

void open_lcd(struct gsl_ts *ts)

//一些全域性變數

static unsigned long old = 0;

extern unsigned long volatile jiffies;

static int level = 0;

static int gsl_halt_flag;

static int flag;

思路:

除錯的時候,根據log:pr_err(「xhlin^le=%d cinfo.finger_num=%d, id_state_old_flag[1]=%d, id_state_flag[1]=%d,id_sign[1]=%d; \n」,level,cinfo.finger_num,id_state_old_flag[1],id_state_flag[1],id_sign[1]);

發現快速雙擊的時候,cinfo.finger_num會由1,變為0,再變為1

長按的時候,cinfo.finger_num一直為1,且id_sign[1]的值不間斷變大

快速雙擊log

長按log

所以以此區別,來實現雙擊喚醒,每次喚醒後,和每次無效雙擊後,要把level清0

記一次tp喚醒函式異常導致的lcd喚醒慢

機器休眠後,按電源鍵喚醒,2s多螢幕才亮,檢視核心資訊,沒發現什麼報錯資訊。先檢查lcd的初始化 去掉多餘的延時,喚醒時間依然很長。繼續分析核心資訊,從按下電源鍵到開背光,用時2s多,發現tp喚醒時間較長。直接修改tp的i2c位址 或者拔掉tp 讓tp驅動不跑,喚醒時間就正常了。繼續分析tp的喚醒函...

告訴你最真實的TP公司

筆者自己把tp公司分為兩大類五小類 第一大類,硬tp公司。介紹 所謂硬tp公司就是以採購跟包銷為主要模式的tp公司。主要運營方法就是跟廠商承諾一年銷售多少交易額的貨物,然後廠商要給予低價供貨支援 銷售返點跟推廣廣告費支援。優勢 這樣從廠商的角度容易接受,因為羊毛出在羊身上,廠商會計算供貨的利潤跟廣告...

解決方案 duilib中禁止乙個視窗雙擊最大化

用duilib開發了乙個視窗,比如是登入視窗,那麼這個視窗的視窗的雙擊最大化就毫無意義,甚至帶來災難,我們就要明確禁止這樣的行為。我們應該明確,乙個視窗建立的時候就賦予了它一些屬性,那我們就首先看看如何建立視窗的,即create函式。例如,你定義了乙個視窗類叫loginwnd,你會在需要的時候這用進...