我们先来看看platform_bus的定义:
struct device platform_bus =
{ .bus_id
=
"platform", };
struct bus_type platform_bus_type =
{ .name
=
"platform", .dev_attrs
=
platform_dev_attrs, .match
=
platform_match, .uevent
=
platform_uevent, .suspend
=
platform_suspend, .suspend_late
=
platform_suspend_late, .resume_early
=
platform_resume_early, .resume
=
platform_resume, };
int __init
platform_bus_init(void) { int
error;
error =
device_register(&platform_bus); if
(error) return
error; error =
bus_register(&platform_bus_type); if
(error) device_unregister(&platform_bus); return
error; } |
platform_bus数据结构描述了platform
bus设备,platform_bus_type描述了platform
bus总线,它提供了platform总线设备和驱动的匹配函数。platform总线是由函数platform_bus_init(void)初始化的。
对于Linux我们一般的设备驱动程序来说,就像前面Bus一段提到的那样,我们不需要关心platform总线本身,我们只要调用我们的设备和驱动接口就可以了。
如果你想让platform总线来管理设备,那么,你需要先向platform系统注册设备,这个过程是通过下面的函数接口来实现的:
int platform_device_add(struct platform_device *pdev); int
platform_device_register(struct platform_device
*pdev); |
我们一般需要调用platform_device_register函数来向系统添加platform设备。这两个函数唯一的差别就是platform_device_register在添加设备前会初始化platform_device的dev数据成员,它是一个struct
device类型数据。当一个platform_device添加到platform总线中后,platform总线就会为它找到匹配的设备驱动程序,很显然,在这之前,你需要向系统注册platform_driver。
我们先来看看platform总线设备驱动的结构:
struct platform_driver { int
(*probe)(struct platform_device *); int
(*remove)(struct platform_device *); void
(*shutdown)(struct platform_device *); int
(*suspend)(struct platform_device *, pm_message_t
state); int (*suspend_late)(struct
platform_device *, pm_message_t state); int
(*resume_early)(struct platform_device
*); int (*resume)(struct platform_device
*); struct device_driver
driver; };
extern int platform_driver_register(struct platform_driver
*); |
很显然,它“继承”自struct device_driver,同样类似于struct
device_driver,一般我们需要实现probe函数,及指定platform_driver能驱动的设备的名字。
下面这个例子告诉你如何使用platoform总线,这是一个Android Goldfish
GPIO驱动程序。它本身就是一个platform设备驱动(goldfish-gpio),同时,它又会向系统注新的设备(android-timed-gpio),这个新设备又被timed_output.c驱动程序驱动。
...... #include
struct platform_device
timed_gpio_device = { .name =
"android-timed-gpio", .id
=
-1, .dev.platform_data =
&timed_gpio_platform_data, };
static int
goldfish_gpio_probe(struct platform_device
*pdev) { struct goldfish_gpio_data
*gpio_data; ...... error =
platform_device_register(&timed_gpio_device); ...... return
0; }
static int goldfish_gpio_remove(struct platform_device
*pdev) { int
i; struct goldfish_gpio_data
*gpio_data; ...... platform_device_unregister(&timed_gpio_device); ...... return
0; }
static struct platform_driver goldfish_gpio_driver =
{ .probe =
goldfish_gpio_probe, .remove
=
goldfish_gpio_remove, .driver =
{ .name
= "goldfish-gpio" } };
static int
__init goldfish_gpio_init(void) { return
platform_driver_register(&goldfish_gpio_driver); }
static
void __exit
goldfish_gpio_exit(void) { platform_driver_unregister(&goldfish_gpio_driver); } |
这个新注册的设备(timed_gpio_device)由timed_output驱动管理,通过浏览这段代码,你应该对如何使用platform总线有个全面的了解。(本想把全部code放在这里,但超过最大字数限制!)
static struct class *timed_gpio_class; struct timed_gpio_data
{ struct device
*dev; struct hrtimer
timer; spinlock_t
lock; unsigned
gpio; int
max_timeout; u8
active_low; }; ......
static int android_timed_gpio_probe(struct
platform_device *pdev) { struct
timed_gpio_platform_data *pdata =
pdev->dev.platform_data; struct
timed_gpio *cur_gpio; struct timed_gpio_data
*gpio_data, *gpio_dat; int i, ret =
0; ...... }
static int
android_timed_gpio_remove(struct platform_device *pdev) { }
static
struct platform_driver android_timed_gpio_driver =
{ .probe
=
android_timed_gpio_probe, .remove
=
android_timed_gpio_remove, .driver
=
{ .name
=
"android-timed-gpio", .owner
=
THIS_MODULE, }, };
static int
__init
android_timed_gpio_init(void) { timed_gpio_class
= class_create(THIS_MODULE,
"timed_output"); if
(IS_ERR(timed_gpio_class)) return
PTR_ERR(timed_gpio_class); return platform_driver_register(&android_timed_gpio_driver); }
static
void __exit
android_timed_gpio_exit(void) { class_destroy(timed_gpio_class); platform_driver_unregister(&android_timed_gpio_driver); } |
Kobject和kset提到Linux的设备模型,就不得不提kobject和kset这两个内核对象,他们才是Linux内核设备模型的最基础的结构,但讲解他们却是一个枯燥过程,限于篇幅,这个就不作介绍了,请参考Linux文档
。
后记
在这里,我们简单的介绍了Linux的设备模型,包括基本总线、设备、驱动的关系,同时也简单的介绍了Linux2.6内核的platform总线。这些内容应该足够让你了解如何使用Linux设备模型来管理设备了。
阅读(1393) | 评论(0) | 转发(0) |