1/* 2 * Copyright (c) 2022 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 "fbdev_driver.h" 16 17#include <cstdio> 18#include <cstdlib> 19#include <cstring> 20#include <memory> 21#include <fcntl.h> 22#include <sys/ioctl.h> 23#include <sys/mman.h> 24#include <sys/types.h> 25#include <unistd.h> 26#include "log/log.h" 27#include "securec.h" 28#include "ui_rotation.h" 29#include "updater_ui_const.h" 30 31namespace Updater { 32FbdevDriver::~FbdevDriver() 33{ 34 ReleaseFb(&buff_); 35} 36 37void FbdevDriver::FBLog() const 38{ 39 LOG(INFO) << "id=" << finfo_.id; 40 LOG(INFO) << "sem_start=" << finfo_.smem_start; 41 LOG(INFO) << "smem_len=" << finfo_.smem_len; 42 LOG(INFO) << "type=" << finfo_.type; 43 LOG(INFO) << "line_length=" << finfo_.line_length; 44 LOG(INFO) << "mmio_start=" << finfo_.mmio_start; 45 LOG(INFO) << "mmio_len=" << finfo_.mmio_len; 46 LOG(INFO) << "visual=" << finfo_.visual; 47 48 LOG(INFO) << "The xres=" << vinfo_.xres; 49 LOG(INFO) << "The yres=" << vinfo_.yres; 50 LOG(INFO) << "xres_virtual=" << vinfo_.xres_virtual; 51 LOG(INFO) << "yres_virtual=" << vinfo_.yres_virtual; 52 LOG(INFO) << "xoffset=" << vinfo_.xoffset; 53 LOG(INFO) << "yoffset=" << vinfo_.yoffset; 54 LOG(INFO) << "bits_per_pixel is :" << vinfo_.bits_per_pixel; 55 LOG(INFO) << "red.offset=" << vinfo_.red.offset; 56 LOG(INFO) << "red.length=" << vinfo_.red.length; 57 LOG(INFO) << "red.msb_right=" << vinfo_.red.msb_right; 58 LOG(INFO) << "green.offset=" << vinfo_.green.offset; 59 LOG(INFO) << "green.length=" << vinfo_.green.length; 60 LOG(INFO) << "green.msb_right=" << vinfo_.green.msb_right; 61 LOG(INFO) << "blue.offset=" << vinfo_.blue.offset; 62 LOG(INFO) << "blue.length=" << vinfo_.blue.length; 63 LOG(INFO) << "blue.msb_right=" << vinfo_.blue.msb_right; 64 LOG(INFO) << "transp.offset=" << vinfo_.transp.offset; 65 LOG(INFO) << "transp.length=" << vinfo_.transp.length; 66 LOG(INFO) << "transp.msb_right=" << vinfo_.transp.msb_right; 67 LOG(INFO) << "height=" << vinfo_.height; 68} 69 70bool FbdevDriver::Init() 71{ 72 if (devPath_.empty()) { 73 LOG(ERROR) << "dev path is empty, init failed, check whether SetDevPath correctly called"; 74 return false; 75 } 76 int fd = open(devPath_.c_str(), O_RDWR | O_CLOEXEC); 77 if (fd < 0) { 78 LOG(ERROR) << "cannot open fb0"; 79 return false; 80 } 81 82 (void)FbPowerContrl(fd, false); 83 (void)FbPowerContrl(fd, true); 84 85 if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo_) < 0) { 86 LOG(ERROR) << "failed to get fb0 info"; 87 close(fd); 88 return false; 89 } 90 91 if (ioctl(fd, FBIOGET_VSCREENINFO, &vinfo_) < 0) { 92 LOG(ERROR) << "failed to get fb0 info"; 93 close(fd); 94 return false; 95 } 96 97 FBLog(); 98 99 buff_.width = vinfo_.xres; 100 buff_.height = vinfo_.yres; 101 buff_.size = finfo_.line_length * vinfo_.yres; 102 buff_.vaddr = mmap(nullptr, finfo_.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 103 if (buff_.vaddr == MAP_FAILED) { 104 LOG(ERROR) << "failed to mmap framebuffer"; 105 close(fd); 106 return false; 107 } 108 (void)memset_s(buff_.vaddr, finfo_.smem_len, 0, finfo_.smem_len); 109 fd_ = fd; 110 return true; 111} 112 113void FbdevDriver::Flip(const uint8_t *buf) 114{ 115 if (fd_ < 0) { 116 return; 117 } 118 UiRotation::GetInstance().RotateBuffer(buf, static_cast<uint8_t *>(buff_.vaddr), buff_.size); 119 if (ioctl(fd_, FBIOPAN_DISPLAY, &vinfo_) < 0) { 120 LOG(ERROR) << "failed to display fb0!"; 121 } 122} 123 124void FbdevDriver::GetGrSurface(GrSurface &surface) 125{ 126 surface.height = static_cast<int>(vinfo_.yres); 127 surface.rowBytes = finfo_.line_length; 128 surface.pixelBytes = vinfo_.bits_per_pixel / 8; // 8: byte bit len 129 surface.width = static_cast<int>(surface.rowBytes / surface.pixelBytes); 130} 131 132void FbdevDriver::Blank(bool blank) 133{ 134 FbPowerContrl(fd_, !blank); 135 if (blankHook_ != nullptr) { 136 blankHook_(fd_, blank); 137 } 138} 139 140void FbdevDriver::Exit(void) 141{ 142 ReleaseFb(&buff_); 143} 144 145void FbdevDriver::SetDevPath(const std::string &devPath) 146{ 147 devPath_ = devPath; 148} 149 150void FbdevDriver::RegisterBlankHook(FbBlankHook blankHook) 151{ 152 blankHook_ = blankHook; 153} 154 155void FbdevDriver::ReleaseFb(const struct FbBufferObject *fbo) 156{ 157 /* 158 * When fd_ isn't less than 0, then fbo->vaddr is valid and can by safely munmap. 159 * this can be guaranteed by FbdevDriver::Init. 160 */ 161 if (fd_ < 0) { 162 return; 163 } 164 munmap(fbo->vaddr, fbo->size); 165 close(fd_); 166 fd_ = -1; 167} 168 169bool FbdevDriver::FbPowerContrl(int fd, bool powerOn) 170{ 171 if (fd < 0) { 172 return false; 173 } 174 if (ioctl(fd, FBIOBLANK, powerOn ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN) < 0) { 175 LOG(ERROR) << "failed to set fb0 power " << powerOn; 176 return false; 177 } 178 return true; 179} 180} // namespace Updater 181