diff --git a/IMX6ULL/doc_pic/05_Input/DRV_02_编写input_dev驱动框架.md b/IMX6ULL/doc_pic/05_Input/DRV_02_编写input_dev驱动框架.md new file mode 100644 index 0000000..9ece0fb --- /dev/null +++ b/IMX6ULL/doc_pic/05_Input/DRV_02_编写input_dev驱动框架.md @@ -0,0 +1,63 @@ +## 编写input_dev驱动框架 + +参考资料: + +* Linux 5.x内核文档 +* Documentation\input\input-programming.rst + * Documentation\input\event-codes.rst +* Linux 4.x内核文档 + * Documentation\input\input-programming.txt + * Documentation\input\event-codes.txt + +* 本节视频代码:GIT仓库中 + + ```shell + IMX6ULL\source\05_Input\02_input_dev_framework + STM32MP157\source\A7\05_Input\02_input_dev_framework + ``` + + + +### 1. 回顾框架 + +![image-20210326102626660](pic/05_Input/03_input_driver_module.png) + +### 2. 怎么编写input_dev驱动 + +#### 2.1 分配/设置/注册input_dev + +![image-20210324140549118](pic/05_Input/08_input_dev.png) + + + +#### 2.2 硬件相关的操作 + +* 申请中断 + +* 在中断服务程序里 + + * 读取硬件获得数据 + + * 上报数据 + + ```shell + void input_event(struct input_dev *dev, + unsigned int type, unsigned int code, int value); + + static inline void input_sync(struct input_dev *dev); // 实质也是 input_event + ``` + + + +### 3. 现场编程 + +![image-20210326095621949](pic/05_Input/12_write_input_dev.png) + +* 在设备树里创建一个节点 + * 指定硬件资源等信息 +* 编译一个plartform_driver驱动 + * 在probe函数里 + * 从设备树获得资源 + * 分配/设置/注册input_dev + * 硬件相关的操作 + * request_irq等 \ No newline at end of file diff --git a/IMX6ULL/doc_pic/05_Input/DRV_02_编写input_dev驱动框架.tif b/IMX6ULL/doc_pic/05_Input/DRV_02_编写input_dev驱动框架.tif new file mode 100644 index 0000000..2a3d6e9 Binary files /dev/null and b/IMX6ULL/doc_pic/05_Input/DRV_02_编写input_dev驱动框架.tif differ diff --git a/IMX6ULL/doc_pic/05_Input/pic/05_Input/03_input_driver_module.png b/IMX6ULL/doc_pic/05_Input/pic/05_Input/03_input_driver_module.png index 6587a82..3ef6934 100644 Binary files a/IMX6ULL/doc_pic/05_Input/pic/05_Input/03_input_driver_module.png and b/IMX6ULL/doc_pic/05_Input/pic/05_Input/03_input_driver_module.png differ diff --git a/IMX6ULL/doc_pic/05_Input/pic/05_Input/12_write_input_dev.png b/IMX6ULL/doc_pic/05_Input/pic/05_Input/12_write_input_dev.png new file mode 100644 index 0000000..fe1b808 Binary files /dev/null and b/IMX6ULL/doc_pic/05_Input/pic/05_Input/12_write_input_dev.png differ diff --git a/IMX6ULL/source/05_Input/02_input_dev_framework/input_dev.c b/IMX6ULL/source/05_Input/02_input_dev_framework/input_dev.c new file mode 100644 index 0000000..ba540ff --- /dev/null +++ b/IMX6ULL/source/05_Input/02_input_dev_framework/input_dev.c @@ -0,0 +1,120 @@ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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); + input_sync(g_input_dev); + + return IRQ_HANDLED; +} + + +/* alloc/set/register platform_driver */ +static int input_dev_demo_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + int error; + struct resource *irq; + + /* get hardware info from device tree */ + + /* alloc/set/register input_dev */ + g_input_dev = devm_input_allocate_device(dev); + + 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; + + /* set 1: which type event ? */ + __set_bit(EV_KEY, g_input_dev->evbit); + __set_bit(EV_ABS, g_input_dev->evbit); + + /* set 2: which event ? */ + __set_bit(BTN_TOUCH, g_input_dev->keybit); + __set_bit(ABS_MT_SLOT, g_input_dev->absbit); + __set_bit(ABS_MT_POSITION_X, g_input_dev->absbit); + __set_bit(ABS_MT_POSITION_Y, g_input_dev->absbit); + + /* set 3: event params ? */ + input_set_abs_params(g_input_dev, ABS_MT_POSITION_X, 0, 0xffff, 0, 0); + input_set_abs_params(g_input_dev, ABS_MT_POSITION_Y, 0, 0xffff, 0, 0); + + error = input_register_device(g_input_dev); + + /* hardware opration */ + 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; +} + +static int input_dev_demo_remove(struct platform_device *pdev) +{ + free_irq(g_irq, NULL); + input_unregister_device(g_input_dev); + return 0; +} + +static const struct of_device_id input_dev_demo_of_match[] = { + { .compatible = "100ask,input_dev_demo", }, + { }, +}; + +static struct platform_driver input_dev_demo_driver = { + .probe = input_dev_demo_probe, + .remove = input_dev_demo_remove, + .driver = { + .name = "input_dev_demo", + .of_match_table = input_dev_demo_of_match, + } +}; + + +static int __init input_dev_demo_init(void) +{ + return platform_driver_register(&input_dev_demo_driver); +} + +static void __exit input_dev_demo_exit(void) +{ + platform_driver_unregister(&input_dev_demo_driver); +} + +module_init(input_dev_demo_init); +module_exit(input_dev_demo_exit); + +MODULE_LICENSE("GPL"); + + diff --git a/IMX6ULL/source/05_Input/02_input_dev_framework/input_dev.dts b/IMX6ULL/source/05_Input/02_input_dev_framework/input_dev.dts new file mode 100644 index 0000000..631f311 --- /dev/null +++ b/IMX6ULL/source/05_Input/02_input_dev_framework/input_dev.dts @@ -0,0 +1,6 @@ +/ { + input_dev_demo { + compatible = "100ask,input_dev_demo"; + interrupts = <...>; + }; +}; diff --git a/README.md b/README.md index 47bd253..44a6ed9 100644 --- a/README.md +++ b/README.md @@ -151,6 +151,8 @@ git clone https://e.coding.net/weidongshan/doc_and_source_for_drivers.git * 2021.03.25 发布"Input子系统":DRV_01_Input子系统框架详解 +* 2021.03.26 发布"Input子系统":DRV_02_编写input_dev驱动框架 + diff --git a/STM32MP157/doc_pic/05_Input/DRV_02_编写input_dev驱动框架.md b/STM32MP157/doc_pic/05_Input/DRV_02_编写input_dev驱动框架.md new file mode 100644 index 0000000..9ece0fb --- /dev/null +++ b/STM32MP157/doc_pic/05_Input/DRV_02_编写input_dev驱动框架.md @@ -0,0 +1,63 @@ +## 编写input_dev驱动框架 + +参考资料: + +* Linux 5.x内核文档 +* Documentation\input\input-programming.rst + * Documentation\input\event-codes.rst +* Linux 4.x内核文档 + * Documentation\input\input-programming.txt + * Documentation\input\event-codes.txt + +* 本节视频代码:GIT仓库中 + + ```shell + IMX6ULL\source\05_Input\02_input_dev_framework + STM32MP157\source\A7\05_Input\02_input_dev_framework + ``` + + + +### 1. 回顾框架 + +![image-20210326102626660](pic/05_Input/03_input_driver_module.png) + +### 2. 怎么编写input_dev驱动 + +#### 2.1 分配/设置/注册input_dev + +![image-20210324140549118](pic/05_Input/08_input_dev.png) + + + +#### 2.2 硬件相关的操作 + +* 申请中断 + +* 在中断服务程序里 + + * 读取硬件获得数据 + + * 上报数据 + + ```shell + void input_event(struct input_dev *dev, + unsigned int type, unsigned int code, int value); + + static inline void input_sync(struct input_dev *dev); // 实质也是 input_event + ``` + + + +### 3. 现场编程 + +![image-20210326095621949](pic/05_Input/12_write_input_dev.png) + +* 在设备树里创建一个节点 + * 指定硬件资源等信息 +* 编译一个plartform_driver驱动 + * 在probe函数里 + * 从设备树获得资源 + * 分配/设置/注册input_dev + * 硬件相关的操作 + * request_irq等 \ No newline at end of file diff --git a/STM32MP157/doc_pic/05_Input/DRV_02_编写input_dev驱动框架.tif b/STM32MP157/doc_pic/05_Input/DRV_02_编写input_dev驱动框架.tif new file mode 100644 index 0000000..2a3d6e9 Binary files /dev/null and b/STM32MP157/doc_pic/05_Input/DRV_02_编写input_dev驱动框架.tif differ diff --git a/STM32MP157/doc_pic/05_Input/pic/05_Input/03_input_driver_module.png b/STM32MP157/doc_pic/05_Input/pic/05_Input/03_input_driver_module.png index 6587a82..3ef6934 100644 Binary files a/STM32MP157/doc_pic/05_Input/pic/05_Input/03_input_driver_module.png and b/STM32MP157/doc_pic/05_Input/pic/05_Input/03_input_driver_module.png differ diff --git a/STM32MP157/doc_pic/05_Input/pic/05_Input/12_write_input_dev.png b/STM32MP157/doc_pic/05_Input/pic/05_Input/12_write_input_dev.png new file mode 100644 index 0000000..fe1b808 Binary files /dev/null and b/STM32MP157/doc_pic/05_Input/pic/05_Input/12_write_input_dev.png differ diff --git a/STM32MP157/source/A7/05_Input/02_input_dev_framework/input_dev.c b/STM32MP157/source/A7/05_Input/02_input_dev_framework/input_dev.c new file mode 100644 index 0000000..ba540ff --- /dev/null +++ b/STM32MP157/source/A7/05_Input/02_input_dev_framework/input_dev.c @@ -0,0 +1,120 @@ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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); + input_sync(g_input_dev); + + return IRQ_HANDLED; +} + + +/* alloc/set/register platform_driver */ +static int input_dev_demo_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + int error; + struct resource *irq; + + /* get hardware info from device tree */ + + /* alloc/set/register input_dev */ + g_input_dev = devm_input_allocate_device(dev); + + 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; + + /* set 1: which type event ? */ + __set_bit(EV_KEY, g_input_dev->evbit); + __set_bit(EV_ABS, g_input_dev->evbit); + + /* set 2: which event ? */ + __set_bit(BTN_TOUCH, g_input_dev->keybit); + __set_bit(ABS_MT_SLOT, g_input_dev->absbit); + __set_bit(ABS_MT_POSITION_X, g_input_dev->absbit); + __set_bit(ABS_MT_POSITION_Y, g_input_dev->absbit); + + /* set 3: event params ? */ + input_set_abs_params(g_input_dev, ABS_MT_POSITION_X, 0, 0xffff, 0, 0); + input_set_abs_params(g_input_dev, ABS_MT_POSITION_Y, 0, 0xffff, 0, 0); + + error = input_register_device(g_input_dev); + + /* hardware opration */ + 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; +} + +static int input_dev_demo_remove(struct platform_device *pdev) +{ + free_irq(g_irq, NULL); + input_unregister_device(g_input_dev); + return 0; +} + +static const struct of_device_id input_dev_demo_of_match[] = { + { .compatible = "100ask,input_dev_demo", }, + { }, +}; + +static struct platform_driver input_dev_demo_driver = { + .probe = input_dev_demo_probe, + .remove = input_dev_demo_remove, + .driver = { + .name = "input_dev_demo", + .of_match_table = input_dev_demo_of_match, + } +}; + + +static int __init input_dev_demo_init(void) +{ + return platform_driver_register(&input_dev_demo_driver); +} + +static void __exit input_dev_demo_exit(void) +{ + platform_driver_unregister(&input_dev_demo_driver); +} + +module_init(input_dev_demo_init); +module_exit(input_dev_demo_exit); + +MODULE_LICENSE("GPL"); + + diff --git a/STM32MP157/source/A7/05_Input/02_input_dev_framework/input_dev.dts b/STM32MP157/source/A7/05_Input/02_input_dev_framework/input_dev.dts new file mode 100644 index 0000000..631f311 --- /dev/null +++ b/STM32MP157/source/A7/05_Input/02_input_dev_framework/input_dev.dts @@ -0,0 +1,6 @@ +/ { + input_dev_demo { + compatible = "100ask,input_dev_demo"; + interrupts = <...>; + }; +};