1c5e268c6Sopenharmony_ci/* 2c5e268c6Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd. 3c5e268c6Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4c5e268c6Sopenharmony_ci * you may not use this file except in compliance with the License. 5c5e268c6Sopenharmony_ci * You may obtain a copy of the License at 6c5e268c6Sopenharmony_ci * 7c5e268c6Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8c5e268c6Sopenharmony_ci * 9c5e268c6Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10c5e268c6Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11c5e268c6Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12c5e268c6Sopenharmony_ci * See the License for the specific language governing permissions and 13c5e268c6Sopenharmony_ci * limitations under the License. 14c5e268c6Sopenharmony_ci */ 15c5e268c6Sopenharmony_ci 16c5e268c6Sopenharmony_ci#ifndef DISPLAY_COMMAND_DATA_PACKER_H 17c5e268c6Sopenharmony_ci#define DISPLAY_COMMAND_DATA_PACKER_H 18c5e268c6Sopenharmony_ci 19c5e268c6Sopenharmony_ci#include <memory> 20c5e268c6Sopenharmony_ci#include <securec.h> 21c5e268c6Sopenharmony_ci#include "common/include/display_interface_utils.h" 22c5e268c6Sopenharmony_ci#include "hilog/log.h" 23c5e268c6Sopenharmony_ci 24c5e268c6Sopenharmony_cinamespace OHOS { 25c5e268c6Sopenharmony_cinamespace HDI { 26c5e268c6Sopenharmony_cinamespace Display { 27c5e268c6Sopenharmony_ciclass CommandDataPacker { 28c5e268c6Sopenharmony_cipublic: 29c5e268c6Sopenharmony_ci CommandDataPacker() 30c5e268c6Sopenharmony_ci : packSize_(0), 31c5e268c6Sopenharmony_ci writePos_(0), 32c5e268c6Sopenharmony_ci curSecOffset_(0), 33c5e268c6Sopenharmony_ci settingSecLen_(0), 34c5e268c6Sopenharmony_ci curSecLenPos_(0), 35c5e268c6Sopenharmony_ci data_(nullptr), 36c5e268c6Sopenharmony_ci isAdaptiveGrowth_(false) 37c5e268c6Sopenharmony_ci { 38c5e268c6Sopenharmony_ci } 39c5e268c6Sopenharmony_ci 40c5e268c6Sopenharmony_ci ~CommandDataPacker() 41c5e268c6Sopenharmony_ci { 42c5e268c6Sopenharmony_ci if (data_ != nullptr) { 43c5e268c6Sopenharmony_ci delete[] data_; 44c5e268c6Sopenharmony_ci } 45c5e268c6Sopenharmony_ci } 46c5e268c6Sopenharmony_ci 47c5e268c6Sopenharmony_ci bool Init(size_t size = INIT_DATA_SIZE, bool isAdaptiveGrowth = false) 48c5e268c6Sopenharmony_ci { 49c5e268c6Sopenharmony_ci writePos_ = 0; 50c5e268c6Sopenharmony_ci curSecOffset_ = 0; 51c5e268c6Sopenharmony_ci settingSecLen_ = 0; 52c5e268c6Sopenharmony_ci curSecLenPos_ = 0; 53c5e268c6Sopenharmony_ci isAdaptiveGrowth_ = false; 54c5e268c6Sopenharmony_ci packSize_ = size; 55c5e268c6Sopenharmony_ci uint32_t alignedSize = (packSize_ + ALLOC_PAGE_SIZE - 1) & (~(ALLOC_PAGE_SIZE - 1)); 56c5e268c6Sopenharmony_ci if (data_ != nullptr) { 57c5e268c6Sopenharmony_ci delete[] data_; 58c5e268c6Sopenharmony_ci } 59c5e268c6Sopenharmony_ci data_ = new char[alignedSize]; 60c5e268c6Sopenharmony_ci DISPLAY_CHK_RETURN(data_ == nullptr, false, 61c5e268c6Sopenharmony_ci HDF_LOGE("%{public}s, alloc memory failed", __func__)); 62c5e268c6Sopenharmony_ci packSize_ = alignedSize; 63c5e268c6Sopenharmony_ci isAdaptiveGrowth_ = isAdaptiveGrowth; 64c5e268c6Sopenharmony_ci return true; 65c5e268c6Sopenharmony_ci } 66c5e268c6Sopenharmony_ci 67c5e268c6Sopenharmony_ci bool WriteUint64(uint64_t value) 68c5e268c6Sopenharmony_ci { 69c5e268c6Sopenharmony_ci return Write<uint64_t>(value); 70c5e268c6Sopenharmony_ci } 71c5e268c6Sopenharmony_ci 72c5e268c6Sopenharmony_ci bool WriteUint32(uint32_t value) 73c5e268c6Sopenharmony_ci { 74c5e268c6Sopenharmony_ci return Write<uint32_t>(value); 75c5e268c6Sopenharmony_ci } 76c5e268c6Sopenharmony_ci 77c5e268c6Sopenharmony_ci bool WriteUint8(uint8_t value) 78c5e268c6Sopenharmony_ci { 79c5e268c6Sopenharmony_ci return Write<uint32_t>(value); 80c5e268c6Sopenharmony_ci } 81c5e268c6Sopenharmony_ci 82c5e268c6Sopenharmony_ci bool WriteInt32(int32_t value) 83c5e268c6Sopenharmony_ci { 84c5e268c6Sopenharmony_ci return Write<int32_t>(value); 85c5e268c6Sopenharmony_ci } 86c5e268c6Sopenharmony_ci 87c5e268c6Sopenharmony_ci bool WriteBool(bool value) 88c5e268c6Sopenharmony_ci { 89c5e268c6Sopenharmony_ci return Write<int32_t>(value); 90c5e268c6Sopenharmony_ci } 91c5e268c6Sopenharmony_ci 92c5e268c6Sopenharmony_ci size_t ValidSize() 93c5e268c6Sopenharmony_ci { 94c5e268c6Sopenharmony_ci return writePos_; 95c5e268c6Sopenharmony_ci } 96c5e268c6Sopenharmony_ci 97c5e268c6Sopenharmony_ci size_t PackSize() 98c5e268c6Sopenharmony_ci { 99c5e268c6Sopenharmony_ci return packSize_; 100c5e268c6Sopenharmony_ci } 101c5e268c6Sopenharmony_ci 102c5e268c6Sopenharmony_ci char *GetDataPtr() 103c5e268c6Sopenharmony_ci { 104c5e268c6Sopenharmony_ci return data_; 105c5e268c6Sopenharmony_ci } 106c5e268c6Sopenharmony_ci 107c5e268c6Sopenharmony_ci void RollBack(size_t writePos) 108c5e268c6Sopenharmony_ci { 109c5e268c6Sopenharmony_ci writePos_ = writePos; 110c5e268c6Sopenharmony_ci } 111c5e268c6Sopenharmony_ci 112c5e268c6Sopenharmony_ci bool PackBegin(int32_t beginCmd) 113c5e268c6Sopenharmony_ci { 114c5e268c6Sopenharmony_ci writePos_ = 0; 115c5e268c6Sopenharmony_ci settingSecLen_ = sizeof(int32_t); 116c5e268c6Sopenharmony_ci curSecLenPos_ = 0; 117c5e268c6Sopenharmony_ci curSecOffset_ = writePos_; 118c5e268c6Sopenharmony_ci DISPLAY_CHK_RETURN(WriteInt32(beginCmd) == false, false, 119c5e268c6Sopenharmony_ci HDF_LOGE("%{public}s, write beginCmd error", __func__)); 120c5e268c6Sopenharmony_ci return true; 121c5e268c6Sopenharmony_ci } 122c5e268c6Sopenharmony_ci 123c5e268c6Sopenharmony_ci bool BeginSection(int32_t cmdId, uint32_t len = 0) 124c5e268c6Sopenharmony_ci { 125c5e268c6Sopenharmony_ci // len must be 4 byte alignment. 126c5e268c6Sopenharmony_ci DISPLAY_CHK_RETURN((len & SECTION_LEN_ALIGN - 1) != 0, false, 127c5e268c6Sopenharmony_ci HDF_LOGE("%{public}s, length is not aligned by 4 bytes", __func__)); 128c5e268c6Sopenharmony_ci // Update current data before next section. 129c5e268c6Sopenharmony_ci curSecOffset_ = writePos_; 130c5e268c6Sopenharmony_ci DISPLAY_CHK_RETURN(WriteUint32(SECTION_END_MAGIC) == false, false, 131c5e268c6Sopenharmony_ci HDF_LOGE("%{public}s, write SECTION_END_MAGIC error", __func__)); 132c5e268c6Sopenharmony_ci DISPLAY_CHK_RETURN(WriteInt32(cmdId) == false, false, 133c5e268c6Sopenharmony_ci HDF_LOGE("%{public}s, write cmdID error", __func__)); 134c5e268c6Sopenharmony_ci curSecLenPos_ = writePos_; 135c5e268c6Sopenharmony_ci settingSecLen_ = len; 136c5e268c6Sopenharmony_ci // Now we don't write section len here, 137c5e268c6Sopenharmony_ci // but write it on EndSection. 138c5e268c6Sopenharmony_ci writePos_ += sizeof(uint32_t); 139c5e268c6Sopenharmony_ci return true; 140c5e268c6Sopenharmony_ci } 141c5e268c6Sopenharmony_ci 142c5e268c6Sopenharmony_ci bool EndSection() 143c5e268c6Sopenharmony_ci { 144c5e268c6Sopenharmony_ci // Write cmd len before data related is updated. 145c5e268c6Sopenharmony_ci DISPLAY_CHK_RETURN(writePos_ < curSecOffset_, false, 146c5e268c6Sopenharmony_ci HDF_LOGE("%{public}s, error: writePos_ after curSecOffset_", __func__)); 147c5e268c6Sopenharmony_ci // Write cmd len before data related is updated. 148c5e268c6Sopenharmony_ci uint32_t actualLen = writePos_ - curSecOffset_; 149c5e268c6Sopenharmony_ci uint32_t updatedLen = actualLen > settingSecLen_ ? actualLen : settingSecLen_; 150c5e268c6Sopenharmony_ci // We must check "writePos" < packSize_ Before write 151c5e268c6Sopenharmony_ci if ((curSecLenPos_ + sizeof(updatedLen)) > packSize_) { 152c5e268c6Sopenharmony_ci HDF_LOGE("%{public}s, error: current pos > packSize", __func__); 153c5e268c6Sopenharmony_ci return false; 154c5e268c6Sopenharmony_ci } else { 155c5e268c6Sopenharmony_ci *reinterpret_cast<uint32_t *>(data_ + curSecLenPos_) = updatedLen; 156c5e268c6Sopenharmony_ci } 157c5e268c6Sopenharmony_ci writePos_ = curSecOffset_ + updatedLen; 158c5e268c6Sopenharmony_ci 159c5e268c6Sopenharmony_ci DISPLAY_CHK_RETURN(writePos_ >= packSize_, false, 160c5e268c6Sopenharmony_ci HDF_LOGE("%{public}s, error: writePos_ > packSize", __func__)); 161c5e268c6Sopenharmony_ci return true; 162c5e268c6Sopenharmony_ci } 163c5e268c6Sopenharmony_ci 164c5e268c6Sopenharmony_ci bool PackEnd(int32_t endCmd) 165c5e268c6Sopenharmony_ci { 166c5e268c6Sopenharmony_ci DISPLAY_CHK_RETURN(WriteInt32(endCmd) == false, false, 167c5e268c6Sopenharmony_ci HDF_LOGE("%{public}s, write endCmd error", __func__)); 168c5e268c6Sopenharmony_ci DISPLAY_CHK_RETURN(writePos_ >= packSize_, false, 169c5e268c6Sopenharmony_ci HDF_LOGE("%{public}s, error: writePos_ > packSize", __func__)); 170c5e268c6Sopenharmony_ci return true; 171c5e268c6Sopenharmony_ci } 172c5e268c6Sopenharmony_ci 173c5e268c6Sopenharmony_ci void Dump() 174c5e268c6Sopenharmony_ci { 175c5e268c6Sopenharmony_ci HDF_LOGI("---------------------------------------------\n"); 176c5e268c6Sopenharmony_ci HDF_LOGI("ALLOC_PAGE_SIZE =%{public}d\n", ALLOC_PAGE_SIZE); 177c5e268c6Sopenharmony_ci HDF_LOGI("INIT_DATA_SIZE =%{public}d\n", INIT_DATA_SIZE); 178c5e268c6Sopenharmony_ci HDF_LOGI("SECTION_END_MAGIC =0x%{public}x\n", SECTION_END_MAGIC); 179c5e268c6Sopenharmony_ci HDF_LOGI("packSize_ =%{public}zu\n", packSize_); 180c5e268c6Sopenharmony_ci HDF_LOGI("writePos_ =%{public}zu\n", writePos_); 181c5e268c6Sopenharmony_ci HDF_LOGI("curSecOffset_ =%{public}zu\n", curSecOffset_); 182c5e268c6Sopenharmony_ci HDF_LOGI("settingSecLen_ =%{public}d\n", settingSecLen_); 183c5e268c6Sopenharmony_ci HDF_LOGI("curSecLenPos_ =%{public}zu\n", curSecLenPos_); 184c5e268c6Sopenharmony_ci uint32_t i = 0; 185c5e268c6Sopenharmony_ci for (; sizeof(int32_t) * i < writePos_;) { 186c5e268c6Sopenharmony_ci HDF_LOGI("%{public}08x ", *reinterpret_cast<uint32_t *>(data_ + sizeof(int32_t) * i)); 187c5e268c6Sopenharmony_ci i++; 188c5e268c6Sopenharmony_ci if ((i % DUMP_LINE_LEN) == 0) { 189c5e268c6Sopenharmony_ci HDF_LOGI("\n"); 190c5e268c6Sopenharmony_ci } else if ((i % DUMP_HALF_LINE_SPACE) == 0) { 191c5e268c6Sopenharmony_ci HDF_LOGI(" "); 192c5e268c6Sopenharmony_ci } else { 193c5e268c6Sopenharmony_ci } 194c5e268c6Sopenharmony_ci } 195c5e268c6Sopenharmony_ci HDF_LOGI("\n"); 196c5e268c6Sopenharmony_ci } 197c5e268c6Sopenharmony_ci 198c5e268c6Sopenharmony_ciprivate: 199c5e268c6Sopenharmony_ci template <typename T> 200c5e268c6Sopenharmony_ci bool Write(T value) 201c5e268c6Sopenharmony_ci { 202c5e268c6Sopenharmony_ci size_t writeSize = sizeof(T); 203c5e268c6Sopenharmony_ci size_t newSize = writePos_ + writeSize; 204c5e268c6Sopenharmony_ci if (newSize > packSize_) { 205c5e268c6Sopenharmony_ci if (!isAdaptiveGrowth_) { 206c5e268c6Sopenharmony_ci HDF_LOGE("%{public}s: command packer is overflow", __func__); 207c5e268c6Sopenharmony_ci return false; 208c5e268c6Sopenharmony_ci } 209c5e268c6Sopenharmony_ci newSize = (newSize + ALLOC_PAGE_SIZE - 1) & (~(ALLOC_PAGE_SIZE - 1)); 210c5e268c6Sopenharmony_ci char *newData = new char[newSize]; 211c5e268c6Sopenharmony_ci if (newData == nullptr) { 212c5e268c6Sopenharmony_ci HDF_LOGE("%{public}s: mem alloc failed", __func__); 213c5e268c6Sopenharmony_ci return false; 214c5e268c6Sopenharmony_ci } 215c5e268c6Sopenharmony_ci if (memcpy_s(newData, newSize, data_, packSize_) != EOK) { 216c5e268c6Sopenharmony_ci HDF_LOGE("%{public}s: memcpy_s failed", __func__); 217c5e268c6Sopenharmony_ci delete[] newData; 218c5e268c6Sopenharmony_ci newData = nullptr; 219c5e268c6Sopenharmony_ci return false; 220c5e268c6Sopenharmony_ci } 221c5e268c6Sopenharmony_ci delete[] data_; 222c5e268c6Sopenharmony_ci data_ = newData; 223c5e268c6Sopenharmony_ci packSize_ = newSize; 224c5e268c6Sopenharmony_ci } 225c5e268c6Sopenharmony_ci *reinterpret_cast<T *>(data_ + writePos_) = value; 226c5e268c6Sopenharmony_ci writePos_ += writeSize; 227c5e268c6Sopenharmony_ci 228c5e268c6Sopenharmony_ci return true; 229c5e268c6Sopenharmony_ci } 230c5e268c6Sopenharmony_ci 231c5e268c6Sopenharmony_ciprivate: 232c5e268c6Sopenharmony_ci static constexpr uint32_t ALLOC_PAGE_SIZE = 1024; 233c5e268c6Sopenharmony_ci static constexpr uint32_t INIT_DATA_SIZE = 32 * ALLOC_PAGE_SIZE; 234c5e268c6Sopenharmony_ci static constexpr uint32_t SECTION_END_MAGIC = 0xB5B5B5B5; 235c5e268c6Sopenharmony_ci static constexpr uint32_t SECTION_LEN_ALIGN = 4; 236c5e268c6Sopenharmony_ci static constexpr uint32_t DUMP_HALF_LINE_SPACE = 4; 237c5e268c6Sopenharmony_ci static constexpr uint32_t DUMP_LINE_LEN = 8; 238c5e268c6Sopenharmony_ci 239c5e268c6Sopenharmony_ciprivate: 240c5e268c6Sopenharmony_ci size_t packSize_; 241c5e268c6Sopenharmony_ci size_t writePos_; 242c5e268c6Sopenharmony_ci size_t curSecOffset_; 243c5e268c6Sopenharmony_ci uint32_t settingSecLen_; 244c5e268c6Sopenharmony_ci size_t curSecLenPos_; 245c5e268c6Sopenharmony_ci char *data_; 246c5e268c6Sopenharmony_ci bool isAdaptiveGrowth_; 247c5e268c6Sopenharmony_ci}; 248c5e268c6Sopenharmony_ci} // namespace Display 249c5e268c6Sopenharmony_ci} // namespace HDI 250c5e268c6Sopenharmony_ci} // namespace OHOS 251c5e268c6Sopenharmony_ci#endif // DISPLAY_COMMAND_DATA_PACKER_H 252