免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3140 | 回复: 3
打印 上一主题 下一主题

我的基于input子系统的触摸板驱动,起不来,望赐教 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-03-19 22:12 |只看该作者 |倒序浏览
在linuxdrivers.cn上发表过,转贴到这里问问.

这几天研究触摸板的Linux驱动。看了不少资料,发现主要的代码没有多少,关键倒是和Linux内核交互的东西高不明白。
拿内核源码的驱动改成自己的,硬是起不来,又不知道如何解决。
下面是我的源代码框架,贴在这里,顺便列出自己不明白的地方,请达人指教:

#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/serio.h>
#include <linux/init.h>

#define DRIVER_DESC "Serial touchpad driver"

MODULE_AUTHOR("foobar<foobar@foobar.com>");

MODULE_DESCRIPTION(DRIVER_DESC);

MODULE_LICENSE("GPL");

/**
&nbsp;* Per-touchpad data.
&nbsp;*/

struct sertp {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct input_dev *dev; /**< input device */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct serio *serio; /**< serio struct */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s32 id; /**< device id */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;u8 buf[8]; /**< buffer to receive data */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;u8 pre_cnt; /**< received byte pre_cnter */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s8 phys[32];
};


static irqreturn_t sertp_interrupt(struct serio *serio,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;u8 data,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;u32 flags,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct pt_regs *regs)
{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct sertp *sertp = serio_get_drvdata(serio);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printk (KERN_ALERT "sertp_interrupt\n");

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sertp_process_data(sertp, data, regs); /* start processing data */

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return IRQ_HANDLED;
}

static void sertp_disconnect(struct serio *serio)
{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct sertp *sertp = serio_get_drvdata(serio);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printk (KERN_ALERT "sertp_disconnect\n");

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;input_unregister_device(sertp->dev);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;serio_close(serio);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;serio_set_drvdata(serio, NULL);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;kfree(sertp);
&nbsp;}

static int sertp_connect(struct serio *serio, struct serio_driver *drv)
{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct sertp *sertp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct input_dev *input_dev;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int err;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printk (KERN_ALERT "sertp_connect\n");     /* allocate our struct data and input device */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sertp = kzalloc(sizeof(struct sertp), GFP_KERNEL);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;input_dev = input_allocate_device();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (!sertp || !input_dev) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;err = -ENOMEM;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;goto fail;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sertp->serio = serio;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sertp->id = serio->id.id;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sertp->dev = input_dev;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;snprintf(sertp->phys, sizeof(sertp->phys), "%s/input0", serio->phys); /* Q0 */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;input_dev->private = sertp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;input_dev->name = "Serial TouchPad";
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;input_dev->phys = sertp->phys; /* Q1 */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;input_dev->id.bustype = BUS_RS232;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;input_dev->id.vendor  = SERIO_ANY; /* Q2 */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;input_dev->id.product = sertp->id;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;input_dev->id.version = 0x0100;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;input_dev->cdev.dev = &serio->dev;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y) | BIT(REL_WHEEL) | BIT(REL_HWHEEL);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;serio_set_drvdata(serio, sertp);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;err = serio_open(serio, drv);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (err) goto fail;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;input_register_device(sertp->dev);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 0;
&nbsp;fail:     serio_set_drvdata(serio, NULL);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;input_free_device(input_dev);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;kfree(sertp);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return err;
}

static struct serio_device_id sertp_serio_ids[] = {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{         .type  = SERIO_RS232,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.proto = SERIO_ANY, /* Q3 */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.extra = SERIO_ANY,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.id    = SERIO_ANY,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ 0 }
};

MODULE_DEVICE_TABLE(serio, sertp_serio_ids);

static struct serio_driver sertp_drv = {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.driver        = {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.name    = "sertp",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.description    = DRIVER_DESC,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.id_table    = sertp_serio_ids,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.interrupt    = sertp_interrupt,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.connect    = sertp_connect,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.disconnect    = sertp_disconnect,
};

static int __init sertp_init(void)
{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printk (KERN_ALERT "sertp_init\n");
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;serio_register_driver(&sertp_drv);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 0;
}

static void __exit sertp_exit(void)
{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printk (KERN_ALERT "sertp_exit\n");

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;serio_unregister_driver(&sertp_drv);
}

/* Module interfaces */
module_init(sertp_init);
module_exit(sertp_exit);


以上是基于串口的触摸板驱动。
我的设计流程大致如下:
1. 接好硬件设备,我的串口触摸板只接了Rx和Tx两根线,不知道这样能不能触发中断;
2. 编写如上代码,然后写了一个Makefile生成.ko模块文件;
3. 使用insmod指令加载驱动模块,发现加载的时候打印出"sertp_init"字符串,表明初始化函数成功调用;
4. 但是实际触摸触摸板时,发现connect函数和中断函数均为调用。但是硬件设备能够正常往串口发送数据的,我用moni调试过,能够确保硬件没问题;
5. 使用rmmod指令卸载模块,发现卸载时打印出"sertp_exit"字符串,表明退出函数成功调用。
我不清楚是哪一步有问题,导致设备发生事件时没有产生中断。请指教

对于上面的代码,标示为Q0~Q3的是我不太明白的地方:
Q0:这条语句的含义是什么?
Q1:serio->phys是做什么用的,需要驱动程序员自己手动填写的还是由input子系统事先预填的?
Q2:input_dev->id有四个字段,bustype、vendor、product和version,这四个字段是怎么确定的?当然了,我这个是串口驱动,bustype我想应该填写BUS_RS232,对不?
Q3:这里的serio_device_id又是4个字段,除了.type我参照touchscreen/elo.c的驱动填写成SERIO_RS232,其他的我真是丈二和尚摸不着头脑,望赐教。

最倒霉的是connect和中断函数不被调用,我连调试也不知道怎么入手

最后给所有进行串口调试的同仁推荐一个Linux下的很不错的串口监视器:Moni
http://www.rolf-schroedter.de/moni/
能够输出16进制数值。程序用Tcl/Tk编写的,使用了startkit封装。使用按主页提示先下载一个tclkit,然后运行。

那个minicom我搞了半天也不能显示16进制,根本无法进行串口调试,只好放弃。

[ 本帖最后由 shaohao 于 2009-3-19 22:17 编辑 ]

论坛徽章:
0
2 [报告]
发表于 2009-03-19 22:35 |只看该作者
这样说的话是中断问题而不是input子系统的问题吧~

你先跑裸机 看看中断是否能触发~

能的话再换到linux下,看看中断能不能触发

一步步调试吧~

bustype、vendor、product和version这4个字段是自己写的 加载什么样的驱动就写死的了  不会动态获取的~

论坛徽章:
0
3 [报告]
发表于 2009-03-22 23:45 |只看该作者
是中断的问题吗?
问题是我的connect函数都没有调用啊!

论坛徽章:
0
4 [报告]
发表于 2009-03-22 23:54 |只看该作者
connect没有调用的话说明设备关键字匹配不正确或者没有匹配吧 = =

尝试一下在/drivers/input/input.c的input_attach_handler中加一个

printk(KERN_INFO "device:%s   handler:%s \n" , dev->name , handler->name);

看看你的设备和驱动之间是否进行过匹配,然后试试看匹配是否通过

匹配正确的话才能进入到connect中~ = 3=
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP