装载自http://blog.youkuaiyun.com/sjwangjinbao/article/details/6077225
编写总线设备驱动程序的时候,发现2.6.33.2内核中的struct device已经没有bus_id的成员了,发现了const char *init_name成员。但是,这个成员是不能直接用来设置和读取设备名的。
对内核操作的方法为dev_name和dev_set_name。内核中的定义是:
1) dev_name
static inline const char *dev_name(const struct device *dev)
{
return kobject_name(&dev->kobj);
}
2) dev_set_name
/**
* dev_set_name - set a device name
* @dev: device
* @fmt: format string for the device's name
*/
int dev_set_name(struct device *dev, const char *fmt, ...)
{
va_list vargs;
int err;
va_start(vargs, fmt);
err = kobject_set_name_vargs(&dev->kobj, fmt, vargs);
va_end(vargs);
return err;
}
EXPORT_SYMBOL_GPL(dev_set_name);
具体使用例子请看我接下来的关于总线设备驱动的例子的文章。
装载自:http://blog.youkuaiyun.com/sjwangjinbao/article/details/6077236
这里总结下简单的总线设备驱动的框架程序。
0、建立文件夹busdevdrv
1、总线
在文件夹内建立总线文件bus.c,代码如下。
#include <linux/device.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/string.h>
MODULE_AUTHOR("sjwangjinbao");
MODULE_LICENSE("Dual BSD/GPL");
static char *Version = "$Revision: 1.0 $";
static int my_match(struct device *dev, struct device_driver *driver)
{
return !strncmp(dev_name(dev), driver->name, strlen(driver->name) );
}
static void my_bus_release(struct device *dev)
{
printk("my bus release/n");
}
struct device my_bus = {
.release = my_bus_release
};
struct bus_type my_bus_type = {
.name = "my_bus",
.match = my_match,
};
EXPORT_SYMBOL(my_bus);
EXPORT_SYMBOL(my_bus_type);
/*
* Export a simple attribute.
*/
static ssize_t show_bus_version(struct bus_type *bus, char *buf)
{
return snprintf(buf, PAGE_SIZE, "%s/n", Version);
}
static BUS_ATTR(version, S_IRUGO, show_bus_version, NULL);
static int __init my_bus_init(void)
{
int ret;
/*注册总线*/
ret = bus_register(&my_bus_type);
if (ret)
{
return ret;
}
/*创建属性文件*/
if (bus_create_file(&my_bus_type, &bus_attr_version))
{
printk("Fail to create version attribute!/n");
}
/*初始化总线设备*/
dev_set_name(&my_bus, "my_bus0");
/*注册总线设备*/
ret = device_register(&my_bus);
if (ret)
{
printk("Fail to register device:my_bus!/n");
}
return ret;
}
static void my_bus_exit(void)
{
device_unregister(&my_bus);
bus_unregister(&my_bus_type);
}
module_init(my_bus_init);
module_exit(my_bus_exit);
2、设备
在文件夹下建立设备文件dev.c,代码如下。
#include <linux/device.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/string.h>
MODULE_AUTHOR("sjwangjinbao");
MODULE_LICENSE("Dual BSD/GPL");
extern struct device my_bus;
extern struct bus_type my_bus_type;
static void my_dev_release(struct device *dev)
{
}
struct device my_dev = {
.bus = &my_bus_type,
.parent = &my_bus,
.release = my_dev_release,
};
/*
* Export a simple attribute.
*/
static ssize_t mydev_show(struct device *dev,struct device_attribute *attr, char *buf)
{
return sprintf(buf, "%s/n", "This is sjwangjinbao device!");
}
static DEVICE_ATTR(dev, S_IRUGO, mydev_show, NULL);
static int __init my_device_init(void)
{
int ret = 0;
/*初始化设备*/
dev_set_name(&my_dev, "my_dev");
/*注册设备*/
device_register(&my_dev);
/*创建属性文件*/
device_create_file(&my_dev, &dev_attr_dev);
return ret;
}
static void my_device_exit(void)
{
device_unregister(&my_dev);
}
module_init(my_device_init);
module_exit(my_device_exit);
3、驱动
在文件夹下建立驱动文件drv.c,代码如下。
#include <linux/device.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/string.h>
MODULE_AUTHOR("sjwangjinbao");
MODULE_LICENSE("Dual BSD/GPL");
extern struct bus_type my_bus_type;
static int my_probe(struct device *dev)
{
printk("Driver found device which my driver can handle!/n");
return 0;
}
static int my_remove(struct device *dev)
{
printk("Driver found device unpluged!/n");
return 0;
}
struct device_driver my_driver = {
.name = "my_dev",
.probe = my_probe,
};
/*
* Export a simple attribute.
*/
static ssize_t mydriver_show(struct device_driver *driver, char *buf)
{
return sprintf(buf, "%s/n", "This is sjwangjinbao driver!");
}
static DRIVER_ATTR(drv, S_IRUGO, mydriver_show, NULL);
static int __init my_driver_init(void)
{
int ret = 0;
/*注册驱动*/
driver_register(&my_driver);
/*创建属性文件*/
driver_create_file(&my_driver, &driver_attr_drv);
return ret;
}
static void my_driver_exit(void)
{
driver_unregister(&my_driver);
}
module_init(my_driver_init);
module_exit(my_driver_exit);
4、Makefile
在文件夹下建立Makefile,如下。
ifneq ($(KERNELRELEASE),)
obj-m := bus.o dev.o drv.o
else
KDIR := /usr/src/linux-2.6.33.2
all:
make -C $(KDIR) M=$(PWD) modules
clean:
rm -f *.ko *.o *.mod.o *.mod.c *.symvers
endif
5、make
在文件夹下执行make命令,将得到bus.ko, dev.ko, drv.ko三个文件。
6、添加模块
使用root用户依次调用如下命令添加3个模块:
insmod bus.ko
insmod dev.ko
insmod.drv.ko
这时候,会在/sys/bus下面发现my_bus已经存在了。到/sys/bus/my_bus/devices/看看,发现我们的my_dev设备已 经存在了;到/sys/bus/my_bus/drivers/看看,发现我们的my_dev驱动也存在了。在到/sys/bus/my_bus /devices/my_dev/driver去瞧瞧,发现my_dev驱动已经存在了,这说明我们的 my_dev设备和my_dev驱动已经联系在一起了。同样,在/sys/bus/my_bus/drivers/my_dev下也会发现有个 my_dev的设备,这也说明我们的 my_dev设备和my_dev驱动已经联系在一起了。
另外,我们也可以查看他们的属性。
1) 在/sys/bus/my_bus下,我们发现有个version文件,用cat查看它,得到输出为:
$Revision: 1.9 $
这正是我们在程序中指定的。
2) 在/sys/bus/my_bus/devices/my_dev下,我们会发现有个 dev文件,用cat查看它,结果为:
This is my device!
这也正是我们程序中指定的。
3) 在/sys/bus/my_bus/drivers/my_dev下,我们也会发现drv文件,用cat查看结果为:
This is my driver!
当然,这也是我们在程序中指定的。