linux裝置驅動uevent詳解,高通平臺battery上報電量例項
1,uevent是什麼呢?
uevent是一種linux裝置模型中的一個組成部分。kset中包含的uevent_ops結構體擁有uevent的操作函式。
uevent可以在裝置發生變化時主動通知應用層。是對普通先註冊裝置後註冊驅動模式的一種補充。一般用作usb裝置的自動驅動載入、電池電量上報等。
2,uevent主動通知應用層的原理是什麼?
有兩種方式,第一種是設定環境變數後使用call_usermodehelper_setup函式直接呼叫應用層程式;第二種是通過netlink嚮應用層傳送訊息,在應用層的守護程序收到訊息後完成相關操作。其中第一種本方式較少使用,以第二種為主。
ps:netlink是一種基於socket的核心空間與使用者空間的雙向通訊機制,十分靈活好用。
3,sys目錄下有許多uevent節點,它們是幹什麼的?
最開始我對uevent的理解感到困惑就是因為這些uevent節點,如cat /sys/devices/soc/qpnp-smbcharger-17/power_supply/battery/uevent節點可以檢視到電池狀態,充放電電流等等資訊,好像uevent就像其他sysfs中的節點一樣僅僅供上層讀取。然而這並不是uevent的全部,在上面解釋的uevent機制中是完全不需要這些節點存在的,事實上上層也並不會去使用這些節點。這些節點的存在僅僅是為了除錯目的,可以提供一種簡單方式檢測到uevent的中間資訊。但在android的電源管理結構中電池的相關資訊是通過讀取/sys/devices/soc/qpnp-smbcharger-17/power_supply/battery/uevent節點獲取的,netlink訊息只發出KOBJ_CHANGE的action kobject_uevent(&cm->dev->kobj, KOBJ_CHANGE),去觸發上層讀取sys節點。
注意:這些uevent節點與/dev/input/eventX節點雖然名字相似,但其原理和作用是完全不同的。eventX節點是輸入子系統的事件上報介面,需要上層來讀取eventX節點。
4,使用uevent上報電量的例項分析
kernel\drivers\power\qpnp-smbcharger.c
電量狀態變化的中斷函式中呼叫smbchg_charging_status_change函式
static int smbchg_charging_status_change(struct smbchg_chip *chip)
{
smbchg_vfloat_adjust_check(chip);
set_property_on_fg(chip, POWER_SUPPLY_PROP_STATUS,
get_prop_batt_status(chip));
return 0;
}
set_property_on_fg原始碼位於kernel\drivers\power\qpnp-smbcharger.c
set_property指標賦值位於qpnp-charger.c的prob函式中static int set_property_on_fg(struct smbchg_chip *chip, enum power_supply_property prop, int val) { int rc; union power_supply_propval ret = {0, }; if (!chip->bms_psy && chip->bms_psy_name) chip->bms_psy = power_supply_get_by_name((char *)chip->bms_psy_name); if (!chip->bms_psy) { pr_smb(PR_STATUS, "no bms psy found\n"); return -EINVAL; } ret.intval = val; rc = chip->bms_psy->set_property(chip->bms_psy, prop, &ret); if (rc) pr_smb(PR_STATUS, "bms psy does not allow updating prop %d rc = %d\n", prop, rc); return rc; }
static int qpnp_charger_probe(struct spmi_device *spmi)
{
chip->batt_psy.set_property = qpnp_batt_power_set_property;
}
qpnp_batt_power_set_property函式的實現程式碼位置:kernel\drivers\power\qpnp-charger.c
此函式用於設定uevent節點,並且發出netlink訊息通知上層讀取
static int qpnp_batt_power_set_property(struct power_supply *psy,
enum power_supply_property psp,
const union power_supply_propval *val)
{
struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
batt_psy);
int rc = 0;
switch (psp) {
case POWER_SUPPLY_PROP_COOL_TEMP:
rc = qpnp_chg_configure_jeita(chip, psp, val->intval);
break;
case POWER_SUPPLY_PROP_WARM_TEMP:
rc = qpnp_chg_configure_jeita(chip, psp, val->intval);
break;
case POWER_SUPPLY_PROP_CAPACITY:
chip->fake_battery_soc = val->intval; //將電量值賦值到fake_battery_soc變數
power_supply_changed(&chip->batt_psy); //呼叫power_supply_changed傳送netlink訊息,通知應用層重新讀取
break;
...
default:
return -EINVAL;
}
pr_debug("psy changed batt_psy\n");
power_supply_changed(&chip->batt_psy);
return rc;
}
power_supply_changed(&chip->batt_psy);原始碼位於kernel\drivers\power\power_supply_core.cstatic void power_supply_changed_work(struct work_struct *work)
{
unsigned long flags;
struct power_supply *psy = container_of(work, struct power_supply,
changed_work);
dev_dbg(psy->dev, "%s\n", __func__);
spin_lock_irqsave(&psy->changed_lock, flags);
/*
* Check 'changed' here to avoid issues due to race between
* power_supply_changed() and this routine. In worst case
* power_supply_changed() can be called again just before we take above
* lock. During the first call of this routine we will mark 'changed' as
* false and it will stay false for the next call as well.
*/
if (likely(psy->changed)) {
psy->changed = false;
spin_unlock_irqrestore(&psy->changed_lock, flags);
class_for_each_device(power_supply_class, NULL, psy,
__power_supply_changed_work);
power_supply_update_leds(psy);
atomic_notifier_call_chain(&power_supply_notifier,
PSY_EVENT_PROP_CHANGED, psy);
kobject_uevent(&psy->dev->kobj, KOBJ_CHANGE);
spin_lock_irqsave(&psy->changed_lock, flags);
}
/*
* Hold the wakeup_source until all events are processed.
* power_supply_changed() might have called again and have set 'changed'
* to true.
*/
if (likely(!psy->changed))
pm_relax(psy->dev);
spin_unlock_irqrestore(&psy->changed_lock, flags);
}
其中kobject_uevent即傳送netlink訊息到上層kernel\lib\kobject_uevent.cint kobject_uevent(struct kobject *kobj, enum kobject_action action)
{
return kobject_uevent_env(kobj, action, NULL);
}
int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
char *envp_ext[])
{
struct kobj_uevent_env *env;
const char *action_string = kobject_actions[action];
const char *devpath = NULL;
const char *subsystem;
struct kobject *top_kobj;
struct kset *kset;
const struct kset_uevent_ops *uevent_ops;
int i = 0;
int retval = 0;
...
#if defined(CONFIG_NET)
/* send netlink message */
list_for_each_entry(ue_sk, &uevent_sock_list, list) {
struct sock *uevent_sock = ue_sk->sk;
struct sk_buff *skb;
size_t len;
if (!netlink_has_listeners(uevent_sock, 1))
continue;
/* allocate message with the maximum possible size */
len = strlen(action_string) + strlen(devpath) + 2;
skb = alloc_skb(len + env->buflen, GFP_KERNEL);
if (skb) {
char *scratch;
/* add header */
scratch = skb_put(skb, len);
sprintf(scratch, "%[email protected]%s", action_string, devpath);
/* copy keys to our continuous event payload buffer */
for (i = 0; i < env->envp_idx; i++) {
len = strlen(env->envp[i]) + 1;
scratch = skb_put(skb, len);
strcpy(scratch, env->envp[i]);
}
NETLINK_CB(skb).dst_group = 1;
retval = netlink_broadcast_filtered(uevent_sock, skb, //傳送netlink訊息
0, 1, GFP_KERNEL,
kobj_bcast_filter,
kobj);
/* ENOBUFS should be handled in userspace */
if (retval == -ENOBUFS || retval == -ESRCH)
retval = 0;
} else
retval = -ENOMEM;
}
#endif
mutex_unlock(&uevent_sock_mutex);
}
相關推薦
linux裝置驅動uevent詳解,高通平臺battery上報電量例項
本文以高通平臺上的android系統為參照展開探討。1,uevent是什麼呢? uevent是一種linux裝置模型中的一個組成部分。kset中包含的uevent_ops結構體擁有uevent的操作函式。 uevent可以在裝置發生變化時主動通知應用層。是對普通先註冊裝置後
分享《Linux裝置驅動開發詳解》第2版高清電子版
新浪微博:@宋寶華Barry 在@微盤 分享了《linux裝置驅動開發詳解》第2版1080P電子版,擬升級為第3版,3.16核心,Cortex-A9 SMP,Device tree, DVFS, suspend/hibernation, big.LITTLE, CMA,分層/
Linux裝置驅動開發詳解 第3版 (即 Linux裝置驅動開發詳解 基於最新的Linux 4 0核心 )進展同步更
本博實時更新《Linux裝置驅動開發詳解(第3版)》的最新進展。 目前已經完成稿件。 2015
《Linux裝置驅動開發詳解》-- 互斥體(mutex)
儘管訊號量已經可以實現互斥的功能,而且包含 DECLARE_MUTEX() 、init_MUTEX ()等定義訊號量的巨集或函式, 從名字上看就體現出了互斥體的概念, 但是mutex 在 Linux 核心中還是真實地存
《linux裝置驅動開發詳解》筆記——15 linux i2c驅動
結合實際程式碼和書中描述,可能跟書上有一定出入。本文後續晶片相關程式碼參考ZYNQ。 15.1 總體結構 如下圖,i2c驅動分為如下幾個重要模組 核心層core,完成i2c匯流排、裝置、驅動模型,對使用者提供sys檔案系統訪問支援;為i2c內部adpter等提供註冊介面。 adpter,介面卡,實
宋寶華《Linux裝置驅動開發詳解》——sysfs檔案系統與linux裝置模型(5.4.2)
以下讀書筆記內容,摘自宋寶華《Linux裝置驅動開發詳解》一書。 1、sysfs檔案系統的簡介 (1)linux2.6以後的核心引進syfs檔案系統,是虛擬檔案系統; (2)產生一個包括所有系統硬體
關於召回《Linux裝置驅動開發詳解-基於最新的Linux 4.0核心》的通知
問題描述關於《Linux裝置驅動開發詳解:基於最新的Linux 4.0核心》一書1.華章分社在沒
【Linux】Linux裝置驅動開發詳解:基於最新的Linux 4.0核心
1 Linux裝置驅動概述及開發環境構建 1.1 裝置驅動的作用 驅使硬體裝置行動 1.2 無作業系統時的裝置驅動 典型架構:一個無限迴圈中夾雜著對裝置中斷的檢測或者對裝置的輪詢 1.3 有作業系統時的裝置驅動 併發 、記
《Linux裝置驅動開發詳解:基於最新的Linux 4.0核心》一刷勘誤
這是第一次印刷的勘誤,大部分應該買的都是5刷了,這些錯誤基本已經絕跡。還是有部分童鞋買的書老書,
宋寶華《linux裝置驅動開發詳解》——platform裝置驅動(12.2)
以下讀書筆記,整理於宋寶華《linux裝置驅動開發詳解》一書。 1、piatform匯流排出現的原因 在SOC整合的獨立外設控制器、掛接在soc記憶體空間的外設不依附與此類匯流排(PCI、USB、I
linux平臺裝置驅動架構詳解 Linux Platform Device and Driver——神文,非常詳細
從Linux 2.6起引入了一套新的驅動管理和註冊機制:Platform_device和Platform_driver。 Linux中大部分的裝置驅動,都可以使用這套機制, 裝置用Platform_device表示,驅動用Platform_driver進行註冊。 Linux platform driver機
【Linux驅動】Linux裝置樹語法詳解
1 概念Linux核心從3.x開始引入裝置樹的概念,用於實現驅動程式碼與裝置資訊相分離。在裝置樹出現以前,所有關於裝置的具體資訊都要寫在驅動裡,一旦外圍裝置變化,驅動程式碼就要重寫。引入了裝置樹之後,驅動程式碼只負責處理驅動的邏輯,而關於裝置的具體資訊存放到裝置樹檔案中,這樣,如果只是硬體介面資訊的變化而沒有
轉載:linux平臺裝置驅動架構詳解 Linux Platform Device and Driver
從Linux 2.6起引入了一套新的驅動管理和註冊機制:Platform_device和Platform_driver。Linux中大部分的裝置驅動,都可以使用這套機制, 裝置用Platform_device表示,驅動用Platform_driver進行註冊。Linux platform driver機制和傳
《Linux4.0裝置驅動開發詳解》筆記--第十八章:ARM Linux裝置樹
18.1 ARM裝置樹簡介 裝置舒適一種描述印鑑的資料結構,它起源於OpenFirmware(OF) 採用裝置樹前後對比: 採用裝置樹之前:ARM架構的板極硬體細節過多的被硬編碼在arch/arm/plat-xxx和arch/arm/mach-xxx中
《Linux4.0裝置驅動開發詳解》筆記--第二章:Linux核心及核心程式設計
2.1 Linux核心發展及演變 1991年10月5日 Linus Torvalds建立 五個支柱:Unix系統、Minix系統、GNU計劃、POSIX標準和Internet 每2-3個月更新一次大的版本號 2.2 Linux2.6後的核心特點
Linux裝置樹語法詳解【轉】
轉自:https://www.cnblogs.com/xiaojiang1025/p/6131381.html 概念 Linux核心從3.x開始引入裝置樹的概念,用於實現驅動程式碼與裝置資訊相分離。在裝置樹出現以前,所有關於裝置的具體資訊都要寫在驅動裡,一旦外圍裝置變化,驅動程式碼就要重寫。引入了裝置樹之
Linux裝置樹語法詳解
概念 Linux核心從3.x開始引入裝置樹的概念,用於實現驅動程式碼與裝置資訊相分離。在裝置樹出現以前,所有關於裝置的具體資訊都要寫在驅動裡,一旦外圍裝置變化,驅動程式碼就要重寫。引入了裝置樹之後,驅動程式碼只負責處理驅動的邏輯,而關於裝置的具體資訊存放到裝置樹檔案中,
Linux按鍵驅動程式設計詳解---從簡單到不簡單
混雜裝置驅動模型: 1. 混雜裝置描述 在Linux系統中,存在一類字元裝置,它們擁有相同的主裝置號(10),單次裝置號不同,我們稱這類裝置為混 雜裝置(miscdevice).所有的混雜裝置形成一個連結串列,對裝置訪問時核心根據次裝置
LINUX裝置驅動程式(第3版)[高清PDF]
下載地址:網盤下載 內容簡介 編輯 《LINUX裝置驅動程式(第3版)》已針對Linux核心的2610版本徹底更新過了。核心的這個版本針對常見任務完成了合理化設計及相應的簡化,如即插即用、利用sysfs檔案系統和使用者空間互動,以及標準總線上的多裝置管理等等
FS_S5PC100平臺上Linux Camera驅動開發詳解(一)
說明: 理解攝像頭驅動需要四個前提: 1)攝像頭基本的工作原理和S5PC100整合的 Camera控制器 的工作原理 2)platform_device和platform_driver工作原理 3)Linu