成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Linux下被遺忘的gpio_keys按鍵驅動

系統 Linux
我們新項目硬件設計上使用gpio口做按鍵,所以我就需要搞定這個驅動,本來想自己寫一個gpio口的按鍵驅動,然后看了下內核下面的代碼,已經有現成的了。

 [[406543]]

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

不過我還是在使用這個驅動上遇到了問題。

1. 先說ADC 按鍵

之前的文章有寫過adc按鍵的實現,無非就是為了省點GPIO口。

RK 利用SARADC 來做多個按鍵

2. GPIO 按鍵硬件原理圖

3. 驅動代碼

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

完整代碼可查看 

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

驅動代碼流程,從probe處開始

剛開始的時候,我連dts文件都不會寫,因為之前沒有接觸過這個驅動。然后看了gpio_keys_get_devtree_pdata函數,之后又看了內核代碼下其他項目其他平臺的dts文件,才知道怎么寫這個驅動的dts文件。

實話說,這個驅動完成了很多我們需要的功能,比如防抖,比如中斷,比如按鍵label等等。

3.1 gpio_keys_get_devtree_pdata 函數解析dts文件

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

我們的這個項目,就只傳入了gpio口。

3.2 gpio_keys_setup_key 函數

這個函數用來設置gpio口的中斷的,直接看代碼會比較清楚。

下面這個函數,我還沒有想清楚它的作用,看了回調函數里面的實現,是為了把開啟的工作隊列停止掉。但是我加了打印并沒有打印,我猜測是為了防止誤觸發,就是按鍵按下的時間非常短的時候,才會調用這個。 

  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 驅動修改

驅動修改的代碼如下 

  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: 

可以確定的是,如果不修改的話,肯定是會出錯的。

你要知道,這個驅動是在2005年就完成編寫了,中間經過了多少次的系統升級,而且很多廠商主推的還是ADC按鍵驅動,GPIO口驅動默認情況下是會被拋棄的,廠商釋放的SDK根本就不會記得修改這個驅動代碼,所以別以為你的手機運行正常里面就沒有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. 測試驅動

燒錄后按下按鍵,可以看到鍵值上報.

 

 

責任編輯:龐桂玉 來源: 良許Linux
相關推薦

2021-11-29 07:55:45

Linux GPIO Linux 系統

2022-04-22 11:16:35

Linux工具命令

2024-03-27 13:03:27

AI技術論壇

2009-08-12 09:02:52

Linux未來LinuxWindows

2009-09-03 09:08:08

Linuxroot密碼遺忘

2020-07-20 11:23:24

信息安全個人信息數據安全

2014-10-28 10:53:39

UNIX

2022-05-17 14:17:50

物理安全網絡攻擊網絡安全

2022-08-22 07:08:12

敏捷開發軟件

2017-11-21 09:10:54

Linux命令行技巧

2020-10-14 09:41:02

Hi3861GPIO點燈

2011-01-06 16:29:08

linuxtasklet機制

2009-04-24 10:57:25

2021-03-05 11:52:50

LinuxSPI驅動詳解

2011-01-05 13:00:19

2012-06-27 09:43:59

Win RTWin NT

2020-11-02 12:07:11

鴻蒙 GPIO

2023-07-10 09:52:51

機器谷歌

2020-04-09 11:03:29

ClouderaHadoopCDP

2022-10-17 11:44:53

C++COMvtable
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 中文字幕免费视频 | 久久久久久久久久久久久久av | 亚洲欧美激情视频 | 亚洲精品久久久久久久久久久 | 国产在线视频一区 | 国产一极毛片 | www久久av | 国产精品日韩一区二区 | 视频一区二区在线观看 | 欧美一级久久久猛烈a大片 日韩av免费在线观看 | 国产精品欧美一区二区三区 | 秋霞国产 | 一级毛片在线播放 | 精品乱码一区二区 | 免费在线观看av | 成人在线视频一区 | 久久国产精品免费视频 | 午夜视频一区 | 中文字幕欧美日韩 | 久久99久久99久久 | 男女在线免费观看 | 欧美成人h版在线观看 | 日韩欧美精品一区 | 日韩成人在线视频 | 国产高清视频在线播放 | 日韩久久久久久久久久久 | 国产一级在线 | 亚洲精品欧美一区二区三区 | 国产精品久久久久久婷婷天堂 | 亚洲福利一区 | 日本精品一区二区三区在线观看视频 | 中文字幕韩在线第一页 | 成人福利在线 | 欧美高清成人 | 国产91视频一区二区 | h视频免费在线观看 | 午夜精品久久久久久久久久久久 | 久久久蜜臀国产一区二区 | 国产一区二区三区在线免费 | 国产成人精品免高潮在线观看 | 日日想夜夜操 |