91欧美超碰AV自拍|国产成年人性爱视频免费看|亚洲 日韩 欧美一厂二区入|人人看人人爽人人操aV|丝袜美腿视频一区二区在线看|人人操人人爽人人爱|婷婷五月天超碰|97色色欧美亚州A√|另类A√无码精品一级av|欧美特级日韩特级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

驅(qū)動(dòng)之路#11:Input子系統(tǒng)數(shù)據(jù)上報(bào)流程

BSP調(diào)試從0到1 ? 來(lái)源:嵌入式分享 ? 作者:嵌入式分享 ? 2026-03-10 08:23 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

題圖:日本東京有一家專(zhuān)門(mén)生產(chǎn)電梯按鈕的公司,該公司把生產(chǎn)過(guò)的1000多種電梯按鈕,做成了一面展示墻,按上去每個(gè)都會(huì)亮。孩子們和大人都很喜歡。

歡迎關(guān)注,每周更新!?

本合集分享的是,我當(dāng)初學(xué)習(xí)Linux驅(qū)動(dòng)的來(lái)時(shí)路——《《驅(qū)動(dòng)之路》開(kāi)篇:自序&前言》。

正文

Input 子系統(tǒng)框架的復(fù)雜程度有三四層樓那么高。幸運(yùn)的是,復(fù)雜那部分代碼大佬前輩們已經(jīng)實(shí)現(xiàn),我們只需搞懂 Input 子系統(tǒng)的框架,然后套用框架實(shí)現(xiàn)具體輸入設(shè)備 driver 端驅(qū)動(dòng)程序即可。因此,可以說(shuō) ai 時(shí)代搞懂框架比理解每行代碼更重要。

但是對(duì)于 Input 子系統(tǒng)這樣復(fù)雜的框架,要徹底理解從硬件底層到用戶(hù)空間的數(shù)據(jù)上報(bào)流程談何容易,必須要找到一個(gè)抓手作為切入點(diǎn)。

然而,分析gpio_keys.c驅(qū)動(dòng)正是掌握 Linux Input 子系統(tǒng)數(shù)據(jù)上報(bào)流程的絕佳途徑,因?yàn)樗且粋€(gè)典型且相對(duì)簡(jiǎn)單的 Input 驅(qū)動(dòng)實(shí)例。

在分析前,請(qǐng)先回顧《驅(qū)動(dòng)之路#01:Hello World!》和 Input 子系統(tǒng)的三層架構(gòu):驅(qū)動(dòng)層、核心層以及事件處理層。

wKgZO2mvZN2AbU7PAAIG2CMGLgw758.png

下面是一個(gè) step-by-step 的指南,帶你從gpio_keys.c出發(fā),徹底理解 Input 子系統(tǒng)的工作機(jī)制。

特別說(shuō)明:本文重點(diǎn)在于理解 Input 子系統(tǒng)數(shù)據(jù)上報(bào)流程,而非gpio_keys.c驅(qū)動(dòng)分析。

從module_init開(kāi)始:驅(qū)動(dòng)入口函數(shù)

閱讀一個(gè)字符設(shè)備驅(qū)動(dòng)程序從入口函數(shù)開(kāi)始,在 gpio_keys.c 中可以看到 gpio_keys_init 注冊(cè)了 gpio_keys_device_driver。當(dāng) driver 與 device 匹配后,gpio_keys_probe 函數(shù)就會(huì)被調(diào)用,接下來(lái)重點(diǎn)分析gpio_keys_probe 函數(shù)。

wKgZO2mvZN2AO6OtAAFAxbsqrOc979.png

驅(qū)動(dòng)層到核心層

驅(qū)動(dòng)核心: gpio_keys_probe 函數(shù)分析

probe函數(shù)在驅(qū)動(dòng)與設(shè)備匹配成功后被調(diào)用,可以看到 probe函數(shù)有 4 步關(guān)鍵操作。

步驟 1:獲取設(shè)備配置信息

首先通過(guò)dev_get_platdata(dev)從平臺(tái)設(shè)備中獲取靜態(tài)定義的平臺(tái)數(shù)據(jù)。如果沒(méi)有靜態(tài)平臺(tái)數(shù)據(jù),則再通過(guò)gpio_keys_get_devtree_pdata(dev)從設(shè)備樹(shù)中解析配置。總之,無(wú)論是設(shè)備樹(shù)還是傳統(tǒng)平臺(tái)數(shù)據(jù),最終都解析到pdata中。

wKgZO2mvZN2AeJ07AAEDJMVRvDE707.png

步驟 2:分配和初始化struct input_dev

通過(guò)devm_input_allocate_device()創(chuàng)建一個(gè)輸入設(shè)備對(duì)象input_dev,這是驅(qū)動(dòng)層與核心層交互的第一步。

wKgZO2mvZN6ASV88AAESzXXDnpA111.png

步驟 3:申請(qǐng) GPIO 和中斷

probe 函數(shù)沒(méi)有直接包含中斷處理函數(shù)的實(shí)現(xiàn),而是通過(guò)調(diào)用 gpio_keys_setup_key() 完成了中斷函數(shù)的注冊(cè)、中斷觸發(fā)方式等配置。

wKgZO2mvZN6Abl0WAAA-eoy6v4c995.png

步驟 4:注冊(cè)輸入設(shè)備

通過(guò) input_register_device()將 input_dev 注冊(cè)到 Input 子系統(tǒng)核心層,調(diào)用此函數(shù)后,Input 核心層會(huì)接手管理這個(gè)輸入設(shè)備并嘗試為它匹配合適的事件處理器(Handler),如 evdev。

注冊(cè)成功后,用戶(hù)空間就可以看到/dev/input/eventX 設(shè)備節(jié)點(diǎn)了。

wKgZO2mvZN6AQLLqAABLPDcqWHY584.png

以上是 probe 函數(shù)關(guān)鍵操作的分析。

中斷處理函數(shù)分析

中斷處理函數(shù)是數(shù)據(jù)上報(bào)流程的起點(diǎn),當(dāng)用戶(hù)按下或松開(kāi)按鍵時(shí),GPIO 電平變化觸發(fā)中斷,此函數(shù)被執(zhí)行。

經(jīng)過(guò)前面分析知道,中斷服務(wù)函數(shù)相關(guān)配置在gpio_keys_setup_key() 中完成,接下來(lái)分析 gpio_keys_setup_key() 。

可以看到有兩種IRQ函數(shù)

gpio_keys_gpio_isr:設(shè)備樹(shù)中的用gpios描述引腳時(shí)調(diào)用;

gpio_keys_irq_isr:設(shè)備樹(shù)中的用interrupts描述引腳時(shí)調(diào)用。

它們有各自的優(yōu)缺點(diǎn),但不是本文的重點(diǎn),這里不展開(kāi)分析。

wKgZO2mvZN6AGUc_AANaoLNwqDQ103.png

我們分析相對(duì)簡(jiǎn)單的 gpio_keys_irq_isr 中斷函數(shù)的處理流程,其中,

核心:調(diào)用input_event(input, EV_KEY, *bdata->code,1)和input_sync(input)進(jìn)行上報(bào)數(shù)據(jù)。

input_event():向 Input 核心層上報(bào)一個(gè)原始事件。這個(gè)事件包含了事件類(lèi)型(EV_KEY)、事件碼(如 KEY_POWER)和值(1 或 0)。

input_sync():上報(bào)一個(gè)同步事件,告訴核心層 “這一組事件已經(jīng)完整上報(bào)完畢”。

wKgZO2mvZN6AMdO2AATY92t5pNQ363.png

至此,數(shù)據(jù)已經(jīng)從硬件驅(qū)動(dòng)層上報(bào)到核心層。

核心層到事件層數(shù)據(jù)流

數(shù)據(jù)從核心層傳遞到事件層函數(shù)調(diào)用關(guān)系比較復(fù)雜,調(diào)用關(guān)系如下。

其中,input_handle_event函數(shù)是 Input 核心層的事件分發(fā)中心,它會(huì)將事件傳遞給所有與該input_dev關(guān)聯(lián)的input_handler(事件處理器)。

而數(shù)據(jù)從核心層傳遞到事件層,是調(diào)用evdev_events 函數(shù)來(lái)實(shí)現(xiàn),然后通過(guò)evdev_pass_values函數(shù)被分發(fā)到各個(gè)客戶(hù)端。

wKgZO2mvZN-AZFU2AAWPtQGk01k574.png

當(dāng)用戶(hù)空間讀取/dev/input/eventX時(shí),實(shí)際上是從對(duì)應(yīng)客戶(hù)端的環(huán)形緩沖區(qū)中讀取數(shù)據(jù)。數(shù)據(jù)最后保存在每個(gè)打開(kāi)設(shè)備文件的進(jìn)程所對(duì)應(yīng)的evdev_client的環(huán)形緩沖區(qū)中。

wKgZO2mvZN-AaTuOAAGpAHHV4Kw875.png

數(shù)據(jù)流:gpio_keys.c驅(qū)動(dòng)->input_event -> input_handle_event -> input_pass_values -> evdev_events -> evdev_pass_values ->寫(xiě)入evdev_client的 buffer ->用戶(hù)空間read讀取。

總結(jié)整個(gè)流程

硬件:用戶(hù)按下按鍵 -> GPIO 電平變化 -> 觸發(fā)中斷。

驅(qū)動(dòng)層 (gpio_keys.c):

gpio_keys_irq_isr 或gpio_keys_gpio_isr 中斷服務(wù)程序被調(diào)用。

調(diào)用input_event()和input_sync()向上層(核心層)上報(bào)事件。

核心層 (input.c):

input_event()->input_handle_event()接收事件。

核心層將事件分發(fā)給所有匹配的 input_handler。

事件處理層 (evdev.c):

evdev_event()接收事件。

將事件打包成struct input_event并寫(xiě)入內(nèi)核緩沖區(qū)(buffer)。

喚醒正在等待數(shù)據(jù)的用戶(hù)空間應(yīng)用程序。

用戶(hù)空間:應(yīng)用程序的 read()調(diào)用返回,讀取到 struct input_event 數(shù)據(jù)并進(jìn)行解析。

看完本文,可自行閱讀源碼分析,關(guān)鍵代碼閱讀順序:

drivers/input/keyboard/gpio_keys.c- 具體輸入設(shè)備驅(qū)動(dòng)程序

drivers/input/input.c- 核心框架

drivers/input/evdev.c- 事件處理

include/linux/input.h- 數(shù)據(jù)結(jié)構(gòu)和 API

(完)

本人專(zhuān)注 Linux 驅(qū)動(dòng) & Linux/Android BSP 開(kāi)發(fā)調(diào)試,可接外包項(xiàng)目/技術(shù)支持/問(wèn)題定位。有需求或交個(gè)朋友可加微信:【Chen_WeChat2026】。

更多原創(chuàng)技術(shù)文章:《README 2026》。

審核編輯 黃宇

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 驅(qū)動(dòng)
    +關(guān)注

    關(guān)注

    12

    文章

    1958

    瀏覽量

    88577
  • 子系統(tǒng)
    +關(guān)注

    關(guān)注

    0

    文章

    116

    瀏覽量

    13512
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    基于 ROS + ADI 芯片方案 的 人形機(jī)器人子系統(tǒng)級(jí)BOM清單(以腿部子系統(tǒng)為例)

    基于 ROS + ADI 芯片方案 的 人形機(jī)器人子系統(tǒng)級(jí)BOM清單 (以 腿部子系統(tǒng) 為例),包括核心感知、執(zhí)行與通信模塊,配合主控系統(tǒng)通過(guò) ROS2 實(shí)現(xiàn)分布式控制與狀態(tài)反饋。 一、腿部
    的頭像 發(fā)表于 06-17 17:06 ?2056次閱讀

    迅為RK3568開(kāi)發(fā)板驅(qū)動(dòng)指南GPIO子系統(tǒng)GPIO子系統(tǒng)API函數(shù)的引入

    迅為RK3568開(kāi)發(fā)板驅(qū)動(dòng)指南GPIO子系統(tǒng)GPIO子系統(tǒng)API函數(shù)的引入
    的頭像 發(fā)表于 05-29 14:05 ?1048次閱讀
    迅為RK3568開(kāi)發(fā)板<b class='flag-5'>驅(qū)動(dòng)</b>指南GPIO<b class='flag-5'>子系統(tǒng)</b>GPIO<b class='flag-5'>子系統(tǒng)</b>API函數(shù)的引入

    迅為RK3568驅(qū)動(dòng)指南GPIO子系統(tǒng) GPIO操作函數(shù)實(shí)驗(yàn)

    迅為電子RK3568開(kāi)發(fā)板驅(qū)動(dòng)指南GPIO子系統(tǒng) GPIO操作函數(shù)實(shí)驗(yàn)
    的頭像 發(fā)表于 05-28 15:24 ?1367次閱讀
    迅為RK3568<b class='flag-5'>驅(qū)動(dòng)</b>指南GPIO<b class='flag-5'>子系統(tǒng)</b> GPIO操作函數(shù)實(shí)驗(yàn)

    RK3568驅(qū)動(dòng)指南|第十二篇 GPIO子系統(tǒng)-第135章 GPIO子系統(tǒng)與pinctrl子系統(tǒng)相結(jié)合實(shí)驗(yàn)

    RK3568驅(qū)動(dòng)指南|第十二篇 GPIO子系統(tǒng)-第135章 GPIO子系統(tǒng)與pinctrl子系統(tǒng)相結(jié)合實(shí)驗(yàn)
    的頭像 發(fā)表于 05-23 13:47 ?1040次閱讀
    RK3568<b class='flag-5'>驅(qū)動(dòng)</b>指南|第十二篇 GPIO<b class='flag-5'>子系統(tǒng)</b>-第135章 GPIO<b class='flag-5'>子系統(tǒng)</b>與pinctrl<b class='flag-5'>子系統(tǒng)</b>相結(jié)合實(shí)驗(yàn)

    嵌入式學(xué)習(xí)-飛凌嵌入式ElfBoard ELF 1板卡-input子系統(tǒng)之基于input子系統(tǒng)的光線傳感器驅(qū)動(dòng)

    \\bh1726 BH1726光線傳感器采用了i2c接口,所以需要將其注冊(cè)成i2c設(shè)備,來(lái)讀取其內(nèi)部寄存器的測(cè)量值,然后通過(guò)input子系統(tǒng)上報(bào)到用戶(hù)空間,下面來(lái)看一下驅(qū)動(dòng)的具體實(shí)現(xiàn)
    發(fā)表于 04-16 11:05

    嵌入式學(xué)習(xí)-飛凌嵌入式ElfBoard ELF 1板卡-input子系統(tǒng)之基于input子系統(tǒng)的按鍵驅(qū)動(dòng)

    例程代碼路徑:ELF 1開(kāi)發(fā)板資料包\\03-例程源碼\\03-2 驅(qū)動(dòng)例程源碼\\08_input子系統(tǒng)\\keyboard下面以控制開(kāi)發(fā)板上的K2為例進(jìn)行講解。修改設(shè)備樹(shù)(一)查看原理圖和引腳
    發(fā)表于 04-16 10:57

    飛凌嵌入式ElfBoard ELF 1板卡-input子系統(tǒng)之基于input子系統(tǒng)的光線傳感器驅(qū)動(dòng)

    \\bh1726BH1726光線傳感器采用了i2c接口,所以需要將其注冊(cè)成i2c設(shè)備,來(lái)讀取其內(nèi)部寄存器的測(cè)量值,然后通過(guò)input子系統(tǒng)上報(bào)到用戶(hù)空間,下面來(lái)看一下驅(qū)動(dòng)的具體實(shí)現(xiàn)
    發(fā)表于 04-16 10:39

    飛凌嵌入式ElfBoard ELF 1板卡-input子系統(tǒng)之基于input子系統(tǒng)的按鍵驅(qū)動(dòng)

    例程代碼路徑:ELF 1開(kāi)發(fā)板資料包\\03-例程源碼\\03-2 驅(qū)動(dòng)例程源碼\\08_input子系統(tǒng)\\keyboard下面以控制開(kāi)發(fā)板上的K2為例進(jìn)行講解。修改設(shè)備樹(shù)(一)查看原理圖和引腳
    發(fā)表于 04-15 10:58

    嵌入式學(xué)習(xí)-飛凌嵌入式ElfBoard ELF 1板卡-input子系統(tǒng)input子系統(tǒng)簡(jiǎn)單構(gòu)建流程

    _driver的輸入設(shè)備驅(qū)動(dòng)程序,它使用Input子系統(tǒng)提供的API來(lái)創(chuàng)建和注冊(cè)輸入設(shè)備。在驅(qū)動(dòng)程序的初始化函數(shù)my_input_drive
    發(fā)表于 04-15 10:54

    嵌入式學(xué)習(xí)-飛凌嵌入式ElfBoard ELF 1板卡-input子系統(tǒng)input子系統(tǒng)簡(jiǎn)介

    使用了設(shè)備驅(qū)動(dòng)程序來(lái)管理輸入設(shè)備。每個(gè)輸入設(shè)備都由一個(gè)驅(qū)動(dòng)程序進(jìn)行控制,驅(qū)動(dòng)程序負(fù)責(zé)與硬件進(jìn)行通信并將輸入事件傳遞給Input子系統(tǒng)。輸入事
    發(fā)表于 04-15 10:42

    飛凌嵌入式ElfBoard ELF 1板卡-input子系統(tǒng)input子系統(tǒng)簡(jiǎn)單構(gòu)建流程

    _driver的輸入設(shè)備驅(qū)動(dòng)程序,它使用Input子系統(tǒng)提供的API來(lái)創(chuàng)建和注冊(cè)輸入設(shè)備。在驅(qū)動(dòng)程序的初始化函數(shù)my_input_drive
    發(fā)表于 04-15 10:29

    飛凌嵌入式ElfBoard ELF 1板卡-input子系統(tǒng)input子系統(tǒng)簡(jiǎn)介

    使用了設(shè)備驅(qū)動(dòng)程序來(lái)管理輸入設(shè)備。每個(gè)輸入設(shè)備都由一個(gè)驅(qū)動(dòng)程序進(jìn)行控制,驅(qū)動(dòng)程序負(fù)責(zé)與硬件進(jìn)行通信并將輸入事件傳遞給Input子系統(tǒng)。輸入事
    發(fā)表于 04-15 10:27

    嵌入式學(xué)習(xí)-飛凌嵌入式ElfBoard ELF 1板卡-Pinctrl和GPIO子系統(tǒng)之GPIO子系統(tǒng)

    GPIO(General Purpose Input/Output)子系統(tǒng)是用于控制和管理通用輸入/輸出引腳的一部分。它提供了一種標(biāo)準(zhǔn)化的方式來(lái)訪問(wèn)和操作硬件平臺(tái)上的GPIO引腳,使開(kāi)發(fā)人員能夠通過(guò)
    發(fā)表于 03-25 13:29

    飛凌嵌入式ElfBoard ELF 1板卡-Pinctrl和GPIO子系統(tǒng)之GPIO子系統(tǒng)

    GPIO(General Purpose Input/Output)子系統(tǒng)是用于控制和管理通用輸入/輸出引腳的一部分。它提供了一種標(biāo)準(zhǔn)化的方式來(lái)訪問(wèn)和操作硬件平臺(tái)上的GPIO引腳,使開(kāi)發(fā)人員能夠通過(guò)
    發(fā)表于 03-24 15:41

    飛凌嵌入式ElfBoard ELF 1板卡-Pinctrl和GPIO子系統(tǒng)之Pinctrl子系統(tǒng)

    pinctrl(Pin Control)子系統(tǒng)是Linux內(nèi)核中的一個(gè)模塊化子系統(tǒng),用于管理和控制硬件引腳(Pin)的配置和功能。它提供了一種統(tǒng)一的接口,使驅(qū)動(dòng)程序可以對(duì)硬件引腳進(jìn)行靈活的配置和控制
    發(fā)表于 03-22 09:23