platform设备驱动

Linux2.6以后的设备中,需关心总线、设备和驱动这三个实体,总线将设备和驱动绑定。系统每注册一个设备的时候,都会寻找适配的驱动,相反一样,匹配由总线完成

虚拟总线设备

struct platform_device 
{
        const char * name; //设备名称
        int id;
        struct device dev;
        u32 num_resources; //设备使用各类资源的数量
        struct resource * resource; //设备使用的资源
        struct platform_device_id *id_entry;
};

 虚拟总线驱动

struct platform_driver 
{  
      int (*probe)(struct platform_device *);  
      int (*remove)(struct platform_device *);  
      void (*shutdown)(struct platform_device *);  
      int (*suspend)(struct platform_device *, pm_message_t state);  
      int (*suspend_late)(struct platform_device *, pm_message_t state);  
      int (*resume_early)(struct platform_device *);  
      int (*resume)(struct platform_device *);  
      struct pm_ext_ops *pm;  
      struct device_driver driver;  
};  

匹配通过系统为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);
     
     /*Attempt an OF style match first   */
     if(of_driver_match_device(dev,drv))
          return 1;

     /*Then try ACPI style match   */
     if(acpi_driver_match_device(dev,drv))
          return 1;

     /* match against the id table first */
     if (pdrv->id_table)
          return platform_match_id(pdrv->id_table, pdev) != NULL;

     /* fall-back to driver name match */
     return (strcmp(pdev->name, drv->name) == 0);
}

从上述可以看出,匹配有四种可能性,一是基于设备树风格的匹配,二是基于ACPI风格的匹配,三是匹配ID表(platform——device设备名是否出现在platform_driver的ID表),四是匹配platform_device设备名和驱动的名字

以下是完成的一个huaqin的platform驱动的实例,这个huaqin有一个属性节点,编译下载到手机后,adb root之后,

adb shell cat /sys/bus/platform/device/huaqin/hello ,或者 adb shell cat /sys/bus/platform/deriver/huaqin/hello屏幕上输出一个hello world 字符串

例1

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

struct att_dev                         //设备结构体
{
    struct platform_device *pdev;      //虚拟设备
    struct kobject *kobj;              //对象
};
 
static struct att_dev *dev = NULL;     //结构体指针
 
static ssize_t att_store(struct device *dev,
                         struct device_attribute *attr,
                         const char *buf, size_t count)
{
    printk("echo debug buf\n");
 
    return count;
}
 
static ssize_t att_show(struct device *dev,
                        struct device_attribute *attr,
                        char *buf)
{
         return snprintf(buf, PAGE_SIZE, "hello world\n");           //返回一个字符串,宏是页的字节的大小
}

static DEVICE_ATTR(hello,S_IRUGO | S_IWUSR ,att_show,att_store);     //定义一个宏 设置属性节点hello,参数1为节点名,参数2为权限



static  int huaqin_probe(struct platform_device *pdev)               //匹配platform总线成功后 在huaqin下创建一个hello节点
{
	int ret;
	ret = sysfs_create_file(&pdev->dev.kobj,&dev_attr_hello.attr); //这个节点位于/sys/bus/platform/device/huaqin/hello  
 	if(ret < 0)
    	{
        	return -ENOMEM;
    	}
   	return 0;

}

static int huaqin_remove(struct platform_device *pdev)
{

	return 0;
}


struct platform_driver hello_pdrv={
	.probe	= huaqin_probe,
	.remove	= huaqin_remove,
	.driver	= {
		.name	= "huaqin",
		.owner	= THIS_MODULE,
		},
	};



static int __init hello_init(void)
{
	int ret;
	printk(KERN_INFO "Hello World enter\n");
	
	
    	dev = kzalloc(sizeof(struct att_dev),GFP_KERNEL);
    	if(dev == NULL)
    	{
        	printk("%s get dev memory error\n",__func__);
        	return -ENOMEM;
    	}

    	dev->pdev = platform_device_register_simple("huaqin", -1, NULL, 0); //注册设备

	ret = platform_driver_register(&hello_pdrv);
	if (ret) {
		printk("fail to register hello driver @ %s()\n", __func__); //注册驱动
	}



	return 0;
}


static void __exit hello_exit(void)
{
        sysfs_remove_file(&dev->pdev->dev.kobj,&dev_attr_hello.attr);

    	kobject_del(dev->kobj);

    	platform_device_unregister(dev->pdev);

	platform_driver_unregister(&hello_pdrv);
	if(dev != NULL)
        	kfree(dev);

}


module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("A simple Hello World Module");


例2

#include
#include
#include 
#include
#include 
#include 



static ssize_t att_show(struct device_driver *ddd, char *buf)
{
    return snprintf(buf, PAGE_SIZE, "hello world\n");
}
static ssize_t att_store(struct device *dev,struct device_attribute *attr,const char *buf, size_t count)
{
    return count;
}
 
 
static DRIVER_ATTR(hello,S_IRUGO | S_IWUSR , att_show,att_store);//描述驱动属性值





static int hello_main_pdrv_probe(struct platform_device *pdev)
{
	printk("@%s: hello probe done!\n", __func__);
	return 0;
}

static int hello_main_pdrv_remove(struct platform_device *pdev)
{
	return 0;
}

struct platform_device hello_pdev = {
		.name	= "huaqin",
		.id	= -1,
	};


struct platform_driver hello_pdrv={
	.probe	= hello_main_pdrv_probe,
	.remove	= hello_main_pdrv_remove,
	.driver	= {
		.name	= "huaqin",
		.owner	= THIS_MODULE,
		},
	};
static int __init hello_init(void)
{
	int ret = 0;
	printk(KERN_INFO "Hello World enter\n");

	ret = platform_device_register(&hello_pdev);
	if (ret) {
		printk("fail to register srs device @ %s()\n", __func__);
	}

	ret = platform_driver_register(&hello_pdrv);
	if (ret) {
		printk("fail to register hello driver @ %s()\n", __func__);
	}
	
	if (driver_create_file(&hello_pdrv.driver, &driver_attr_hello))
           printk(KERN_NOTICE "Unable to create version attribute\n");

	return 0;
}


static void __exit hello_exit(void)
{
	printk(KERN_INFO "Hello World exit\n");
}


module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("A simple Hello World Module");

 

你可能感兴趣的:(驱动)