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#include "dev/fbdev_driver.h"
16#include "charger_log.h"
17
18#include "securec.h"
19#include <cstdio>
20#include <cstdlib>
21#include <cstring>
22#include <fcntl.h>
23#include <memory>
24#include <sys/ioctl.h>
25#include <sys/mman.h>
26#include <sys/types.h>
27#include <unistd.h>
28
29namespace OHOS {
30namespace PowerMgr {
31FbdevDriver::~FbdevDriver()
32{
33    ReleaseFb(&buff_);
34}
35
36bool FbdevDriver::Init()
37{
38    if (devPath_.empty()) {
39        BATTERY_HILOGE(FEATURE_CHARGING, "dev path is empty, init failed, check whether SetDevPath correctly called");
40        return false;
41    }
42    int fd = open(devPath_.c_str(), O_RDWR | O_CLOEXEC);
43    if (fd < 0) {
44        BATTERY_HILOGE(FEATURE_CHARGING, "cannot open fb0");
45        return false;
46    }
47
48    (void)FbPowerContrl(fd, false);
49    (void)FbPowerContrl(fd, true);
50
51    if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo_) < 0) {
52        BATTERY_HILOGE(FEATURE_CHARGING, "failed to get fb0 info");
53        close(fd);
54        return false;
55    }
56
57    if (ioctl(fd, FBIOGET_VSCREENINFO, &vinfo_) < 0) {
58        BATTERY_HILOGE(FEATURE_CHARGING, "failed to get fb0 info");
59        close(fd);
60        return false;
61    }
62
63    buff_.width = vinfo_.xres;
64    buff_.height = vinfo_.yres;
65    buff_.size = finfo_.line_length * vinfo_.yres;
66    buff_.vaddr = mmap(nullptr, finfo_.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
67    if (buff_.vaddr == MAP_FAILED) {
68        BATTERY_HILOGE(FEATURE_CHARGING, "failed to mmap framebuffer");
69        close(fd);
70        return false;
71    }
72    (void)memset_s(buff_.vaddr, finfo_.smem_len, 0, finfo_.smem_len);
73    fd_ = fd;
74    return true;
75}
76
77void FbdevDriver::Flip(const uint8_t* buf)
78{
79    if (fd_ < 0 || memcpy_s(buff_.vaddr, buff_.size, buf, buff_.size) != EOK) {
80        return;
81    }
82    if (ioctl(fd_, FBIOPAN_DISPLAY, &vinfo_) < 0) {
83        BATTERY_HILOGE(FEATURE_CHARGING, "failed to display fb0!");
84    }
85}
86
87void FbdevDriver::GetDisplayInfo(DisplayInfo& dsInfo)
88{
89    dsInfo.width = static_cast<int>(vinfo_.xres);
90    dsInfo.height = static_cast<int>(vinfo_.yres);
91    dsInfo.rowBytes = finfo_.line_length;
92    dsInfo.pixelBytes = vinfo_.bits_per_pixel / 8; // 8: byte bit len
93}
94
95void FbdevDriver::Blank(bool blank)
96{
97    FbPowerContrl(fd_, !blank);
98    if (blankHook_ != nullptr) {
99        blankHook_(fd_, blank);
100    }
101}
102
103void FbdevDriver::Exit()
104{
105    ReleaseFb(&buff_);
106}
107
108void FbdevDriver::SetDevPath(const std::string& devPath)
109{
110    devPath_ = devPath;
111}
112
113void FbdevDriver::RegisterBlankHook(FbBlankHook blankHook)
114{
115    blankHook_ = blankHook;
116}
117
118void FbdevDriver::ReleaseFb(const struct FbBufferObject* fbo)
119{
120    /*
121     * When fd_ isn't less than 0, then fbo->vaddr is valid and can by safely munmap.
122     * this can be guaranteed by FbdevDriver::Init.
123     */
124    if (fd_ < 0) {
125        return;
126    }
127    munmap(fbo->vaddr, fbo->size);
128    close(fd_);
129    fd_ = -1;
130}
131
132bool FbdevDriver::FbPowerContrl(int fd, bool powerOn)
133{
134    if (fd < 0) {
135        return false;
136    }
137    if (ioctl(fd, FBIOBLANK, powerOn ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN) < 0) {
138        BATTERY_HILOGE(FEATURE_CHARGING, "failed to set fb0, %{public}s", strerror(errno));
139        return false;
140    }
141    return true;
142}
143} // namespace PowerMgr
144} // namespace OHOS
145