首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

Timed GPIO驱动程序分析(2)

Timed GPIO驱动程序分析(2)

Timed GPIO驱动程序是android系统基于linux内核新增加的一类驱动程序,这类驱动程序主要是运用了内核定时器,与内核定时器进行绑定,使得控制GPIO口的高低电平与时间打上关系,既可以实现在一定的时间实现GPIO口为高或者低电平。Timed GPIO驱动被实现为平台设备驱动,Timed GPIO驱动源码位于如下目录:\kernel\drivers\staging\android


Timed GPIO驱动程序主要包括如下几个文件:

Timed_gpio.c

Timed_gpio.h

Timed_output.c

Timed_output.h


Timed_gpio.c文件为具体的驱动程序,Timed_output.c为向sys文件系统注册类的框架代码,

下面将具体分析每一个文件的作用及实现的具体功能。

首先分析注册类的框架代码 :Timed_output.c   Timed_output.h


Timed_output.h文件分析:

struct timed_output_dev {

        const char        *name;

                void         (*enable)(struct timed_output_dev *sdev, int timeout);

                int         (*get_time)(struct timed_output_dev *sdev);

                struct device        *dev;

            int                index;

            int                state;

};


extern int timed_output_dev_register(struct timed_output_dev *dev);

extern void timed_output_dev_unregister(struct timed_output_dev *dev);

Timed_output.h文件主要定义了一个结构体timed_output_dev设备结构体,该结构体表示一个具体的设备,

Name:代表Time GPIO设备的名字,enable:为一个函数指针,主要用于设置定时器的过期时间,

Enable:用于获取离过期还剩余的时间。Index:为设备索引号,代表同一名字的设备的数量,state带表当前设备的状态值。

timed_output_dev_register,timed_output_dev_unregister这两个函数声明用于timed_output设备的注册和卸载。


Timed_output.c文件分析:

该文件主要用于向系统注册timed_output驱动程序框架,其中主要实现了Timed_output.h文件中定义的结构体及函数。


timed_output框架注册函数的实现,这个函数用于将驱动程序注册到kernel中,后面分析Timed GPIO驱动的具体实现时会调用此函数向系统注册Timed GPIO驱动。

int timed_output_dev_register(struct timed_output_dev *tdev)

{

        int ret;

        if (!tdev || !tdev->name || !tdev->enable || !tdev->get_time)

                return -EINVAL;

        ret = create_timed_output_class(); 调用此函数在sys/class下生成timed_output类

        if (ret < 0)

                return ret;

        tdev->index = atomic_inc_return(&device_count);

        tdev->dev = device_create(timed_output_class, NULL,

                MKDEV(0, tdev->index), NULL, tdev->name);

        if (IS_ERR(tdev->dev))

                return PTR_ERR(tdev->dev);

        ret = device_create_file(tdev->dev, &dev_attr_enable);

        if (ret < 0)

                goto err_create_file;

        dev_set_drvdata(tdev->dev, tdev);

        tdev->state = 0;

        return 0;

err_create_file:

        device_destroy(timed_output_class, MKDEV(0, tdev->index));

        printk(KERN_ERR "timed_output: Failed to register driver %s\n",

                        tdev->name);

        return ret;

}


此函数用于在sys/class下面创建类,类的名字为timed_output

static int create_timed_output_class(void)

{

        if (!timed_output_class) {

                timed_output_class = class_create(THIS_MODULE, "timed_output");

                if (IS_ERR(timed_output_class))

                        return PTR_ERR(timed_output_class);

                atomic_set(&device_count, 0);

        }

        return 0;

}



其中下面两个函数最为关键,是内核空间和用户空间的传值过程的具体实现函数,

enable_show函数调用get_time函数并将返回的剩余时间写入buf并传递到用户空间。


static ssize_t enable_show(struct device *dev, struct device_attribute *attr,

                char *buf)

{

        struct timed_output_dev *tdev = dev_get_drvdata(dev);

        int remaining = tdev->get_time(tdev);

        return sprintf(buf, "%d\n", remaining);

}


enable_store函数用于将用户空间传递来的buf值写入内核空间。

static ssize_t enable_store(

                struct device *dev, struct device_attribute *attr,

                const char *buf, size_t size)

{

        struct timed_output_dev *tdev = dev_get_drvdata(dev);

        int value;

        if (sscanf(buf, "%d", &value) != 1)

                return -EINVAL;

        tdev->enable(tdev, value);

        return size;

}


Timed_gpio.h文件分析:

#ifndef _LINUX_TIMED_GPIO_H

#define _LINUX_TIMED_GPIO_H

#define TIMED_GPIO_NAME "timed-gpio" //Time_GPIO驱动的名字,将显示在/sys/class/ timed_output目录下

struct timed_gpio {

        const char *name; //GPIO的名字

        unsigned         gpio; //具体的GPIO管脚

        int                max_timeout;//最大的超时时间

        u8                 active_low; //IO口电平状态表示位

};

timed_gpio结构体仅用于定义单个的GPIO的相关信息

gpio_platform_data结构体用于定义一组GPIO的相关信息

struct timed_gpio_platform_data {

        int                 num_gpios;

        struct timed_gpio *gpios;

};

#endif


下面将分析具体的Timed_gpio驱动程序

timed_gpio_driver定义如下:

该函数指明了具体的初始化函数(pore)和移除函数(remove)以及驱动的名字额模块。

static struct platform_driver timed_gpio_driver = {

        .probe                = timed_gpio_probe,

        .remove                = timed_gpio_remove,

        .driver                = {

                .name                = TIMED_GPIO_NAME,

                .owner                = THIS_MODULE,

        },

};


调用platform_driver_register函数向kernel注册平台驱动

static int __init timed_gpio_init(void)

{

        return platform_driver_register(&timed_gpio_driver);

}

继承事业,薪火相传
返回列表