手把手教你写Linux设备驱动---input子系统(四)--电容屏驱动ft5x06编写(一)(基于友善之臂4412开发板)

xiaoxiao2021-02-28  129

这一节,我们将从零开始写tiny4412的触摸屏驱动ft5x06,写这节博客之前,先了解下需要什么知识:

1、i2c驱动相关的知识

2、输入子系统

3、中断

4、工作队列

关于i2c驱动相关的知识,在后期的博文里会专门写几篇博文来进行总结,这里就不再说i2c相关的知识,我们先知道怎么用就行了。

首先,我在ts.h构造了一个ts_info_st结构体,用来存放触摸屏的中断线,x坐标,y坐标,压力值。

用ts_st构造了该触摸屏的设备结构体。

我们还是直接看点实际的东西,上代码:

ts.h

#ifndef __TS_H #define __TH_H struct ts_info_st { int irq ; int xres ; int yres ; int pressure ; }; //I2c_transfer 读写设备--->可能睡眠--->用工作队列 struct ts_st { int x ; //坐标 int y ; int irq ; //中断 int xres ; int yres ; int pressure ; //触摸力度 struct work_struct work ; //用于创建工作队列用 struct i2c_client *client ; //用于i2c struct input_dev *dev ; //用于输入子系统 }; #endifts_drv.c

#include <linux/module.h> #include <linux/init.h> #include <linux/sched.h> #include <linux/irq.h> #include <linux/interrupt.h> #include <linux/input.h> #include <linux/workqueue.h> #include <linux/i2c.h> #include <linux/slab.h> #include "ts.h" struct ts_st *ts ; struct ts_info_st *pdata ; //一旦有中断,就会在串口终端打印中断号 irqreturn_t ts_handler(int irq , void *data) { printk("ts touch !\n"); printk("irq : %d\n",irq); return IRQ_HANDLED ; } //匹配成功就会调用probe函数 int ts_probe(struct i2c_client *client , const struct i2c_device_id *id) { int ret ; printk("probe\n"); //从i2c的client获取设备相关的数据保存到pdata里 pdata = client->dev.platform_data ; ts = kzalloc(sizeof(*ts),GFP_KERNEL); if(!ts){ return -ENOMEM ; } //给ts指针赋值 printk("malloc success!\n"); ts->client = client ; ts->irq = pdata->irq ; //获取中断号 ts->xres = pdata->xres ; //获取x坐标 ts->yres = pdata->yres ; //获取y坐标 ts->pressure = pdata->pressure ; //申请输入设备 ts->dev = input_allocate_device(); if(!ts->dev){ ret = -ENOMEM ; goto alloc_input_error ; } ts->dev->name = client->name ; //"myts"-->board_info_ ts->dev->phys = "xxxxx" ; ts->dev->uniq = "20170506" ; ts->dev->id.bustype = BUS_I2C ; ts->dev->id.vendor = 10010; ts->dev->id.product = 10111 ; ts->dev->id.version = 1 ; //以上赋值是表示注册设备以后的信息,可以通过cat /proc/bus/input查看 //注册input事件 ret = input_register_device(ts->dev); if(ret){ goto register_input_error ; } //注册中断-->中断下降沿 ret = request_irq(ts->irq , ts_handler , IRQF_TRIGGER_FALLING , client->name , ts) ; if(ret){ goto irq_erro ; } printk("register irq success!\n"); return ret ; register_input_error: input_free_device(ts->dev); alloc_input_error: kfree(ts); irq_erro : input_unregister_device(ts->dev); free_irq(ts->irq,&ts); kfree(ts); } //i2c的id_table struct i2c_device_id id_table[] = { {"myts",123}, {"herts","456"}, {}, }; //实现i2c驱动操作结构体 struct i2c_driver ts_drv = { .probe = ts_probe , .driver = { .name = "myts", }, .id_table = id_table , }; static int __init hello_init(void) { printk("Hello, kenerl installed for YYXXXXXXXXXX20170423!\n"); int ret ; ret = i2c_add_driver(&ts_drv); //添加一个i2c驱动 if(ret != 0){ printk("i2c add driver fair!\n"); i2c_del_driver(&ts_drv); //删除一个i2c驱动 return -1 ; } printk("i2c_add driver success!\n"); return 0; } static void __exit hello_cleanup(void) { printk("Good-bye, removed!\n"); i2c_del_driver(&ts_drv); } module_init(hello_init); module_exit(hello_cleanup); MODULE_LICENSE("GPL");

编写Makefile,这里我们在外面写一个用驱动就可以加载的模块:

obj-m += ts_drv.o ROOTFS = . KERNEL_SRC = /work/android-5.0.2/kernel all: make -C $(KERNEL_SRC) M=`pwd` modules clean: make -C $(KERNEL_SRC) M=`pwd` clean rm -rf app install: make -C $(KERNEL_SRC) M=`pwd` modules_install INSTALL_MOD_PATH=$(ROOTFS) app: arm-linux-gcc app.c -o app写完驱动后,在当前目录下执行make:

然后,我们通过adb push命令,将该ko放入android根文件系统的system目录下。

如果你的系统的分区没有设置成可读可写,还需要在当前目录下执行:adb remount就可以了。

接下来,执行adb push  ts_drv.ko   /system

然后切换到我的minicom终端,此时Android系统已经启动,我切换到system目录下,执行insmod ts_drv.ko后,然后手点击触摸屏,就会有驱动信息弹出来,做这个步骤之前,要把友善提供的内核里的写好的触摸屏驱动给卸载掉,否则不会成功,请注意。

我们看到,触摸屏的时候,中断服务程序就会被调用,打印出中断号。

下一节,我们将进一步完善这个触摸屏驱动程序。

Engineer-Bruce_Yang 认证博客专家 嵌入式硬件 单片机 arm开发 本科毕业于华南理工大学,现美国卡罗尔工商管理硕士研究生在读,曾就职于世界名企伟易达、联发科技等,多年嵌入式产品开发经验,在智能玩具、安防产品、平板电脑、手机开发有丰富的实战开发经验,现任深圳市云之手科技有限公司副总经理、研发总工程师。
转载请注明原文地址: https://www.6miu.com/read-65041.html

最新回复(0)