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);
}
欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) | Powered by Discuz! 7.0.0 |