成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

OpenHarmony HDF Input驅動模型分析與使用

開發 前端
本文梳理了 HDF_Input 模型工作流程,重點介紹了器件驅動適配,以 Hi3516dv300 開發板觸屏為例進行了詳細的代碼說明,希望通過本文檔您能初步掌握基于 HDF 框架的 Input 設備的開發步驟與流程。

[[423128]]

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

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

https://harmonyos.51cto.com

概述

輸入設備是用戶與計算機系統進行人機交互的主要裝置之一,是用戶與計算機或者其他設備通信的橋梁。常見的輸入設備有鍵盤、鼠標、游戲桿、觸摸屏等。本文檔將介紹如何使用 Hi3516DV300 開發板完成基于 HDF_Input 模型的觸摸屏(Touch Screen)器件驅動開發,從而使開發者快速入門。

硬件資源簡介

Touch 設備與主機通訊一般采用 I2C 總線完成數據的交互,為了提高觸屏數據的實時性,觸屏 IC 都會提供中斷支持。當有觸屏事件發生時,會觸發主機中斷管腳完成一次中斷響應。中斷處理函數中主機通過 I2C 總線讀取觸屏 IC 寄存器完成一次數據采集。

Hi3516DV300 開發板套件所提供的觸摸屏器件 IC 為 GT911,該器件采用標準 I2C 與主機通信,通過 6pin 軟排線與主板連接。6pin 分布以及實物連接圖如下圖所示:

OpenHarmony HDF Input驅動模型分析與使用-鴻蒙HarmonyOS技術社區

Input模型簡介

Input模型概覽

OpenHarmony HDF Input驅動模型分析與使用-鴻蒙HarmonyOS技術社區

Input 驅動模型核心部分由設備管理層、公共驅動層、器件驅動層組成。器件產生的數據借助平臺數據通道能力從內核傳遞到用戶態,驅動模型通過配置文件適配不同器件及硬件平臺,提高開發者的器件驅動開發效率。如下部分為模型各部分的說明:

(1)input 設備管理:為各類輸入設備驅動提供 input 設備的注冊、注銷接口,同時統一管理 input 設備列表;

(2)input 平臺驅動:指各類 input 設備的公共抽象驅動(例如觸摸屏的公共驅動),負責對板級硬件進行初始化、硬件中斷處理、向 manager 注冊 input 設備等;

(3)input 器件驅動:指各器件廠家的差異化驅動,通過適配平臺驅動預留的差異化接口,實現器件驅動開發量最小化;

(4)input 數據通道:提供一套通用的數據上報通道,各類別的 input 設備驅動均可用此通道上報 input 事件;

(5)input 配置解析:負責對 input 設備的板級配置及器件私有配置進行解析及管理。

Input模型工作流程解析

為了讓開發者更清晰的了解 Input 模型工作流程,本節將對 input 模型加載的關鍵流程代碼進行說明。

本章節為 Input 模型工作流程說明,開發者無需進行開發。

私有配置信息解析

示例代碼路徑:

  1. ./drivers/framework/model/input/driver/input_config_parser.c 

 根據 OSAL 提供的配置解析函數,可以將 hcs 文件中各字段含義進行解析,具體請參考 input_config_parser.c 中各函數的實現。如果提供的模板不能滿足需求,在 hcs 文件中添加相應信息后,需要根據添加的字段開發相應的解析函數。

  1. static int32_t ParseAttr(struct DeviceResourceIface *parser, const struct DeviceResourceNode *attrNode, BoardAttrCfg *attr) 
  2. int32_t ret; 
  3. // 獲取inputType字段信息,保存在BoardAttrCfg結構體中 
  4.     ret = parser->GetUint8(attrNode, "inputType", &attr->devType, 0);      
  5.     CHECK_PARSER_RET(ret, "GetUint8"); 
  6.     ... 
  7.     return HDF_SUCCESS; 

管理驅動層初始化及注冊驅動至HDF框架

示例代碼路徑:

  1. ./drivers/framework/model/input/driver/hdf_input_device_manager.c 
  2. static int32_t HdfInputManagerInit(struct HdfDeviceObject *device) 
  3. {  
  4. /* 分配內存給manager,manager中將存放所有input設備 */ 
  5.     g_inputManager = InputManagerInstance(); 
  6.     ... 
  7. struct HdfDriverEntry g_hdfInputEntry = { 
  8.     .moduleVersion = 1, 
  9.     .moduleName = "HDF_INPUT_MANAGER"
  10.     .Bind = HdfInputManagerBind, 
  11.     .Init = HdfInputManagerInit, 
  12.     .Release = HdfInputManagerRelease, 
  13. }; 
  14. HDF_INIT(g_hdfInputEntry);        //驅動注冊入口 

公共驅動層初始化及注冊驅動至HDF框架

示例代碼路徑:

  1. ./drivers/framework/model/input/driver/hdf_touch.c 
  2. static int32_t HdfTouchDriverProbe(struct HdfDeviceObject *device) 
  3.    ... 
  4.     /* 板級信息結構體內存申請及hcs配置信息解析 */ 
  5.     boardCfg = BoardConfigInstance(device); 
  6.     ... 
  7.     /* 公共驅動結構體內存申請 */ 
  8.     touchDriver = TouchDriverInstance(); 
  9.     ... 
  10.     /* 依據解析出的板級信息進行公共資源初始化,如IIC初始化 */ 
  11.     ret = TouchDriverInit(touchDriver, boardCfg); 
  12.     if (ret == HDF_SUCCESS) { 
  13.         ... 
  14.        /* 添加驅動至公共驅動層驅動管理鏈表,當設備與驅動進行綁定時使用該鏈表進行查詢 */ 
  15.         AddTouchDriver(touchDriver); 
  16.         ... 
  17.     } 
  18.     ... 
  19. struct HdfDriverEntry g_hdfTouchEntry = { 
  20.     .moduleVersion = 1, 
  21.     .moduleName = "HDF_TOUCH"
  22.     .Bind = HdfTouchDriverBind, 
  23.     .Init = HdfTouchDriverProbe, 
  24.     .Release = HdfTouchDriverRelease, 
  25. }; 
  26.                                 
  27. HDF_INIT(g_hdfTouchEntry);       //驅動注冊入口 

器件驅動層初始化及注冊驅動至HDF框架

具體請參考適配器件私有驅動器件層驅動初始化及注冊驅動至 HDF 框架部分。

具體調用邏輯串聯函數

Input 模型管理層驅動 init 函數初始化了設備管理鏈表,公共驅動層初始化函數完成了相關結構體的內存申請。器件驅動相關信息通過 RegisterChipDevice 函數對公共驅動層相關結構體進行信息填充,同時完成了相關硬件信息的初始化(如中斷注冊等),綁定設備與驅動組成 inputDev 通過 RegisterInputDevice 函數向驅動管理層進行注冊,在 RegisterInputDevice 函數中主要實現了將 inputDev 向設備管理鏈表的添加等功能。如下所示為兩個函數的實現部分:

函數具體實現代碼位置

  1. ./drivers/framework/model/input/driver/hdf_touch.c 
  2. int32_t RegisterChipDevice(ChipDevice *chipDev) 
  3. … 
  4. /* 綁定設備與驅動,從而通過InputDeviceInstance函數創建inputDev */ 
  5.     DeviceBindDriver(chipDev); 
  6. … 
  7. /* 主要包含器件中斷注冊及中斷處理函數,處理函數中有數據上報用戶態的數據通道 */ 
  8. ChipDriverInit(chipDev); 
  9. … 
  10.     /* 申請內存實例化InputDev */ 
  11. inputDev = InputDeviceInstance(chipDev); 
  12.     … 
  13.     /* 將InputDev設備注冊至input驅動管理層 */ 
  14. RegisterInputDevice(inputDev); 
  15. … 

 函數具體實現代碼位置

  1. ./drivers/framework/model/input/driver/hdf_input_device_manager.c 
  2. int32_t RegisterInputDevice(InputDevice *inputDev) 
  3. … 
  4.     /* 申請ID,該ID對于不同input設備唯一 */ 
  5.     ret = AllocDeviceID(inputDev); 
  6. … 
  7. /* 該函數包含了對hid類設備的特殊處理,對于觸摸屏驅動,該函數無實質操作; */ 
  8.     CreateDeviceNode(inputDev); 
  9.     /* 內核態數據傳送至用戶態需使用IOService能力,需要申請buffer */ 
  10.     AllocPackageBuffer(inputDev); 
  11.     /* 將input設備添加進設備全局管理鏈表 */ 
  12.     AddInputDevice(inputDev); 
  13.     ··· 

TouchScreen器件驅動開發

基于 Input 模型適配一款觸摸屏 IC 需要完成的具體工作見下。

配置設備描述信息

驅動注冊到 HDF 框架所需要的設備驅動描述信息,如驅動是否加載以及加載次序等。

配置文件路徑:

  1. ./drivers/adapter/khdf/linux/hcs/device_info/device_info.hcs 

device_info.hcs 中的信息主要提供給 HDF 框架使用,包含了 Input 模型各層驅動注冊到 HDF 框架所必需的信息,開發者無特殊場景需求無需改動。各驅動層私有配置信息通過“deviceMatchAttr”字段與 input_config.hcs 中的“match_attr”相關內容進行匹配。

配置文件中與 input 模塊相關的內容如下所示

  1. input :: host { 
  2. hostName = "input_host"
  3. priority = 100; 
  4. device_input_manager :: device {       // Input管理層設備描述信息 
  5. device0 :: deviceNode { 
  6. policy = 2;                      // 向內核用戶態均發布服務 
  7. priority = 100;                   // input管理層驅動優先級默認為100 
  8. preload = 0;                     // 加載該驅動 
  9. permission = 0660;               // 驅動創建設備節點權限 
  10. moduleName = "HDF_INPUT_MANAGER"; // 與驅動入口moduleName匹配 
  11. serviceName = "hdf_input_host";  // HDF框架生成的節點名 
  12. deviceMatchAttr = "";         // manager目前不需要私有配置,因此為空 
  13. device_hdf_touch :: device {              // Input公共驅動層設備描述信息 
  14. device0 :: deviceNode { 
  15.         policy = 2;                     // 向內核用戶態均發布服務 
  16.         priority = 120;                 // input公共驅動優先級默認為120 
  17.         preload = 0;                   // 加載該驅動 
  18.         permission = 0660;             // 驅動創建設備節點權限 
  19.         moduleName = "HDF_TOUCH";   // 與驅動入口的moduleName匹配 
  20.         serviceName = "hdf_input_event1";  // HDF框架生成的節點名 
  21.         deviceMatchAttr = "touch_device1";  // 與 “match_attr”字段一致 
  22.     } 
  23. device_touch_chip :: device {              // Input器件驅動層信息 
  24.     device0 :: deviceNode { 
  25.         policy = 0;                    // 向內核用戶態均不發布服務 
  26.         priority = 130;                 // input器件驅動優先級默認為130 
  27.         preload = 0;                   // 加載該驅動 
  28.         permission = 0660;             // 驅動創建設備節點權限 
  29.         moduleName = "HDF_TOUCH_GT911";   // 與moduleName匹配 
  30.         serviceName = "hdf_touch_gt911_service"; // HDF框架節點名 
  31.         deviceMatchAttr = "zsj_gt911_5p5"; // 與“match_attr”字段一致 
  32.     } 

 該配置文件中需要重點關注的字段有:

“priority”決定驅動加載順序;

“preload”決定驅動是否加載;

“moduleName ”需要與驅動注冊入口處的“moduleName ”字段保持一致;

“serviceName ”HDF 框架依據該字段創建節點名;

“deviceMatchAttr ”需要與私有配置信息中的“match_attr”字段保持一致。

通過配置設備描述信息,使得 HDF 框架通過 moduleName 與注冊至驅動入口的代碼相匹配,保證了驅動的正常加載,通過 priority 字段保證了各驅動的加載順序。

配置Touchscreen器件信息

器件私有信息包括上下電時序等,平臺硬件信息包括器件連接主板的 GPIO 端口信息等。

配置文件路徑:

  1. ./drivers/adapter/khdf/linux/hcs/input/input_config.hcs 

input_config.hcs 中的信息由驅動代碼進行讀取解析,主要由公共驅動層的私有配置信息及器件驅動層的私有配置信息組成。文件中的配置包含板級硬件信息及器件私有配置信息,實際業務開發時,可根據具體需求增刪及修改對應內容。

  1.  pinConfig { 
  2.               rstGpio = 3;      // 復位管腳連接主機芯片的3號管腳 
  3.               intGpio = 4;     // 中斷管腳連接主機芯片的4號管腳 
  4.               rstRegCfg = [0x112f0094, 0x400];   // 復位管腳配置信息 
  5.               intRegCfg = [0x112f0098, 0x400];  // 中斷管腳配置信息 
  6.           } 
  7.           powerConfig { 
  8.               /* 0:unused 1:ldo 2:gpio 3:pmic */ 
  9.               vccType = 2;             // GPIO供電 
  10.               vccNum = 20;            // gpio20 
  11.               vccValue = 1800;         // 電壓幅值為1800mV 
  12.               vciType = 1;             // LDO供電 
  13.               vciNum = 12;            // ldo12 
  14.               vciValue = 3300;         // 電壓幅值為3300mV  
  15.           } 
  16. featureConfig { 
  17.               capacitanceTest = 0;      // 容值測試 
  18.               gestureMode = 0;        // 手勢模式 
  19.               gloverMode = 0;         // 手套模式 
  20.               coverMode = 0;          // 皮套模式 
  21.               chargerMode = 0;        // 充電模式 
  22.               knuckleMode = 0;        // 指關節模式 
  23.           } 
  24.       } 
  25.       chipConfig {                    // 器件私有信息配置 
  26.           template touchChip {        // 模板 
  27.               match_attr = ""
  28.               chipName = "gt911";    // 觸摸屏IC型號 
  29.               vendorName = "zsj";    // 供應商 
  30.               chipInfo = "AAAA11222";     
  31.  /*1~4字符代表產品名,5~6字符代表IC型號,7~9字符代表模型型號*/ 
  32.               busType = 0;            // 0代表I2C,1代表SPI 
  33.               deviceAddr = 0x5D;      // 器件IC通信地址 
  34. /* 1代表上升沿觸發,2代表下降沿觸發,4代表高電平觸發,8代表低電平觸發*/ 
  35.               irqFlag = 2;                
  36.               maxSpeed = 400;        // 最大通信速率為400Hz 
  37.               chipVersion = 0;         // 觸摸屏IC版本號 
  38. powerSequence { 
  39. /* 上電時序的配置含義說明: [類型, 狀態, 方向 , 延時] 
  40. <type> 0代表空,1代表vcc電源1.8V,2代表VCI電源3.3V, 
  41. 3代表復位管腳,4代表中斷管腳 
  42.  <status> 0代表下電或拉低,1代表上電或拉高,2代表無操作 
  43. <dir> 0代表輸入方向,1代表輸出方向,2代表無操作 
  44. <delay> 代表延時多少毫秒, 例如20代表延時20ms 
  45.  */ 
  46. powerOnSeq = [4, 0, 1, 0,    // 中斷管腳配置為輸出,且進行拉低 
  47.              3, 0, 1, 10,   // 復位管腳配置為輸出,且進行拉低,延時10ms 
  48.              3, 1, 2, 60,   // 復位管腳無操作,且進行拉高,延時60ms 
  49.              4, 2, 0, 0];   // 中斷管腳配置為輸入 
  50. suspendSeq = [3, 0, 2, 10];   // 復位管腳無操作,且進行拉低,延時10ms 
  51. resumeSeq = [3, 1, 2, 10];    // 復位管腳無操作,且進行拉高,延時10ms 
  52. powerOffSeq = [3, 0, 2, 10,   // 復位管腳無操作,且進行拉低,延時10ms 
  53.              1, 0, 2, 20];   // 電源正極管腳無操作,且進行拉低,延時20ms 
  54. chip0 :: touchChip { 
  55. /* 與設備描述配置信息中器件私有配置信息的“match_attr”字段保持一致 */ 
  56.           match_attr = "zsj_gt911_5p5";    
  57. /* 產品名+模組編號+芯片編號的組合信息 用于給用戶態區分當前器件 */             
  58.           chipInfo = "ZIDN45100";     
  59. /*  IC型號的版本 */               
  60.           chipVersion = 0;            
  61.                 } 
  62.             } 
  63.         } 
  64.     } 

示例中“touchConfig”包含了“touch0”,"touch0"包含了“boardConfig”與“chipConfig”;“boardConfig”字段包含了 Hi3516DV300 板級硬件信息,“chipConfig”包含了觸摸屏器件的私有信息,如果需要替換觸摸屏器件,重新配置“chipConfig”對應的字段信息即可。同時產品可以配置多款觸摸屏,示例中用“touch0”代表了套件中默認的觸摸屏的硬件接口以及器件的配置信息,如產品需要配置副屏,可在與“touch0”并列的位置配置“touch1”的信息。

適配器件私有驅動

Input 模型對 Input 設備開發流程進行了抽象,開發者只需要適配器件驅動層,無需改動管理驅動層以及公共驅動層。

Input 模型由三層驅動組成,開發者適配一款全新觸摸屏驅動只需要適配器件驅動層即可,重點實現差異化接口,本小節以代碼示例的形式展示開發者需要重點完成的工作。

觸摸屏器件差異化接口適配

示例代碼路徑

  1. ./drivers/framework/model/input/driver/touchscreen/touch_gt911.c 
  2. static struct TouchChipOps g_gt911ChipOps = {     // 器件IC接口 
  3. .Init = ChipInit,                         // 初始化 
  4. .Detect = ChipDetect,                   // 器件檢測 
  5. .Resume = ChipResume,                 // 喚醒 
  6. .Suspend = ChipSuspend,                // 休眠 
  7. .DataHandle = ChipDataHandle,           // 器件數據讀取 
  8. .UpdateFirmware = UpdateFirmware,      // 固件升級 
  9. }; 
  10. /* 不同觸摸屏廠家使用的IC不一樣,對應的寄存器操作也不一樣,因此器件驅動層代碼重點適配差異化接口部分,如下示例代碼展示了GT911的數據解析*/ 
  11. static int32_t ChipDataHandle(ChipDevice *device) 
  12. ... 
  13. /*  GT911獲取坐標之前需先讀取狀態寄存器  */ 
  14. reg[0] = (GT_BUF_STATE_ADDR >> ONE_BYTE_OFFSET) & ONE_BYTE_MASK;  
  15. reg[1] = GT_BUF_STATE_ADDR & ONE_BYTE_MASK; 
  16. ret = InputI2cRead(i2cClient, reg, GT_ADDR_LEN, &touchStatus, 1); 
  17. if (ret < 0 || touchStatus == GT_EVENT_INVALID) { 
  18. return HDF_FAILURE; 
  19. ... 
  20. /* 根據狀態寄存器的值讀取數據寄存器數據 */ 
  21. reg[0] = (GT_X_LOW_BYTE_BASE >> ONE_BYTE_OFFSET) & ONE_BYTE_MASK; 
  22. reg[1] = GT_X_LOW_BYTE_BASE & ONE_BYTE_MASK; 
  23. pointNum = touchStatus & GT_FINGER_NUM_MASK; 
  24. if (pointNum == 0 || pointNum > MAX_SUPPORT_POINT) { 
  25. HDF_LOGE("%s: pointNum is invalid, %u", __func__, pointNum); 
  26.  (void)ChipCleanBuffer(i2cClient); 
  27. OsalMutexUnlock(&device->driver->mutex); 
  28. return HDF_FAILURE; 
  29. frame->realPointNum = pointNum; 
  30. frame->definedEvent = TOUCH_DOWN; 
  31. (void)InputI2cRead(i2cClient, reg, GT_ADDR_LEN, buf, GT_POINT_SIZE * pointNum); 
  32. /* 對獲取的數據進行解析 */ 
  33. ParsePointData(device, frame, buf, pointNum); 
  34. ... 
  35.  
  36. static void ParsePointData(ChipDevice *device, FrameData *frame, uint8_t *buf, uint8_t pointNum) 
  37.     ... 
  38. /* 每個坐標值由兩個字節組成,對獲取的單字節數據進行拼接得到最終的坐標值 */ 
  39. for (i = 0; i < pointNum; i++) { 
  40. frame->fingers[i].trackId = buf[GT_POINT_SIZE * i + GT_TRACK_ID]; 
  41. frame->fingers[i].y = (buf[GT_POINT_SIZE * i + GT_X_LOW] & ONE_BYTE_MASK) | ((buf[GT_POINT_SIZE * i + GT_X_HIGH] & ONE_BYTE_MASK) << ONE_BYTE_OFFSET); 
  42.         frame->fingers[i].x = (buf[GT_POINT_SIZE * i + GT_Y_LOW] & ONE_BYTE_MASK) | ((buf[GT_POINT_SIZE * i + GT_Y_HIGH] & ONE_BYTE_MASK) << ONE_BYTE_OFFSET); 
  43. /* 對解析出來的坐標值進行打印 */ 
  44.   HDF_LOGD("%s: x = %d, y = %d", __func__, frame->fingers[i].x, 
  45. frame->fingers[i].y); 

器件層驅動初始化及注冊驅動至HDF框架

示例代碼路徑

  1. ./drivers/framework/model/input/driver/touchscreen/touch_gt911.c 
  2. static int32_t HdfGoodixChipInit(struct HdfDeviceObject *device) 
  3.     ... 
  4. /* 器件配置結構體內存申請、配置信息解析及掛載 */ 
  5.     chipCfg = ChipConfigInstance(device); 
  6.     ... 
  7. /* 器件實例化 */ 
  8.     chipDev = ChipDeviceInstance(); 
  9.     ... 
  10.     /* 器件信息掛載及器件私有操作掛載 */ 
  11.     chipDev->chipCfg = chipCfg; 
  12.     chipDev->ops = &g_gt911ChipOps; 
  13.     ... 
  14.     /* 注冊器件驅動至平臺驅動 */ 
  15.     RegisterChipDevice(chipDev); 
  16.     ... 
  17. struct HdfDriverEntry g_touchGoodixChipEntry = { 
  18. .moduleVersion = 1, 
  19. /* 該moduleName與device_info.hcs文件中器件驅動層的moduleName信息相匹配*/ 
  20. .moduleName = "HDF_TOUCH_GT911",    
  21. .Init = HdfGoodixChipInit,           // 器件驅動初始化函數 
  22. }; 
  23. HDF_INIT(g_touchGoodixChipEntry);      // 注冊器件驅動至HDF框架 

器件私有驅動層主要實現了各器件廠商差異較大的部分,如器件休眠喚醒、數據解析以及固件升級等。

編譯入口添加

編輯 Makefile 文件,添加本示例中的內容:

文件路徑:

  1. ./drivers/adapter/khdf/linux/model/input/Makefile 

添加內容如下:

  1. obj-$(CONFIG_DRIVERS_HDF_TP_5P5_GT911) += \ 
  2. $(INPUT_ROOT_DIR)/touchscreen/touch_gt911.o 

其中 touch_gt911.o 為本示例中追加的內容

至此,基于 HDF 框架及 Input 模型的觸摸屏驅動適配完成。

總結

本文梳理了 HDF_Input 模型工作流程,重點介紹了器件驅動適配,以 Hi3516dv300 開發板觸屏為例進行了詳細的代碼說明,希望通過本文檔您能初步掌握基于 HDF 框架的 Input 設備的開發步驟與流程。

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

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

https://harmonyos.51cto.com

 

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

2021-09-10 15:10:50

鴻蒙HarmonyOS應用

2021-09-07 15:48:28

鴻蒙HarmonyOS應用

2023-09-14 15:49:42

PWM鴻蒙

2023-09-06 15:35:14

2022-04-20 20:28:40

HDF 驅動框架鴻蒙操作系統

2022-04-01 15:18:04

HarmonyHDF 驅動鴻蒙

2021-09-08 15:09:29

鴻蒙HarmonyOS應用

2023-09-13 15:33:57

I2C鴻蒙

2023-03-20 16:05:49

HDF傳感器驅動開發

2022-10-17 14:29:24

鴻蒙應用開發

2022-08-08 19:35:37

HDF驅動開發鴻蒙

2023-03-21 18:06:49

ADC數字轉換器

2022-05-16 11:50:45

HDF驅動框架

2021-11-26 15:34:27

鴻蒙HarmonyOS應用

2023-06-26 16:13:43

馬達驅動模型鴻蒙

2021-12-15 10:02:25

鴻蒙HarmonyOS應用

2022-09-05 15:18:23

HDF單鏈表嵌入式系統

2023-08-17 15:01:08

ArkUI布局渲染

2021-11-30 14:52:41

鴻蒙HarmonyOS應用

2023-03-16 15:18:16

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 精品久久影院 | 精品一区二区三区91 | 久久精品视频在线观看 | 久久久久久一区 | 欧美一区二区三区在线看 | 精品1区2区3区 | 日韩中文字幕一区二区 | 久久av影院| 亚洲国产精品自拍 | 精品国产一二三区 | 精品久久久久一区二区国产 | 91亚洲国产 | 老头搡老女人毛片视频在线看 | 日韩一区二区三区四区五区六区 | 中文字幕1区2区3区 亚洲国产成人精品女人久久久 | 综合一区二区三区 | 精品日韩一区 | 精品国产一区二区三区久久狼黑人 | 午夜av一区二区 | 盗摄精品av一区二区三区 | 久久国产精品偷 | 精品欧美一区二区三区久久久 | 精品欧美黑人一区二区三区 | 玩丰满女领导对白露脸hd | 成人av大全 | 成人免费淫片aa视频免费 | 91网站在线播放 | 四虎永久免费黄色影片 | 日本欧美在线 | 亚洲欧美精品国产一级在线 | 福利色导航 | 国产一区二区三区久久久久久久久 | 中文字幕第一页在线 | 色综合久久天天综合网 | 国产成人精品av | 婷婷综合| 黑人巨大精品欧美一区二区免费 | 久久午夜剧场 | 91视频在线看| 男女网站在线观看 | 精品久久久久久久久久久久久久 |