Linux的uevent事件機制

 2023-12-25 阅读 25 评论 0

摘要:uevent事件機制 Linux設計了一種uevent的機制。當有新的設備加入的時候,將設備的信息發送消息到用戶態。而用戶態有一個udev的進程監聽這個信息。當收到信息后做一定的解析,根據解析到的結果和用戶程序的配置做一些處理,也包括加載驅動程序。 內核部分&#

uevent事件機制

Linux設計了一種uevent的機制。當有新的設備加入的時候,將設備的信息發送消息到用戶態。而用戶態有一個udev的進程監聽這個信息。當收到信息后做一定的解析,根據解析到的結果和用戶程序的配置做一些處理,也包括加載驅動程序。

內核部分,Uevent是Kobject的一部分,用于在Kobject狀態發生改變時,例如增加、移除等,通知用戶空間程序,主要涉及kobject.h和kobject_uevent.c兩個文件,如下:

include/linux/kobject.h
lib/kobject_uevent.c
  • 內核上報事件,調用kobject_uevent_env函數進行上報事件

  • int kobject_uevent_env(struct kobjectkobj, enum kobject_action action,charenvp_ext[])

    static const char *kobject_actions[] ={
    [KOBJ_ADD] = “add”,
    [KOBJ_REMOVE] = “remove”,
    [KOBJ_CHANGE] = “change”,
    [KOBJ_MOVE] = “move”,
    [KOBJ_ONLINE] = “online”,
    [KOBJ_OFFLINE] = “offline”,
    };

比如下面的一個HDMI插拔的uevent字符串

 {SUBSYSTEM=extcon, SEQNUM=2706, ACTION=change, DEVTYPE=hdmi_audio, STATE=HDMI=1, DEVPATH=/devices/virtual/amhdmitx/amhdmitx0/hdmi_audio, NAME=hdmitx_extcon_audio}

android層面去讀取uevent事件

frameworks/base/core/jni/android_os_UEventObserver.cpp
uevent_init()  //open socket for UEventObserver
uevent_next_event(buffer, sizeof(buffer) //讀取uevent事件for (;;) {int length = uevent_next_event(buffer, sizeof(buffer) - 1);if (length <= 0) {return NULL;}buffer[length] = '\0';ALOGV("Received uevent message: %s", buffer);if (isMatch(buffer, length)) {// Assume the message is ASCII.jchar message[length];for (int i = 0; i < length; i++) {message[i] = buffer[i];}return env->NewString(message, length);}
}frameworks/base/core/java/android/os/UEventObserver.java
創建一個UEventThread線程不停的讀取消息while (true) {String message = nativeWaitForNextEvent();if (message != null) {if (DEBUG) {Log.d(TAG, message);}sendEvent(message);}}

amlogic平臺調試的例子

  • 這里主要是添加了gpio按鍵的uevent事件上報給android,下面是一個上報的簡單例子,主要是傳輸字符串,這里可以任意指定

    char data[64];
    char *envp[] = { data, NULL };
    snprintf(data, sizeof(data), “code=%d,state=up”, key->code);
    kobject_uevent_env(&kp->config_dev->kobj, KOBJ_CHANGE, envp);

  • app里面的修改

      mObserver.startObserving("DEVPATH=/devices/virtual/gpio_keyboard/gpio_keyboard");mObserver.startObserving("DEVPATH=/devices/adc_keypad.13/input/input1");private UEventObserver mObserver = new UEventObserver() {@Overridepublic void onUEvent(UEventObserver.UEvent event) {Log.i("onUEvent","event:"+event +"  code = "+event.get("code"));}};
    
  • 注意點startObserving這個里面傳入的是設備的驅動路徑,必須填寫正確,onUEvent接收到的就是回調的時間信息

      09-11 00:08:59.942  7450  7474 I onUEvent: event:{DEVNAME=gpio_keyboard, SUBSYSTEM=gpio_keyboard, SEQNUM=4095, MAJOR=222, ACTION=change, DEVPATH=/devices/virtual/gpio_keyboard/gpio_keyboard, MINOR=0, code=473,state=down}  code = 473,state=down09-11 00:09:00.151  7450  7474 I onUEvent: event:{DEVNAME=gpio_keyboard, SUBSYSTEM=gpio_keyboard, SEQNUM=4096, MAJOR=222, ACTION=change, DEVPATH=/devices/virtual/gpio_keyboard/gpio_keyboard, MINOR=0, code=473,state=up}  code = 473,state=up09-11 00:08:55.147  7450  7474 I onUEvent: event:{PROP=0, SUBSYSTEM=input, PRODUCT=10/1/1/100, SEQNUM=4091, EV=100003, ACTION=change, DEVPATH=/devices/adc_keypad.13/input/input1, PHYS="adc_keypad/input0", KEY=3c000000 0 0 0 0 0 40000 0, NAME="adc_keypad", MODALIAS=input:b0010v0001p0001e0100-e0,1,14,k1DA,1DB,1DC,1DD,ramlsfw, code=477,state=down}  code = 477,state=down09-11 00:08:55.291  7450  7474 I onUEvent: event:{PROP=0, SUBSYSTEM=input, PRODUCT=10/1/1/100, SEQNUM=4092, EV=100003, ACTION=change, DEVPATH=/devices/adc_keypad.13/input/input1, PHYS="adc_keypad/input0", KEY=3c000000 0 0 0 0 0 40000 0, NAME="adc_keypad", MODALIAS=input:b0010v0001p0001e0100-e0,1,14,k1DA,1DB,1DC,1DD,ramlsfw, code=477,state=up}  code = 477,state=up
    

驅動舉例說明:

+++ b/drivers/gtinput/gtinput.c
@@ -344,11 +344,37 @@ static ssize_t gtinputdev_det_power_store(struct device *gtinput_class_dev,return size;}
+/* add by caizd for AC power detecte */
+static ssize_t gtinputdev_power_det_show(struct device *gtinput_class_dev,
+                               struct device_attribute *attr, char *buf)
+{
+       return sprintf(buf, "%s\n", "gtinput_power_det_show: sysfs test read");
+}
+
+static ssize_t gtinputdev_power_det_store(struct device *gtinput_class_dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t size)
+{
+       unsigned int usdata;
+       char kdata[64];
+       char *envp[] = {kdata, NULL};
+       int ret;
+
+       ret = sscanf(buf, "%d", &usdata);
+
+       snprintf(kdata, sizeof(kdata), "AC_power_det=%d", usdata);
+       kobject_uevent_env(&gtinput_class_dev->kobj, KOBJ_CHANGE, envp);
+//     printk("\n #####-czd-: AC_power_det=%d #####\n", usdata);
+
+       return size;
+}
+/* add end */static DEVICE_ATTR(gtinputdev_det_power, 0664, gtinputdev_det_power_show, gtinputdev_det_power_store);
+static DEVICE_ATTR(gtinputdev_power_det, 0664, gtinputdev_power_det_show, gtinputdev_power_det_store); /* add by caizd for AC power detecte */static const struct file_operations gtinput_fops = {.owner = THIS_MODULE,
@@ -403,6 +429,7 @@ static int gtinput_init(void)device_create_file(gtinput_class_dev, &dev_attr_gtinputdev_bat);device_create_file(gtinput_class_dev, &dev_attr_gtinputdev_bat_dc);device_create_file(gtinput_class_dev, &dev_attr_gtinputdev_det_power);
+       device_create_file(gtinput_class_dev, &dev_attr_gtinputdev_power_det); /* add by caizd for AC power detecte */

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/5/194847.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息