精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Hi3516驅動開發全面詳解

開發 前端
內核驅動是軟件與硬件交互的橋梁,通過文件系統接口訪問OpenHarmony內核的硬件資源,是用戶與內核之間、進程與進程之間通信的一種方式。

[[410422]]

想了解更多內容,請訪問:

51CTO和華為官方合作共建的鴻蒙技術社區

https://harmonyos.51cto.com

驅動框架介紹

驅動子系統

內核驅動是軟件與硬件交互的橋梁,通過文件系統接口訪問OpenHarmony內核的硬件資源,是用戶與內核之間、進程與進程之間通信的一種方式。每類驅動代表一種能力,用戶可以根據需求選擇對應驅動,完成數據的傳輸。OpenHarmony驅動子系統采用C面向對象編程模型構建,通過平臺解耦、內核解耦,兼容不同內核,提供了歸一化的驅動平臺底座,旨在為開發者提供更精準、更高效的開發環境,力求做到一次開發,多系統部署。

1、架構

OpenHarmony驅動框架采用主從架構設計模式,圍繞著框架、模型、能力庫和工具四個維度能力展開構建。

Hi3516驅動開發-鴻蒙HarmonyOS技術社區

2、目錄

  1. drivers 
  2. ├── adapter               #適配平臺差異性的代碼 
  3. ├── framework             #驅動框架核心代碼 
  4. └── peripheral            #外設驅動代碼 
  5. └── liteos                #hievent和tzdrivert驅動代碼。hievent:事件日志管理驅動;tzdrivert:用于ree/tee切換、通訊,提供應用層訪問的設備節點 

3、驅動框架交互流程

Hi3516驅動開發-鴻蒙HarmonyOS技術社區

驅動框架完成大部分驅動加載的動作,用戶只需注冊自己所需的接口和配置,然后驅動框架就會解析配置的內容,完成驅動加載和初始化動作。

4、安裝

OpenHarmony驅動主要部署在內核態,當前主要采用靜態鏈接方式,隨內核子系統編譯和系統鏡像打包。

Hi3516驅動開發-鴻蒙HarmonyOS技術社區

5、HDF驅動加載的過程

Hi3516驅動開發-鴻蒙HarmonyOS技術社區

HDF Framework

1、簡介

HDF Framework提供包括驅動框架、配置管理、配置解析、驅動通用框架模型、硬件通用平臺能力接口等,驅動框架的架構圖:

Hi3516驅動開發-鴻蒙HarmonyOS技術社區

 2、目錄

  1. /drivers/framework 
  2. ├── ability        #提供驅動開發的能力支持,如消息模型庫等 
  3. │   ├── config     #配置解析代碼 
  4. │   └── sbuf       #數據序列化代碼 
  5. ├── core           #實現驅動框架的核心代碼 
  6. │   ├── adapter    #實現對內核操作接口適配,提供抽象化的接口供開發者使用 
  7. │   ├── common     #驅動框架公共基礎代碼 
  8. │   ├── host       #驅動宿主環境模塊 
  9. │   ├── manager    #驅動框架管理模塊 
  10. │   └── shared     #host和manager共享模塊代碼 
  11. ├── include        #驅動框架對外提供能力的頭文件 
  12. │   ├── config     #提供配置解析能力的頭文件 
  13. │   ├── core       #驅動框架對外提供的頭文件 
  14. │   ├── net        #網絡數據操作相關的頭文件 
  15. │   ├── osal       #系統適配相關接口的頭文件 
  16. │   ├── platform   #平臺設備相關接口的頭文件 
  17. │   ├── utils      #驅動框架公共能力的頭文件 
  18. │   └── wifi       #WLAN對外提供能力的頭文件 
  19. ├── model          #提供驅動通用框架模型 
  20. │   ├── display    #顯示框架模型 
  21. │   ├── input      #輸入框架模型 
  22. │   ├── network    #WLAN框架模型 
  23. │   └── sensor     #Sensor驅動模型 
  24. ├── support        #提系統的基礎能力  
  25. │   └── platform   #平臺設備驅動框架及訪問接口,范圍包括GPIO、I2C、SPI等 
  26. ├── tools          #hdf框架工具相關的源碼 
  27. │   └── hc-gen     #配置管理工具源碼 
  28. └── utils          #提供基礎數據結構和算法等 

HDF適配

HDF適配主要實現OpenHarmony驅動子系統內核或用戶態驅動框架的代碼和編譯腳本,提供驅動框架的能力。

2、目錄

  1. /drivers/adapter 
  2. ├── khdf/linux          #提供驅動框架對Linux內核依賴適配 
  3. ├── khdf/liteos         #提供驅動框架對LiteOS-A內核依賴適配 
  4. ├── khdf/liteos_m       #提供驅動框架對LiteOS-M內核依賴適配 
  5. ├── uhdf                #提供用戶態驅動接口對系統依賴適配 
  6. └── uhdf2               #提供用戶態驅動框架對系統依賴適配 

linux khdf

1、簡介

drivers/adapter/khdf/linux下提供OpenHarmony驅動子系統適配linux內核的代碼和編譯腳本,在linux內核中部署OpenHarmony驅動框架。

2、目錄

  1. /drivers/adapter/khdf/linux 
  2. ├── config               #linux內核下編譯配置解析代碼的編譯腳本 
  3. ├── hcs                  #linux內核下HDF的配置管理目錄 
  4. ├── manager              #linux內核下啟動適配啟動HDF框架代碼 
  5. ├── model                #驅動模型適配linux代碼 
  6. │   ├── display          #顯示驅動模型 
  7. │   ├── input            #輸入驅動模型 
  8. │   ├── network          #wifi驅動模型 
  9. │   └── sensor           #傳感器驅動模型 
  10. ├── network              #適配linux內核網絡代碼 
  11. ├── osal                 #適配linux內核的posix接口 
  12. ├── platform             #平臺設備接口適配linux內核代碼 
  13. │   ├── emmc             #emmc操作接口 
  14. │   ├── gpio             #gpio接口 
  15. │   ├── i2c              #i2c接口 
  16. │   ├── mipi_dsi         #mipi dsi接口 
  17. │   ├── pwm              #pwm接口 
  18. │   ├── rtc              #rtc接口 
  19. │   ├── sdio             #sdio接口 
  20. │   ├── spi              #spi接口 
  21. │   ├── uart             #uart接口 
  22. │   └── watchdog         #watchdog接口 

peripheral

1、簡介

peripheral主要包含各外設器件驅動相關的HDI(Hardware Driver Interface)接口、HAL實現、驅動模型及測試用例等,根據模塊劃分不同目錄,具體模塊的相關信息可參閱各模塊子目錄下的readme。

2、目錄

代碼目錄為 /drivers/peripheral,其中包含的各子目錄簡介如下。

  • audio:Audio HDI接口的定義,用于管理聲卡驅動的加載和卸載、創建音頻播放對象3及錄音對象、選擇音頻場景、設置音頻屬性及音量、控制音頻播放及錄音的啟停等。
  • codec:Codec HDI接口的定義,這些接口對上層服務提供媒體編解碼的驅動能力。
  • display:Display HDI 接口定義及其默認實現,對上層圖形服務提供顯示驅動能力,包括顯示圖層的管理、顯示內存的管理及硬件圖形加速。
  • format:Format HDI接口定義,此類接口對上層服務提供媒體文件復用和解復用的驅動能力。
  • input:Input HDI接口定義及其實現,對上層輸入系統服務提供操作input設備的驅動能力,包括input設備管理、業務流控制、數據上報等。
  • sensor:Sensor HDI接口定義與實現,接口主要包括所有Sensor信息查詢、Sensor啟停、Sensor訂閱/去訂閱、Sensor參數配置等穩定的接口,簡化服務開發。
  • wlan:WLAN HDI接口定義與實現,包括創建和銷毀HAL層和WLAN驅動的通道、獲取本設備支持的WLAN特性等。

HDF

1、HDF驅動開發簡介

HDF框架以組件化的驅動模型作為核心設計思路,為開發者提供更精細化的驅動管理,讓驅動開發和部署更加規范。HDF框架將一類設備驅動放在同一個host里面,開發者也可以將驅動功能分層獨立開發和部署,支持一個驅動多個node,HDF框架管理驅動模型如下圖所示:

Hi3516驅動開發-鴻蒙HarmonyOS技術社區

基于HDF(Hardware Driver Foundation驅動框架)開發驅動,用戶只需注冊自己所需的接口和配置,然后驅動框架就會解析配置的內容,完成驅動加載和初始化動作。

開發者基于HDF驅動框架開發的驅動主要包含三大部分:

  • 驅動程序部分----完成驅動的功能邏輯。
  • 驅動配置信息----指示驅動的加載信息內容。
  • 驅動資源配置----配置驅動的硬件配置信息。

驅動程序主要是完成驅動功能的邏輯代碼:

對于開發者首先看到的是驅動入口部分,驅動入口部分通過DriverEntry進行描述。

其中主要包含Bind, Init 和Release三個接口。

  1. struct HdfDriverEntry g_deviceSample = { 
  2.     .moduleVersion = 1, 
  3.     .moduleName = "sample_driver",  
  4.     .Bind = SampleDriverBind, 
  5.     .Init = SampleDriverInit, 
  6.     .Release = SampleDriverRelease, 
  7. }; 

Bind接口描述:該接口的作用主要是完成驅動設備和設備服務接口的bind動作。

  1. int32_t SampleDriverBind(struct HdfDeviceObject *deviceObject) 
  2.     // TODO: Bind device service to device object. 
  3.     // And you can also initialize device resources here. 
  4.     return HDF_SUCCESS; 

Init接口描述:當框架完成設備綁定動作后,就開始調用驅動初始化接口,當初始化成功后,驅動框架根據配置文件決定是否對外創建設備服務接口,還是只是對當前服務接口可見。如果Init初始化失敗的話,驅動框架就會主動釋放創建的設備接口等信息。

  1. int32_t SampleDriverInit(struct HdfDeviceObject *deviceObject) 
  2.     // TODO: Init hardware or other resources here. 
  3.     return HDF_SUCCESS; 

Release接口描述:當用戶需要卸載驅動時,驅動框架先通過該接口通知驅動程序釋放資源。然后在執行其他內部資源釋放。

  1. void SampleDriverRelease(struct HdfDeviceObject *deviceObject) 
  2.     // Release all resources. 
  3.     return

2、驅動加載

HDF驅動加載包括按需加載和按序加載。

  • 按需加載

HDF框架支持驅動在系統啟動過程中默認加載,或者在系統啟動之后動態加載。

  1. typedef enum {    DEVICE_PRELOAD_ENABLE = 0,    DEVICE_PRELOAD_ENABLE_STEP2,    DEVICE_PRELOAD_DISABLE,    DEVICE_PRELOAD_INVALID} DevicePreload; 
  2. 1. 
  3. 1. 
  4. 1. 

復制配置文件中preload 字段配成 0 (DEVICE_PRELOAD_ENABLE ),則系統啟動過程中默認加載;配成1(DEVICE_PRELOAD_ENABLE_STEP2),當系統支持快啟的時候,則在系統系統完成之后再加載這一類驅動,否則和DEVICE_PRELOAD_ENABLE 含義相同;

配成2(DEVICE_PRELOAD_DISABLE),則系統啟動過程中默認不加載,支持后續動態加載,當用戶態獲取驅動服務(參考消息機制)時,如果驅動服務不存在時,HDF框架會嘗試動態加載該驅動。

  • 按序加載

HDF框架支持驅動在系統啟動的過程中按照驅動的優先級進行加載。

配置文件中的priority(取值范圍為整數0到200)是用來表示host和驅動的優先級,不同的host內的驅動,host的priority值越小,驅動加載優先級越高;同一個host內驅動的priority值越小,加載優先級越高。

3、驅動服務管理

HDF框架可以集中管理驅動服務,開發者可直接通過HDF框架對外提供的能力接口獲取驅動相關的服務。

4、驅動消息機制

HDF框架提供統一的驅動消息機制,支持用戶態應用向內核態驅動發送消息,也支持內核態驅動向用戶態應用發送消息。

驅動開發步驟

驅動實現

驅動實現包含驅動業務代碼和驅動入口注冊,具體寫法如下:

驅動業務代碼

  1. #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 0;}// 驅動自身業務初始的接口int32_t HdfSampleDriverInit(struct HdfDeviceObject *deviceObject){    HDF_LOGD("Sample driver Init success");    return 0;}// 驅動資源釋放的接口void HdfSampleDriverRelease(struct HdfDeviceObject *deviceObject){    HDF_LOGD("Sample driver release success");    return;} 

驅動入口注冊到HDF框架

  1. // 定義驅動入口的對象,必須為HdfDriverEntry(在hdf_device_desc.h中定義)類型的全局變量struct HdfDriverEntry g_sampleDriverEntry = {    .moduleVersion = 1,    .moduleName = "sample_driver",    .Bind = HdfSampleDriverBind,    .Init = HdfSampleDriverInit,    .Release = HdfSampleDriverRelease,};// 調用HDF_INIT將驅動入口注冊到HDF框架中,在加載驅動時HDF框架會先調用Bind函數,再調用Init函數加載該驅動,當Init調用異常時,HDF框架會調用Release釋放驅動資源并退出。HDF_INIT(g_sampleDriverEntry); 

驅動編譯

驅動代碼的編譯必須要使用HDF框架提供的Makefile模板進行編譯。

  1. include $(LITEOSTOPDIR)/../../drivers/adapter/lite/khdf/lite.mk #導入hdf預定義內容,必需MODULE_NAME :=    #生成的結果文件LOCAL_INCLUDE :=  #本驅動的頭文件目錄LOCAL_SRCS :=     #本驅動的源代碼文件LOCAL_CFLAGS :=  #自定義的編譯選項include $(HDF_DRIVER) #導入模板makefile完成編譯 

編譯結果文件鏈接到內核鏡像,添加到device目錄下的lite.mk里面,示例如下:

  1. LITEOS_BASELIB +=  -lxxx  #鏈接生成的靜態庫LIB_SUBDIRS    +=         #驅動代碼Makefile的目錄 

驅動配置

HDF使用HCS作為配置描述源碼,HCS詳細介紹參考配置管理介紹。

驅動配置包含兩部分,HDF框架定義的驅動設備描述和驅動的私有配置信息,具體寫法如下:

  • 驅動設備描述(必選)

HDF框架加載驅動所需要的信息來源于HDF框架定義的驅動設備描述,因此基于HDF框架開發的驅動必須要在HDF框架定義的device_info.hcs配置文件中添加對應的設備描述,驅動的設備描述填寫如下所示:

  1. root {    device_info {        match_attr = "hdf_manager";        template host {       // host模板,繼承該模板的節點(如下sample_host)如果使用模板中的默認值,則節點字段可以缺省            hostName = "";            priority = 100;            template device {                template deviceNode {                    policy = 0;                    priority = 100;                    preload = 0;                    permission = 0664;                    moduleName = "";                    serviceName = "";                    deviceMatchAttr = "";                }            }        }        sample_host :: host{            hostName = "host0";    // host名稱,host節點是用來存放某一類驅動的容器            priority = 100;        // host啟動優先級(0-200),值越大優先級越低,建議默認配100,優先級相同則不保證host的加載順序            device_sample :: device {        // sample設備節點                device0 :: deviceNode {      // sample驅動的DeviceNode節點                    policy = 1;              // policy字段是驅動服務發布的策略,在驅動服務管理章節有詳細介紹                    priority = 100;          // 驅動啟動優先級(0-200),值越大優先級越低,建議默認配100,優先級相同則不保證device的加載順序                    preload = 0;             // 驅動按需加載字段,在本章節最后的說明有詳細介紹                    permission = 0664;       // 驅動創建設備節點權限                    moduleName = "sample_driver";   // 驅動名稱,該字段的值必須和驅動入口結構的moduleName值一致                    serviceName = "sample_service";    // 驅動對外發布服務的名稱,必須唯一                    deviceMatchAttr = "sample_config"; // 驅動私有數據匹配的關鍵字,必須和驅動私有數據配置表中的match_attr值相等                }            }        }    }} 
  • 驅動私有配置信息(可選)

如果驅動有私有配置,則可以添加一個驅動的配置文件,用來填寫一些驅動的默認配置信息,HDF框架在加載驅動的時候,會將對應的配置信息獲取并保存在HdfDeviceObject 中的property里面,通過Bind和Init(參考驅動開發)傳遞給驅動,驅動的配置信息示例如下:

  1. root {    SampleDriverConfig {        sample_version = 1;        sample_bus = "I2C_0";        match_attr = "sample_config";   //該字段的值必須和device_info.hcs中的deviceMatchAttr值一致    }} 

 配置信息定義之后,需要將該配置文件添加到板級配置入口文件hdf.hcs(這一塊可以通過OpenHarmony驅動子系統在DevEco集成驅動開發套件工具一鍵式配置,具體使用方法參考驅動開發套件中的介紹),示例如下:

  1. #include "device_info/device_info.hcs"#include "sample/sample_config.hcs" 

驅動開發示例

下面基于HDF框架,提供一個簡單的UART(Universal Asynchronous Receiver/Transmitter)平臺驅動開發樣例,包含配置文件的添加,驅動代碼的實現以及用戶態程序和驅動交互的流程。驅動程序源碼位于vendor/huawei/hdf/sample目錄

添加配置

HCS(HDF Configuration Source)是HDF驅動框架的配置描述源碼,內容以Key-Value為主要形式。它實現了配置代碼與驅動代碼解耦,便于開發者進行配置管理。

HC-GEN**(HDF Configuration Generator)**是HCS配置轉換工具,可以將HDF配置文件轉換為軟件可讀取的文件格式:

在弱性能環境中,轉換為配置樹源碼,驅動可直接調用C代碼獲取配置。

在高性能環境中,轉換為HCB(HDF Configuration Binary)二進制文件,驅動可使用HDF框架提供的配置解析接口獲取配置。

設備配置文件和驅動配置文件的路徑定義在板級配置入口文件hdf.hcs(vendor\hisilicon\hispark_taurus\config\hdf.hcs)

  1. #include "../../../../device/hisilicon/hispark_taurus/sdk_liteos/config/i2c/i2c_config.hcs"#include "../../../../device/hisilicon/hispark_taurus/sdk_liteos/config/gpio/gpio_config.hcs"#include "../../../../device/hisilicon/hispark_taurus/sdk_liteos/config/uart/uart_config.hcs"#include "../../../../device/hisilicon/hispark_taurus/sdk_liteos/config/sdio/sdio_config.hcs"#include "../../../../device/hisilicon/hispark_taurus/sdk_liteos/config/emmc/emmc_config.hcs"#include "../../../../device/hisilicon/hispark_taurus/sdk_liteos/config/watchdog/watchdog_config.hcs"#include "../../../../device/hisilicon/hispark_taurus/sdk_liteos/config/usb/usb_config.hcs"#include "../../../../device/hisilicon/hispark_taurus/sdk_liteos/config/rtc/rtc_config.hcs"#include "../../../../device/hisilicon/hispark_taurus/sdk_liteos/config/spi/spi_config.hcs"#include "../../../../device/hisilicon/hispark_taurus/sdk_liteos/config/pwm/pwm_config.hcs"#include "../../../../device/hisilicon/hispark_taurus/sdk_liteos/config/dmac/dmac_config.hcs"#include "device_info/device_info.hcs"#include "wifi/wlan_platform.hcs"#include "wifi/wlan_chip_hi3881.hcs"#include "lcd/lcd_config.hcs"#include "input/input_config.hcs"#include "sensor/sensor_config.hcs"root {    module = "hisilicon,hi35xx_chip";} 

 1、在HDF框架的驅動配置文件(例如device\hisilicon\hispark_taurus\sdk_liteos\config\uart\uart_config.hcs)中添加該驅動的配置信息,如下所示:

  1. root {    platform {        uart_sample {            num = 5;            base = 0x120a0000;  // UART base register address            irqNum = 38;            baudrate = 115200;            uartClk = 24000000; // 24 M            wlen = 0x60;        // 8 bit width            parity = 0;            stopBit = 0;            match_attr = "sample_uart_5";        }    }} 

 2、在HDF框架的設備配置文件(例如vendor\hisilicon\hispark_taurus\config\device_info\device_info.hcs)中添加該驅動的設備節點信息,如下所示:

  1. root {    device_info {        platform :: host {            hostName = "platform_host";            priority = 50;            device_uart :: device {                device5 :: deviceNode {                    policy = 2;                    priority = 10;                    permission = 0660;                    moduleName = "UART_SAMPLE";                      serviceName = "HDF_PLATFORM_UART_5";                    deviceMatchAttr = "sample_uart_5";                }            }        }    }} 

注冊uart驅動入口

基于HDF框架注冊UART驅動的入口HdfDriverEntry,代碼如下:

  1. // 綁定UART驅動接口到HDF框架static int32_t SampleUartDriverBind(struct HdfDeviceObject *device){    struct UartHost *uartHost = NULL;    if (device == NULL) {        return HDF_ERR_INVALID_OBJECT;    }    HDF_LOGI("Enter %s:", __func__);    uartHost = UartHostCreate(device);    if (uartHost == NULL) {        HDF_LOGE("%s: UartHostCreate failed", __func__);        return HDF_FAILURE;    }    uartHost->service.Dispatch = SampleDispatch;    return HDF_SUCCESS;} // 從UART驅動的HCS中獲取配置信息static uint32_t GetUartDeviceResource(    struct UartDevice *device, const struct DeviceResourceNode *resourceNode){    struct UartResource *resource = &device->resource;    struct DeviceResourceIface *dri = NULL;    dri = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);    if (dri == NULL || dri->GetUint32 == NULL) {        HDF_LOGE("DeviceResourceIface is invalid");        return HDF_FAILURE;    }    if (dri->GetUint32(resourceNode, "num", &resource->num, 0) != HDF_SUCCESS) {        HDF_LOGE("uart config read num fail");        return HDF_FAILURE;    }    if (dri->GetUint32(resourceNode, "base", &resource->base, 0) != HDF_SUCCESS) {        HDF_LOGE("uart config read base fail");        return HDF_FAILURE;    }    resource->physBase = (unsigned long)OsalIoRemap(resource->base, 0x48);    if (resource->physBase == 0) {        HDF_LOGE("uart config fail to remap physBase");        return HDF_FAILURE;    }    if (dri->GetUint32(resourceNode, "irqNum", &resource->irqNum, 0) != HDF_SUCCESS) {        HDF_LOGE("uart config read irqNum fail");        return HDF_FAILURE;    }    if (dri->GetUint32(resourceNode, "baudrate", &resource->baudrate, 0) != HDF_SUCCESS) {        HDF_LOGE("uart config read baudrate fail");        return HDF_FAILURE;    }    if (dri->GetUint32(resourceNode, "wlen", &resource->wlen, 0) != HDF_SUCCESS) {        HDF_LOGE("uart config read wlen fail");        return HDF_FAILURE;    }    if (dri->GetUint32(resourceNode, "parity", &resource->parity, 0) != HDF_SUCCESS) {        HDF_LOGE("uart config read parity fail");        return HDF_FAILURE;    }    if (dri->GetUint32(resourceNode, "stopBit", &resource->stopBit, 0) != HDF_SUCCESS) {        HDF_LOGE("uart config read stopBit fail");        return HDF_FAILURE;    }    if (dri->GetUint32(resourceNode, "uartClk", &resource->uartClk, 0) != HDF_SUCCESS) {        HDF_LOGE("uart config read uartClk fail");        return HDF_FAILURE;    }    return HDF_SUCCESS;} // 將UART驅動的配置和接口附加到HDF驅動框架static int32_t AttachUartDevice(struct UartHost *host, struct HdfDeviceObject *device){    int32_t ret;    struct UartDevice *uartDevice = NULL;    if (device->property == NULL) {        HDF_LOGE("%s: property is NULL", __func__);        return HDF_FAILURE;    }    uartDevice = (struct UartDevice *)OsalMemCalloc(sizeof(struct UartDevice));    if (uartDevice == NULL) {        HDF_LOGE("%s: OsalMemCalloc uartDevice error", __func__);        return HDF_ERR_MALLOC_FAIL;    }    ret = GetUartDeviceResource(uartDevice, device->property);    if (ret != HDF_SUCCESS) {        (void)OsalMemFree(uartDevice);        return HDF_FAILURE;    }    host->num = uartDevice->resource.num;    host->priv = uartDevice;    AddUartDevice(host);    return InitUartDevice(uartDevice);} // 初始化UART驅動static int32_t SampleUartDriverInit(struct HdfDeviceObject *device){    int32_t ret;    struct UartHost *host = NULL;    if (device == NULL) {        HDF_LOGE("%s: device is NULL", __func__);        return HDF_ERR_INVALID_OBJECT;    }    HDF_LOGI("Enter %s:", __func__);    host = UartHostFromDevice(device);    if (host == NULL) {        HDF_LOGE("%s: host is NULL", __func__);        return HDF_FAILURE;    }    ret = AttachUartDevice(host, device);    if (ret != HDF_SUCCESS) {        HDF_LOGE("%s: attach error", __func__);        return HDF_FAILURE;    }    host->method = &g_sampleUartHostMethod;    return ret;} static void DeinitUartDevice(struct UartDevice *device){    struct UartRegisterMap *regMap = (struct UartRegisterMap *)device->resource.physBase;    /* wait for uart enter idle. */    while (UartPl011IsBusy(regMap));    UartPl011ResetRegisters(regMap);    uart_clk_cfg(0, false);    OsalIoUnmap((void *)device->resource.physBase);    device->state = UART_DEVICE_UNINITIALIZED;} // 解綁并釋放UART驅動static void DetachUartDevice(struct UartHost *host){    struct UartDevice *uartDevice = NULL;    if (host->priv == NULL) {        HDF_LOGE("%s: invalid parameter", __func__);        return;    }    uartDevice = host->priv;    DeinitUartDevice(uartDevice);    (void)OsalMemFree(uartDevice);    host->priv = NULL;} // 釋放UART驅動static void SampleUartDriverRelease(struct HdfDeviceObject *device){    struct UartHost *host = NULL;    HDF_LOGI("Enter %s:", __func__);    if (device == NULL) {        HDF_LOGE("%s: device is NULL", __func__);        return;    }    host = UartHostFromDevice(device);    if (host == NULL) {        HDF_LOGE("%s: host is NULL", __func__);        return;    }    if (host->priv != NULL) {        DetachUartDevice(host);    }    UartHostDestroy(host);} struct HdfDriverEntry g_sampleUartDriverEntry = {    .moduleVersion = 1,    .moduleName = "UART_SAMPLE",    .Bind = SampleUartDriverBind,    .Init = SampleUartDriverInit,    .Release = SampleUartDriverRelease,}; HDF_INIT(g_sampleUartDriverEntry); 

注冊uart驅動接口

HDF框架提供了UART驅動接口的模板方法UartHostMethod,實現UART驅動接口的代碼如下:

  1. static int32_t SampleUartHostInit(struct UartHost *host){    HDF_LOGI("%s: Enter", __func__);    if (host == NULL) {        HDF_LOGE("%s: invalid parameter", __func__);        return HDF_ERR_INVALID_PARAM;    }    return HDF_SUCCESS;}static int32_t SampleUartHostDeinit(struct UartHost *host){    HDF_LOGI("%s: Enter", __func__);    if (host == NULL) {        HDF_LOGE("%s: invalid parameter", __func__);        return HDF_ERR_INVALID_PARAM;    }    return HDF_SUCCESS;}// 向UART中寫入數據static int32_t SampleUartHostWrite(struct UartHost *host, uint8_t *data, uint32_t size){    HDF_LOGI("%s: Enter", __func__);    uint32_t idx;    struct UartRegisterMap *regMap = NULL;    struct UartDevice *device = NULL;    if (host == NULL || data == NULL || size == 0) {        HDF_LOGE("%s: invalid parameter", __func__);        return HDF_ERR_INVALID_PARAM;    }    device = (struct UartDevice *)host->priv;    if (device == NULL) {        HDF_LOGE("%s: device is NULL", __func__);        return HDF_ERR_INVALID_PARAM;    }    regMap = (struct UartRegisterMap *)device->resource.physBase;    for (idx = 0; idx < size; idx++) {        UartPl011Write(regMap, data[idx]);    }    return HDF_SUCCESS;} // 設置UART的波特率static int32_t SampleUartHostSetBaud(struct UartHost *host, uint32_t baudRate){    HDF_LOGI("%s: Enter", __func__);    struct UartDevice *device = NULL;    struct UartRegisterMap *regMap = NULL;    UartPl011Error err;    if (host == NULL) {        HDF_LOGE("%s: invalid parameter", __func__);        return HDF_ERR_INVALID_PARAM;    }    device = (struct UartDevice *)host->priv;    if (device == NULL) {        HDF_LOGE("%s: device is NULL", __func__);        return HDF_ERR_INVALID_PARAM;    }    regMap = (struct UartRegisterMap *)device->resource.physBase;    if (device->state != UART_DEVICE_INITIALIZED) {        return UART_PL011_ERR_NOT_INIT;    }    if (baudRate == 0) {        return UART_PL011_ERR_INVALID_BAUD;    }    err = UartPl011SetBaudrate(regMap, device->uartClk, baudRate);    if (err == UART_PL011_ERR_NONE) {        device->baudrate = baudRate;    }    return err;} // 獲取UART的波特率static int32_t SampleUartHostGetBaud(struct UartHost *host, uint32_t *baudRate){    HDF_LOGI("%s: Enter", __func__);    struct UartDevice *device = NULL;    if (host == NULL) {        HDF_LOGE("%s: invalid parameter", __func__);        return HDF_ERR_INVALID_PARAM;    }    device = (struct UartDevice *)host->priv;    if (device == NULL) {        HDF_LOGE("%s: device is NULL", __func__);        return HDF_ERR_INVALID_PARAM;    }    *baudRate = device->baudrate;    return HDF_SUCCESS;} // 在HdfUartSampleInit方法中綁定struct UartHostMethod g_sampleUartHostMethod = {    .Init = SampleUartHostInit,    .Deinit = SampleUartHostDeinit,    .Read = NULL,    .Write = SampleUartHostWrite,    .SetBaud = SampleUartHostSetBaud,    .GetBaud = SampleUartHostGetBaud,    .SetAttribute = NULL,    .GetAttribute = NULL,    .SetTransMode = NULL,}; 

 uart驅動Makefile如下:

  1. include $(LITEOSTOPDIR)/config.mkinclude $(LITEOSTOPDIR)/../../drivers/adapter/khdf/liteos/lite.mkMODULE_NAME := hdf_uart_sampleLOCAL_CFLAGS += $(HDF_INCLUDE)LOCAL_SRCS += src/uart_sample.c \              src/uart_pl011_sample.c \              src/buf_fifo.c \              src/uart_dev_sample.c \              src/uart_dispatch_sample.c \LOCAL_INCLUDE := ./includeLOCAL_CFLAGS += -fstack-protector-stronginclude $(HDF_DRIVER) 

 在device/hisilicon/drivers/lite.mk編譯腳本中增加示例UART驅動模塊,代碼如下: 

  1. LITEOS_BASELIB += -lhdf_uart_sampleLIB_SUBDIRS += $(LITEOS_SOURCE_ROOT)/vendor/huawei/hdf/sample/platform/uart 

用戶程序和驅動交互代碼

UART驅動成功初始化后,會創建/dev/uartdev-5設備節點,通過設備節點與UART驅動交互的代碼如下:

  1. #include #include #include #include "hdf_log.h"#define HDF_LOG_TAG "hello_uart"#define INFO_SIZE 16int main(void){ int ret; int fd; const char info[INFO_SIZE] = {" HELLO UART! "}; fd = open("/dev/uartdev-5", O_RDWR); if (fd < 0) { HDF_LOGE("hello_uart uartdev-5 open failed %d", fd); return -1; } ret = write(fd, info, INFO_SIZE); if (ret != 0) { HDF_LOGE("hello_uart write uartdev-5 ret is %d", ret); } ret = close(fd); if (ret != 0) { HDF_LOGE("hello_uart uartdev-5 close failed %d", fd); return -1; } return ret;} 

將應用程序編譯進hello_uart_sample組件,應用的編譯文件:

(1)vendor/huawei/hdf/sample/platform/uart/BUILD.gn

  1. import("//build/lite/config/component/lite_component.gni")lite_component("hello_uart_sample") { features = [ "dev:hello_uart""dispatch:hello_uart_dispatch", ]} 

(2)vendor/huawei/hdf/sample/platform/uart/dev/BUILD.gn:

  1. HDF_FRAMEWORKS = "//drivers/framework"executable("hello_uart") { sources = [ "hello_uart_dev.c" ] include_dirs = [ "$HDF_FRAMEWORKS/ability/sbuf/include""$HDF_FRAMEWORKS/core/shared/include""$HDF_FRAMEWORKS/core/host/include""$HDF_FRAMEWORKS/core/master/include""$HDF_FRAMEWORKS/include/core""$HDF_FRAMEWORKS/include/utils""$HDF_FRAMEWORKS/utils/include""$HDF_FRAMEWORKS/include/osal""//drivers/adapter/uhdf/posix/include""//third_party/bounds_checking_function/include""//base/hiviewdfx/hilog_lite/interfaces/native/innerkits", ] deps = [ "//base/hiviewdfx/hilog_lite/frameworks/featured:hilog_shared""//drivers/adapter/uhdf/manager:hdf_core""//drivers/adapter/uhdf/posix:hdf_posix_osal", ] public_deps = [ "//third_party/bounds_checking_function:libsec_shared" ] defines = [ "__USER__" ] cflags = [ "-Wall""-Wextra""-Wno-format""-Wno-format-extra-args", ]} 

在build/lite/components/drivers.json驅動配置中hdf_hi3516dv300_liteos_a組件下的targets中增加hello_uart_sample組件,代碼如下:

  1. "components": [ { "component""hdf_hi3516dv300_liteos_a""description""""optional""false""dirs": ["vendor/huawei/hdf/sample/platform/uart"], "targets": [ "//vendor/huawei/hdf/sample/platform/uart:hello_uart_sample" ], "rom""""ram""""output": [], "adapted_board": [], "adapted_kernel": [ "liteos_a" ], "features": [], "deps": { "third_party": [ "bounds_checking_function" ], "components": [ "hilog" ] } } ]} 

修改單板配置文件(vendor/hisilicon/hispark_taurus/config.json),新增hdf_hi3516dv300_liteos_a組件的條目,如下所示代碼片段為driver子系統配置

  1. "subsystem""drivers""components": [ { "component""adapter_uhdf""features":[] }, { "component""peripheral_display""features":[] }, { "component""hdf_hi3516dv300_liteos_a""features":[] }, { "component""peripheral_input""features":[] }, { "component""peripheral_sensor""features":[] }, { "component""peripheral_wlan""features":[] } ] }, 

編譯

如果Linux編譯環境通過Docker方式安裝,具體編譯過程請參見Docker方式獲取編譯環境的編譯操作。如果Linux編譯環境通過軟件包方式安裝,請進入源碼根目錄,執行如下命令進行編譯:

  1. hb set(設置編譯路徑).(選擇當前路徑)選擇ipcamera_hispark_taurus并回車hb build -f(執行編譯) 

運行

燒錄成功之后,可執行文件在bin目錄下(/bin/hello_uart),運行:

Hi3516驅動開發-鴻蒙HarmonyOS技術社區

想了解更多內容,請訪問:

51CTO和華為官方合作共建的鴻蒙技術社區

https://harmonyos.51cto.com

 

責任編輯:jianghua 來源: 鴻蒙社區
相關推薦

2021-05-25 14:47:43

鴻蒙HarmonyOS應用

2021-03-29 15:36:46

鴻蒙HarmonyOS應用

2021-04-09 09:45:21

鴻蒙HarmonyOS應用

2021-11-09 15:28:41

鴻蒙HarmonyOS應用

2021-03-16 09:49:16

鴻蒙HarmonyOS應用

2022-04-15 14:45:49

Hi3516系統類型燒錄鴻蒙

2021-06-25 09:28:46

鴻蒙HarmonyOS應用

2021-09-24 10:20:42

鴻蒙HarmonyOS應用

2021-12-03 09:50:39

鴻蒙HarmonyOS應用

2022-02-16 16:01:02

Hi3516開發板鴻蒙

2021-07-21 09:58:50

鴻蒙HarmonyOS應用

2021-10-09 10:12:39

鴻蒙HarmonyOS應用

2021-03-02 14:30:20

鴻蒙HarmonyOS應用

2021-07-19 15:34:05

鴻蒙HarmonyOS應用

2021-08-06 15:09:22

鴻蒙HarmonyOS應用

2022-03-14 15:26:59

Hi3516Ark子系統鴻蒙

2022-08-10 15:58:54

LED燈鴻蒙

2021-07-07 09:45:20

鴻蒙HarmonyOS應用

2021-07-08 16:16:59

鴻蒙HarmonyOS應用

2022-04-02 20:45:04

Hi3516開發板操作系統鴻蒙
點贊
收藏

51CTO技術棧公眾號

www.桃色.com| 四虎精品欧美一区二区免费| 日本黄色一级视频| 国产精品成人av| 精品久久久久久久人人人人传媒| 国产精品无码一区二区在线| 91高清在线视频| 国产一区二区中文字幕| 97超级碰碰碰久久久| 欧美丰满美乳xxⅹ高潮www| 96视频在线观看欧美| 午夜国产精品影院在线观看| 亚洲欧洲国产日韩精品| 好男人在线视频www| 日韩av中文字幕一区二区| 欧美乱人伦中文字幕在线| www.自拍偷拍| 日韩精品成人在线观看| 色婷婷av一区二区三区gif| 91制片厂免费观看| 男同在线观看| 大白屁股一区二区视频| 国产精品色午夜在线观看| 国产网友自拍视频| 首页国产精品| 亚洲精品自产拍| 97免费公开视频| 日本一区免费网站| 婷婷亚洲久悠悠色悠在线播放| 一区二区三区四区在线视频| 亚洲av毛片成人精品| 精品一区二区三区不卡| 国产91精品在线播放| 精品在线视频免费观看| 91精品99| 久久精品国产免费观看| 内射毛片内射国产夫妻| 妖精视频一区二区三区| 亚洲第一精品久久忘忧草社区| 日韩欧美亚洲另类| 精品亚洲美女网站| 欧美午夜宅男影院在线观看| 国产日韩亚洲欧美在线| 成人日批视频| 中文字幕日本不卡| 偷拍视频一区二区| 国产一区电影| 久久精品亚洲麻豆av一区二区 | www.久久久久| 最新中文字幕av| 欧美人与拘性视交免费看| 亚洲黄色免费三级| 在线中文字日产幕| jizz18欧美18| 精品福利一区二区三区免费视频| 成人免费播放视频| 国产一区二区三区精品在线观看| 欧美日韩成人在线| 岛国毛片在线播放| 亚洲综合伊人| 日韩一级大片在线| 久久无码专区国产精品s| 午夜免费欧美电影| 日韩欧美国产系列| 亚洲成人av免费观看| 日本在线视频一区二区三区| 日韩精品一区在线| xxxx视频在线观看| 久久久精品国产**网站| 日韩电影免费在线观看中文字幕| 丰满少妇一区二区| 精品理论电影| 久久精品人人爽| 欧美黄色一区二区三区| 亚洲经典在线| 日韩av123| 亚洲视频在线免费播放| 国产真实乱子伦精品视频| 91精品国产综合久久久久久丝袜| www.色呦呦| 不卡一区在线观看| 人禽交欧美网站免费| 日本福利专区在线观看| 亚洲黄色免费电影| 免费国产黄色网址| 成人午夜一级| 日韩免费一区二区三区在线播放| 中国特级黄色片| 欧美大胆a级| 亚洲性生活视频在线观看| 制服丨自拍丨欧美丨动漫丨| 狠狠入ady亚洲精品经典电影| 97视频在线观看网址| 青青草视频在线观看免费| 久久国产生活片100| 成人资源av| 国产精品久久一区二区三区不卡| 亚洲欧洲日产国码二区| 国产人妻777人伦精品hd| 在线成人视屏 | 日本老熟妇毛茸茸| 久久电影天堂| 亚洲国产精彩中文乱码av| 日本美女xxx| 欧美日韩精品一本二本三本| 国产成人鲁鲁免费视频a| 精品女同一区二区三区| 久久久久久日产精品| 永久免费精品视频网站| 深夜成人在线| 91精品国产综合久久福利软件| 人体私拍套图hdxxxx| 不卡日本视频| 欧美精品999| 136福利视频导航| 成人va在线观看| 亚洲欧洲日本国产| 天堂中文在线播放| 日韩免费一区二区| 美女网站视频色| 亚洲中字在线| 国产91视觉| 欧美成人xxx| 色婷婷狠狠综合| 男人网站在线观看| 艳女tv在线观看国产一区| 国产精品久久久久久久久男| 免费观看黄色av| 尤物在线观看一区| 色婷婷成人在线| 欧美美女在线| 欧日韩在线观看| 欧美一级一区二区三区| 一区二区在线观看免费视频播放 | 国产精品白丝jk白祙喷水网站| 日本精品一区二区| 忘忧草在线日韩www影院| 欧美成人一区二区| 国产极品国产极品| 韩国欧美国产一区| 正在播放一区二区三区| 国内自拍亚洲| 色综合影院在线| 中日韩av在线| 国产精品丝袜一区| 天堂av在线网站| 欧美限制电影| 国产狼人综合免费视频| av资源种子在线观看| 欧洲国内综合视频| 日本一区二区视频在线播放| 天堂久久久久va久久久久| 久久久人人爽| 男人最爱成人网| 亚洲欧美另类在线观看| 国产精品va无码一区二区三区| 91年精品国产| 日本久久久精品视频| 九九精品久久| 国产精品自拍偷拍| 国产最新在线| 日韩一区二区三区四区 | 欧美另类综合| 成人自拍网站| 色资源二区在线视频| 日韩av在线天堂网| 台湾佬中文在线| 国产欧美日本一区视频| 手机av在线网| 欧美激情在线| 国产视频在线观看一区| 中文字幕在线直播| 一区二区三区视频免费在线观看| 中文字字幕在线观看| 亚洲欧洲美洲综合色网| 国产成人精品一区二区在线小狼 | 麻豆一区二区| 人人爽久久涩噜噜噜网站| caoporn国产精品免费视频| 制服丝袜亚洲精品中文字幕| 国产亚洲精品码| 91色|porny| 日本在线观看免费视频| 亚洲九九视频| 国内一区二区三区在线视频| 电影一区二区| 欧美激情综合色综合啪啪五月| 五月婷婷六月丁香综合| 欧美系列亚洲系列| 久久久久成人片免费观看蜜芽 | 秋霞欧美一区二区三区视频免费| 国产成人精品三级麻豆| 亚洲熟妇国产熟妇肥婆| 久久精品国产99久久| 成人欧美一区二区三区视频| 免费观看一级欧美片| 久久精品最新地址| 日本一区高清| 日韩一区二区在线播放| 超碰在线免费97| 亚洲国产精品久久久男人的天堂 | 免费成人网www| 91最新国产视频| 中文在线资源| 欧美床上激情在线观看| 久青青在线观看视频国产| 日韩美女视频一区二区在线观看| 日韩欧美国产另类| 亚洲18色成人| 日韩福利小视频| 久久免费精品国产久精品久久久久| 国产精品自在自线| 久久免费国产| www.夜夜爱| 99精品美女| 欧美日韩一区二区三| 91免费精品国偷自产在线在线| 国产噜噜噜噜噜久久久久久久久| 一区二区三区四区日本视频| 久久久免费在线观看| 国产精品扒开做爽爽爽的视频| 亚洲天堂影视av| 香蕉视频网站在线| 欧美大胆人体bbbb| 国产精品视频一二区| 在线视频一区二区免费| 天堂在线免费观看视频| 亚洲最新在线观看| 九九热最新地址| 国产精品网站导航| 成人免费网站黄| 99久久精品国产一区二区三区| 国产又粗又猛又爽又黄| 精品综合免费视频观看| 在线免费视频一区| 日韩福利电影在线观看| 黑森林福利视频导航| 99精品国产99久久久久久福利| 成人小视频在线观看免费| 国产精品久久久久久久免费观看 | 久久精品a一级国产免视看成人| 亚洲成人久久久久| 亚洲精品成人电影| 日韩一区二区精品葵司在线| 国产乱淫片视频| 7777精品久久久大香线蕉| 亚洲中文一区二区三区| 欧美日韩黄视频| 亚洲怡红院av| 制服丝袜亚洲精品中文字幕| 国产女人18毛片水真多| 欧美一级片在线| 精品欧美一区二区精品少妇| 精品少妇一区二区三区日产乱码 | 国产激情视频一区二区三区欧美| 一个色综合久久| 精品一区二区在线免费观看| 亚洲精品在线网址| 国产91精品免费| 亚洲视频天天射| 99r精品视频| 久久久久久九九九九九| 国产精品人妖ts系列视频| 中国美女黄色一级片| 中文字幕一区三区| 丝袜美腿小色网| 亚洲一区二区精品久久av| 日本少妇在线观看| 欧美性生交大片免费| 成人免费视频国产免费| 欧美人xxxx| 丰满熟妇人妻中文字幕| 日韩精品中文字幕视频在线| 好男人免费精品视频| 久久精品人人爽| av漫画网站在线观看| 亚洲一区二区成人在线观看| 免费看一级一片| 欧美视频免费在线观看| 做爰无遮挡三级| 日韩一区二区免费在线电影| 天天干天天摸天天操| 尤物yw午夜国产精品视频明星| 亚洲成a人v欧美综合天堂麻豆| 欧美国产日韩一区二区| 久久毛片亚洲| 国产又爽又黄的激情精品视频| 风间由美一区二区av101 | 国产精品久久占久久| 成人短视频在线观看免费| 国产精品美女| 国产一区二区在线观看免费视频| 成人性生交大片免费看中文| 极品人妻videosss人妻| 亚洲国产精品天堂| 亚洲综合一区中| 日韩高清av一区二区三区| 日韩毛片久久久| 45www国产精品网站| 成人亚洲精品| 久久精品ww人人做人人爽| 亚洲成人国产| www.四虎成人| 豆国产96在线|亚洲| 国产三级aaa| 欧美日韩一区二区三区| 国产av无码专区亚洲a∨毛片| 亚洲偷欧美偷国内偷| 黄色网页在线播放| 日韩免费av一区二区| 91国内精品白嫩初高生| 亚洲成人自拍| 久久久精品网| 国产污在线观看| 亚洲免费在线视频一区 二区| 亚洲天堂一区在线| 欧美第一区第二区| 蜜桃av在线免费观看| 国产成人综合亚洲| 牛牛影视久久网| 成人在线免费观看视频网站| 久久精品国产一区二区三| 色婷婷在线影院| 精品人伦一区二区三区蜜桃网站| 亚洲av无码乱码国产精品| 日韩一区二区av| 91国内外精品自在线播放| 免费在线成人av电影| 精品动漫3d一区二区三区免费版| 99视频在线观看视频| 国产精品第一页第二页第三页| 中文字幕精品无码一区二区| 亚洲精品国精品久久99热| 丰满的护士2在线观看高清| 91在线播放国产| 99久久99视频只有精品| 少妇网站在线观看| 国产目拍亚洲精品99久久精品| 波多野结衣av无码| 亚洲欧美在线磁力| sis001欧美| 日本黄网免费一区二区精品| 三级一区在线视频先锋 | 午夜精品福利影院| 国产精品久在线观看| 你懂的在线观看一区二区| 日本a在线免费观看| 岛国一区二区在线观看| 国产亚洲精品女人久久久久久| 日韩视频一区二区在线观看| 天堂成人av| www.成人av.com| 亚洲欧洲一区| 亚洲一级av无码毛片精品| 精品欧美国产一区二区三区| 日本五码在线| 国产精品久久久久久久久久久不卡| 国产日产精品_国产精品毛片| 久久久久久久片| 欧美国产1区2区| 一二三四区在线| 欧美不卡视频一区发布| 成人盗摄视频| 又粗又黑又大的吊av| 久久精品一区二区三区av| 亚洲天天综合网| 伦理中文字幕亚洲| 一区二区免费| 日韩精品一区二区三区久久| 久久精品无码一区二区三区| 中文字幕 国产| 欧美成人在线影院| 日韩福利视频一区| 制服丝袜综合网| 一区二区三区色| 日韩美女一级视频| 欧美午夜精品免费| 亚洲一区二区在线免费| 夜夜爽夜夜爽精品视频| 神马精品久久| 国产区亚洲区欧美区| 国产精品v欧美精品v日本精品动漫| 中国极品少妇videossexhd| 日本韩国欧美一区| 91麻豆免费在线视频| 免费成人看片网址| 精久久久久久久久久久| 懂色av.com| 中文字幕无线精品亚洲乱码一区 | 69久久99精品久久久久婷婷 | 日韩av免费在线| 亚洲色图网站| 蜜桃精品成人影片| 欧美丰满嫩嫩电影| 性欧美freesex顶级少妇| 亚洲第一页在线视频| 99国产精品久| 99国产精品久久久久99打野战| 欧美自拍视频在线| 欧美女激情福利|