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