zoukankan      html  css  js  c++  java
  • Linux的notifier机制的应用

    在linux内核系统中,各个模块、子系统之间是相互独立的。Linux内核可以通过通知链机制来获取由其它模块或子系统产生的它感兴趣的某些事件。

    notifier_block结构体在include/linux/notifier.h中定义:

    struct notifier_block {
    	notifier_fn_t notifier_call;
    	struct notifier_block __rcu *next;
    	int priority;
    };
    

    priority用来定义优先级,高优先级的处理例程将被优先执行,数值越大,优先级越高。

    回到函数的原型定义:

    typedef    int (*notifier_fn_t)(struct notifier_block *nb,
                unsigned long action, void *data);
    

    TP属于输入子系统,可以通过获取framebuffer子系统来实现亮屏和灭屏时触发相应的事件。

    fb_register_client和fb_unregister_client函数定义在drivers/video/fb_notify.c:

    /**
     *	fb_register_client - register a client notifier
     *	@nb: notifier block to callback on events
     */
    int fb_register_client(struct notifier_block *nb)
    {
    	return blocking_notifier_chain_register(&fb_notifier_list, nb);
    }
     
    /**
     *    fb_unregister_client - unregister a client notifier
     *    @nb: notifier block to callback on events
     */
    int fb_unregister_client(struct notifier_block *nb)
    {
        return blocking_notifier_chain_unregister(&fb_notifier_list, nb);
    }
    
    

    当framebuffer子系统发生事件时,调用notifier_call_chain()来触发相应的处理函数。

    /**
     * fb_notifier_call_chain - notify clients of fb_events
     *
     */
    int fb_notifier_call_chain(unsigned long val, void *v)
    {
    	return blocking_notifier_call_chain(&fb_notifier_list, val, v);
    }
    

    下面是一个实例:

    struct msg21xx_ts_data {
    	struct input_dev *input;
    	struct hrtimer timer;
    	struct work_struct work;
    	int irq;
    	struct dentry *dir;
    	char *ts_info;
    	u8 addr;
    	int fw_major;
    	int fw_minor;
    #ifdef CONFIG_FB
    	struct notifier_block fb_notif;
    #endif
    	bool suspended;
    	struct i2c_client *client;
    	struct regulator *vdd;
    	struct regulator *vcc_i2c;
    	struct msg21xx_platform_data *pdata;
    	struct workqueue_struct *msg21xx_wq;
    	struct mutex msg21xx_mutex;
    };
    

    probe函数中与notifier相关部分实现:

    struct msg21xx_ts_data *data;
     
    data = kzalloc(sizeof(struct msg21xx_ts_data), GFP_KERNEL);
    if (!data) {
        dev_err(&client->dev, "%s: Alloc mem fail!", __func__);
        err = -ENOMEM;
        goto exit;
    }
     
    #ifdef CONFIG_FB
    data->fb_notif.notifier_call = fb_notifier_callback;
    err = fb_register_client(&data->fb_notif);
    if (err)
        dev_err(&client->dev, "Unable to register fb_notifier: %d
    ",
            err);
    #endif
    

    fb_notifier_callback实现:

    
    #ifdef CONFIG_FB
    static int fb_notifier_callback(struct notifier_block *self,
    			unsigned long event, void *data)
    {
    	struct fb_event *evdata = data;
    	int *blank;
    	struct msg21xx_ts_data *msg21xx_data =
    		container_of(self, struct msg21xx_ts_data, fb_notif);
     
    	if (evdata && evdata->data && event == FB_EVENT_BLANK &&
    			msg21xx_data && msg21xx_data->client) {
    		blank = evdata->data;
    		if (*blank == FB_BLANK_UNBLANK)
    			msg21xx_ts_resume(&msg21xx_data->client->dev);
    		else if (*blank == FB_BLANK_POWERDOWN)
    			msg21xx_ts_suspend(&msg21xx_data->client->dev);
    	}
     
    	return 0;
    }
    #endif
    

    msg21xx_ts_suspend和msg21xx_ts_resume实现如下,主要是操作TP的电源和RST脚,LCD灭屏时,为了降低系统的功耗,需要将TP的power关闭,同时将TP的复位脚拉低,让TP自身进入低功耗模式。

    #if defined(CONFIG_PM) || defined(CONFIG_PM_RUNTIME)
    static int msg21xx_ts_suspend(struct device *dev)
    {
    	struct msg21xx_ts_data *data = dev_get_drvdata(dev);
    	int err;
     
    	if (data->suspended) {
    		dev_info(dev, "Already in suspend state
    ");
    		return 0;
    	}
     
    	disable_irq(data->client->irq);
     
    	err = msg21xx_power_on(data, false);
    	if (err)
    		dev_err(dev, "power off failed");
     
    	gpio_set_value_cansleep(data->pdata->reset_gpio, 0);
     
    	data->suspended = true;
    	return 0;
    }
     
    static int msg21xx_ts_resume(struct device *dev)
    {
    	struct msg21xx_ts_data *data = dev_get_drvdata(dev);
    	int err;
     
    	if (!data->suspended) {
    		dev_dbg(dev, "Already in awake state
    ");
    		return 0;
    	}
     
    	err = msg21xx_power_on(data, true);
    	if (err) {
    		dev_err(dev, "power on failed");
    		return err;
    	}
     
    	enable_irq(data->client->irq);
    	gpio_set_value_cansleep(data->pdata->reset_gpio, 1);
    	data->suspended = false;
    	return 0;
    }
    #endif
    
  • 相关阅读:
    Python--安装 pip 和 scapy
    windows设置代理
    麦子的《我奋斗了18年才和你坐在一起喝咖啡》
    Tar命令
    test
    markdown语法
    js apply call
    windows文件大小和占用空间为何不一样
    prolog笔记
    html文字超出显示省略号
  • 原文地址:https://www.cnblogs.com/linhaostudy/p/9909267.html
Copyright © 2011-2022 走看看