linux platform match
来源:互联网 发布:手机淘宝模版售后服务 编辑:程序博客网 时间:2024/06/02 02:58
当向linux系统总线添加设备或驱动时,总是会调用各总线对应的match匹配函数来判断驱动和设备是否匹配,这些match函数之间都存在一定的差异,本文先对常用的match匹配函数进行讲解,以后会陆续添加新的内容。
一. 驱动和设备匹配过程常用数据结构
1. of_device_id
struct of_device_id
{
charname[32];
char type[32];
char compatible[128];
#ifdef __KERNEL__
void*data;
#else
kernel_ulong_t data;
#endif
};
2. platform_device_id
struct platform_device_id {
char name[PLATFORM_NAME_SIZE];
kernel_ulong_t driver_data
__attribute__((aligned(sizeof(kernel_ulong_t))));
};
二. 平台设备、驱动匹配platform_match
static int platform_match(struct device *dev, struct device_driver *drv)
{
struct platform_device *pdev = to_platform_device(dev);
struct platform_driver *pdrv = to_platform_driver(drv);
if (pdrv->id_table)
return platform_match_id(pdrv->id_table, pdev) != NULL;
return (strcmp(pdev->name, drv->name) == 0);
}
static inline int of_driver_match_device(struct device *dev,
{
return of_match_device(drv->of_match_table, dev) != NULL;
}
struct of_device_id *of_match_device(const struct of_device_id *matches,
{
if ((!matches) || (!dev->of_node))
return NULL;
return of_match_node(matches, dev->of_node);
}
const struct of_device_id *of_match_node(const struct of_device_id *matches,
{
if (!matches)
return NULL;
while (matches->name[0] || matches->type[0] || matches->compatible[0]) {
int match = 1;if (matches->name[0])
match &= node->name&& !strcmp(matches->name, node->name);
if (matches->type[0])
match &= node->type&& !strcmp(matches->type, node->type);
if (matches->compatible[0])
match &= of_device_is_compatible(node,matches->compatible);
if (match)
return matches;
matches++;
}
return NULL;
}
static const struct platform_device_id *platform_match_id(
{
while (id->name[0]) {
if (strcmp(pdev->name, id->name) == 0) {
pdev->id_entry = id;return id;
}
id++;
}
return NULL;
}
三. i2c设备、驱动匹配i2c_device_match
static int i2c_device_match(struct device *dev, struct device_driver *drv)
{
struct i2c_client*client = i2c_verify_client(dev);
struct i2c_driver
* driver; if (!client)
return 0;
if (of_driver_match_device(dev, drv))
return 1;
driver = to_i2c_driver(drv);
if (driver->id_table)
return i2c_match_id(driver->id_table, client) != NULL;
return 0;
}
如i2c_device_match所示,i2c通过两种方式进行匹配设备和驱动,一种是of_device_id,另一种是 i2c_device_id,i2c_device_id数据结构和platform_device_id一样。I2C里的两种匹配方式和之前的 platform判断方式都是一样,这里就不展开。
四. usb设备、驱动匹配usb_device_match
当向usb总线上注册驱动或添加设备时,就会调用usb_match_device进行驱动和设备配对,函数如下:
static int usb_device_match(struct device *dev, struct device_driver *drv)
{
if (is_usb_device(dev)) {
if (!is_usb_device_driver(drv))
return 0;
return 1;
} else if (is_usb_interface(dev)) {
struct usb_interface *intf;
struct usb_driver *usb_drv;
const struct usb_device_id *id;
if (is_usb_device_driver(drv))
return 0;
intf = to_usb_interface(dev);
usb_drv = to_usb_driver(drv);
id = usb_match_id(intf, usb_drv->id_table);
if (id)
return 1;
id = usb_match_dynamic_id(intf, usb_drv);
if (id)
return 1;
}
return 0;
}
struct usbdrv_wrap {
struct device_driver driver;
int for_devices;
}
static inline int is_usb_device_driver(struct device_driver *drv)
{
return container_of(drv, struct usbdrv_wrap, driver)->for_devices;
}
const struct usb_device_id *usb_match_id(struct usb_interface *interface,
{
if (id == NULL)
return NULL;
for (; id->idVendor || id->idProduct || id->bDeviceClass ||
id->bInterfaceClass || id->driver_info; id++) {
if (usb_match_one_id(interface, id))
return id;
}
return NULL;
}
int usb_match_one_id(struct usb_interface *interface,const struct usb_device_id *id)
{
struct usb_host_interface *intf;
struct usb_device *dev;
if (id == NULL)
return 0;
intf = interface->cur_altsetting;
dev = interface_to_usbdev(interface);
if (!usb_match_device(dev, id))
return 0;
if (dev->descriptor.bDeviceClass == USB_CLASS_VENDOR_SPEC &&
!(id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
(id->match_flags & (USB_DEVICE_ID_MATCH_INT_CLASS |
USB_DEVICE_ID_MATCH_INT_SUBCLASS | USB_DEVICE_ID_MATCH_INT_PROTOCOL)))
return 0;
if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS) &&
(id->bInterfaceClass != intf->desc.bInterfaceClass))
return 0;
if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS) &&
(id->bInterfaceSubClass != intf->desc.bInterfaceSubClass))
return 0;
if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL) &&
(id->bInterfaceProtocol != intf->desc.bInterfaceProtocol))
return 0;
return 1;
}
usb_match_one_id和函数中的usb_match_device都是围绕着usb_device_id进行匹配的,该结构定义如下:
struct usb_device_id {
__u16 match_flags;
__u16 idVendor;
__u16 idProduct;
__u16 bcdDevice_lo;
__u16 bcdDevice_hi;
__u8 bDeviceClass;
__u8 bDeviceSubClass;
__u8 bDeviceProtocol;
__u8 bInterfaceClass;
__u8 bInterfaceSubClass;
__u8 bInterfaceProtocol;
kernel_ulong_tdriver_info;
};
from http://blog.sina.com.cn/s/blog_67e1c5cc0101nto7.html
- linux platform match
- linux platform match
- linux platform match
- linux platform 设备驱动之 match 自动匹配
- linux platform 设备驱动之 match 自动匹配
- platform match 和probe
- Platform Bus Match
- linux platform
- linux platform
- linux platform
- Linux platform
- linux platform
- WINCE5.0 解决 EVC中 The targeted platform does not match the connected platform 的问题
- 转:去掉烦人的The targeted platform does not match the connected platform. Continue?
- linux ------ platform device 与 platform driver
- linux的platform驱动
- Linux driver model ----- platform
- Linux driver model ----- platform
- Android画折线图和柱状图(附源代码)
- java与设计模式之状态模式
- RobHess的SIFT源码分析:kdtree.h和kdtree.c文件
- 你可能不知道的Shell
- FFMpeg对MPEG2 TS流解码的流程分析
- linux platform match
- Internet路由 --- 主机路由表和转发表
- MyEclipse+SDK+ADT安装
- 委托的学习
- UML中几种类间关系:继承、实现、依赖、关联、聚合、组合的联系与区别
- USACO 1.1 Your Ride Is Here
- J2SE小结
- VIJOS P1040 高精度乘法
- HDU3625-----第二类strling number的简单应用