自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Linux下被遺忘的gpio_keys按鍵驅(qū)動(dòng)

系統(tǒng) Linux
我們新項(xiàng)目硬件設(shè)計(jì)上使用gpio口做按鍵,所以我就需要搞定這個(gè)驅(qū)動(dòng),本來想自己寫一個(gè)gpio口的按鍵驅(qū)動(dòng),然后看了下內(nèi)核下面的代碼,已經(jīng)有現(xiàn)成的了。

 [[406543]]

我們新項(xiàng)目硬件設(shè)計(jì)上使用gpio口做按鍵,所以我就需要搞定這個(gè)驅(qū)動(dòng),本來想自己寫一個(gè)gpio口的按鍵驅(qū)動(dòng),然后看了下內(nèi)核下面的代碼,已經(jīng)有現(xiàn)成的了。Linux內(nèi)核下游很多很多的現(xiàn)成驅(qū)動(dòng),只要你想得到的,基本都是有現(xiàn)成的,當(dāng)然了,不包括一些非正常的需求性問題,學(xué)會(huì)在Linux下找驅(qū)動(dòng),看驅(qū)動(dòng)和內(nèi)核代碼,我覺得是一件享受和快樂的事情。

不過我還是在使用這個(gè)驅(qū)動(dòng)上遇到了問題。

1. 先說ADC 按鍵

之前的文章有寫過adc按鍵的實(shí)現(xiàn),無非就是為了省點(diǎn)GPIO口。

RK 利用SARADC 來做多個(gè)按鍵

2. GPIO 按鍵硬件原理圖

3. 驅(qū)動(dòng)代碼

  1. kernel-4.4/drivers/input/keyboard/gpio_keys.c 

完整代碼可查看 

  1. https://gitee.com/weiqifa/gpio_key/blob/master/gpio_keys.c 

驅(qū)動(dòng)代碼流程,從probe處開始

剛開始的時(shí)候,我連dts文件都不會(huì)寫,因?yàn)橹皼]有接觸過這個(gè)驅(qū)動(dòng)。然后看了gpio_keys_get_devtree_pdata函數(shù),之后又看了內(nèi)核代碼下其他項(xiàng)目其他平臺的dts文件,才知道怎么寫這個(gè)驅(qū)動(dòng)的dts文件。

實(shí)話說,這個(gè)驅(qū)動(dòng)完成了很多我們需要的功能,比如防抖,比如中斷,比如按鍵label等等。

3.1 gpio_keys_get_devtree_pdata 函數(shù)解析dts文件

這個(gè)文件解析的dts 有兩種方式,一種是直接傳入irq的,一種是只傳入gpio口的。

我們的這個(gè)項(xiàng)目,就只傳入了gpio口。

3.2 gpio_keys_setup_key 函數(shù)

這個(gè)函數(shù)用來設(shè)置gpio口的中斷的,直接看代碼會(huì)比較清楚。

下面這個(gè)函數(shù),我還沒有想清楚它的作用,看了回調(diào)函數(shù)里面的實(shí)現(xiàn),是為了把開啟的工作隊(duì)列停止掉。但是我加了打印并沒有打印,我猜測是為了防止誤觸發(fā),就是按鍵按下的時(shí)間非常短的時(shí)候,才會(huì)調(diào)用這個(gè)。 

  1. /**  
  2.  * devm_add_action() - add a custom action to list of managed resources  
  3.  * @dev: Device that owns the action  
  4.  * @action: Function that should be called  
  5.  * @data: Pointer to data passed to @action implementation  
  6.  *  
  7.  * This adds a custom action to the list of managed resources so that  
  8.  * it gets executed as part of standard resource unwinding.  
  9.  */  
  10. int devm_add_action(struct device *dev, void (*action)(void *), void *data)  
  11.  
  12.  struct action_devres *devres;  
  13.  devres = devres_alloc(devm_action_release,  
  14.          sizeof(struct action_devres), GFP_KERNEL);  
  15.  if (!devres)  
  16.   return -ENOMEM; 
  17.  devres->datadata = data;  
  18.  devres->actionaction = action;  
  19.  devres_add(dev, devres);  
  20.  return 0;  

3.3 驅(qū)動(dòng)修改

驅(qū)動(dòng)修改的代碼如下 

  1. --- a/kernel-4.4/drivers/input/keyboard/gpio_keys.c  
  2. +++ b/kernel-4.4/drivers/input/keyboard/gpio_keys.c  
  3. @@ -32,6 +32,11 @@  
  4.  #include <linux/of_irq.h>  
  5.  #include <linux/spinlock.h>  
  6.  
  7. +#define LOG_TAG "[BUTTON]: %s() line: %d "  
  8. +#define PRINTK_T(fmt, args...)  printk(KERN_INFO LOG_TAG fmt, __FUNCTION__, __LINE__,  ##args)  
  9.  
  10.  
  11.  struct gpio_button_data {  
  12.         const struct gpio_keys_button *button;  
  13.         struct input_dev *input;  
  14. @@ -462,9 +467,8 @@ static int gpio_keys_setup_key(struct platform_device *pdev,  
  15.         spin_lock_init(&bdata->lock);  
  16.         if (gpio_is_valid(button->gpio)) {  
  17.  
  18. -               error = devm_gpio_request_one(&pdev->dev, button->gpio,  
  19. -                                             GPIOF_IN, desc);  
  20. +               PRINTK_T("gpio:%d\n",button->gpio);  
  21. +               error = devm_gpio_request(&pdev->dev, button->gpio,desc);  
  22.                 if (error < 0) {  
  23.                         dev_err(dev, "Failed to request GPIO %d, error %d\n",  
  24.                                 button->gpio, error);  
  25. @@ -483,7 +487,9 @@ static int gpio_keys_setup_key(struct platform_device *pdev,  
  26.                 if (button->irq) {  
  27.                         bdata->irq = button->irq;  
  28.                 } else {  
  29. +                       gpio_direction_input(button->gpio);  
  30.                         irq = gpio_to_irq(button->gpio);  
  31. +                       PRINTK_T("===weiqifa=== irq :%d\n",irq);  
  32.                         if (irq < 0) {  
  33.                                 error = irq 
  34.                                 dev_err(dev,  
  35. @@ -540,8 +546,10 @@ static int gpio_keys_setup_key(struct platform_device *pdev,  
  36.         if (!button->can_disable)  
  37.                 irqflags |= IRQF_SHARED;  
  38. -       error = devm_request_any_context_irq(&pdev->dev, bdata->irq,  
  39. -                                            isr, irqflags, desc, bdata);  
  40. +       PRINTK_T("===weiqifa=== devm_request_threaded_irq()\n");  
  41. +       error = devm_request_threaded_irq(&pdev->dev, bdata->irq,NULL,  
  42. +                                            isr, irqflags| IRQF_ONESHOT, desc, bdata);  
  43.         if (error < 0) {  
  44.                 dev_err(dev, "Unable to claim irq %d; error %d\n",  
  45.                         bdata->irq, error);  
  46. @@ -709,6 +717,8 @@ static int gpio_keys_probe(struct platform_device *pdev)  
  47.         int i, error;  
  48.         int wakeup = 0  
  49. +       PRINTK_T("start.\n"); 
  50.  
  51.         if (!pdata) {  
  52.                 pdata = gpio_keys_get_devtree_pdata(dev);  
  53.                 if (IS_ERR(pdata))  
  54. @@ -779,6 +789,8 @@ static int gpio_keys_probe(struct platform_device *pdev)  
  55.         device_init_wakeup(&pdev->dev, wakeup);  
  56. +       PRINTK_T("end.\n"); 
  57.  
  58.         return 0;  
  59.  err_remove_group: 

可以確定的是,如果不修改的話,肯定是會(huì)出錯(cuò)的。

你要知道,這個(gè)驅(qū)動(dòng)是在2005年就完成編寫了,中間經(jīng)過了多少次的系統(tǒng)升級,而且很多廠商主推的還是ADC按鍵驅(qū)動(dòng),GPIO口驅(qū)動(dòng)默認(rèn)情況下是會(huì)被拋棄的,廠商釋放的SDK根本就不會(huì)記得修改這個(gè)驅(qū)動(dòng)代碼,所以別以為你的手機(jī)運(yùn)行正常里面就沒有bug,bug無處不在,只是我們有了重啟大法而已。

4. dts 代碼 

  1. gpio-keys {  
  2.    compatible = "gpio-keys" 
  3.    #address-cells = <1> 
  4.    #size-cells = <0> 
  5.    autorepeat; 
  6.     //pinctrl-names = "default" 
  7.    //pinctrl-0 = <&pwrbtn> 
  8.    button@0 {  
  9.      gpios = <&pio 49 IRQ_TYPE_EDGE_BOTH> 
  10.      linux,code = <KEY_F13> 
  11.      label = "GPIO F13 Power" 
  12.      linux,input-type = <1> 
  13.      gpio-key,wakeup = <1> 
  14.      debounce-interval = <100> 
  15.    };  
  16.    button@1 {  
  17.      gpios = <&pio 48 IRQ_TYPE_EDGE_BOTH> 
  18.      linux,code = <KEY_F14> 
  19.      label = "GPIO F14 Power" 
  20.      linux,input-type = <1> 
  21.      gpio-key,wakeup = <1> 
  22.      debounce-interval = <100> 
  23.    };  
  24.    button@2 {  
  25.      gpios = <&pio 51 IRQ_TYPE_EDGE_BOTH> 
  26.      linux,code = <KEY_F15> 
  27.      label = "GPIO F15 Power" 
  28.      linux,input-type = <1> 
  29.      gpio-key,wakeup = <1> 
  30.      debounce-interval = <100> 
  31.    };  
  32.  }; 

5. 測試驅(qū)動(dòng)

燒錄后按下按鍵,可以看到鍵值上報(bào).

 

 

責(zé)任編輯:龐桂玉 來源: 良許Linux
相關(guān)推薦

2021-11-29 07:55:45

Linux GPIO Linux 系統(tǒng)

2022-04-22 11:16:35

Linux工具命令

2024-03-27 13:03:27

AI技術(shù)論壇

2009-08-12 09:02:52

Linux未來LinuxWindows

2009-09-03 09:08:08

Linuxroot密碼遺忘

2020-07-20 11:23:24

信息安全個(gè)人信息數(shù)據(jù)安全

2014-10-28 10:53:39

UNIX

2020-10-14 09:41:02

Hi3861GPIO點(diǎn)燈

2022-05-17 14:17:50

物理安全網(wǎng)絡(luò)攻擊網(wǎng)絡(luò)安全

2017-11-21 09:10:54

Linux命令行技巧

2022-08-22 07:08:12

敏捷開發(fā)軟件

2020-11-02 12:07:11

鴻蒙 GPIO

2011-01-05 13:00:19

2011-01-06 16:29:08

linuxtasklet機(jī)制

2021-03-05 11:52:50

LinuxSPI驅(qū)動(dòng)詳解

2009-04-24 10:57:25

2023-07-10 09:52:51

機(jī)器谷歌

2012-06-27 09:43:59

Win RTWin NT

2020-10-28 10:03:43

Hi3861 GPIO點(diǎn)燈按鍵

2020-04-09 11:03:29

ClouderaHadoopCDP
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號