linux 内核4.9.11如何使用热拔插

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux 内核4.9.11如何使用热拔插相关的知识,希望对你有一定的参考价值。

参考技术A

在Linux系统中,当系统配置发生变化时,如:添加kset到系统;移动kobject, 一个通知会从内核空间发送到用户空间,这就是热插拔事件。热插拔事件会导致用户空间中相应的处理程序(如udev,mdev)被调用, 这些处理程序会通过加载驱动程序, 创建设备节点等来响应热插拔事件。

操作集合

Struct kset_uevent_ops 

int (*filter)(struct kset *kset, struct kobject *kobj);

const char *(*name)(struct kset *kset, struct kobject *kobj);

int (*uevent)(struct kset *kset, struct kobject *kobj,

struct kobj_uevent_env *env);

当该kset所管理的kobject和kset状态发生变化时(如被加入,移动),这三个函数将被调用。

Filter:决定是否将事件传递到用户空间。如果filter返回0,将不传递事件。

Name:负责将相应的字符串传递给用户空间的热插拔处理程序。

Uevent:将用户空间需要的参数添加到环境变量中。

int (*uevent)(struct kset *kset,

struct kobject *kobj, /*产生事件的目标对象*/

char **envp, /*一个保存其他环境变量定义(通常为NAME=value的格式)的数组*/

int num_envp, /*环境变量数组中包含的变量数(数组大小)*/

char *buffer, int buffer_size/*环境变量被放入的缓冲区的指针和字节数*/

);/*返回值正常时是,若返回非零值将终止热插拔事件的产生*/


实例源码: temp.rar    

请点击输入图片描述


点击(此处)折叠或打开

    /**

    * 热插拔事件

    * Lzy    2012-7-27

    */

    #include <linux/device.h>

    #include <linux/module.h>

    #include <linux/kernel.h>

    #include <linux/init.h>

    #include <linux/string.h>

    #include <linux/sysfs.h>

    #include <linux/stat.h>

    #include <linux/kobject.h>

    static struct attribute test_attr =


    .name = "kobj_config",

    .mode = S_IRWXUGO,

    ;

    static struct attribute *def_attrs[] =


    &test_attr,

    NULL,

    ;

    ssize_t kobj_test_show(struct kobject *kobject,struct attribute *attr,char *buf)


    printk("Have show -->\\n");

    printk("attrname: %s.\\n",attr->name);

    sprintf(buf,"%s\\n",attr->name);

    return strlen(attr->name) + 2;


    ssize_t kobj_test_store(struct kobject *kobject,struct attribute *attr, const char *buf,size_t size)


    printk("Have store -->\\n");

    printk("write: %s.\\n",buf);

    return size;


    static struct sysfs_ops obj_test_sysops =


    .show = kobj_test_show,

    .store = kobj_test_store,        

    ;

    void obj_test_release(struct kobject *kobject)


    printk("[kobj_test: release!]\\n");


    static struct kobj_type ktype =


    .release = obj_test_release,

    .sysfs_ops = &obj_test_sysops,

    .default_attrs = def_attrs,

    ;

    static int kset_filter(struct kset *kset,struct kobject *kobj)


    //    int ret=0;

    //    struct kobj_type *ktype = get_ktype(kobj); /* 得到属性类型 */

    //    ret = (ktype == &ktype_part);

    printk("Filter: kobj %s.\\n",kobj->name);

    return 1;


    static const char *kset_name(struct kset *kset,struct kobject *kobj)

        

    static char buf[20];

    /*    struct device *dev = to_dev(kobj);

    if(dev->bus)

    return dev->bus->name;

    else if(dev->class)

    return dev->class->name;

    else

    */    

    printk("Name kobj %s.\\n",kobj->name);

    sprintf(buf,"%s","kset_name");


    return buf;


    static int kset_uevent(struct kset *kset,struct kobject *kobj, struct kobj_uevent_env *env)


    int i = 0;

    printk("uevent: kobj %s.\\n",kobj->name);

    while(i < env->envp_idx)


    printk("%s.\\n",env->envp[i]);

    i ++;


    return 0;


    static struct kset_uevent_ops uevent_ops =


    .filter = kset_filter,

    .name = kset_name,

    .uevent = kset_uevent,

    ;

    struct kset *kset_p;

    struct kset kset_c;

    static int __init kset_test_init(void)


    int ret = 0;

    printk("kset test init!\\n");

    /* 创建并注册 kset_p */

    kset_p = kset_create_and_add("kset_p", &uevent_ops, NULL);    

    kobject_set_name(&kset_c.kobj,"kset_c");

    kset_c.kobj.kset = kset_p;    /* 添加 kset_c 到 kset_p */

    /* 对于较新版本的内核,在注册 kset 之前,需要 

    * 填充 kset.kobj 的 ktype 成员,否则注册不会成功 */

    kset_c.kobj.ktype = &ktype;

    ret = kset_register(&kset_c);

    if(ret)

    kset_unregister(kset_p);

    return ret;


    static void __exit kset_test_exit(void)


    printk("kset test exit!\\n");

    kset_unregister(&kset_c);

    kset_unregister(kset_p);


    module_init(kset_test_init);

    module_exit(kset_test_exit);

    MODULE_AUTHOR("Lzy");

    MODULE_LICENSE("GPL");

HDMI接口之HPD(热拔插)

    HDMI (Pin 19)/DVI(Pin16)的功能是热插拔检测(HPD),这个信号将作为HDMI 源端(Source)是否发起EDID读,是否开始发送TMDS信号的依据。HPD是从HDMI显示器端(Sink)生成并输出送往HDMI 源端(Source)的一个检测信号。热插拔检测的作用是当显示器等HDMI接口的显示设备通过HDMI/DVI接口与HDMI 源端(Source)相连或断开连接时,HDMI源端(Source)能够通过HDMI/DVI的HPD引脚检测出这一事件,并做出响应。下面以HDMI为例讲述HPD的原理和实现方式。

    1.显示器通过HDMI连接HDMI源端设备,当HDMI 源端(Source)通过HDMI接口的HPD引脚检测到显示器与HDMI源端(Source)相连时(HPD从低电平到高电平),HDMI 源端(Source)认为已经有显示设备连接,并通过HDMI接口中的显示器数据通道DDC(DDC I2C总线)读取显示器EDID存储器中存储的EDID数据(扩展显示器识别数据),如果检测到显示器的工作模式范围与HDMI 源端(Source)的输出设置相适应,则HDMI 源端(Source)就激活TMDS信号发送电路发送正常的HDMI信号给显示设备。所以Sink端的EDID是在HPD从低电平到高电平的转换时被HDMI Source端读取的。如果需要强制刷新EDID, 可以发起一个HPD信号(拉低HPD,再拉高HPD),让HDMI source来读取新的EDID内容。

       2.显示器断开HDMI连接时,当HDMI 源端(Source)通过HPD引脚检测到显示器的HDMI接口与HDMI 源端(Source)断开时,HDMI 源端(Source)就断开TMDS信号发送电路,停止发送HDMI信号。

       3.HDMI 源端(Source)对HPD信号的要求,当HDMI 源端(Source)检测到HDMI/DVI接口上的HPD引脚电压大于2V时,判断为HDMI显示设备(Sink)通过HDMI/DVI接口与HDMI源端(Source)连接:当检测到HPD引脚电压小于0.8V时,则判断为HDMI显示设备(Sink)通过HDMI/DVI接口与HDMI 源端(Source)之间的连接已经断开。  
技术图片

   4.HPD信号的实现一般是在HDMI的Sink端,通过一个1K欧姆的电阻上拉到HDMI +5V,同时,本地的主处理器可以通过一个GPIO来控制它,如下图所示。

技术图片

当HDMI 源端(Source)通过HDMI接口与HDMI Sink端连接时,HDMI源端(Source)通过HDMI的第18脚(PWR_CON,PIN18,也就是 HDMI_5V)将+5V电压加到HDMISink端的DDC存储器(EDID数据存储器)向DDC存储器供电,确保即使HDMI Sink端不开机,HDMI 源端(Source)也能通过HDMI接口读取EDID数据。 HDMI 源端(Source)开机后产生 +5V并通过第18脚向HDMISink端(HDMI显示器)供电,此时HDMISink端(HDMI显示器)接收到5V电压后通过内部电路使HDMI接口第19脚HPD转变为高电平(1K欧姆电阻上拉)。此时HDMI源端(Source)通过第19 Pin接收到HPD高电平,判断HDMI Sink端(HDMI显示器)通过HDMI接口与HDMI 源端连接,于是通过HDMI接口的第15、16脚DDC通道(I2C)读取显示器中的EDID数据,并使HDMI 源端的TMDS信号发送电路开始工作。当HDMI显示器与HDMI 源端之间的HDMI连接断开时,HDMI 源端一侧的HDP信号为低电平,那么HDMI源端的TMDS信号发送电路停止工作。

由于在判断HDMI Sink端的HPD电路预留了一个控制端,如果HDMI Sink端的主处理器需要复位HDMI链接(包括重新HDCP握手认证),就可以拉低并再次拉高HPD来实现这个功能。

如前面介绍EDID时所述,HDMI规范规定,发送设备要检测接收设备的第一个CEAEDID 扩展块中是否包含HDMI VSDB,这个HDMIVSDB中是否包含IEEE 数据标识符0x000C03, 只有包含这个数据标识符的设备,才会被认为是HDMI设备,否则,被当作DVI设备处理。

一个HDMI设备的EDID 通常包含两个模块,第一个是EDID1.3的数据模块,第二个是CEA 861B模块,这个861B模块中,一定要包含数据标示符 0x000C03。HDMI发送设备(Source)检测到HPD 信号由低变高时,就会去读取Sink端的EDID 数据,来确认接收装置是否出现变化,并确定是工作在HDMI模式还是DVI模式。 

 


转载自https://blog.csdn.net/jiayu5100687/article/details/81604739





以上是关于linux 内核4.9.11如何使用热拔插的主要内容,如果未能解决你的问题,请参考以下文章

linux 上热拔插事件的检测

HDMI接口之HPD(热拔插)

linux设备模型

GB28181PJSIP库回声消除热拔插声音去抖

Linux盘符绑定槽位

Linux设备模型_Uevent