/sys/bus一个总线设备驱动

来源:互联网 发布:eclipse.ini 配置优化 编辑:程序博客网 时间:2024/04/30 03:32

20131010

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";//名字命名为chungedevice_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";//名字命名为chungedevice_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");

}