gpio驱动分析2

来源:互联网 发布:小米5如何备份数据 编辑:程序博客网 时间:2024/06/05 08:45

(本文所介绍内核基于linux-2.6.36内核) 

了解完gpio设置之后,下面再对gpio的事件处理流程进行介绍。

Event事件处理定义在drivers/input/evdev.c

函数的注册与注销:drivers/input/evdev.cline904-line925

 

static struct input_handler evdev_handler = {

       .event           = evdev_event,          // Pass incoming event to all connected clients.

       .connect       = evdev_connect,                    // Create new evdev device.

       .disconnect  = evdev_disconnect,

       .fops             = &evdev_fops,

       .minor           = EVDEV_MINOR_BASE,

       .name           = "evdev",

       .id_table       = evdev_ids,

};

 

static int __init evdev_init(void)

{

       return input_register_handler(&evdev_handler);

}

 

static void __exit evdev_exit(void)

{

       input_unregister_handler(&evdev_handler);

}

 

module_init(evdev_init);

module_exit(evdev_exit);

 

evdev中关键的处理功能从evdev_fops开始file operations定义了所有对event的打开关闭以及读写功能:

static const struct file_operations evdev_fops = {

       .owner          = THIS_MODULE,

       .read             = evdev_read,

       .write           = evdev_write,

       .poll              = evdev_poll,

       .open            = evdev_open,

       .release  = evdev_release,

       .unlocked_ioctl    = evdev_ioctl,

#ifdef CONFIG_COMPAT

       .compat_ioctl      = evdev_ioctl_compat,

#endif

       .fasync          = evdev_fasync,

       .flush            = evdev_flush

};

 

1

static int evdev_open(struct inode *inode, struct file *file)

{

       error = mutex_lock_interruptible(&evdev_table_mutex);

       if (error)

              return error;

       evdev = evdev_table[i];

       if (evdev)

              get_device(&evdev->dev);       // increment reference count for device.

       mutex_unlock(&evdev_table_mutex);

 

       if (!evdev)

              return -ENODEV;

 

       bufsize = evdev_compute_buffer_size(evdev->handle.dev);

 

       client = kzalloc(sizeof(struct evdev_client) +

                            bufsize * sizeof(struct input_event),

                      GFP_KERNEL);

       if (!client) {

              error = -ENOMEM;

              goto err_put_evdev;

       }

// 添加evdev_client结构到链表evdev->client_list(好让输入事件到来的时候填写该结构并唤醒进程读取)

       client->bufsize = bufsize;

       spin_lock_init(&client->buffer_lock);

       client->evdev = evdev;

       evdev_attach_client(evdev, client);

 

       error = evdev_open_device(evdev);

       if (error)

              goto err_free_client;

 

       file->private_data = client;

       nonseekable_open(inode, file);

}

 

2

 

static ssize_t evdev_read(struct file *file, char __user *buffer,

                       size_t count, loff_t *ppos)

{

       struct evdev_client *client = file->private_data;

       struct evdev *evdev = client->evdev;

       struct input_event event;

       int retval;

 

       if (count < input_event_size())       //判断输入时间数据量是否正确

              return -EINVAL;

//缓存中没有数据可读、设备是存在的,如果设置为NONBLOCK方式来读,立即返回.

       if (client->head == client->tail && evdev->exist &&

           (file->f_flags & O_NONBLOCK))

              return -EAGAIN;

// sleep until a condition gets true

       retval = wait_event_interruptible(evdev->wait,

              client->head != client->tail || !evdev->exist);

       if (retval)

              return retval;

 

       if (!evdev->exist)

              return -ENODEV;

//client-buffer中读取数据,并添加到链表中。

       while (retval + input_event_size() <= count &&

              evdev_fetch_next_event(client, &event)) {

              // copy_to_user

              if (input_event_to_user(buffer + retval, &event))

                     return -EFAULT;

 

              retval += input_event_size();

       }

 

       return retval;

}

 

input_event_to_user为止一个键盘输入处理将数据传递给用户空间,处理结束。

 

static ssize_t evdev_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)功能相对应的,还有static ssize_t evdev_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)功能,实现client-buffer的写操作。

 

总结一下,洋洋洒洒的把程序贴了这么多,无非是想把gpio的注册流程和event的处理流程一程序的形式梳理一遍,这两个工作流程其实都简单的体现了一个module的处理过程,本人水平有限,没能把更详尽的注释整理出来,也仅限于自己半懂得水平,刚开始接触这些东西,难免还有些错误,继续努力中。。。

原创粉丝点击