一、HDF驅動簡介
HDF(Hardware Driver Foundation)驅動框架,為驅動開發者提供驅動框架能力,包括驅動加載、驅動服務管理、驅動消息機制和配置管理。
簡單來說:HDF框架的驅動和Linux的驅動比較相似都是由配置文件和驅動源碼組成。
HDF驅動:配置文件HCS + 驅動源碼。
Linux驅動:配置文件DTS + 驅動源碼。
二、HCS文件簡介
HCS(HDF Configuration Source)是HDF驅動框架的配置描述源碼,內容以Key-Value為主要形式。它實現了配置代碼與驅動代碼解耦,便于開發者進行配置管理。HC-GEN(HDF Configuration Generator)是HCS配置轉換工具,可以將HDF配置文件轉換為軟件可讀取的文件格式:
在弱性能環境中,轉換為配置樹源碼或配置樹宏定義,驅動可直接調用C代碼或宏式APIs獲取配置。
在高性能環境中,轉換為HCB(HDF Configuration Binary)二進制文件,驅動可使用HDF框架提供的配置解析接口獲取配置。
HCS文件示例:
root {device_info {match_attr = "hdf_manager";template host {hostName = "";priority = 100;template device {template deviceNode {policy = 0;priority = 100;preload = 0;permission = 0664;moduleName = "";serviceName = "";deviceMatchAttr = "";}}}base :: host {hostName = "base_host";priority = 50;device_support :: device {device0 :: deviceNode {policy = 2;priority = 10;permission = 0644;moduleName = "HDF_KEVENT";serviceName = "hdf_kevent";}}}}
}
上面是我從一個HCS文件中截取了一點內容,HCS子定義了一套格式。
三、HCS語法說明
下面是從官網的一個截圖:
HCS經過HC-GEN編譯生成HCB文件,HDF驅動框架中的HCS Parser模塊會從HCB文件中重建配置樹,HDF驅動模塊使用HCS Parser提供的配置讀取接口獲取配置內容。
表3 HCS配置語法保留關鍵字
|關鍵字 | 用途 |說明|
關鍵字 | 用途 | 說明 |
---|---|---|
root | 配置根節點 | - |
include | 引用其他HCS配置文件 | - |
delete | 刪除節點或屬性 | 只能用于操作include導入的配置樹 |
template | 定義模板節點 | - |
match_attr | 用于標記節點的匹配查找屬性 | 解析配置時可以使用該屬性的值查找到對應節點 |
HCS主要分為屬性(Attribute)和節點(Node)兩種結構。
詳細語法說明參考:https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/driver/driver-hdf-manage.md
上面的示例代碼中有:moduleName = “HDF_KEVENT”;
這塊的 moduleName 和 DTS文件中驅動節點的 compatible 功能相同,用來匹配對應的驅動代碼。
上面的示例代碼中有:serviceName = “hdf_kevent”;
當驅動匹配成功后最終在/dev路徑下面生成的節點名稱 “hdf_kevent”。但是是否在/dev下面生成節點信息和policy的屬性有關。
只有policy = 2時,在/dev下面才能看到節點信息。
typedef enum {/* 驅動不提供服務 */SERVICE_POLICY_NONE = 0,/* 驅動對內核態發布服務 */SERVICE_POLICY_PUBLIC = 1,/* 驅動對內核態和用戶態都發布服務 */SERVICE_POLICY_CAPACITY = 2,/* 驅動服務不對外發布服務,但可以被訂閱 */SERVICE_POLICY_FRIENDLY = 3,/* 驅動私有服務不對外發布服務,也不能被訂閱 */SERVICE_POLICY_PRIVATE = 4,/* 錯誤的服務策略 */SERVICE_POLICY_INVALID
} ServicePolicy;
四、驅動代碼介紹
驅動實現包含驅動業務代碼實現和驅動入口注冊,具體寫法如下:
- 驅動業務代碼
#include "hdf_device_desc.h" // HDF框架對驅動開發相關能力接口的頭文件
#include "hdf_log.h" // HDF框架提供的日志接口頭文件#define HDF_LOG_TAG sample_driver // 打印日志所包含的標簽,如果不定義則用默認定義的HDF_TAG標簽。// 將驅動對外提供的服務能力接口綁定到HDF框架。
int32_t HdfSampleDriverBind(struct HdfDeviceObject *deviceObject)
{HDF_LOGD("Sample driver bind success");return HDF_SUCCESS;
}// 驅動自身業務初始化的接口
int32_t HdfSampleDriverInit(struct HdfDeviceObject *deviceObject)
{HDF_LOGD("Sample driver Init success");return HDF_SUCCESS;
}// 驅動資源釋放的接口
void HdfSampleDriverRelease(struct HdfDeviceObject *deviceObject)
{HDF_LOGD("Sample driver release success");return;
}
- 驅動入口注冊到HDF框架
// 定義驅動入口的對象,必須為HdfDriverEntry(在hdf_device_desc.h中定義)類型的全局變量。
struct HdfDriverEntry g_sampleDriverEntry = {.moduleVersion = 1,.moduleName = "HDF_KEVENT",.Bind = HdfSampleDriverBind,.Init = HdfSampleDriverInit,.Release = HdfSampleDriverRelease,
};// 調用HDF_INIT將驅動入口注冊到HDF框架中。在加載驅動時HDF框架會先調用Bind函數,再調用Init函數加載該驅動;當Init調用異常時,HDF框架會調用Release釋放驅動資源并退出。
HDF_INIT(g_sampleDriverEntry);
只要驅動代碼中的moduleName配置和HCS文件中moduleName配置內容相同就會執行驅動中的Bind函數,Bind函數執行成功后就會執行Init函數。如果Bind和Init函數有一個執行失敗會立刻執行Release函數。
五、其他
今天就介紹到這里,我最近幾年一直從事音頻開發,主要做Linux、Open Harmony系統的音頻開發。做過RK系列、海思和展銳的音頻適配,大家有什么問題可以留言咨詢。