/***********************************************************************************
*
* mdev,bus,device,driver,platform
*
* 声明:
* 1. 本系列文档是在vim下编辑,请尽量是用vim来阅读,在其它编辑器下可能会
* 不对齐,从而影响阅读.
* 2. 由于本人水平有限,很难阐述清楚bus device driver platform的关系
* 所以强烈要求您详细参考本次提供的预热文章.
*
*
* 2015-3-21 晴 深圳 尚观 Opt 曾剑锋
**********************************************************************************/ \\\\\\\\\\\--*目录*--//////////
| 一. 预热文章:
| 二. mdev 原理及配置:
| 三. bus device driver接口:
| 四. platform bus接口
\\\\\\\\\\\\\\\//////////////// 一. 预热文章:
. linux设备驱动模型(上):
http://m.blog.csdn.net/blog/zhuzongwei1988/5785461
. [嵌入式Linux学习七步曲之第四篇 Linux内核移植]详解Linux2.6内核中
基于platform机制的驱动模型:
http://blog.csdn.net/sailor_8318/article/details/5267698
. [嵌入式Linux学习七步曲之第五篇 Linux内核移植]PowerPC+Linux2..25平台
下的I2C驱动架构分析:
http://blog.csdn.net/sailor_8318/article/details/5905988
. [嵌入式Linux学习七步曲之第五篇 Linux内核移植]PowerPC+Linux2..25平台
下的SPI驱动架构分析:
http://blog.csdn.net/sailor_8318/article/details/5977733 二. mdev 原理及配置:
. 在/etc/init.d/rcS中最后执行命令:
#采用设备模型进行创建设备节点的必须加上,热插拔处理
echo "/sbin/mdev" > /proc/sys/kernel/hotplug
mdev -s
. mdev扫描/sys/lock(块设备保存在/sys/block目录下,2.6.25版本以后,块设备也保存在
/sys/class/block目录下.mdev扫描/sys/block是为了实现向后兼容和/sys/class两个
目录下的dev属性文件,从该dev属性文件中获取设备编号(dev属性文件以"major:minor\n"
形式保存设备编号),并以包含该dev属性文件的目录名称作为设备名device_name(即包含
dev属性文件的目录为device_name,而/sys/class和/device_name之间的那部分目录称为
subsystem,也就是每个dev属性文件所在的路径都可表示/sys/class/subsystem/device_name/dev),
. 并在/dev目录下创建相应的设备文件.例如:
cat /sys/class/tty/tty0/dev会得到4:,subsystem为tty,device_name为tty0.
. 系统运行起来以后,每次创建新的节点的时候都会调用mdev,并根据/etc/mdev.conf文件
做相应的事,如果配置中没有对应的配置,那就按常规处理:
cat > /etc/mdev.conf << EOF
misc_dev : =test/my_device
event.* : =input/
mice : =input/
mouse0 : =input/
dsp : =sound/
sdb[-] : * /sbin/auto_mount
EOF
配置解析:
. 格式: <device regex> <uid>:<gid> <octal permissins> [<@|$|*> <command>]
. @在创建设备节点后运行命令;
. $在删除设备节点前运行命令;
. *创建设备节点后和创建设干杯节点前都会运行命令;
. =input: 表示将mice放在/dev/input目录下;
. =test/my_device: 表示将misc_dev改名字为my_device,并放在/dev/test目录下;
. 按照上面的操作,可以实现U盘的自动挂载. 三. bus device driver接口:
. 总线注册:
struct bus_type bus;
bus_register(&bus);
. 总线注销:
bus_unregister(&bus);
. 设备注册:
struct device dev;
device_register(&dev);
. 设备注销:
device_unregister(&dev);
. 驱动注册:
struct device_driver drv;
driver_register(&drv);
. 驱动注销:
driver_unregister(&drv);
. bus device接口实例Demo:
...
//总线通过match函数决定总线匹配规则,返回0代表匹配失败
int up_match(struct device *dev, struct device_driver *drv)
{
printk("try to match!\n"); /**
* 通过名字匹配设备和驱动,init_name中的值会赋给kobj.name
* 并且init_name中的值会变成NULL,所以如果要通过名字匹配
* 设备驱动,需要比较的是dev->kobj.name和drv->name的值.
* 如下方式是错误的:
* return !strcmp(dev->init_name, drv->name);
*/
return !strcmp(dev->kobj.name, drv->name);
} struct bus_type up_bus = {
.name = "niubi_bus",
.match = up_match,
};
EXPORT_SYMBOL(up_bus); void test_release(struct device *dev)
{
} struct device up_dev = {
.init_name = "bus_device",
.release = test_release,
};
EXPORT_SYMBOL(up_dev); int __init test_init(void)
{
int ret; ret = bus_register(&up_bus);
if(ret)
{
printk("bus_register FAILED!\n");
goto err0;
} ret = device_register(&up_dev);
if(ret)
{
printk("device_register FAILED!\n");
goto err1;
} return ret; err1:
bus_unregister(&up_bus);
err0:
return ret;
} void __exit test_exit(void)
{
bus_unregister(&up_bus);
}
... . device_driver接口实例Demo:
...
extern struct bus_type up_bus; //dev指向匹配的设备结构
static int up_probe(struct device *dev)
{
printk("Probe.\n"); return ;
} static int up_remove(struct device *dev)
{
printk("Remove.\n"); return ;
} struct device_driver drv = {
.owner = THIS_MODULE,
.name = "niubi_dev", //match的时候要用到
.bus = &up_bus,
.probe = up_probe,
.remove = up_remove,
}; int __init test_init(void)
{
int ret;
ret = driver_register(&drv);
if(ret)
printk("driver_register FAILED!\n"); return ret;
} void __exit test_exit(void)
{
driver_unregister(&drv);
}
... 四. platform bus接口
. 注册平台设备:
struct platform_device pdev;
platform_device_register(&dev);
. 注销平台设备:
platform_device_unregister(&dev);
. 注册平台驱动:
struct platform_driver pdrv;
platform_driver_register(&pdrv);
. 注销平台驱动:
platform_driver_unregister(&pdrv); . platform_device接口Demo: #include <linux/module.h>
#include <linux/platform_device.h> //定义自己的平台数据结构
struct my_platform_data {
int w;
int h;
char name[];
}; struct my_platform_data pdata = {
.w = ,
.h = ,
.name = "lcd_screen",
}; struct resource res[] = {
[] = {
.start = 0x10000000,
.end = 0x10000000 + SZ_128 - ,
.flags = IORESOURCE_MEM,
},
[] = {
.start = 0x20000000,
.end = 0x20000000 + SZ_128 - ,
.flags = IORESOURCE_MEM,
},
[] = {
.start = 0x30,
.end = 0x30,
.flags = IORESOURCE_IRQ,
},
}; void test_release(struct device *dev)
{
} //设备的resource保存在设备结构里
struct platform_device pdev = {
.name = "device_v3",
.id = -,
.dev = {
.release = test_release,
.platform_data = &pdata,
},
.num_resources = ARRAY_SIZE(res),
.resource = res,
}; int __init test_init(void)
{
int ret;
ret = platform_device_register(&pdev);
if(ret)
printk("platform_device_register FAILED!\n"); return ret;
} void __exit test_exit(void)
{
platform_device_unregister(&pdev);
} module_init(test_init);
module_exit(test_exit);
MODULE_LICENSE("GPL"); . platform_device接口Demo: #include <linux/module.h>
#include <linux/platform_device.h> //定义自己的平台数据结构
struct my_platform_data {
int w;
int h;
char name[];
}; static int up_probe(struct platform_device *pdev)
{
int i;
struct my_platform_data *pdata = pdev->dev.platform_data; for(i = ; i < pdev->num_resources; i++)
{
printk("start = %x, end = %x\n",
pdev->resource[i].start,
pdev->resource[i].end);
}
printk("==========================\n");
printk("platform data.\n");
printk("width = %d, height = %d\n%s\n",
pdata->w, pdata->h, pdata->name); return ;
} static int up_remove(struct platform_device *pdev)
{
printk("In %s func.\n", __func__); return ;
} //最后一个元素清0
struct platform_device_id up_ids[] = {
{"device_v1", },
{"device_v2", },
{"device_v3", },
{"device_v4", },
{"device_v5", },
{},
}; //使用id_table和设备匹配
struct platform_driver pdrv = {
.probe = up_probe,
.remove = up_remove,
.driver = {
.name = "xxxxxxx",
.owner = THIS_MODULE,
},
.id_table = up_ids,
}; int __init test_init(void)
{
int ret;
ret = platform_driver_register(&pdrv);
if(ret)
printk("platform_driver_register FAILED!\n"); return ret;
} void __exit test_exit(void)
{
platform_driver_unregister(&pdrv);
} module_init(test_init);
module_exit(test_exit);
MODULE_LICENSE("GPL");

Samsung_tiny4412(驱动笔记10)----mdev,bus,device,driver,platform的更多相关文章

  1. linux下bus,device,driver三者关系

    linux下bus,device,driver三者关系 1.bus: 总线作为主机和外设的连接通道,有些总线是比较规范的,形成了很多协议.如 PCI,USB,1394,IIC等.任何设备都可以选择合适 ...

  2. Samsung_tiny4412(驱动笔记01)----linux 3.5,U-Boot,Busybox,SD卡启动环境搭建

    /*********************************************************************************** * * linux 3.5,U ...

  3. Samsung_tiny4412(驱动笔记04)----volatile,container_of,file_operations,file,inode

    /*********************************************************************************** * * volatile,co ...

  4. Samsung_tiny4412(驱动笔记03)----字符设备驱动基本操作及调用流程

    /*********************************************************************************** * * 字符设备驱动基本操作及 ...

  5. Samsung_tiny4412(驱动笔记09)----alloc_pages,kmalloc,vmalloc,kmem_cache,class

    /*********************************************************************************** * * alloc_pages ...

  6. Samsung_tiny4412(驱动笔记07)----spinlock,semaphore,atomic,mutex,completion,interrupt

    /*********************************************************************************** * * spinlock,se ...

  7. Samsung_tiny4412(驱动笔记06)----list_head,proc file system,GPIO,ioremap

    /**************************************************************************** * * list_head,proc fil ...

  8. Samsung_tiny4412(驱动笔记05)----Makefile,open,read,write,lseek,poll,ioctl,fasync

    /*********************************************************************************** * * Makefile,op ...

  9. 【驱动笔记10】再谈IRP

    文章作者:grayfox作者主页:http://nokyo.blogbus.com原始出处:http://www.blogbus.com/nokyo-logs/34010655.html 这一节会对I ...

随机推荐

  1. shell 判断字符串是否为空

    #!/bin/bash a="" if [ -n "$a" ] then echo "-n $a : 字符串长度不为 0" else ech ...

  2. python 二叉排序树

    class BSTNode: def __init__(self, data, left=None, right=None): self.data = data self.left = left se ...

  3. .NET身份证验证

    身份证号码编码规则及校验位校验算法 算法地址:http://jingyan.baidu.com/article/7f41ececff944a593d095c8c.html 简单验证长度 /// < ...

  4. 页面资源缓存 html css js

    html <meta http-equiv="Expires" content="0"><meta http-equiv="Prag ...

  5. Python -- xlrd,xlwt,xlutils 读写同一个Excel

    最近开始学习python,想做做简单的自动化测试,需要读写excel,然后就找到了xlrd来读取Excel文件,使用xlwt来生成Excel文件(可以控制Excel中单元格的格式),需要注意的是,用x ...

  6. HTML表单组件

    HTML表单组件 一.说明 form标签里面的东西 二.效果图 三.代码 <!DOCTYPE html> <html> <head> <title>Fo ...

  7. Phalcon框架数据库读写分离的实现方法

    Phalcon框架和Yaf类似,是一款用C实现的拓展级别的框架,不过其功能实现更加丰富,设计思路基于依赖注入.容器等方式,更符合现代框架思想.本文主要针对Phalcon框架数据库层的读写分离进行说明, ...

  8. C#正则过滤HTML标签并保留指定标签的方法

    本文实例讲述了C#正则过滤html标签并保留指定标签的方法.分享给大家供大家参考,具体如下: 这边主要看到一个过滤的功能: public static string FilterHtmlTag(str ...

  9. (GoRails )使用Vue.js制作拖拉list功能(v1-4) gem 'acts_as_list'(自动排列顺序)

    系列视频: use Vue.js to build the drag and drop support for the list themselves the cards that are under ...

  10. Confluence 6 从外部目录中同步数据如何工作

    下面是有关缓存功能的一些摘要信息: 用户和用户组的缓存信息保存在应用程序的数据库中. 当你连接一个新的外部目录到系统中的时候,一个同步任务将会启动被,并且在后台运行拷贝所有需要的用户和用户组信息,以及 ...