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