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 writePos_ = 0; 50 curSecOffset_ = 0; 51 settingSecLen_ = 0; 52 curSecLenPos_ = 0; 53 isAdaptiveGrowth_ = false; 54 packSize_ = size; 55 uint32_t alignedSize = (packSize_ + ALLOC_PAGE_SIZE - 1) & (~(ALLOC_PAGE_SIZE - 1)); 56 if (data_ != nullptr) { 57 delete[] data_; 58 } 59 data_ = new char[alignedSize]; 60 DISPLAY_CHK_RETURN(data_ == nullptr, false, 61 HDF_LOGE("%{public}s, alloc memory failed", __func__)); 62 packSize_ = alignedSize; 63 isAdaptiveGrowth_ = isAdaptiveGrowth; 64 return true; 65 } 66 WriteUint64(uint64_t value)67 bool WriteUint64(uint64_t value) 68 { 69 return Write<uint64_t>(value); 70 } 71 WriteUint32(uint32_t value)72 bool WriteUint32(uint32_t value) 73 { 74 return Write<uint32_t>(value); 75 } 76 WriteUint8(uint8_t value)77 bool WriteUint8(uint8_t value) 78 { 79 return Write<uint32_t>(value); 80 } 81 WriteInt32(int32_t value)82 bool WriteInt32(int32_t value) 83 { 84 return Write<int32_t>(value); 85 } 86 WriteBool(bool value)87 bool WriteBool(bool value) 88 { 89 return Write<int32_t>(value); 90 } 91 ValidSize()92 size_t ValidSize() 93 { 94 return writePos_; 95 } 96 PackSize()97 size_t PackSize() 98 { 99 return packSize_; 100 } 101 GetDataPtr()102 char *GetDataPtr() 103 { 104 return data_; 105 } 106 RollBack(int32_t writePos)107 void RollBack(int32_t writePos) 108 { 109 writePos_ = writePos; 110 } 111 PackBegin(int32_t beginCmd)112 bool PackBegin(int32_t beginCmd) 113 { 114 writePos_ = 0; 115 settingSecLen_ = sizeof(int32_t); 116 curSecLenPos_ = 0; 117 curSecOffset_ = writePos_; 118 DISPLAY_CHK_RETURN(WriteInt32(beginCmd) == false, false, 119 HDF_LOGE("%{public}s, write beginCmd error", __func__)); 120 return true; 121 } 122 123 bool BeginSection(int32_t cmdId, uint32_t len = 0) 124 { 125 // len must be 4 byte alignment. 126 DISPLAY_CHK_RETURN((len & SECTION_LEN_ALIGN - 1) != 0, false, 127 HDF_LOGE("%{public}s, length is not aligned by 4 bytes", __func__)); 128 // Update current data before next section. 129 curSecOffset_ = writePos_; 130 DISPLAY_CHK_RETURN(WriteUint32(SECTION_END_MAGIC) == false, false, 131 HDF_LOGE("%{public}s, write SECTION_END_MAGIC error", __func__)); 132 DISPLAY_CHK_RETURN(WriteInt32(cmdId) == false, false, 133 HDF_LOGE("%{public}s, write cmdID error", __func__)); 134 curSecLenPos_ = writePos_; 135 settingSecLen_ = len; 136 // Now we don't write section len here, 137 // but write it on EndSection. 138 writePos_ += sizeof(uint32_t); 139 return true; 140 } 141 EndSection()142 bool EndSection() 143 { 144 // Write cmd len before data related is updated. 145 DISPLAY_CHK_RETURN(writePos_ < curSecOffset_, false, 146 HDF_LOGE("%{public}s, error: writePos_ after curSecOffset_", __func__)); 147 // Write cmd len before data related is updated. 148 uint32_t actualLen = writePos_ - curSecOffset_; 149 uint32_t updatedLen = actualLen > settingSecLen_ ? actualLen : settingSecLen_; 150 // We must check "writePos" < packSize_ Before write 151 if ((curSecLenPos_ + sizeof(updatedLen)) > packSize_) { 152 HDF_LOGE("%{public}s, error: current pos > packSize", __func__); 153 return false; 154 } else { 155 *reinterpret_cast<uint32_t *>(data_ + curSecLenPos_) = updatedLen; 156 } 157 writePos_ = curSecOffset_ + updatedLen; 158 159 DISPLAY_CHK_RETURN(writePos_ >= packSize_, false, 160 HDF_LOGE("%{public}s, error: writePos_ > packSize", __func__)); 161 return true; 162 } 163 PackEnd(int32_t endCmd)164 bool PackEnd(int32_t endCmd) 165 { 166 DISPLAY_CHK_RETURN(WriteInt32(endCmd) == false, false, 167 HDF_LOGE("%{public}s, write endCmd error", __func__)); 168 DISPLAY_CHK_RETURN(writePos_ >= packSize_, false, 169 HDF_LOGE("%{public}s, error: writePos_ > packSize", __func__)); 170 return true; 171 } 172 Dump()173 void Dump() 174 { 175 HDF_LOGI("---------------------------------------------\n"); 176 HDF_LOGI("ALLOC_PAGE_SIZE =%{public}d\n", ALLOC_PAGE_SIZE); 177 HDF_LOGI("INIT_DATA_SIZE =%{public}d\n", INIT_DATA_SIZE); 178 HDF_LOGI("SECTION_END_MAGIC =0x%{public}x\n", SECTION_END_MAGIC); 179 HDF_LOGI("packSize_ =%{public}zu\n", packSize_); 180 HDF_LOGI("writePos_ =%{public}zu\n", writePos_); 181 HDF_LOGI("curSecOffset_ =%{public}zu\n", curSecOffset_); 182 HDF_LOGI("settingSecLen_ =%{public}d\n", settingSecLen_); 183 HDF_LOGI("curSecLenPos_ =%{public}zu\n", curSecLenPos_); 184 uint32_t i = 0; 185 for (; sizeof(int32_t) * i < writePos_;) { 186 HDF_LOGI("%{public}08x ", *reinterpret_cast<uint32_t *>(data_ + sizeof(int32_t) * i)); 187 i++; 188 if ((i % DUMP_LINE_LEN) == 0) { 189 HDF_LOGI("\n"); 190 } else if ((i % DUMP_HALF_LINE_SPACE) == 0) { 191 HDF_LOGI(" "); 192 } else { 193 } 194 } 195 HDF_LOGI("\n"); 196 } 197 198 private: 199 template <typename T> Write(T value)200 bool Write(T value) 201 { 202 size_t writeSize = sizeof(T); 203 size_t newSize = writePos_ + writeSize; 204 if (newSize > packSize_) { 205 if (!isAdaptiveGrowth_) { 206 HDF_LOGE("%{public}s: command packer is overflow", __func__); 207 return false; 208 } 209 newSize = (newSize + ALLOC_PAGE_SIZE - 1) & (~(ALLOC_PAGE_SIZE - 1)); 210 char *newData = new char[newSize]; 211 if (newData == nullptr) { 212 HDF_LOGE("%{public}s: mem alloc failed", __func__); 213 return false; 214 } 215 if (memcpy_s(newData, newSize, data_, packSize_) != EOK) { 216 HDF_LOGE("%{public}s: memcpy_s failed", __func__); 217 delete[] newData; 218 newData = nullptr; 219 return false; 220 } 221 delete[] data_; 222 data_ = newData; 223 packSize_ = newSize; 224 } 225 *reinterpret_cast<T *>(data_ + writePos_) = value; 226 writePos_ += writeSize; 227 228 return true; 229 } 230 231 private: 232 static constexpr uint32_t ALLOC_PAGE_SIZE = 1024; 233 static constexpr uint32_t INIT_DATA_SIZE = 32 * ALLOC_PAGE_SIZE; 234 static constexpr uint32_t SECTION_END_MAGIC = 0xB5B5B5B5; 235 static constexpr uint32_t SECTION_LEN_ALIGN = 4; 236 static constexpr uint32_t DUMP_HALF_LINE_SPACE = 4; 237 static constexpr uint32_t DUMP_LINE_LEN = 8; 238 239 private: 240 size_t packSize_; 241 size_t writePos_; 242 size_t curSecOffset_; 243 uint32_t settingSecLen_; 244 size_t curSecLenPos_; 245 char *data_; 246 bool isAdaptiveGrowth_; 247 }; 248 } // namespace Display 249 } // namespace HDI 250 } // namespace OHOS 251 #endif // DISPLAY_COMMAND_DATA_PACKER_H 252