[转]输入简单流程

现在看用户获取触摸屏输入的一个流程(以tsdev为例/drivers/input/tsdev.c):
static struct file_operations tsdev_fops = {
        .owner =        THIS_MODULE,
        .open =         tsdev_open,
        .release =      tsdev_release,
        .read =         tsdev_read,
        .poll =         tsdev_poll,
        .fasync =       tsdev_fasync,
        .ioctl =        tsdev_ioctl,
};
假设所有初始化早已完成,用户open该设备后,使用read系统调用进入内核,系统
转移控制到tsdev_read,使用wait_event_interruptible等待事件。

此时驱动层得到用户输入,于是调用input_report_abs,input_report_abs只是
input_event的简单包装:
static inline void input_report_abs(struct input_dev *dev, 
                                     unsigned int code, int value)
{
        input_event(dev, EV_ABS, code, value);
}

void input_event(struct input_dev *dev, unsigned int type, 
                                  unsigned int code, int value)
{
    ...
    switch (type) {
        ...
        case EV_ABS:
            ...
            break;
        ...
    }
    ...

    if (dev->grab)
        dev->grab->handler->event(dev->grab, type, code, value);
    else
        list_for_each_entry(handle, &dev->h_list, d_node)
            if (handle->open)
                handle->handler->event(handle, type, code, value);
}
前面的处理关系具体设备,见最后对handler函数的调用,就是从input_dev的h_list链
上的input_handle获得每一个相关input_handler,并调用其中的event函数,对tsdev
来说:
static struct input_handler tsdev_handler = {
        .event =        tsdev_event,
        .connect =      tsdev_connect,
        .disconnect =   tsdev_disconnect,
        .fops =         &tsdev_fops,
        .minor =        TSDEV_MINOR_BASE,
        .name =         "tsdev",
        .id_table =     tsdev_ids,
};
即调用tsdev_event函数,接着看:
static void tsdev_event(struct input_handle *handle, unsigned int type,
                        unsigned int code, int value)
{
    ...
    switch (type) {
        case EV_ABS:
            break;
    ...
    list_for_each_entry(list, &tsdev->list, node) {
        int x, y, tmp;
        do_gettimeofday(&time);
        list->event[list->head].millisecs = time.tv_usec / 100;
        list->event[list->head].pressure = tsdev->pressure;

        x = tsdev->x;
        y = tsdev->y;
        /* Calibration */
        if (!list->raw) {
            x = ((x * tsdev->cal.xscale) >> 8) + tsdev->cal.xtrans;
            y = ((y * tsdev->cal.yscale) >> 8) + tsdev->cal.ytrans;
            if (tsdev->cal.xyswap) {
                tmp = x; x = y; y = tmp;
            }
        }

        list->event[list->head].x = x;
        list->event[list->head].y = y;
        list->head = (list->head + 1) & (TSDEV_BUFFER_SIZE - 1);
        kill_fasync(&list->fasync, SIGIO, POLL_IN);
    }
    wake_up_interruptible(&tsdev->wait);
}
它填充数据,并唤醒等待着的请求。于是前面等待着的read请求就可继续了,
回到tsdev_read中,copy_to_user拷贝数据,最后返回用户层。


一个简单流程就结束了。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值