2013年10月10日
1.
udev不会将/sys/bus下面的设备放到/dev下面;
udev会将/sys/class下面的设备放到/dev下面,给应用层提供接口。
2.***
当设备移出的时候,调用release函数;当驱动作用于设备的时候,调用probe函数;
当驱动不在作用设备的时候,调用remove函数。
insmod bus/bus.ko
insmod device/device.ko
insmod driver/driver.ko==>调用probe
rmmod driver ===> 调用remove
rmmod device ===>调用remove 再调用/device/release
*************************************************************
第一个例子:
Bus.c/bus.h/device.c/driver.c/Makefile
Bus.c:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
#include "bus.h"
//#include <linux/types.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("you");
int my_match(struct device *dev, struct device_driver *drv);
struct bus_type person;
EXPORT_SYMBOL(person);
int test_init()
{
person.name = "person";
person.match = my_match;
bus_register(&person);
return 0;
}
void test_exit()
{
bus_unregister(&person);
printk("exit module");
}
module_init(test_init);
module_exit(test_exit);
int my_match(struct device *dev, struct device_driver *drv){
//if(!strcmp(dev->init_name,drv->name)){
// printk("match ok\n");
// return 1;
//}
struct person_device *pdev = container_of(dev,struct person_device,dev);
struct person_device_driver *pdrv = container_of(drv,struct person_device_driver,dev_drv);
if((pdev->pid==pdrv->pid)&&(pdev->vid==pdrv->vid))
{
printk("match ok\n");
return 0;
}
return 1;
}
//device.c
int person_device_register(struct person_device *pdev)
{
pdev->dev.bus = &person;
return device_register(&pdev->dev);
}
EXPORT_SYMBOL(person_device_register);
void person_device_unregister(struct person_device *pdev)
{
device_unregister(&pdev->dev);
}
EXPORT_SYMBOL(person_device_unregister);
//driver.c
int person_driver_register(struct person_device_driver *pdri)
{
pdri->dev_drv.bus = &person;
return driver_register(&pdri->dev_drv);
}
EXPORT_SYMBOL(person_driver_register);
void person_driver_unregister(struct person_device_driver *pdri)
{
driver_unregister(&pdri->dev_drv);
}
EXPORT_SYMBOL(person_driver_unregister);
Bus.h:
struct person_device{
struct device dev;
unsigned int vid,pid;
};
int person_device_register(struct person_device *pdev);
void person_device_unregister(struct person_device *pdev);
struct person_device_driver{
struct device_driver dev_drv;
unsigned int vid,pid;
};
int person_driver_register(struct person_device_driver *pdri);
void person_driver_unregister(struct person_device_driver *pdri);
Device.c:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/device.h>
#include "../bus/bus.h"
MODULE_LICENSE("GPL");
MODULE_AUTHOR("you");
//struct person_device{
// struct device dev;
//};
//
void my_release(struct device *dev);
extern struct bus_type person;//欺骗编译器:在其它文件中声明,这个文件中来用
struct person_device chunge;
//int person_device_register(struct person_device *pdev);
//void person_device_unregister(struct person_device *pdev);
int test_init()
{
chunge.dev.init_name = "chunge";//名字命名为chunge与device_driver中的名字相同,在bus.c中我们来匹配设备与设备驱动
// chunge.dev.bus = &person;
chunge.dev.release = my_release;
chunge.vid = 0x1234;
chunge.pid = 0x5678;
person_device_register(&chunge);
return 0;
}
void test_exit()
{
person_device_unregister(&chunge);
printk("exit module\n");
}
module_init(test_init);
module_exit(test_exit);
//int person_device_register(struct person_device *pdev)
//{
// return device_register(&pdev->dev);
//}
//void person_device_unregister(struct person_device *pdev)
//{
// device_unregister(&pdev->dev);
//}
void my_release(struct device *dev)
{
printk("release\n");
}
Driver.c:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
#include "../bus/bus.h"
MODULE_LICENSE("GPL");
MODULE_AUTHOR("you");
//struct person_device_driver{
//
// struct device_driver dev_drv;
//};
int my_probe(struct device *dev);
int my_remove(struct device *dev);
struct person_device_driver chunge_drv;
//extern struct bus_type person;//因为我们要在这个文件中用person,但又没有定义;
//int person_driver_register(struct person_device_driver *pdri);
//void person_driver_unregister(struct person_device_driver *pdri);
int test_init()
{
chunge_drv.dev_drv.name ="chunge";
//chunge_drv.dev_drv.bus = &person;
chunge_drv.dev_drv.probe = my_probe;
chunge_drv.dev_drv.remove = my_remove;
chunge_drv.vid = 0x1234;
chunge_drv.pid = 0x5678;
person_driver_register(&chunge_drv);
return 0;
}
void test_exit()
{
person_driver_unregister(&chunge_drv);
printk("exit module\n");
}
module_init(test_init);
module_exit(test_exit);
//int person_driver_register(struct person_device_driver *pdri)
//{
// return driver_register(&pdri->dev_drv);
//}
//void person_driver_unregister(struct person_device_driver *pdri)
//{
// driver_unregister(&pdri->dev_drv);
//}
int my_probe(struct device *dev)
{
printk("probe\n");
return 0;
}
int my_remove(struct device *dev)
{
printk("remove\n");
return 0;
}
Makefile:
default:
make -C /home/linux-2.6.28_smdk6410 M=`pwd`
clean:
make -C /home/linux-2.6.28_smdk6410 M=`pwd` clean
rm -rf modules.order
obj-m +=driver.o
*************************************************************
第二个例子:
Bus.c/device.c/driver.c==>写到bus.c里面:
最开始,我们就先把对应的设备挂在一个总线上:
按一下按键,将设备添加到总线上面,再按一下按键就移除,按键。
注册了一个中断线,在其后又用到了内核机制中的工作队列。
注:工作队列:上半部在中断上下文,下半部在进程上下文;
Tasklet:上下半部都在中断上下文中。
Bus.h:
struct person_device{
struct device dev;
unsigned long vid,pid;
};
int person_device_register(struct person_device *pdev);
void person_device_unregister(struct person_device *pdev);
struct person_device_driver{
struct device_driver dev_drv;
unsigned long vid,pid;
};
int person_driver_register(struct person_device_driver *pdri);
void person_driver_unregister(struct person_device_driver *pdri);
Bus.c:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/irq.h>
#include "bus.h"
//#include <linux/types.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("you");
int my_match(struct device *dev, struct device_driver *drv);
int my_probe(struct device *dev);
int my_remove(struct device *dev);
void my_release(struct device *dev);
irqreturn_t do_irq(int irq,void *data);
void function(struct work_struct *w);
struct person_device_driver chunge_drv;
struct person_device chunge;
struct bus_type person;
struct work_struct w;
int test_init()
{
printk("init module\n");
person.name = "person";
person.match = my_match;
bus_register(&person);
chunge_drv.dev_drv.name ="chunge";
chunge_drv.dev_drv.probe = my_probe;
chunge_drv.dev_drv.remove = my_remove;
chunge_drv.vid = 0x1234;
chunge_drv.pid = 0x5678;
person_driver_register(&chunge_drv);//系统自动调用probe函数
set_irq_type(IRQ_EINT(0),IRQ_TYPE_EDGE_FALLING);
int ret = request_irq(IRQ_EINT(0),do_irq,IRQF_SHARED,"s2",0x222);
if(ret<0)
{
printk("request_irq\n");
return 1;
}
INIT_WORK(&w,function);
return 0;
}
void test_exit()
{
person_driver_unregister(&chunge_drv);//系统自动的调用remove函数
bus_unregister(&person);
printk("exit module");
}
module_init(test_init);
module_exit(test_exit);
int my_match(struct device *dev, struct device_driver *drv){
struct person_device *pdev = container_of(dev,struct person_device,dev);
struct person_device_driver *pdrv = container_of(drv,struct person_device_driver,dev_drv);
if((pdev->pid==pdrv->pid)&&(pdev->vid==pdrv->vid))
{
printk("match ok\n");
return 0;
}
return 1;
}
//device.c
int person_device_register(struct person_device *pdev)
{
pdev->dev.bus = &person;
return device_register(&pdev->dev);
}
void person_device_unregister(struct person_device *pdev)
{
device_unregister(&pdev->dev);
}
//driver.c
int person_driver_register(struct person_device_driver *pdri)
{
pdri->dev_drv.bus = &person;
return driver_register(&pdri->dev_drv);
}
void person_driver_unregister(struct person_device_driver *pdri)
{
driver_unregister(&pdri->dev_drv);
}
int my_probe(struct device *dev)
{
printk("probe\n");
return 0;
}
int my_remove(struct device *dev)
{
printk("remove\n");
return 0;
}
irqreturn_t do_irq(int irq,void *data)
{
printk("s2 down\n");
schedule_work(&w);
return IRQ_HANDLED;
}
void function(struct work_struct *w)
{
static int flag = 1;
if(flag)
{
memset(&chunge,0,sizeof(chunge));
chunge.dev.init_name = "chunge";//名字命名为chunge与device_driver中的名字相同,在bus.c中我们来匹配设备与设备驱动
chunge.dev.release = my_release;
chunge.vid = 0x1234;
chunge.pid = 0x5678;
person_device_register(&chunge);
}
else{
person_device_unregister(&chunge);//系统自动调用release函数
}
flag ^= 1;
}
void my_release(struct device *dev)
{
printk("release\n");
}