1# Standard System Solution – Yangfan Porting Case 2 3This document describes how to port standard system functions based on the yangfan development board of the RK3399 chip from Rockchip. The porting processing mainly includes product configuration adding, kernel startup and upgrade, ADM-based conversion of audio, case summary of the camera, TP, LCD, Wi-Fi, BT, vibrator, sensor, and graphics display modules, as well as related function adaptation. 4The development board system porting uses the solution where the board warehouse and SoC code are separated. The board warehouse stores adaptation code of on-board modules, such as audio, camera, TP, and Wi-Fi. The SoC warehouse stores adaptation codes of SoC driver modules, such as I2C, ISP, and RGA. 5 6## Product Configuration and Directory Planning 7 8### Product Configuration 9 10Create a **config.json** file in the `//vendor/yangfan` directory of the product and specify the CPU architecture. Configuration of `//vendor/yangfan/rk3399.json` is as follows: 11 12``` 13{ 14 "product_name": "yangfan",--- Product name: yangfan 15 "device_company": "rockchip",--- Board vendor: Rockchip 16 "device_build_path": "device/board/isoftstone/yangfan",--- Device building path: device/board/isoftstone/yangfan 17 "target_cpu": "arm",--- Target CPU: arm 18 "type": "standard",--- OS type: standard 19 "version": "3.0",--- Version: 3.0 20 "board": "yangfan",--- Board name: yangfan 21 "enable_ramdisk": true,--- Enable memory virtual disk: true 22 "build_selinux": true,--- Build selinux: true 23 "inherit": [ "productdefine/common/inherit/rich.json", "productdefine/common/inherit/chipset_common.json" ], 24 "subsystems": [ 25 { 26 "subsystem": "security", 27 "components": [ 28 { 29 "component": "selinux", 30 "features": [] 31 } 32 ] 33 }, 34 { 35 "subsystem": "communication", 36 "components": [ 37 { 38 "component": "netmanager_ext", 39 "features": [] 40 } 41 ] 42 }, 43 ... 44} 45``` 46 47 48The main configurations are as follows: 49 501. "product_name": "yangfan",--- Product name: yangfan 512. "device_company": "rockchip",--- Board vendor: Rockchip 523. "device_build_path": "device/board/isoftstone/yangfan",--- Device building path: device/board/isoftstone/yangfan 534. "target_cpu": "arm",--- Target CPU: arm 545. "type": "standard",--- OS type: standard 556. "version": "3.0",--- Version: 3.0 567. "board": "yangfan",--- Board name: yangfan 578. "enable_ramdisk": true,--- Enable memory virtual disk: true 58 59You can find defined subsystems in `//build/subsystem_config.json`. You can also customize subsystems. 60 61You are advised to copy the configuration file of Hi3516DV300 and delete the **hisilicon_products** subsystem, which is used to compile the kernel for Hi3516DV300 and is not suitable for RK3568. 62 63### Directory Planning 64 65This solution designs the directory structure using the [board and SoC decoupling idea](https://gitee.com/openharmony-sig/sig-content/blob/master/devboard/docs/board-soc-arch-design.md), and plans the SoC adaptation directory as follows: 66 67``` 68device 69├── board --- Board vendor directory 70│ └── isoftstone --- Board vendor 71│ └── yangfan --- Board name: yangfan 72└── soc --- SoC vendor directory 73 └── rockchip --- SoC vendor: Rockchip 74 └── rk3399 --- SoC series: RK3399, mainly solutions provided by the SoC manufacturer and closed-source libraries 75 76 77``` 78The planned product demo directory is as follows: 79``` 80vendor 81└── isoftstone 82 └── yangfan --- Product name: product, HCS, and demo related 83``` 84 85## **Kernel Startup** 86 87### Secondary Boot 88 89Unlike traditional boot that directly mounts **system** and boots using **init** of **system**, secondary boot is to mount **ramdsik**, boot using **init** of **ramdsik**, perform necessary initialization operations (such as mounting the **system** and **vendor** partitions, and then switch to **init** of **system**. 90 91RK3399 adaptation is to pack **ramdisk** compiled in the mainline version into **boot_linux.img**. The procedure is as follows: 92 931. Enable secondary boot. 94 95Enable **enable_ramdisk** in **//vendor/yangfan/rk3399.json**. 96 97 ``` 98 { 99 "product_name": "yangfan", 100 "device_company": "rockchip", 101 "device_build_path": "device/board/isoftstone/yangfan", 102 "target_cpu": "arm", 103 "type": "standard", 104 "version": "3.0", 105 "board": "yangfan", 106 "enable_ramdisk": true, 107 "build_selinux": true, 108 ... 109 } 110 ``` 111 1122. Pack the **ramdsik.img** file compiled in the mainline version to **boot_linux.img**. 113 114Configuration: 115 116RK supports **uboot** from **ramdisk**. You only need to add **ramdisk.img** to the configuration file of the packed **boot_linux.img**. Therefore, the **its** format of the mainline version is not used. Specifically, add the following content to the kernel compilation script **make-ohos.sh**: 117 118``` 119function make_extlinux_conf() 120{ 121 dtb_path=$1 122 uart=$2 123 image=$3 124 125 echo "label rockchip-kernel-5.10" > ${EXTLINUX_CONF} 126 echo " kernel /extlinux/${image}" >> ${EXTLINUX_CONF} 127 echo " fdt /extlinux/${TOYBRICK_DTB}" >> ${EXTLINUX_CONF} 128 if [ "enable_ramdisk" == "${ramdisk_flag}" ]; then 129 echo " initrd /extlinux/ramdisk.img" >> ${EXTLINUX_CONF} 130 fi 131 cmdline="append earlycon=uart8250,mmio32,${uart} root=PARTUUID=614e0000-0000-4b53-8000-1d28000054a9 rw rootwait rootfstype=ext4" 132 echo " ${cmdline}" >> ${EXTLINUX_CONF} 133} 134``` 135 136### Packing 137 138Add the **make-boot.sh** script for packing the boot image. This script can be called when the boot image is packed after **ramdisk** is compiled. The main content is as follows: 139 140``` 141genext2fs -B ${blocks} -b ${block_size} -d boot_linux -i 8192 -U boot_linux.img 142``` 143 144For details about modification for calling **make-boot.sh**, see [RK3568 adaptation to secondary boot]( https://gitee.com/openharmony/build/pulls/569/files). 145 146### INIT Configuration 147 148For details about the init configuration, see [Startup Subsystem](https://gitee.com/openharmony/docs/blob/master/zh-cn/readme/%E5%90%AF%E5%8A%A8%E6%81%A2%E5%A4%8D%E5%AD%90%E7%B3%BB%E7%BB%9F.md). 149 150## **Audio** 151 152### Introduction 153 154This section describes how to develop the audio driver framework based on the Hardware Driver Foundation (HDF) in OpenHarmony 3.0, including detailed introduction to the composition of the audio driver framework, functional component implementation, and service nodes. 155 156![Audio driver framework](figures/isoftstone/yangfan-Audio-ADM.png) 157 1581. Audio Driver Model (ADM) 159 160 The ADM helps system developers to develop scenario-specific applications for the multimedia audio subsystem. With the ADM, codec and DSP device vendors can adapt their driver code based on the APIs provided by the ADM and implement quick development and easy adaptation to HarmonyOS. 161 1622. Audio Control Dispatch 163 164 The Audio Control Dispatch dispatches the control instructions from the Audio Interface Lib to the driver layer. 165 1663. Audio Stream Dispatch 167 168 The Audio Control Dispatch receives data streams from the Audio Interface Lib and distributes the data streams to the driver layer. 169 1704. Card Manager 171 172 The Card Manager manages multiple audio adapters. Each audio adapter consists of the digital audio interface (DAI), platform, codec, accessory, DSP, and Smart Audio Power Manager (SAPM) modules. 173 1745. Platform Driver 175 176 The Platform Driver is the driver adaptation layer. 177 1786. Smart Audio Power Manager (SAPM) 179 180 The SAPM is the power manager module that optimizes the power consumption policies of the entire ADM power. 181 182### Audio Driver Introduction 183 184#### Code Directory 185 186``` 187drivers 188 ├── framework 189 │ └── model 190 │ │ └── audio # Framework code 191 │ │ ├─── common # Common implementation 192 │ │ ├─── core # Core 193 │ │ ├─── dispatch # Control stream and data stream implementation 194 │ │ └── sapm # Power manager 195 │ └── include 196 │ └── audio # External API 197 ├── adapter 198 │ └──khdf 199 │ └── linux 200 │ └── model 201 │ └── audio # Compilation file 202 └── peripheral 203 └── audio 204 └── chipsets 205 └── rk3399 # Driver implementation 206 ├── accessory #SmartPA driver 207 ├── dai #I2S driver 208 └── soc #Dma driver 209``` 210 211#### Audio Process Description 212 213##### Startup Process 214 215![](figures/isoftstone/yangfan-Audio-start.png) 216 2171. When the system starts, the platform, codec, accessory, DSP, and DAI drivers of the audio module are loaded first. Each driver obtains the configuration information from its configuration file and saves the obtained information to the data structures. 2182. Each driver module calls the ADM registration interface to add itself to the linked list of the driver module. 2193. The ADM module reads configurations of hdf_audio_driver_0 (audio card_0) and hdf_audio_driver_1 (audio card_1), and loads specific devices of each module. 2204. The ADM module initializes each module device by calling the initialization API of the respective module. 2215. The initialized audio devices are added to the **cardManager** linked list. 222 223##### Playback Process 224 225![](figures/isoftstone/yangfan-Audio-play.png) 226 2271. The Interface Lib dispatches the **Render Open** instruction through the service launched by the driver for handling the playback streaming (referred to as driver service hereinafter). Upon receiving the instruction, the Stream Dispatch service calls the API of each module to deliver the instruction. 2282. The Audio Interface Lib sends a path selection instruction to the Control Dispatch service. The Control Dispatch service calls the DAI API to set the path. 2293. The Interface Lib dispatches hardware parameters through the driver service. Upon receiving the parameters, the Stream Dispatch service calls the API of each module to set hardware parameters. 2304. The Interface Lib dispatches the start playing instruction through the driver service. Upon receiving the instruction, the Stream Dispatch service calls the API of each module to perform related settings for each module. 2315. The Interface Lib dispatches audio data through the driver service. Upon receiving the data, the Stream Dispatch service calls the **Platform AudioPcmWrite** API to send the audio data to direct memory access (DMA). 2326. The Interface Lib dispatches the stop playing instruction through the driver service. Upon receiving the instruction, the Stream Dispatch service calls the stop API of each module to perform related settings for each module. 2337. The Interface Lib dispatches the **Render Close** instruction through the driver service. Upon receiving the instruction, the Stream Dispatch service calls the **Platform AudioRenderClose** API to release resources. 234 235##### Control Process 236 237![](figures/isoftstone/yangfan-Audio-commond.png) 238 2391. To adjust the volume, the Audio Interface Lib sends an instruction for obtaining the volume range to the Control Dispatch service. The Control Dispatch service parses the instruction and calls **get()** of the codec module to obtain the volume range. 2402. The Audio Interface Lib sends an instruction for setting the volume to the Control Dispatch service. The Control Dispatch service parses the instruction and calls **Set()** of the codec module to set the volume. 241 242#### Implementation Description 243 2441. Driver registration 245 246 Take the registration function of codec as an example. When the codec driver is initialized, the following codec registration function is called to register codec with the **codecController** linked list. 247 248 ```c 249 int32_t AudioRegisterCodec(struct HdfDeviceObject *device, struct CodecData *codecData, struct DaiData *daiData) 250 { 251 ... 252 253 codec = (struct CodecDevice *)OsalMemCalloc(sizeof(*codec)); 254 ... 255 256 OsalMutexInit(&codec->mutex); 257 codec->devCodecName = codecData->drvCodecName; 258 codec->devData = codecData; 259 codec->device = device; 260 261 ret = AudioSocRegisterDai(device, daiData); 262 ... 263 DListInsertHead(&codec->list, &codecController); 264 ... 265 } 266 ``` 267 2682. Data stream data distribution 269 270 During audio recording or playback, the Lib layer distributes or reads data using Dispatch. After receiving the request from the Lib layer, the API distributes or returns the data. 271 272 ```c 273 static int32_t StreamDispatch(struct HdfDeviceIoClient *client, int cmdId, 274 struct HdfSBuf *data, struct HdfSBuf *reply) 275 { 276 unsigned int count = sizeof(g_streamDispCmdHandle) / sizeof(g_streamDispCmdHandle[0]); 277 for (unsigned int i = 0; i < count; ++i) { 278 if ((cmdId == (int)(g_streamDispCmdHandle[i].cmd)) && (g_streamDispCmdHandle[i].func != NULL)) { 279 return g_streamDispCmdHandle[i].func(client, data, reply); 280 } 281 } 282 ADM_LOG_ERR("invalid [cmdId=%d]", cmdId); 283 return HDF_FAILURE; 284 } 285 ``` 286 2873. Control function registration API 288 289 Control functions such as volume control, gain control, and channel control are added to the audio adapter control list using this API. 290 291 ```c 292 int32_t AudioAddControls(struct AudioCard *audioCard, const struct AudioKcontrol *controls, int32_t controlMaxNum) 293 { 294 ... 295 296 for (i = 0; i < controlMaxNum; i++) { 297 control = AudioAddControl(audioCard, &controls[i]); 298 if (control == NULL) { 299 ADM_LOG_ERR("Add control fail!"); 300 return HDF_FAILURE; 301 } 302 DListInsertHead(&control->list, &audioCard->controls); 303 } 304 ADM_LOG_DEBUG("Success."); 305 return HDF_SUCCESS; 306 } 307 ``` 308 3094. Power management API 310 311 Add component implementation: 312 313 ```c 314 int32_t AudioSapmNewComponents(struct AudioCard *audioCard, 315 const struct AudioSapmComponent *component, int32_t cptMaxNum) 316 { 317 ... 318 319 for (i = 0; i < cptMaxNum; i++) { 320 ret = AudioSapmNewComponent(audioCard, component); 321 if (ret != HDF_SUCCESS) { 322 ADM_LOG_ERR("AudioSapmNewComponent fail!"); 323 return HDF_FAILURE; 324 } 325 component++; 326 } 327 328 return HDF_SUCCESS; 329 } 330 331 ``` 332 333 Add channel implementation: 334 335 ```c 336 337 int32_t AudioSapmAddRoutes(struct AudioCard *audioCard, const struct AudioSapmRoute *route, int32_t routeMaxNum) 338 { 339 ... 340 341 for (i = 0; i < routeMaxNum; i++) { 342 ret = AudioSapmAddRoute(audioCard, route); 343 if (ret != HDF_SUCCESS) { 344 ADM_LOG_ERR("AudioSapmAddRoute failed!"); 345 return HDF_FAILURE; 346 } 347 route++; 348 } 349 return HDF_SUCCESS; 350 } 351 352 ``` 353 354 Add control function implementation: 355 356 ```c 357 358 int32_t AudioSapmNewControls(struct AudioCard *audioCard) 359 { 360 ... 361 362 DLIST_FOR_EACH_ENTRY(sapmComponent, &audioCard->components, struct AudioSapmComponent, list) { 363 if (sapmComponent->newCpt) { 364 continue; 365 } 366 if (sapmComponent->kcontrolsNum > 0) { 367 sapmComponent->kcontrols = OsalMemCalloc(sizeof(struct AudioKcontrol*) * sapmComponent->kcontrolsNum); 368 if (sapmComponent->kcontrols == NULL) { 369 ADM_LOG_ERR("malloc kcontrols fail!"); 370 return HDF_FAILURE; 371 } 372 } 373 374 switch (sapmComponent->sapmType) { 375 case AUDIO_SAPM_ANALOG_SWITCH: 376 case AUDIO_SAPM_MIXER: 377 case AUDIO_SAPM_MIXER_NAMED_CTRL: 378 case AUDIO_SAPM_SPK: 379 case AUDIO_SAPM_PGA: 380 ret = AudioSapmNewMixerControls(sapmComponent, audioCard); 381 break; 382 case AUDIO_SAPM_MUX: 383 case AUDIO_SAPM_VIRT_MUX: 384 case AUDIO_SAPM_VALUE_MUX: 385 ret = AudioSapmNewMuxControls(sapmComponent, audioCard); 386 break; 387 default: 388 ret = HDF_SUCCESS; 389 break; 390 } 391 ... 392 393 ReadInitComponentPowerStatus(sapmComponent); 394 sapmComponent->newCpt = 1; 395 DListInsertTail(&sapmComponent->dirty, &audioCard->sapmDirty); 396 } 397 398 ret = AudioSapmPowerComponents(audioCard); 399 ... 400 401 return HDF_SUCCESS; 402 } 403 404 ``` 405 4065. Control stream data distribution 407 408 During audio recording or playback, the Lib layer delivers the control instruction using Dispatch. After receiving the instruction, the API distributes the instruction to each driver module. 409 410 ```c 411 static int32_t ControlDispatch(struct HdfDeviceIoClient *client, int cmdId, 412 struct HdfSBuf *data, struct HdfSBuf *reply) 413 { 414 ... 415 416 if (cmdId >= AUDIODRV_CTRL_IOCTRL_ELEM_BUTT || cmdId < 0) { 417 ADM_LOG_ERR("Invalid [cmdId=%d].", cmdId); 418 return HDF_FAILURE; 419 } 420 421 for (i = 0; i < HDF_ARRAY_SIZE(g_controlDispCmdHandle); ++i) { 422 if ((cmdId == (int)(g_controlDispCmdHandle[i].cmd)) && (g_controlDispCmdHandle[i].func != NULL)) { 423 return g_controlDispCmdHandle[i].func(client, data, reply); 424 } 425 } 426 return HDF_FAILURE; 427 } 428 ``` 429 430### Audio Service Introduction 431 432#### Service Node 433 434Three services are provided for the HDI layer based on the audio driver of the ADM framework: hdf_audio_render, hdf_audio_capture, and hdf_audio_control. 435The audio driver service nodes of the development board are as follows: 436 437``` 438console:/dev # ls -al hdf_audio_* 439crw------- 1 system system 249, 5 1970-01-01 00:21 hdf_audio_capture // Audio recording data stream service. 440crw------- 1 system system 249, 3 1970-01-01 00:21 hdf_audio_codec_dev0 // Audio device name. 441crw------- 1 system system 249, 4 1970-01-01 00:21 hdf_audio_control // Audio control stream service. 442crw------- 1 system system 249, 6 1970-01-01 00:21 hdf_audio_render // Playback data stream service. 443``` 444 4451. Audio control stream service 446 447 This service receives control instructions from the Lib layer, including the volume control, gain control, and channel control instructions. These control instructions are distributed to the driver through the control stream service. 448 4492. Audio data playback service 450 451 This service receives audio data and playback parameters from the Lib layer, as well as instructions for starting, pausing, resuming, and stopping the playback. These instructions are distributed to the driver through the audio data and playback service. 452 4533. Audio recording service 454 455 This service transmits audio data to the Lib layer and receives audio recording parameters from the Lib layer, as well as receive instructions for starting, pausing, resuming, and stopping audio recording. These instructions are distributed to the driver through the audio recording service. 456 457#### Driver Service 458 459Each audio device includes the following services. 460 461| **hdf_audio_codec_dev0** | **Audio Device** | 462| ------------------------ | ---------------------- | 463| dma_service_0 | DMA driver service | 464| dai_service | CPU DAI driver service | 465| codec_service_0 | Codec driver service | 466| dsp_service_0 | (Optional) DSP driver service| 467 468| **hdf_audio_codec_dev1** | **Audio Device** | 469| ------------------------ | --------------------------------- | 470| dma_service_0 | DMA driver service | 471| dai_service | CPU DAI driver service | 472| codec_service_1 | Accessory driver service (SmartPA)| 473| dsp_service_0 | (Optional) DSP driver service | 474 475#### Code Path 476 477``` 478vendor/rockchip/rk3399/hdf_config/khdf 479├── audio # Audio private configuration file 480├── device_info 481| └── device_info.hcs # Device configuration file 482└── hdf.hcs # Reference the HCS configuration file 483``` 484 485#### Configuration Node Description 486 487Take the codec driver as an example. Add the codec node information to the **audio host** node in the **device_info.hcs** file. 488 489``` 490 audio :: host { 491 hostName = "audio_host"; 492 priority = 60; 493... 494 device_codec :: device { 495 device0 :: deviceNode { 496 policy = 1; 497 priority = 50; 498 preload = 0; 499 permission = 0666; 500 moduleName = "CODEC_ES8316"; 501 serviceName = "codec_service_0"; 502 deviceMatchAttr = "hdf_codec_driver"; 503 } 504 } 505... 506 } 507``` 508 509#### Driver Implementation 510 511Modify the driver file to implement the driver logic that is the same as that of **moduleName** of **device_info.hcs**. 512 513``` 514/* HdfDriverEntry implementations */ 515static int32_t Es8316DriverBind(struct HdfDeviceObject *device) 516{ 517... 518 return HDF_SUCCESS; 519} 520 521static int32_t Es8316DriverInit(struct HdfDeviceObject *device) 522{ 523... 524 return HDF_SUCCESS; 525} 526 527/* HdfDriverEntry definitions */ 528struct HdfDriverEntry g_es8316DriverEntry = { 529 .moduleVersion = 1, 530 .moduleName = "CODEC_ES8316", 531 .Bind = Es8316DriverBind, 532 .Init = Es8316DriverInit, 533 .Release = NULL, 534}; 535HDF_INIT(g_es8316DriverEntry); 536``` 537 538### Summary 539 540 A unified architecture is provided for audio development of OpenHarmony and unified APIs are provided for audio drivers of various platforms based on the ADM of the HDF framework. Audio drivers developed for one platform can be applied to multiple platforms, improving the development efficiency. This document briefly introduces the ADM to help developers develop their applications. 541 542## **Camera** 543 544### Introduction 545 546This section describes how to develop the audio driver framework based on the Hardware Driver Foundation (HDF) in OpenHarmony 3.0, including detailed introduction to the composition of the camera driver framework, functional component implementation, and service nodes. 547 548### Camera driver framework 549 550 OpenHarmony HDF camera driver module architecture 551 552![img](https://gitee.com/openharmony/drivers_peripheral/raw/master/camera/figures/logic-view-of-modules-related-to-this-repository_zh.png) 553 554The following uses the camera host as an example: 555 5561. HDI implementation: implements standard device APIs for OpenHarmony cameras. 5572. PipelineCorer: connects to the HDI implementation layer for control instruction and stream transfer, establishes data channels, and manages camera devices. 5583. Platform Adaptation: shields the differences between bottom-layer chips and OSs for multi-platform adaptation. 559 560According to analysis of the USB camera of RK3399E/T, Linux 4.19 is used as the kernel. The USB camera depends on the UVC of V4L2 under Linux. According to the architecture diagram, the HDF camera is compatible with the UVC of V4L2 under Linux. Therefore, you need to ensure that the USB and camera drivers required by the UVC are normal before debugging. 561 562 563### Camera Driver Introduction 564 565#### Configuration 566 567arch/arm64/configs/rockchip_linux_defconfig 568 569```c 570CONFIG_VIDEO_V4L2_SUBDEV_API=y 571CONFIG_MEDIA_USB_SUPPORT=y 572CONFIG_USB_VIDEO_CLASS=y 573``` 574 575#### Node Information 576 577Before inserting the USB camera: 578 579``` 580# ls -l dev/video* 581crw-rw---- 1 root root 81, 0 2013-01-18 10:59 dev/video0 582crw-rw---- 1 root root 81, 1 2013-01-18 10:59 dev/video1 583crw-rw---- 1 root root 81, 2 2013-01-18 10:59 dev/video2 584crw-rw---- 1 root root 81, 3 2013-01-18 10:59 dev/video3 585crw-rw---- 1 root root 81, 4 2013-01-18 10:59 dev/video4 586crw-rw---- 1 root root 81, 5 2013-01-18 10:59 dev/video5 587crw-rw---- 1 root root 81, 6 2013-01-18 10:59 dev/video6 588crw-rw---- 1 root root 81, 7 2013-01-18 10:59 dev/video7 589crw-rw---- 1 root root 81, 8 2013-01-18 10:59 dev/video8 590crw-rw---- 1 root root 81, 9 2013-01-18 10:59 dev/video9 591# 592``` 593 594After inserting the USB camera, add the **dev/video10** and **dev/video11** nodes. 595 596``` 597# ls -l dev/video* 598crw-rw---- 1 root root 81, 0 2013-01-18 10:59 dev/video0 599crw-rw---- 1 root root 81, 1 2013-01-18 10:59 dev/video1 600crw------- 1 root root 81, 10 2013-01-18 11:01 dev/video10 601crw------- 1 root root 81, 11 2013-01-18 11:01 dev/video11 602crw-rw---- 1 root root 81, 2 2013-01-18 10:59 dev/video2 603crw-rw---- 1 root root 81, 3 2013-01-18 10:59 dev/video3 604crw-rw---- 1 root root 81, 4 2013-01-18 10:59 dev/video4 605crw-rw---- 1 root root 81, 5 2013-01-18 10:59 dev/video5 606crw-rw---- 1 root root 81, 6 2013-01-18 10:59 dev/video6 607crw-rw---- 1 root root 81, 7 2013-01-18 10:59 dev/video7 608crw-rw---- 1 root root 81, 8 2013-01-18 10:59 dev/video8 609crw-rw---- 1 root root 81, 9 2013-01-18 10:59 dev/video9 610# 611``` 612 613#### Opening a Device Node 614 615In the code environment of OpenHarmony, compile the following code as an executable program and execute the program on the development board. The node is opened successfully if no error is reported. 616 617```c 618#include <stdio.h> 619#include <sys/types.h> 620#include <sys/stat.h> 621#include <fcntl.h> 622#include <stdlib.h> 623#include <unistd.h> 624#include <sys/ioctl.h> 625#include <linux/videodev2.h> 626#include <string.h> 627#include <sys/mman.h> 628 629int main(void) 630{ 631 // 1. Open the device. 632 int fd = open("/dev/video10", O_RDWR); 633 if (fd < 0) { 634 printf("open device fail\n"); 635 return -1; 636 } 637 638 close(fd); 639 return 0; 640} 641``` 642 643#### Obtaining Parameters 644 645```c 646#include <stdio.h> 647#include <sys/types.h> 648#include <sys/stat.h> 649#include <fcntl.h> 650#include <stdlib.h> 651#include <unistd.h> 652#include <sys/ioctl.h> 653#include <linux/videodev2.h> 654#include <string.h> 655#include <sys/mman.h> 656 657int main(void) 658{ 659 // 1. Open the device. 660 int fd = open("/dev/video10", O_RDWR); 661 if (fd < 0) { 662 printf("open device fail\n"); 663 return -1; 664 } 665 666 // 2. Obtain the format ioctl (file descriptor, command, and structure corresponding to the command) supported by the camera. 667 struct v4l2_fmtdesc v4fmt; 668 v4fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 669 int i = 0; 670 while(1) { 671 v4fmt.index = i++; 672 int ret = ioctl(fd, VIDIOC_ENUM_FMT, &v4fmt); 673 if (ret < 0) { 674 printf("get fmt fail\n"); 675 } 676 unsigned char *p = (unsigned char*)&v4fmt.pixelformat; 677 printf("index=%d\n", v4fmt.index); 678 printf("flags=%d\n", v4fmt.flags); 679 printf("description=%s\n", v4fmt.description); 680 printf("pixelformat=%c%c%c%c\n", p[0], p[1], p[2], p[3]); 681 printf("reserved=%d\n", v4fmt.reserved[0]); 682 } 683 684 close(fd); 685 return 0; 686} 687``` 688 689In the code environment of OpenHarmony, compile the preceding code as an executable program and execute the program on the development board. The result shows that the YUYV and MJPEG formats are supported. 690 691 index=0 692 flags=0 693 description=YUYV 4:2:2 694 pixelformat=YUYV 695 reserved=0 696 697 index=1 698 flags=1 699 description=Motion-JPEG 700 pixelformat=MJPG 701 reserved=0 702#### Setting the Buffer Queue 703 704```c 705#include <stdio.h> 706#include <sys/types.h> 707#include <sys/stat.h> 708#include <fcntl.h> 709#include <stdlib.h> 710#include <unistd.h> 711#include <sys/ioctl.h> 712#include <linux/videodev2.h> 713#include <string.h> 714#include <sys/mman.h> 715 716int main(void) 717{ 718 // 1. Open the device. 719 int fd = open("/dev/video10", O_RDWR); 720 if (fd < 0) { 721 printf("open device fail\n"); 722 return -1; 723 } 724 725 // 2. Set the collection format. 726 struct v4l2_format vfmt; 727 vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 728 vfmt.fmt.pix.width = 640; 729 vfmt.fmt.pix.height = 480; 730 vfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; // Set the video capture format (which must be the same as the one obtained above). 731 int ret = ioctl(fd, VIDIOC_S_FMT, &vfmt); // Set the format. 732 if (ret < 0) { 733 printf("set fmt fail\n"); 734 return -1; 735 } 736 memset(&vfmt, 0, sizeof(vfmt)); 737 vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 738 ret = ioctl(fd, VIDIOC_G_FMT, &vfmt); // Obtain the format. 739 if (ret < 0) { 740 printf("set->get fmt fail\n"); 741 return -1; 742 } 743 744 // 3. Apply for the kernel buffer queue. 745 struct v4l2_requestbuffers reqbuffer; 746 reqbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 747 reqbuffer.count = 4; // Apply for four buffers. 748 reqbuffer.memory = V4L2_MEMORY_MMAP; // Memory mapping method: MMAP/USERPTR 749 ret = ioctl(fd, VIDIOC_REQBUFS, &reqbuffer); // Allocate memory. 750 if (ret < 0) { 751 printf("req buffer fail\n"); 752 return -1; 753 } 754 755 // 4. Stop the device. 756 close(fd); 757 return 0; 758} 759``` 760 761In the code environment of OpenHarmony, compile the preceding code as an executable program and execute the program on the development board. 762 763Execution result: **req buffer fail** 764 765Cause analysis: ioctl(fd, VIDIOC_REQBUFS, &reqbuffer); failure 766 767Troubleshooting method 1: Add logs to the kernel to locate the position where **VIDIOC_REQBUFS** fails. After the **ioctl** command is delivered, the **video_usercopy** API in **drivers/media/v4l2-core/v4l2-ioctl.c** will be used. However, the specific failure cause is still not found. 768 769Troubleshooting method 2: Contact Smart Device Tech to check whether the USB camera of the debian version of the Linux 4.19 kernel works properly. Result: After using the **gst-launch-1.0 v4l2src device=/dev/video10 ! image/jpeg, width= 1280, height=720, framerate=30/1 ! jpegparse ! mppjpegdec ! kmssink sync=false** command in the debian version, the HDMI screen can display the preview image properly. 770 771Through the preceding operations, you can determine that the UVC driver of V4L2 under Linux and the external USB camera driver work properly. Next, you need to debug the HDF camera of OpenHarmony. 772 773#### API Introduction 774 775Check the camera-related executable programs in OpenHarmony: **ohos_camera_demo** and **v4l2_main**. 776 777##### ohos_camera_demo 778 779Execution result: After you enter **o**, no preview image is displayed and no error logs are recorded. 780 781``` 782# ohos_camera_demo 783GetUintParameter debug.bytrace.tags.enableflags error. 784Options: 785-h | --help Print this message 786-o | --offline stream offline test 787-c | --capture capture one picture 788-w | --set WB Set white balance Cloudy 789-v | --video capture Viedeo of 10s 790-a | --Set AE Set Auto exposure 791-f | --Set Flashlight Set flashlight ON 5s OFF 792-q | --quit stop preview and quit this app 793o 794Options: 795-h | --help Print this message 796-o | --offline stream offline test 797-c | --capture capture one picture 798-w | --set WB Set white balance Cloudy 799-v | --video capture Viedeo of 10s 800-a | --Set AE Set Auto exposure 801-f | --Set Flashlight Set flashlight ON 5s OFF 802-q | --quit stop preview and quit this app 803 804``` 805 806Cause analysis: Currently, **ohos_camera_demo** supports only MPP and does not support V4L2. Therefore, the debugging of this demo is canceled. 807 808##### v4l2_main 809 810Execution result: After you enter **u**, error message **ERROR:main test:cannot open framebuffer /dev/fb0 file node** is displayed. 811 812``` 813Options: 814-h | --help Print this message 815-p | --preview start preview on platform sensor 816-c | --capture capture one picture 817-w | --set WB Set white balance Cloudy 818-e | --Set AE Set exposure time 819-v | --video capture Viedeo of 10s 820-u | --uvc start preview on uvc preview 821-a | --Set ATE Set Auto exposure 822-q | --quit stop preview and quit this app 823INFO:please input command(input -q exit this app) 824 825u 826ERROR:main test:cannot open framebuffer /dev/fb0 file node 827 828INFO:V4L2OpenDevice /dev/video10 829``` 830 831Cause analysis: Check whether the **dev/fb0** node exists. The **fb0** node does not exist. Check whether there are other **fb0** nodes in the root directory. The **dev/graphics/fb0** node exists. 832 833``` 834# ls -l dev/fb0 835ls: dev/fb0: No such file or directory 836 837# find -name fb0 838./dev/graphics/fb0 839./sys/class/graphics/fb0 840./sys/devices/platform/display-subsystem/graphics/fb0 841``` 842 843You need to change **dev/fb0** in the executable program **v4l2_main** to **dev/graphics/fb0**. Here, **fb0** is **framebuffer**, which is used to display the preview image on the screen. 844 845Modification: drivers/peripheral 846 847```diff 848diff --git a/camera/hal/adapter/platform/v4l2/src/driver_adapter/main_test/v4l2_main.cpp b/camera/hal/adapter/platform/v4l2/src/driver_adapter/main_test/v4l2_main.cpp 849index b351f49..d9c4cb3 100755 850--- a/camera/hal/adapter/platform/v4l2/src/driver_adapter/main_test/v4l2_main.cpp 851+++ b/camera/hal/adapter/platform/v4l2/src/driver_adapter/main_test/v4l2_main.cpp 852@@ -186,9 +186,9 @@ RetCode FBInit() 853 if (g_fbFd) 854 return RC_OK; 855 856- g_fbFd = open("/dev/fb0", O_RDWR); 857+ g_fbFd = open("/dev/graphics/fb0", O_RDWR); 858 if (g_fbFd < 0) { 859- CAMERA_LOGE("main test:cannot open framebuffer %s file node\n", "/dev/fb0"); 860+ CAMERA_LOGE("main test:cannot open framebuffer %s file node\n", "/dev/graphics/fb0"); 861 return RC_ERROR; 862 } 863 864diff --git a/camera/hal/test/v4l2/src/test_display.cpp b/camera/hal/test/v4l2/src/test_display.cpp 865index db908e7..7025deb 100644 866--- a/camera/hal/test/v4l2/src/test_display.cpp 867+++ b/camera/hal/test/v4l2/src/test_display.cpp 868@@ -114,9 +114,9 @@ void TestDisplay::FBLog() 869 870 RetCode TestDisplay::FBInit() 871 { 872- fbFd_ = open("/dev/fb0", O_RDWR); 873+ fbFd_ = open("/dev/graphics/fb0", O_RDWR); 874 if (fbFd_ < 0) { 875- CAMERA_LOGE("main test:cannot open framebuffer %s file node\n", "/dev/fb0"); 876+ CAMERA_LOGE("main test:cannot open framebuffer %s file node\n", "/dev/graphics/fb0"); 877 return RC_ERROR; 878 } 879 880@@ -439,4 +439,4 @@ void TestDisplay::StopStream(std::vector<int>& captureIds, std::vector<int>& str 881 std::cout << "==========[test log]check Capture: ReleaseStreams fail, rc = " << rc << std::endl; 882 } 883 } 884-} 885\ No newline at end of file 886+} 887diff --git a/display/hal/default/display_layer.c b/display/hal/default/display_layer.c 888index ee7a825..e12a653 100644 889--- a/display/hal/default/display_layer.c 890+++ b/display/hal/default/display_layer.c 891@@ -24,7 +24,7 @@ 892 893 #define DEV_ID 0 894 #define LAYER_ID 0 895-#define FB_PATH "/dev/fb0" 896+#define FB_PATH "/dev/graphics/fb0" 897 #define DISP_WIDTH 800 898 #define DISP_HEIGHT 480 899 #define BITS_PER_PIXEL 32 900``` 901 902Run the **./build.sh --product-name rk3399 --ccache --build-target v4l2_main** command to recompile **v4l2_main** after modification. 903 904The executable program path after successful compilation is **./out/rk3399/hdf/hdf/v4l2_main**. 905 906Push the newly compiled **v4l2_main** to the **system/bin** directory on the development board. 907 908``` 909hdc shell "mount -o rw,remount /" 910hdc file send D:\cyyanl\work\RockChip\bin\v4l2_main /system/bin 911``` 912 913Continue to execute **v4l2_main**. If no **framebuffer** error is reported, the issue has been resolved. (Another idea is to analyze why **fb0** is in **/dev/graphics/fb0** instead of **/dev/fb0**, and then change **fb0** to **/dev/fb0**. This idea will be debugged later.) 914 915New error: **ERROR:error: ioctl VIDIOC_QUERYBUF failed.** 916 917``` 918Options: 919-h | --help Print this message 920-p | --preview start preview on platform sensor 921-c | --capture capture one picture 922-w | --set WB Set white balance Cloudy 923-e | --Set AE Set exposure time 924-v | --video capture Viedeo of 10s 925-u | --uvc start preview on uvc preview 926-a | --Set ATE Set Auto exposure 927-q | --quit stop preview and quit this app 928INFO:please input command(input -q exit this app) 929u 930INFO:the fixed information is as follow: 931INFO:id= 932INFO:sem_start=0 933INFO:smem_len=2457600 934... 935INFO:V4L2AllocBuffer 936INFO:V4L2AllocBuffer:memoryType_ = 2 937INFO:V4L2AllocBuffer:V4L2_MEMORY_USERPTR = 2 938INFO:V4L2AllocBuffer:VIDIOC_QUERYBUF = 3226490377 939ERROR:error: ioctl VIDIOC_QUERYBUF failed. 940ERROR:error: Creatbuffer: V4L2AllocBuffer error 941ERROR:main test:V4L2PreviewThread CreatBuffer fail i = 0 942``` 943 944Cause analysis: ioctl(fd, VIDIOC_QUERYBUF, &buf) failure. In the section for setting the format and applying for the buffer queue in the Linux L4V2 UVC driver chapter, the following error is reported: 945 946ioctl(fd, VIDIOC_REQBUFS, &reqbuffer). Therefore, we can conclude that **ioctl VIDIOC_REQBUFS** on OpenHarmony will always report an error. The differences between the two failures are as follows: 947 948The memory mapping methods are different: V4L2_MEMORY_MMAP and V4L2_MEMORY_USERPTR 949 950According to issues of OpenHarmony, memory mapping method V4L2_MEMORY_MMAP is not supported. Next, we still use V4L2_MEMORY_USERPTR of **v4l2_main** for debugging and analysis. 951 952For details, see [Method of Applying for Memory by Adding MMAP on V4L2 Devices](https://gitee.com/openharmony/drivers_peripheral/issues/I4EFWP). 953 954 955Now, analyze the **ioctl(fd, VIDIOC_QUERYBUF, &buf)** failure. View the definition of VIDIOC_QUERYBUF: **videodev2.h** 956 957```c 958#define VIDIOC_QUERYBUF_IOWR('V', 9, struct v4l2_buffer) 959``` 960 961Insert the **ioctl** definition **int ioctl(int fd, int cmd, …); VIDIOC_QUERYBUF** as the input parameter of **cmd**. The input parameter is of the **int** type. This is a digital command code. After the code is sent to the kernel using **ioctl**, the corresponding function operation will be performed. Therefore, the command code delivered in the user state must be consistent with that received by the kernel. Next, let's check the command code consistency. 962 963**videodev2.h** contains 77 command codes for interaction with the kernel. Print the command codes in kernel state and compare them with those in the user state. 964 965Printing in user state: drivers/peripheral 966 967```diff 968diff --git a/camera/hal/adapter/platform/v4l2/src/driver_adapter/src/v4l2_buffer.cpp b/camera/hal/adapter/platform/v4l2/src/driver_adapter/src/v4l2_buffer.cpp 969index d7dd15f..f7254b4 100644 970--- a/camera/hal/adapter/platform/v4l2/src/driver_adapter/src/v4l2_buffer.cpp 971+++ b/camera/hal/adapter/platform/v4l2/src/driver_adapter/src/v4l2_buffer.cpp 972@@ -162,37 +162,119 @@ RetCode HosV4L2Buffers::V4L2DequeueBuffer(int fd) 973 return RC_OK; 974 } 975 976+static void cyyanl_printf_cmd(void) 977+{ 978+#if 1 979+ CAMERA_LOGD("*************************************************************************************"); 980+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_QUERYCAP ) = 0x%x\n", VIDIOC_QUERYCAP ); 981+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_ENUM_FMT ) = 0x%x\n", VIDIOC_ENUM_FMT ); 982+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_G_FMT ) = 0x%x\n", VIDIOC_G_FMT ); 983+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_S_FMT ) = 0x%x\n", VIDIOC_S_FMT ); 984+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_REQBUFS ) = 0x%x\n", VIDIOC_REQBUFS ); 985+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_QUERYBUF ) = 0x%x\n", VIDIOC_QUERYBUF ); 986+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_G_FBUF ) = 0x%x\n", VIDIOC_G_FBUF ); 987+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_S_FBUF ) = 0x%x\n", VIDIOC_S_FBUF ); 988+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_OVERLAY ) = 0x%x\n", VIDIOC_OVERLAY ); 989+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_QBUF ) = 0x%x\n", VIDIOC_QBUF ); 990+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_EXPBUF ) = 0x%x\n", VIDIOC_EXPBUF ); 991+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_DQBUF ) = 0x%x\n", VIDIOC_DQBUF ); 992+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_STREAMON ) = 0x%x\n", VIDIOC_STREAMON ); 993+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_STREAMOFF ) = 0x%x\n", VIDIOC_STREAMOFF ); 994+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_G_PARM ) = 0x%x\n", VIDIOC_G_PARM ); 995+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_S_PARM ) = 0x%x\n", VIDIOC_S_PARM ); 996+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_G_STD ) = 0x%x\n", VIDIOC_G_STD ); 997+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_S_STD ) = 0x%x\n", VIDIOC_S_STD ); 998+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_ENUMSTD ) = 0x%x\n", VIDIOC_ENUMSTD ); 999+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_ENUMINPUT ) = 0x%x\n", VIDIOC_ENUMINPUT ); 1000+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_G_CTRL ) = 0x%x\n", VIDIOC_G_CTRL ); 1001+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_S_CTRL ) = 0x%x\n", VIDIOC_S_CTRL ); 1002+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_G_TUNER ) = 0x%x\n", VIDIOC_G_TUNER ); 1003+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_S_TUNER ) = 0x%x\n", VIDIOC_S_TUNER ); 1004+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_G_AUDIO ) = 0x%x\n", VIDIOC_G_AUDIO ); 1005+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_S_AUDIO ) = 0x%x\n", VIDIOC_S_AUDIO ); 1006+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_QUERYCTRL ) = 0x%x\n", VIDIOC_QUERYCTRL ); 1007+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_QUERYMENU ) = 0x%x\n", VIDIOC_QUERYMENU ); 1008+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_G_INPUT ) = 0x%x\n", VIDIOC_G_INPUT ); 1009+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_S_INPUT ) = 0x%x\n", VIDIOC_S_INPUT ); 1010+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_G_EDID ) = 0x%x\n", VIDIOC_G_EDID ); 1011+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_S_EDID ) = 0x%x\n", VIDIOC_S_EDID ); 1012+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_G_OUTPUT ) = 0x%x\n", VIDIOC_G_OUTPUT ); 1013+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_S_OUTPUT ) = 0x%x\n", VIDIOC_S_OUTPUT ); 1014+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_ENUMOUTPUT ) = 0x%x\n", VIDIOC_ENUMOUTPUT ); 1015+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_G_AUDOUT ) = 0x%x\n", VIDIOC_G_AUDOUT ); 1016+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_S_AUDOUT ) = 0x%x\n", VIDIOC_S_AUDOUT ); 1017+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_G_MODULATOR ) = 0x%x\n", VIDIOC_G_MODULATOR ); 1018+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_S_MODULATOR ) = 0x%x\n", VIDIOC_S_MODULATOR ); 1019+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_G_FREQUENCY ) = 0x%x\n", VIDIOC_G_FREQUENCY ); 1020+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_S_FREQUENCY ) = 0x%x\n", VIDIOC_S_FREQUENCY ); 1021+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_CROPCAP ) = 0x%x\n", VIDIOC_CROPCAP ); 1022+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_G_CROP ) = 0x%x\n", VIDIOC_G_CROP ); 1023+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_S_CROP ) = 0x%x\n", VIDIOC_S_CROP ); 1024+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_G_JPEGCOMP ) = 0x%x\n", VIDIOC_G_JPEGCOMP ); 1025+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_S_JPEGCOMP ) = 0x%x\n", VIDIOC_S_JPEGCOMP ); 1026+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_QUERYSTD ) = 0x%x\n", VIDIOC_QUERYSTD ); 1027+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_TRY_FMT ) = 0x%x\n", VIDIOC_TRY_FMT ); 1028+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_ENUMAUDIO ) = 0x%x\n", VIDIOC_ENUMAUDIO ); 1029+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_ENUMAUDOUT ) = 0x%x\n", VIDIOC_ENUMAUDOUT ); 1030+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_G_PRIORITY ) = 0x%x\n", VIDIOC_G_PRIORITY ); 1031+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_S_PRIORITY ) = 0x%x\n", VIDIOC_S_PRIORITY ); 1032+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_G_SLICED_VBI_CAP ) = 0x%x\n", VIDIOC_G_SLICED_VBI_CAP ); 1033+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_LOG_STATUS ) = 0x%x\n", VIDIOC_LOG_STATUS ); 1034+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_G_EXT_CTRLS ) = 0x%x\n", VIDIOC_G_EXT_CTRLS ); 1035+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_S_EXT_CTRLS ) = 0x%x\n", VIDIOC_S_EXT_CTRLS ); 1036+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_TRY_EXT_CTRLS ) = 0x%x\n", VIDIOC_TRY_EXT_CTRLS ); 1037+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_ENUM_FRAMESIZES ) = 0x%x\n", VIDIOC_ENUM_FRAMESIZES ); 1038+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_ENUM_FRAMEINTERVALS) = 0x%x\n", VIDIOC_ENUM_FRAMEINTERVALS); 1039+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_G_ENC_INDEX ) = 0x%x\n", VIDIOC_G_ENC_INDEX ); 1040+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_ENCODER_CMD ) = 0x%x\n", VIDIOC_ENCODER_CMD ); 1041+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_TRY_ENCODER_CMD ) = 0x%x\n", VIDIOC_TRY_ENCODER_CMD ); 1042+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_S_HW_FREQ_SEEK ) = 0x%x\n", VIDIOC_S_HW_FREQ_SEEK ); 1043+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_CREATE_BUFS ) = 0x%x\n", VIDIOC_CREATE_BUFS ); 1044+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_PREPARE_BUF ) = 0x%x\n", VIDIOC_PREPARE_BUF ); 1045+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_G_SELECTION ) = 0x%x\n", VIDIOC_G_SELECTION ); 1046+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_S_SELECTION ) = 0x%x\n", VIDIOC_S_SELECTION ); 1047+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_DECODER_CMD ) = 0x%x\n", VIDIOC_DECODER_CMD ); 1048+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_TRY_DECODER_CMD ) = 0x%x\n", VIDIOC_TRY_DECODER_CMD ); 1049+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_ENUM_DV_TIMINGS ) = 0x%x\n", VIDIOC_ENUM_DV_TIMINGS ); 1050+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_QUERY_DV_TIMINGS ) = 0x%x\n", VIDIOC_QUERY_DV_TIMINGS ); 1051+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_DV_TIMINGS_CAP ) = 0x%x\n", VIDIOC_DV_TIMINGS_CAP ); 1052+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_ENUM_FREQ_BANDS ) = 0x%x\n", VIDIOC_ENUM_FREQ_BANDS ); 1053+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_DBG_G_CHIP_INFO ) = 0x%x\n", VIDIOC_DBG_G_CHIP_INFO ); 1054+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(VIDIOC_QUERY_EXT_CTRL ) = 0x%x\n", VIDIOC_QUERY_EXT_CTRL ); 1055+ CAMERA_LOGD("cyyanl v4l2 ioctl cmd(BASE_VIDIOC_PRIVATE ) = 0x%x\n", BASE_VIDIOC_PRIVATE ); 1056+ CAMERA_LOGD("*************************************************************************************"); 1057+#endif 1058+} 1059+ 1060 RetCode HosV4L2Buffers::V4L2AllocBuffer(int fd, const std::shared_ptr<FrameSpec>& frameSpec) 1061 { 1062 struct v4l2_buffer buf = {}; 1063 struct v4l2_plane planes[1] = {}; 1064- CAMERA_LOGD("V4L2AllocBuffer\n"); 1065+ CAMERA_LOGD("V4L2AllocBuffer enter\n"); 1066 1067+ cyyanl_printf_cmd(); 1068 if (frameSpec == nullptr) { 1069 CAMERA_LOGE("V4L2AllocBuffer frameSpec is NULL\n"); 1070 return RC_ERROR; 1071 } 1072- 1073 switch (memoryType_) { 1074 case V4L2_MEMORY_MMAP: 1075 // to do something 1076 break; 1077 case V4L2_MEMORY_USERPTR: 1078+ CAMERA_LOGD("V4L2AllocBuffer:V4L2_MEMORY_USERPTR = %d\n", V4L2_MEMORY_USERPTR); 1079 buf.type = bufferType_; 1080 buf.memory = memoryType_; 1081 buf.index = (uint32_t)frameSpec->buffer_->GetIndex(); 1082- 1083 if (bufferType_ == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { 1084+ CAMERA_LOGD("V4L2AllocBuffer:V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE = %d\n", V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); 1085 buf.m.planes = planes; 1086 buf.length = 1; 1087 } 1088``` 1089 1090Printing in kernel state: kernel/linux/linux-4.19/ 1091 1092```diff 1093diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c 1094index 0842a47c6..8aa60407f 100644 1095--- a/drivers/media/usb/uvc/uvc_driver.c 1096+++ b/drivers/media/usb/uvc/uvc_driver.c 1097@@ -2902,10 +2902,93 @@ struct uvc_driver uvc_driver = { 1098 }, 1099 }; 1100 1101+static void cyyanl_printk_cmd(void) 1102+{ 1103+ printk("*************************************************************************************"); 1104+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_QUERYCAP ) = %ld\n", VIDIOC_QUERYCAP ); 1105+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_ENUM_FMT ) = %ld\n", VIDIOC_ENUM_FMT ); 1106+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_G_FMT ) = %ld\n", VIDIOC_G_FMT ); 1107+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_S_FMT ) = %ld\n", VIDIOC_S_FMT ); 1108+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_REQBUFS ) = %ld\n", VIDIOC_REQBUFS ); 1109+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_QUERYBUF ) = %ld\n", VIDIOC_QUERYBUF ); 1110+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_G_FBUF ) = %ld\n", VIDIOC_G_FBUF ); 1111+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_S_FBUF ) = %ld\n", VIDIOC_S_FBUF ); 1112+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_OVERLAY ) = %ld\n", VIDIOC_OVERLAY ); 1113+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_QBUF ) = %ld\n", VIDIOC_QBUF ); 1114+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_EXPBUF ) = %ld\n", VIDIOC_EXPBUF ); 1115+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_DQBUF ) = %ld\n", VIDIOC_DQBUF ); 1116+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_STREAMON ) = %ld\n", VIDIOC_STREAMON ); 1117+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_STREAMOFF ) = %ld\n", VIDIOC_STREAMOFF ); 1118+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_G_PARM ) = %ld\n", VIDIOC_G_PARM ); 1119+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_S_PARM ) = %ld\n", VIDIOC_S_PARM ); 1120+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_G_STD ) = %ld\n", VIDIOC_G_STD ); 1121+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_S_STD ) = %ld\n", VIDIOC_S_STD ); 1122+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_ENUMSTD ) = %ld\n", VIDIOC_ENUMSTD ); 1123+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_ENUMINPUT ) = %ld\n", VIDIOC_ENUMINPUT ); 1124+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_G_CTRL ) = %ld\n", VIDIOC_G_CTRL ); 1125+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_S_CTRL ) = %ld\n", VIDIOC_S_CTRL ); 1126+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_G_TUNER ) = %ld\n", VIDIOC_G_TUNER ); 1127+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_S_TUNER ) = %ld\n", VIDIOC_S_TUNER ); 1128+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_G_AUDIO ) = %ld\n", VIDIOC_G_AUDIO ); 1129+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_S_AUDIO ) = %ld\n", VIDIOC_S_AUDIO ); 1130+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_QUERYCTRL ) = %ld\n", VIDIOC_QUERYCTRL ); 1131+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_QUERYMENU ) = %ld\n", VIDIOC_QUERYMENU ); 1132+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_G_INPUT ) = %ld\n", VIDIOC_G_INPUT ); 1133+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_S_INPUT ) = %ld\n", VIDIOC_S_INPUT ); 1134+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_G_EDID ) = %ld\n", VIDIOC_G_EDID ); 1135+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_S_EDID ) = %ld\n", VIDIOC_S_EDID ); 1136+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_G_OUTPUT ) = %ld\n", VIDIOC_G_OUTPUT ); 1137+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_S_OUTPUT ) = %ld\n", VIDIOC_S_OUTPUT ); 1138+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_ENUMOUTPUT ) = %ld\n", VIDIOC_ENUMOUTPUT ); 1139+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_G_AUDOUT ) = %ld\n", VIDIOC_G_AUDOUT ); 1140+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_S_AUDOUT ) = %ld\n", VIDIOC_S_AUDOUT ); 1141+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_G_MODULATOR ) = %ld\n", VIDIOC_G_MODULATOR ); 1142+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_S_MODULATOR ) = %ld\n", VIDIOC_S_MODULATOR ); 1143+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_G_FREQUENCY ) = %ld\n", VIDIOC_G_FREQUENCY ); 1144+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_S_FREQUENCY ) = %ld\n", VIDIOC_S_FREQUENCY ); 1145+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_CROPCAP ) = %ld\n", VIDIOC_CROPCAP ); 1146+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_G_CROP ) = %ld\n", VIDIOC_G_CROP ); 1147+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_S_CROP ) = %ld\n", VIDIOC_S_CROP ); 1148+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_G_JPEGCOMP ) = %ld\n", VIDIOC_G_JPEGCOMP ); 1149+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_S_JPEGCOMP ) = %ld\n", VIDIOC_S_JPEGCOMP ); 1150+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_QUERYSTD ) = %ld\n", VIDIOC_QUERYSTD ); 1151+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_TRY_FMT ) = %ld\n", VIDIOC_TRY_FMT ); 1152+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_ENUMAUDIO ) = %ld\n", VIDIOC_ENUMAUDIO ); 1153+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_ENUMAUDOUT ) = %ld\n", VIDIOC_ENUMAUDOUT ); 1154+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_G_PRIORITY ) = %ld\n", VIDIOC_G_PRIORITY ); 1155+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_S_PRIORITY ) = %ld\n", VIDIOC_S_PRIORITY ); 1156+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_G_SLICED_VBI_CAP ) = %ld\n", VIDIOC_G_SLICED_VBI_CAP ); 1157+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_LOG_STATUS ) = %ld\n", VIDIOC_LOG_STATUS ); 1158+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_G_EXT_CTRLS ) = %ld\n", VIDIOC_G_EXT_CTRLS ); 1159+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_S_EXT_CTRLS ) = %ld\n", VIDIOC_S_EXT_CTRLS ); 1160+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_TRY_EXT_CTRLS ) = %ld\n", VIDIOC_TRY_EXT_CTRLS ); 1161+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_ENUM_FRAMESIZES ) = %ld\n", VIDIOC_ENUM_FRAMESIZES ); 1162+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_ENUM_FRAMEINTERVALS) = %ld\n", VIDIOC_ENUM_FRAMEINTERVALS); 1163+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_G_ENC_INDEX ) = %ld\n", VIDIOC_G_ENC_INDEX ); 1164+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_ENCODER_CMD ) = %ld\n", VIDIOC_ENCODER_CMD ); 1165+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_TRY_ENCODER_CMD ) = %ld\n", VIDIOC_TRY_ENCODER_CMD ); 1166+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_S_HW_FREQ_SEEK ) = %ld\n", VIDIOC_S_HW_FREQ_SEEK ); 1167+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_CREATE_BUFS ) = %ld\n", VIDIOC_CREATE_BUFS ); 1168+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_PREPARE_BUF ) = %ld\n", VIDIOC_PREPARE_BUF ); 1169+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_G_SELECTION ) = %ld\n", VIDIOC_G_SELECTION ); 1170+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_S_SELECTION ) = %ld\n", VIDIOC_S_SELECTION ); 1171+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_DECODER_CMD ) = %ld\n", VIDIOC_DECODER_CMD ); 1172+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_TRY_DECODER_CMD ) = %ld\n", VIDIOC_TRY_DECODER_CMD ); 1173+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_ENUM_DV_TIMINGS ) = %ld\n", VIDIOC_ENUM_DV_TIMINGS ); 1174+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_QUERY_DV_TIMINGS ) = %ld\n", VIDIOC_QUERY_DV_TIMINGS ); 1175+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_DV_TIMINGS_CAP ) = %ld\n", VIDIOC_DV_TIMINGS_CAP ); 1176+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_ENUM_FREQ_BANDS ) = %ld\n", VIDIOC_ENUM_FREQ_BANDS ); 1177+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_DBG_G_CHIP_INFO ) = %ld\n", VIDIOC_DBG_G_CHIP_INFO ); 1178+ printk("cyyanl v4l2 ioctl cmd(VIDIOC_QUERY_EXT_CTRL ) = %ld\n", VIDIOC_QUERY_EXT_CTRL ); 1179+ printk("cyyanl v4l2 ioctl cmd(BASE_VIDIOC_PRIVATE ) = %ld\n", BASE_VIDIOC_PRIVATE ); 1180+ printk("*************************************************************************************"); 1181+} 1182+ 1183 static int __init uvc_init(void) 1184 { 1185 int ret; 1186- 1187+ printk("cyyanl enter uvc_init\n"); 1188+ cyyanl_printk_cmd(); 1189 uvc_debugfs_init(); 1190 1191 ret = usb_register(&uvc_driver.driver); 1192``` 1193 1194Printing result comparison: **VIDIOC_QUERYBUF** is **0xc0505609** in user state and **0xc0585609** in kernel state. There are several other inconsistent command codes. 1195 1196![](figures/isoftstone/yangfan-print-01.png) 1197 1198Analyze the cause for command code inconsistency. First, find the differences during compilation of **VIDIOC_QUERYBUF** in user state and kernel state. 1199 1200User state: kernel/linux/patches/linux-5.10/prebuilts/usr/include/linux/videodev2.h +1358 1201 1202Kernel state: kernel/linux/linux-4.19/include/uapi/linux/videodev2.h +2361 1203 1204The possible cause is that **VIDIOC_QUERYBUF** inconsistency is caused by header file differences. (Currently, whether the issue can be solved by using linux-4.19 is not verified.) Seek help from the customer and check whether there are similar issues in OpenHarmony. 1205 1206A similar issue is found: https://gitee.com/openharmony/drivers_peripheral/issues/I4NI4M?from=project-issue 1207 1208 1209Now, there are two debugging ideas: 1210 12111. Unify **VIDIOC_QUERYBUF** in user state with that in kernel state. 1212 1213 Solution: Change **0xc0505609** in user state to **0xc0585609** in kernel state. 1214 1215 Modification: drivers/peripheral 1216 1217 ```diff 1218 diff --git a/camera/hal/adapter/platform/v4l2/src/driver_adapter/src/v4l2_buffer.cpp b/camera/hal/adapter/platform/v4l2/src/driver_adapter/src/v4l2_buffer.cpp 1219 index d7dd15f..f7254b4 100644 1220 --- a/camera/hal/adapter/platform/v4l2/src/driver_adapter/src/v4l2_buffer.cpp 1221 +++ b/camera/hal/adapter/platform/v4l2/src/driver_adapter/src/v4l2_buffer.cpp 1222 buf.m.planes = planes; 1223 buf.length = 1; 1224 } 1225 - CAMERA_LOGD("V4L2_MEMORY_USERPTR Print the cnt: %{public}d\n", buf.index); 1226 - 1227 - if (ioctl(fd, VIDIOC_QUERYBUF, &buf) < 0) { 1228 - CAMERA_LOGE("error: ioctl VIDIOC_QUERYBUF failed: %{public}s\n", strerror(errno)); 1229 + if (ioctl(fd, /*VIDIOC_QUERYBUF*/0xc0585609, &buf) < 0) { 1230 + CAMERA_LOGE("error: ioctl VIDIOC_QUERYBUF failed.\n"); 1231 return RC_ERROR; 1232 } 1233 ``` 1234 1235 Run **v4l2_main** again. Result: Signal 4 reports an error. 1236 1237 Cause analysis: **ioctl(fd, /*****VIDIOC_QUERYBUF*****/0xc0585609, &buf)** is successful. According to Signal 4 analysis, the error is possibly still caused by the command codes of **cmd**. 1238 1239 This idea can solve the current issue, but it will cause a new Signal 4 error. 1240 1241 ``` 1242 INFO:main test:allocating display buffer memory 1243 INFO:main test:do_mmap: pmem mmap fd 5 ptr 0xf7508000 len 2457600 1244 INFO:V4L2OpenDevice /dev/video10 1245 INFO:V4L2ReqBuffers buffCont 4 1246 INFO:Creatbuffer frameSpec->buffer index == 0 1247 INFO:V4L2AllocBuffer 1248 Signal 4 1249 ``` 1250 12512. Analyze the root cause of command code inconsistency and make modifications. 1252 1253 Cause analysis: The size of the structure varies according to the 32-bit and 64-bit compilation, which affects the value of **VIDIOC_QUERYBUF**. 1254 1255 Modification: Modify the timestamp definition of the **v4l2_buffer** structure compiled in user state, and replace the header file **#include <linux/videodev2.h>** compiled in user state with 1256 1257 the modified **videodev2.h** file, that is, **#include "videodev2.h"**. (The actual operation is to copy the modified **videodev2.h** file to the **v4l2_main** compilation directory.) 1258 1259 kernel/linux/linux-4.19/ 1260 1261 ```diff 1262 diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h 1263 index ba548d7f0..b0fb48f65 100644 1264 --- a/include/uapi/linux/videodev2.h 1265 +++ b/include/uapi/linux/videodev2.h 1266 @@ -958,13 +958,20 @@ struct v4l2_plane { 1267 * Contains data exchanged by application and driver using one of the Streaming 1268 * I/O methods. 1269 */ 1270 + 1271 +struct timeval_user { 1272 + long tv_sec; 1273 + long tv_usec; 1274 +}; 1275 + 1276 struct v4l2_buffer { 1277 __u32 index; 1278 __u32 type; 1279 __u32 bytesused; 1280 __u32 flags; 1281 __u32 field; 1282 - struct timeval timestamp; 1283 + //struct timeval timestamp; 1284 + struct timeval_user timestamp; 1285 struct v4l2_timecode timecode; 1286 __u32 sequence; 1287 1288 ``` 1289 1290 drivers/peripheral 1291 1292 ```diff 1293 diff --git a/camera/hal/adapter/chipset/rpi/rpi3/device/camera/src/driver_adapter/main_test/project_v4l2_main.h b/camera/hal/adapter/chipset/rpi/rpi3/device/camera/src/driver_adapter/main_test/project_v4l2_main.h 1294 index 00ddea7..962ebc3 100755 1295 --- a/camera/hal/adapter/chipset/rpi/rpi3/device/camera/src/driver_adapter/main_test/project_v4l2_main.h 1296 +++ b/camera/hal/adapter/chipset/rpi/rpi3/device/camera/src/driver_adapter/main_test/project_v4l2_main.h 1297 @@ -15,7 +15,8 @@ 1298 1299 #ifndef HOS_CAMERA_PROJET_HARDWARE_H 1300 #define HOS_CAMERA_PROJET_HARDWARE_H 1301 -#include <linux/videodev2.h> 1302 +//#include <linux/videodev2.h> 1303 +#include "videodev2.h" 1304 1305 namespace OHOS::Camera { 1306 #define PREVIEW_PIXEL_FORMAT V4L2_PIX_FMT_YUV420 1307 diff --git a/camera/hal/adapter/platform/v4l2/src/driver_adapter/include/v4l2_buffer.h b/camera/hal/adapter/platform/v4l2/src/driver_adapter/include/v4l2_buffer.h 1308 index 6f45882..a8d6819 100644 1309 --- a/camera/hal/adapter/platform/v4l2/src/driver_adapter/include/v4l2_buffer.h 1310 +++ b/camera/hal/adapter/platform/v4l2/src/driver_adapter/include/v4l2_buffer.h 1311 @@ -19,7 +19,8 @@ 1312 #include <mutex> 1313 #include <map> 1314 #include <cstring> 1315 -#include <linux/videodev2.h> 1316 +//#include <linux/videodev2.h> 1317 +#include "videodev2.h" 1318 #include <sys/ioctl.h> 1319 #include "v4l2_common.h" 1320 #if defined(V4L2_UTEST) || defined (V4L2_MAIN_TEST) 1321 diff --git a/camera/hal/adapter/platform/v4l2/src/driver_adapter/include/v4l2_control.h b/camera/hal/adapter/platform/v4l2/src/driver_adapter/include/v4l2_control.h 1322 index 5b93f36..05191a7 100644 1323 --- a/camera/hal/adapter/platform/v4l2/src/driver_adapter/include/v4l2_control.h 1324 +++ b/camera/hal/adapter/platform/v4l2/src/driver_adapter/include/v4l2_control.h 1325 @@ -16,7 +16,8 @@ 1326 #ifndef HOS_CAMERA_V4L2_CONTROL_H 1327 #define HOS_CAMERA_V4L2_CONTROL_H 1328 1329 -#include <linux/videodev2.h> 1330 +//#include <linux/videodev2.h> 1331 +#include "videodev2.h" 1332 #include <errno.h> 1333 #include <sys/ioctl.h> 1334 #include "v4l2_common.h" 1335 diff --git a/camera/hal/adapter/platform/v4l2/src/driver_adapter/include/v4l2_dev.h b/camera/hal/adapter/platform/v4l2/src/driver_adapter/include/v4l2_dev.h 1336 index 10dc9b4..e3b3056 100644 1337 --- a/camera/hal/adapter/platform/v4l2/src/driver_adapter/include/v4l2_dev.h 1338 +++ b/camera/hal/adapter/platform/v4l2/src/driver_adapter/include/v4l2_dev.h 1339 @@ -19,7 +19,8 @@ 1340 #include <mutex> 1341 #include <thread> 1342 #include <vector> 1343 -#include <linux/videodev2.h> 1344 +//#include <linux/videodev2.h> 1345 +#include "videodev2.h" 1346 #include <sys/epoll.h> 1347 #include <sys/ioctl.h> 1348 #include <sys/types.h> 1349 diff --git a/camera/hal/adapter/platform/v4l2/src/driver_adapter/include/v4l2_fileformat.h b/camera/hal/adapter/platform/v4l2/src/driver_adapter/include/v4l2_fileformat.h 1350 index de892e9..44bb1b4 100644 1351 --- a/camera/hal/adapter/platform/v4l2/src/driver_adapter/include/v4l2_fileformat.h 1352 +++ b/camera/hal/adapter/platform/v4l2/src/driver_adapter/include/v4l2_fileformat.h 1353 @@ -19,7 +19,8 @@ 1354 #include <vector> 1355 #include <cstring> 1356 #include <fcntl.h> 1357 -#include <linux/videodev2.h> 1358 +//#include <linux/videodev2.h> 1359 +#include "videodev2.h" 1360 #include <sys/ioctl.h> 1361 #include <sys/stat.h> 1362 #include <unistd.h> 1363 diff --git a/camera/hal/adapter/platform/v4l2/src/driver_adapter/include/v4l2_uvc.h b/camera/hal/adapter/platform/v4l2/src/driver_adapter/include/v4l2_uvc.h 1364 index 1a62f37..96c70aa 100644 1365 --- a/camera/hal/adapter/platform/v4l2/src/driver_adapter/include/v4l2_uvc.h 1366 +++ b/camera/hal/adapter/platform/v4l2/src/driver_adapter/include/v4l2_uvc.h 1367 @@ -18,7 +18,8 @@ 1368 #include <thread> 1369 #include <fcntl.h> 1370 #include <linux/netlink.h> 1371 -#include <linux/videodev2.h> 1372 +//#include <linux/videodev2.h> 1373 +#include "videodev2.h" 1374 #include <sys/ioctl.h> 1375 #include <sys/select.h> 1376 #include <linux/netlink.h>zz 1377 diff --git a/camera/hal/adapter/platform/v4l2/src/driver_adapter/main_test/v4l2_main.cpp b/camera/hal/adapter/platform/v4l2/src/driver_adapter/main_test/v4l2_main.cpp 1378 index b351f49..5483b85 100755 1379 --- a/camera/hal/adapter/platform/v4l2/src/driver_adapter/main_test/v4l2_main.cpp 1380 +++ b/camera/hal/adapter/platform/v4l2/src/driver_adapter/main_test/v4l2_main.cpp 1381 @@ -22,7 +22,8 @@ 1382 #include <sys/mman.h> 1383 #include <sys/time.h> 1384 #include <linux/fb.h> 1385 -#include <linux/videodev2.h> 1386 +//#include <linux/videodev2.h> 1387 +#include "videodev2.h" 1388 #include "securec.h" 1389 #include "v4l2_uvc.h" 1390 #include "v4l2_dev.h" 1391 diff --git a/camera/hal/adapter/platform/v4l2/src/driver_adapter/src/v4l2_stream.cpp b/camera/hal/adapter/platform/v4l2/src/driver_adapter/src/v4l2_stream.cpp 1392 index 778cf05..96618be 100644 1393 --- a/camera/hal/adapter/platform/v4l2/src/driver_adapter/src/v4l2_stream.cpp 1394 +++ b/camera/hal/adapter/platform/v4l2/src/driver_adapter/src/v4l2_stream.cpp 1395 @@ -14,7 +14,8 @@ 1396 */ 1397 1398 #include <cstring> 1399 -#include <linux/videodev2.h> 1400 +//#include <linux/videodev2.h> 1401 +#include "videodev2.h" 1402 #include <sys/ioctl.h> 1403 1404 #include "v4l2_stream.h" 1405 diff --git a/camera/hal/test/v4l2/include/test_display.h b/camera/hal/test/v4l2/include/test_display.h 1406 index d437e26..8e5205e 100644 1407 --- a/camera/hal/test/v4l2/include/test_display.h 1408 +++ b/camera/hal/test/v4l2/include/test_display.h 1409 @@ -44,7 +44,8 @@ 1410 #include <errno.h> 1411 #include <getopt.h> 1412 #include <linux/fb.h> 1413 -#include <linux/videodev2.h> 1414 +//#include <linux/videodev2.h> 1415 +#include "videodev2.h" 1416 #include <mutex> 1417 #include <pthread.h> 1418 #include <stdlib.h> 1419 @@ -138,4 +139,4 @@ public: 1420 void StartCapture(int streamId, int captureId, bool shutterCallback, bool isStreaming); 1421 float calTime(struct timeval start, struct timeval end); 1422 }; 1423 -#endif 1424 \ No newline at end of file 1425 +#endif 1426 ``` 1427 1428 Compile **v4l2_main** again and execute it. No error is recorded in logs. The HDMI screen displays the preview image. 1429 1430 1431 1432According to the entire debugging process, the camera supports the YUYV and MJPEG formats. By default, preview in **v4l2_main** uses the YUYV format. Change the format to MJPEG and try again. 1433 1434Modification: 1435 1436```diff 1437diff --git a/camera/hal/adapter/platform/v4l2/src/driver_adapter/main_test/v4l2_main.cpp b/camera/hal/adapter/platform/v4l2/src/driver_adapter/main_test/v4l2_main.cpp 1438index b351f49..5483b85 100755 1439--- a/camera/hal/adapter/platform/v4l2/src/driver_adapter/main_test/v4l2_main.cpp 1440+++ b/camera/hal/adapter/platform/v4l2/src/driver_adapter/main_test/v4l2_main.cpp 1441@@ -394,7 +395,9 @@ void V4L2SetDeviceFormat(DeviceFormat& format, const std::string devname) 1442 1443 if (devname == "uvcvideo" || devname == "uvcvideo1") { 1444 if (g_isPreviewOnUvc) { 1445- format.fmtdesc.pixelformat = V4L2_PIX_FMT_YUYV; 1446+ CAMERA_LOGD("cyyanl enter V4L2SetDeviceFormat : g_isPreviewOnUvc\n"); 1447+ //format.fmtdesc.pixelformat = V4L2_PIX_FMT_YUYV; 1448+ format.fmtdesc.pixelformat = V4L2_PIX_FMT_MJPEG; 1449 format.fmtdesc.width = width; 1450 format.fmtdesc.height = height; 1451 } 1452``` 1453 1454Execution result of **v4l2_main**: The display is abnormal. Currently, do not analyze the MJPEG format. 1455 1456![](figures/isoftstone/yangfan-picture-v4l2_main.png) 1457 1458 1459 1460So far, **v4l2_main** runs properly and images can be previewed. (The abnormal color of the preview image is related to the screen display format and does not need to be modified currently.) Next, debug photographing and video recording. 1461 1462After **v4l2_main** is executed, enter **u** to preview the UVC, run **c** to take photos, and then run **v** to record videos. The photo and video files are generated in the current execution path. 1463 1464``` 1465# ls -l *.jpeg 1466-rwxrw-rw- 1 root 29034400 614400 2013-01-18 15:20 UVC0.jpeg 1467-rwxrw-rw- 1 root 29034400 614400 2013-01-18 15:20 UVC1.jpeg 1468-rwxrw-rw- 1 root 29034400 614400 2013-01-18 15:20 UVC2.jpeg 1469-rwxrw-rw- 1 root 29034400 614400 2013-01-18 15:20 UVC3.jpeg 1470# 1471# ls -l *.h264 1472-rwxrw-rw- 1 root 29034400 85401600 2013-01-18 15:20 uvc.h264 1473``` 1474 1475Export the preceding files to the PC and check them. 1476 1477image **uvc0.jpeg** 1478 1479![](figures/isoftstone/yangfan-picture-uvc0.png) 1480 1481The video file **uvc.h264** can be viewed on the mobile phone and played properly. 1482 1483### Appendixes 1484 1485```c 1486/** 1487 * struct v4l2_buffer - video buffer info 1488 * @index: id number of the buffer 1489 * @type: enum v4l2_buf_type; buffer type (type == *_MPLANE for 1490 * multiplanar buffers); 1491 * @bytesused: number of bytes occupied by data in the buffer (payload); 1492 * unused (set to 0) for multiplanar buffers 1493 * @flags: buffer informational flags 1494 * @field: enum v4l2_field; field order of the image in the buffer 1495 * @timestamp: frame timestamp 1496 * @timecode: frame timecode 1497 * @sequence: sequence count of this frame 1498 * @memory: enum v4l2_memory; the method, in which the actual video data is 1499 * passed 1500 * @offset: for non-multiplanar buffers with memory == V4L2_MEMORY_MMAP; 1501 * offset from the start of the device memory for this plane, 1502 * (or a "cookie" that should be passed to mmap() as offset) 1503 * @userptr: for non-multiplanar buffers with memory == V4L2_MEMORY_USERPTR; 1504 * a userspace pointer pointing to this buffer 1505 * @fd: for non-multiplanar buffers with memory == V4L2_MEMORY_DMABUF; 1506 * a userspace file descriptor associated with this buffer 1507 * @planes: for multiplanar buffers; userspace pointer to the array of plane 1508 * info structs for this buffer 1509 * @length: size in bytes of the buffer (NOT its payload) for single-plane 1510 * buffers (when type != *_MPLANE); number of elements in the 1511 * planes array for multi-plane buffers 1512 * 1513 * Contains data exchanged by application and driver using one of the Streaming 1514 * I/O methods. 1515 */ 1516 1517struct v4l2_buffer { 1518 __u32 index; 1519 __u32 type; 1520 __u32 bytesused; 1521 __u32 flags; 1522 __u32 field; 1523 struct timeval timestamp; 1524 struct v4l2_timecode timecode; 1525 __u32 sequence; 1526 1527 /* memory location */ 1528 __u32 memory; 1529 union { 1530 __u32 offset; 1531 unsigned long userptr; 1532 struct v4l2_plane *planes; 1533 __s32 fd; 1534 } m; 1535 __u32 length; 1536 __u32 reserved2; 1537 __u32 reserved; 1538} 1539``` 1540 1541## TP 1542 1543### TP Driver Model 1544 1545This model mainly defines and implements the following types of Hardware Driver Interfaces (HDIs) of the input module, allowing upper-layer input services to perform operations for the input devices: 1546 1547- **Input Manager**: manages input devices, including enabling and disabling input devices and obtaining the device list. 1548- **Input Reporter**: reports input events, including registering and unregistering data reporting callbacks. 1549- **Input Controller**: controls input devices, including obtaining the device information and device type, and setting power status. 1550 1551**Figure 1** HDI architecture of the input module 1552 1553![dayu200-tp-01.png](figures/dayu200/dayu200-tp-01.png) 1554 1555The source code directory structure is as follows: 1556 1557``` 1558/drivers/peripheral/input 1559├── hal # HAL code 1560│ └── include # HAL header files 1561│ └── src # HAL code implementation 1562├── interfaces # Driver capability APIs provided for upper-layer services 1563│ └── include # APIs exposed 1564├── test # Test code 1565│ └── unittest # Unit test code 1566``` 1567 1568For details, see [README](https://gitee.com/openharmony/drivers_peripheral/blob/master/input/README_zh.md) of the input subsystem. 1569 1570### TP HDF Driver Adaptation 1571 1572#### Configuration Adaptation 1573 1574Disable the Linux TP driver by disabling **TOUCHSCREEN_GT9XX** in the **<rockchip_linux_defconfig>** file. Specifically, change **CONFIG_TOUCHSCREEN_GT9XX=y** as follows: 1575```makefile 1576# CONFIG_TOUCHSCREEN_GT9XX is not set 1577``` 1578#### Driver Adaptation 1579 15801. Modify content in **vendor/rockchip/rk3399/hdf_config/khdf/device_info/device_info.hcs** as follows or add the following content to the file: 1581 1582 ```json 1583 device_touch_chip :: device { 1584 device0 :: deviceNode { 1585 policy = 0; 1586 priority = 130; 1587 preload = 0; 1588 permission = 0660; 1589 moduleName = "HDF_TOUCH_GT911"; 1590 serviceName = "hdf_touch_gt911_service"; 1591 deviceMatchAttr = "zsj_gt911_5p5"; 1592 } 1593 } 1594 ``` 1595 1596 1597 15982. Modify content in **vendor/rockchip/rk3399/hdf_config/khdf/input/input_config.hcs** as follows or add the following content to the file: 1599 1600 ```json 1601 busConfig { 1602 // 0:i2c 1:spi 1603 busType = 0; // I2C communication method 1604 busNum = 7; // I2C code of the touch chip corresponding to the CPU 1605 clkGpio = 72; // I/O pin code corresponding to I2C clk 1606 dataGpio = 71; // I/O pin code corresponding to I2C data 1607 i2cClkIomux = [0xFF77E004, 0x2]; // I2C [reuse register corresponding to the clk pin, which is configured to the I2C7_clk function] 1608 i2cDataIomux = [0xFF77E000, 0x8000]; // I2C [reuse register corresponding to the data pin, which is configured to the I2C7_DATA function] 1609 } 1610 1611 pinConfig { 1612 rstGpio = 150; // I/O pin code corresponding to rst of the touch chip 1613 intGpio = 52; // I/O pin code corresponding to int of the touch chip 1614 rstRegCfg = [0xFF77E028, 0x00000000]; // Reuse register corresponding to the rst pin, which is configured to the common I/O port 1615 intRegCfg = [0xFF770018, 0x00000000]; // Reuse register corresponding to the int pin, which is configured to the common I/O port 1616 } 1617 ``` 1618#### FAQs 1619 1620##### How to solve the problem that the portrait and landscape modes are reversed for the touchscreen? 1621 1622Modify the **ParsePointData** function in **drivers/framework/model/input/driver/touchscreen/touch_gt911.c** to exchange the position of **x** and **y**. 1623 1624##### Modify the **InputPinMuxCfg** function: 1625 1626```c 1627static int32_t InputPinMuxCfg(uint32_t regAddr, int32_t regSize, uint32_t regValue) 1628{ 1629 uint8_t *base = NULL; 1630 uint32_t data = 0; 1631 if (regAddr == 0) { 1632 HDF_LOGE("%s: regAddr invalid", __func__); 1633 return HDF_FAILURE; 1634 } 1635 1636 HDF_LOGE("regAddr = 0x%x, regSize = 0x%x", regAddr, regSize); 1637 base = OsalIoRemap(regAddr, regSize); 1638 if (base == NULL) { 1639 HDF_LOGE("%s: ioremap failed", __func__); 1640 return HDF_FAILURE; 1641 } 1642 // Read and save the original configurations before writing new configurations to the register. Modify the original other pin function configurations. 1643 data = OSAL_READL(base); 1644 data |= regValue; 1645 OSAL_WRITEL(data, base); 1646 OsalIoUnmap((void *)base); 1647 return HDF_SUCCESS; 1648} 1649``` 1650 1651##### How to determine the pin GPIOn_KK code of RK3399? 1652 1653```shell 1654num = 32n+(K-A)8+X 1655# GPIO1_B2 = 1 * 32 + (B-A)*8 + 2 = 32 + 8 + 1 = 42 1656``` 1657 1658| Function | I/O Name | I/O Code| 1659| ------ | -------- | ------ | 1660| TP_INT | GPIO1_C4 | 52 | 1661| TP_RST | GPIO4_C6 | 150 | 1662| TP_SDA | GPIO2_A7 | 71 | 1663| TP_SCL | GPIO2_B0 | 72 | 1664 1665 1666 1667##### How to configure the pin GPIOn_KX reuse function of RK3399? 1668 16691. Find the base address of the GPIO reuse function register, which is **FF77_0000**. 16702. Find the register offset of the GPIOn_K reuse function. 16713. Determine the GPIOn_K reuse function register by **adding the base address and offset**. 16724. Write the reuse function of the corresponding pin based on the reuse function register introduction. 1673 1674| Function | I/O Name | Reuse Register Address| Control Bit| Value | 1675| ------ | -------- | -------------- | ------ | ------------------- | 1676| TP_INT | GPIO1_C4 | 0xFF770018 | 9:8 | 2'b00: GPIO | 1677| TP_RST | GPIO4_C6 | 0xFF77E028 | 13:12 | 2'b00: GPIO | 1678| TP_SDA | GPIO2_A7 | 0xFF77E000 | 15:14 | 2'b10: i2c7nfc_sda| 1679| TP_SCL | GPIO2_B0 | 0xFF77E004 | 1:0 | 2'b10: i2c7nfc_scl| 1680