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 
29 namespace OHOS {
30 namespace PowerMgr {
~FbdevDriver()31 FbdevDriver::~FbdevDriver()
32 {
33     ReleaseFb(&buff_);
34 }
35 
Init()36 bool 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 
Flip(const uint8_t * buf)77 void 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 
GetDisplayInfo(DisplayInfo & dsInfo)87 void 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 
Blank(bool blank)95 void FbdevDriver::Blank(bool blank)
96 {
97     FbPowerContrl(fd_, !blank);
98     if (blankHook_ != nullptr) {
99         blankHook_(fd_, blank);
100     }
101 }
102 
Exit()103 void FbdevDriver::Exit()
104 {
105     ReleaseFb(&buff_);
106 }
107 
SetDevPath(const std::string & devPath)108 void FbdevDriver::SetDevPath(const std::string& devPath)
109 {
110     devPath_ = devPath;
111 }
112 
RegisterBlankHook(FbBlankHook blankHook)113 void FbdevDriver::RegisterBlankHook(FbBlankHook blankHook)
114 {
115     blankHook_ = blankHook;
116 }
117 
ReleaseFb(const struct FbBufferObject * fbo)118 void 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 
FbPowerContrl(int fd,bool powerOn)132 bool 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