中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁(yè) > news >正文

網(wǎng)站備案域名更改廣點(diǎn)通

網(wǎng)站備案域名更改,廣點(diǎn)通,怎么給網(wǎng)站動(dòng)態(tài)做偽靜態(tài),網(wǎng)站建設(shè)夬金手指花總往期內(nèi)容 本專欄往期內(nèi)容: input子系統(tǒng)的框架和重要數(shù)據(jù)結(jié)構(gòu)詳解-CSDN博客input device和input handler的注冊(cè)以及匹配過(guò)程解析-CSDN博客input device和input handler的注冊(cè)以及匹配過(guò)程解析-CSDN博客 I2C子系統(tǒng)專欄: 專欄地址:IIC子系統(tǒng)_憧憬…

往期內(nèi)容

本專欄往期內(nèi)容:

  1. input子系統(tǒng)的框架和重要數(shù)據(jù)結(jié)構(gòu)詳解-CSDN博客
  2. input device和input handler的注冊(cè)以及匹配過(guò)程解析-CSDN博客
  3. input device和input handler的注冊(cè)以及匹配過(guò)程解析-CSDN博客

I2C子系統(tǒng)專欄:

  1. 專欄地址:IIC子系統(tǒng)_憧憬一下的博客-CSDN博客
  2. 具體芯片的IIC控制器驅(qū)動(dòng)程序分析:i2c-imx.c-CSDN博客
    – 末篇,有往期內(nèi)容觀看順序

總線和設(shè)備樹專欄:

  1. 專欄地址:總線和設(shè)備樹_憧憬一下的博客-CSDN博客
  2. 設(shè)備樹與 Linux 內(nèi)核設(shè)備驅(qū)動(dòng)模型的整合-CSDN博客
    – 末篇,有往期內(nèi)容觀看順序

前言

img
img

和之前的驅(qū)動(dòng)程序有點(diǎn)差別(IIC專欄中編寫的控制器驅(qū)動(dòng)框架編寫一個(gè)通用的i2c控制器驅(qū)動(dòng)框架-CSDN博客),在driver中變成注冊(cè)input_dev,file_operations字符驅(qū)程序的創(chuàng)建在input_handler層實(shí)現(xiàn)(原本是在platform_driver中實(shí)現(xiàn)的:file_operation、設(shè)備類的注冊(cè)),實(shí)現(xiàn)了內(nèi)核驅(qū)動(dòng)程序的上層、中轉(zhuǎn)層、下層的分離

下層驅(qū)動(dòng)中,只需要去編寫好設(shè)備的驅(qū)動(dòng)程序,在程序中分配、設(shè)置、注冊(cè)input_dev,發(fā)生中斷時(shí)只需要上報(bào)中斷事件即可,其余的中轉(zhuǎn)層和上層的驅(qū)動(dòng)程序內(nèi)核已經(jīng)做好了。

這個(gè)在之前對(duì)內(nèi)核提供的源碼示例進(jìn)行講解的時(shí)候也很清晰了,詳見(jiàn)本專欄前3章內(nèi)容。

1. 怎么編寫input_dev驅(qū)動(dòng)

這里參考內(nèi)核提供的gpio_keys.c為例子,input_dev上層

\Linux-4.9.88\drivers\input\keyboard\gpio_keys.c:📎gpio_keys.c

1.1 分配、設(shè)置、注冊(cè)input_dev

這一部分主要是probe完成:

img

在gpio_keys.c中,添加了自己理解的一點(diǎn)注釋,如下:

static int gpio_keys_probe(struct platform_device *pdev)
{struct device *dev = &pdev->dev;  // 獲取設(shè)備結(jié)構(gòu)體const struct gpio_keys_platform_data *pdata = dev_get_platdata(dev);  // 從平臺(tái)設(shè)備獲取平臺(tái)數(shù)據(jù)struct gpio_keys_drvdata *ddata;  // 驅(qū)動(dòng)私有數(shù)據(jù)結(jié)構(gòu)struct input_dev *input;  // 輸入設(shè)備結(jié)構(gòu)體size_t size;  // 計(jì)算需要分配的內(nèi)存大小int i, error;  // 循環(huán)計(jì)數(shù)器和錯(cuò)誤碼int wakeup = 0;  // 標(biāo)志位,指示是否支持喚醒功能// 如果 pdata 為 NULL,則從設(shè)備樹獲取平臺(tái)數(shù)據(jù)if (!pdata) {pdata = gpio_keys_get_devtree_pdata(dev);if (IS_ERR(pdata))return PTR_ERR(pdata);  // 返回錯(cuò)誤碼}// 計(jì)算 gpio_keys_drvdata 和按鈕數(shù)據(jù)結(jié)構(gòu)的大小size = sizeof(struct gpio_keys_drvdata) +pdata->nbuttons * sizeof(struct gpio_button_data);// 分配驅(qū)動(dòng)私有數(shù)據(jù)內(nèi)存ddata = devm_kzalloc(dev, size, GFP_KERNEL);if (!ddata) {dev_err(dev, "failed to allocate state\n");  // 分配失敗,輸出錯(cuò)誤信息return -ENOMEM;  // 返回內(nèi)存不足錯(cuò)誤碼}// 分配輸入設(shè)備input = devm_input_allocate_device(dev);if (!input) {dev_err(dev, "failed to allocate input device\n");  // 分配失敗,輸出錯(cuò)誤信息return -ENOMEM;  // 返回內(nèi)存不足錯(cuò)誤碼}ddata->pdata = pdata;  // 保存平臺(tái)數(shù)據(jù)指針ddata->input = input;  // 保存輸入設(shè)備指針mutex_init(&ddata->disable_lock);  // 初始化互斥鎖// 將驅(qū)動(dòng)數(shù)據(jù)指針與平臺(tái)設(shè)備相關(guān)聯(lián)platform_set_drvdata(pdev, ddata);input_set_drvdata(input, ddata);  // 將驅(qū)動(dòng)數(shù)據(jù)與輸入設(shè)備關(guān)聯(lián)// 設(shè)置輸入設(shè)備名稱和物理路徑input->name = pdata->name ? : pdev->name;  // 如果 pdata 中有名稱則使用,否則使用平臺(tái)設(shè)備名稱input->phys = "gpio-keys/input0";  // 設(shè)置物理路徑input->dev.parent = &pdev->dev;  // 設(shè)置設(shè)備的父設(shè)備input->open = gpio_keys_open;  // 設(shè)置打開(kāi)設(shè)備的函數(shù)input->close = gpio_keys_close;  // 設(shè)置關(guān)閉設(shè)備的函數(shù)// 設(shè)置輸入設(shè)備的 IDinput->id.bustype = BUS_HOST;  // 設(shè)置總線類型input->id.vendor = 0x0001;  // 設(shè)置廠商 IDinput->id.product = 0x0001;  // 設(shè)置產(chǎn)品 IDinput->id.version = 0x0100;  // 設(shè)置版本號(hào)// 啟用 Linux 輸入子系統(tǒng)的自動(dòng)重復(fù)功能if (pdata->rep)__set_bit(EV_REP, input->evbit);  // 設(shè)置 EV_REP 事件位// 遍歷每個(gè)按鈕并設(shè)置for (i = 0; i < pdata->nbuttons; i++) {const struct gpio_keys_button *button = &pdata->buttons[i];  // 獲取當(dāng)前按鈕信息struct gpio_button_data *bdata = &ddata->data[i];  // 獲取按鈕數(shù)據(jù)error = gpio_keys_setup_key(pdev, input, bdata, button);  // 設(shè)置按鍵,里面包括設(shè)置了中斷函數(shù)if (error)return error;  // 返回錯(cuò)誤碼if (button->wakeup)  // 如果按鈕支持喚醒功能wakeup = 1;  // 設(shè)置喚醒標(biāo)志}// 創(chuàng)建 sysfs 組,用于導(dǎo)出按鍵和開(kāi)關(guān)error = sysfs_create_group(&pdev->dev.kobj, &gpio_keys_attr_group);if (error) {dev_err(dev, "Unable to export keys/switches, error: %d\n", error);  // 輸出錯(cuò)誤信息return error;  // 返回錯(cuò)誤碼}// 注冊(cè)輸入設(shè)備error = input_register_device(input);if (error) {dev_err(dev, "Unable to register input device, error: %d\n", error);  // 輸出錯(cuò)誤信息goto err_remove_group;  // 錯(cuò)誤處理,移除 sysfs 組}// 初始化喚醒設(shè)備功能device_init_wakeup(&pdev->dev, wakeup);return 0;  // 返回成功err_remove_group:// 在錯(cuò)誤情況下移除 sysfs 組sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group);return error;  // 返回錯(cuò)誤碼
}

可以看出來(lái),分配、設(shè)置、注冊(cè)input_dev,然后去注冊(cè)中斷函數(shù),用于調(diào)用中斷的input_event函數(shù)上報(bào)中斷事件,嘗試寫一個(gè):

static struct input_dev *g_input_dev;
static int g_irq;
static irqreturn_t input_dev_demo_isr(int irq, void *dev_id)
{/* read data *//* report data */input_event(g_input_dev, EV_KEY, XX, 0);//通過(guò) input_event() 上報(bào)事件,input_sync() 用于同步報(bào)告的輸入事件。input_sync(g_input_dev);return IRQ_HANDLED;
}static int input_dev_demo_probe(struct platform_device *pdev)
{struct device *dev = &pdev->dev;int error;struct resource *irq;/* 從設(shè)備樹中獲取硬件信息 *//* 分配、設(shè)置并注冊(cè) input_dev */g_input_dev = devm_input_allocate_device(dev);// 設(shè)置輸入設(shè)備的基本信息g_input_dev->name = "input_dev_demo";g_input_dev->phys = "input_dev_demo";g_input_dev->dev.parent = dev;g_input_dev->id.bustype = BUS_HOST;g_input_dev->id.vendor = 0x0001;g_input_dev->id.product = 0x0001;g_input_dev->id.version = 0x0100;/* 設(shè)置 1: 支持的事件類型 */__set_bit(EV_KEY, g_input_dev->evbit); // 鍵盤或按鈕事件__set_bit(EV_ABS, g_input_dev->evbit); // 絕對(duì)坐標(biāo)事件/* 設(shè)置 2: 支持的具體事件 */__set_bit(BTN_TOUCH, g_input_dev->keybit); // 觸摸按鈕事件__set_bit(ABS_MT_SLOT, g_input_dev->absbit); // 多點(diǎn)觸摸槽位__set_bit(ABS_MT_POSITION_X, g_input_dev->absbit); // 觸摸屏 X 軸坐標(biāo)__set_bit(ABS_MT_POSITION_Y, g_input_dev->absbit); // 觸摸屏 Y 軸坐標(biāo)/* 設(shè)置 3: 事件參數(shù) */input_set_abs_params(g_input_dev, ABS_MT_POSITION_X, 0, 0xffff, 0, 0); // X 坐標(biāo)范圍input_set_abs_params(g_input_dev, ABS_MT_POSITION_Y, 0, 0xffff, 0, 0); // Y 坐標(biāo)范圍// 注冊(cè)輸入設(shè)備error = input_register_device(g_input_dev);/* 硬件操作: 獲取中斷資源并注冊(cè)中斷 */irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);g_irq = irq->start;request_irq(irq->start, input_dev_demo_isr, IRQF_TRIGGER_RISING, "input_dev_demo_irq", NULL);return 0;
}

1.2 硬件相關(guān)操作

  • 申請(qǐng)中斷
  • 在中斷服務(wù)程序里
    • 讀取硬件獲得數(shù)據(jù)
    • 上報(bào)數(shù)據(jù)
void input_event(struct input_dev *dev,unsigned int type, unsigned int code, int value);static inline void input_sync(struct input_dev *dev); // 實(shí)質(zhì)也是 input_event

input子系統(tǒng)中讀取流程解析-CSDN博客
具體內(nèi)容在該章節(jié)的 event 處已經(jīng)講解過(guò)。

2. 代碼

img

#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/sched.h>
#include <linux/pm.h>
#include <linux/slab.h>
#include <linux/sysctl.h>
#include <linux/proc_fs.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/input.h>
#include <linux/gpio_keys.h>
#include <linux/workqueue.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/spinlock.h>/* 定義指向輸入設(shè)備結(jié)構(gòu)體的指針 */
static struct input_dev *input_device_demo;
/* 用于保存輸入設(shè)備的中斷號(hào) */
static int irq_num;/* 中斷服務(wù)程序,處理輸入設(shè)備的事件 */
static irqreturn_t input_device_demo_isr(int irq, void *dev_id)
{/* 可在此處添加數(shù)據(jù)讀取和事件處理邏輯 *//* 向輸入子系統(tǒng)報(bào)告按鍵事件 */input_event(input_device_demo, EV_KEY, KEY_TOUCH, 0);input_sync(input_device_demo);return IRQ_HANDLED;
}/* 分配、配置和注冊(cè)平臺(tái)驅(qū)動(dòng) */
static int input_device_demo_probe(struct platform_device *pdev)
{struct device *dev = &pdev->dev;int error;struct resource *irq;/* 從設(shè)備樹獲取硬件信息 *//* 分配并初始化輸入設(shè)備結(jié)構(gòu)體 */input_device_demo = devm_input_allocate_device(dev);if (!input_device_demo)return -ENOMEM;/* 設(shè)置設(shè)備名稱和物理位置 */input_device_demo->name = "input_device_demo";input_device_demo->phys = "input_device_demo";input_device_demo->dev.parent = dev;/* 設(shè)置設(shè)備的總線類型和ID */input_device_demo->id.bustype = BUS_HOST;input_device_demo->id.vendor = 0x0001;input_device_demo->id.product = 0x0001;input_device_demo->id.version = 0x0100;/* 設(shè)置輸入設(shè)備支持的事件類型 */__set_bit(EV_KEY, input_device_demo->evbit); // 支持按鍵事件__set_bit(EV_ABS, input_device_demo->evbit); // 支持絕對(duì)位置事件/* 設(shè)置輸入設(shè)備支持的具體事件 */__set_bit(BTN_TOUCH, input_device_demo->keybit); // 支持觸摸按鍵事件__set_bit(ABS_MT_SLOT, input_device_demo->absbit); // 多點(diǎn)觸控槽位事件__set_bit(ABS_MT_POSITION_X, input_device_demo->absbit); // X軸位置事件__set_bit(ABS_MT_POSITION_Y, input_device_demo->absbit); // Y軸位置事件/* 設(shè)置具體事件的參數(shù)范圍,例如X和Y坐標(biāo)的最小值、最大值等 */input_set_abs_params(input_device_demo, ABS_MT_POSITION_X, 0, 0xffff, 0, 0);input_set_abs_params(input_device_demo, ABS_MT_POSITION_Y, 0, 0xffff, 0, 0);/* 注冊(cè)輸入設(shè)備 */error = input_register_device(input_device_demo);if (error)return error;/* 硬件操作:從設(shè)備樹獲取中斷資源并注冊(cè)中斷 */irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);irq_num = irq->start;error = request_irq(irq_num, input_device_demo_isr, IRQF_TRIGGER_RISING, "input_device_demo_irq", NULL);if (error)input_unregister_device(input_device_demo);return error;
}/* 驅(qū)動(dòng)移除函數(shù),釋放中斷資源并注銷輸入設(shè)備 */
static int input_device_demo_remove(struct platform_device *pdev)
{free_irq(irq_num, NULL);input_unregister_device(input_device_demo);return 0;
}/* 設(shè)備樹匹配表,用于匹配設(shè)備樹中描述的設(shè)備 */
static const struct of_device_id input_device_demo_of_match[] = {{ .compatible = "input,input_device_demo", },{ },
};/* 定義平臺(tái)驅(qū)動(dòng)結(jié)構(gòu)體,指定probe和remove函數(shù) */
static struct platform_driver input_device_demo_driver = {.probe = input_device_demo_probe,.remove = input_device_demo_remove,.driver = {.name = "input_device_demo",.of_match_table = input_device_demo_of_match,}
};/* 模塊初始化函數(shù),注冊(cè)平臺(tái)驅(qū)動(dòng) */
static int __init input_device_demo_init(void)
{return platform_driver_register(&input_device_demo_driver);
}/* 模塊退出函數(shù),注銷平臺(tái)驅(qū)動(dòng) */
static void __exit input_device_demo_exit(void)
{platform_driver_unregister(&input_device_demo_driver);
}module_init(input_device_demo_init);
module_exit(input_device_demo_exit);MODULE_LICENSE("GPL");

img

在以前的驅(qū)動(dòng)程序模板中,platform_driver中不僅注冊(cè)了file_operation等,也注冊(cè)了中斷處理函數(shù),并且中斷處理函數(shù)中是直接對(duì)中斷事件進(jìn)行處理

但是在內(nèi)核驅(qū)動(dòng)分層中,platform_input_dev,中斷處理函數(shù)只上報(bào)中斷事件給input.c,交由Input.c去調(diào)用input_dev對(duì)應(yīng)的input_handler中的函數(shù)來(lái)處理中斷(filter、events、event函數(shù)),同時(shí)input_handler層提供了app調(diào)用的接口函數(shù),如file_operation中的read

http://www.risenshineclean.com/news/63461.html

相關(guān)文章:

  • 余姚做網(wǎng)站公司網(wǎng)店代運(yùn)營(yíng)和推廣銷售
  • 教育類網(wǎng)站素材如何在百度上發(fā)布自己的文章
  • 做網(wǎng)站可以干什么網(wǎng)站開(kāi)發(fā)建站
  • 網(wǎng)站 建設(shè) 函google關(guān)鍵詞推廣
  • 做棋牌網(wǎng)站一般多少錢中國(guó)體育新聞
  • 淘寶網(wǎng)站的論壇做的怎么樣前端seo是什么
  • 目前最流行網(wǎng)站開(kāi)發(fā)軟件查域名ip地址查詢
  • 網(wǎng)站集群建設(shè)實(shí)施方案重慶seo推廣公司
  • 網(wǎng)站怎么做流量互換品牌營(yíng)銷策劃包括哪些內(nèi)容
  • ps個(gè)人網(wǎng)站制作流程個(gè)人網(wǎng)站怎么建立
  • 佛山新網(wǎng)站建設(shè)策劃百度網(wǎng)頁(yè)版首頁(yè)
  • 成都市網(wǎng)站建設(shè)費(fèi)用及企業(yè)京東關(guān)鍵詞優(yōu)化技巧
  • 汽車門戶網(wǎng)站開(kāi)發(fā)推廣網(wǎng)站的文案
  • 網(wǎng)站建站服務(wù)公司網(wǎng)站維護(hù)一般都是維護(hù)什么
  • wordpress圖片展示插件seo的優(yōu)化步驟
  • 想做機(jī)械加工和橡膠生意怎么做網(wǎng)站磁力搜索引擎2023
  • 舉重運(yùn)動(dòng)員 做網(wǎng)站線上推廣活動(dòng)有哪些
  • 移動(dòng)做績(jī)效的網(wǎng)站網(wǎng)站建設(shè)策劃書范文
  • 海寧市規(guī)劃建設(shè)局網(wǎng)站東莞網(wǎng)站建設(shè)公司
  • wordpress去除評(píng)論限制網(wǎng)站按天扣費(fèi)優(yōu)化推廣
  • 有了網(wǎng)站模板 還要怎樣做域名注冊(cè)要多少錢
  • 亞網(wǎng)互聯(lián)網(wǎng)站設(shè)計(jì)市場(chǎng)營(yíng)銷畢業(yè)后找什么工作
  • 做企業(yè)網(wǎng)站收費(fèi)百度競(jìng)價(jià)推廣效果怎么樣
  • 濰坊做網(wǎng)站的電話泰州百度seo公司
  • 個(gè)人網(wǎng)站模板如何在各大平臺(tái)推廣
  • wordpress國(guó)內(nèi)速度優(yōu)化安卓?jī)?yōu)化清理大師
  • 商品展示網(wǎng)站模板短視頻獲客系統(tǒng)
  • 一個(gè)app能賣多少錢搜索引擎排名優(yōu)化技術(shù)
  • 網(wǎng)站建設(shè)應(yīng)列入啥費(fèi)用搜索引擎營(yíng)銷優(yōu)化的方法
  • vi設(shè)計(jì)說(shuō)明范文解析重慶百度推廣優(yōu)化排名