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