1 /*
2 * Copyright (c) 2021-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
16 #include "surface_dev.h"
17 #include <cerrno>
18 #include <cstring>
19 #include <drm_fourcc.h>
20 #include <fcntl.h>
21 #include <sys/mman.h>
22 #include <xf86drm.h>
23 #include <xf86drmMode.h>
24 #include <linux/fb.h>
25 #include "securec.h"
26 #include "battery_log.h"
27
28 namespace OHOS {
29 namespace HDI {
30 namespace Battery {
31 namespace V1_1 {
32 struct BufferObject {
33 uint32_t width;
34 uint32_t height;
35 uint32_t pitch;
36 uint32_t handle;
37 uint32_t size;
38 uint8_t* vaddr;
39 uint32_t fbId;
40 };
41
42 struct BufferObject g_buff;
43
Flip(char * buf)44 void SurfaceDev::Flip(char* buf)
45 {
46 if (!buf) {
47 BATTERY_HILOGE(FEATURE_CHARGING, "buf is null.");
48 return;
49 }
50 if (memcpy_s(g_buff.vaddr, g_buff.size, static_cast<void*>(buf), g_buff.size) != EOK) {
51 BATTERY_HILOGE(FEATURE_CHARGING, "memcpy_s fail.");
52 return;
53 }
54 }
55
ModesetCreateFb(int32_t fd,struct BufferObject * bo)56 static int32_t ModesetCreateFb(int32_t fd, struct BufferObject* bo)
57 {
58 struct drm_mode_create_dumb create = {};
59 struct drm_mode_map_dumb map = {};
60 const int32_t offsetNumber = 4;
61 uint32_t handles[offsetNumber] = {0};
62 uint32_t pitches[offsetNumber] = {0};
63 uint32_t offsets[offsetNumber] = {0};
64 int32_t ret;
65
66 /* create a dumb-buffer, the pixel format is XRGB888 */
67 const int32_t pixelDepth = 32;
68 create.width = bo->width;
69 create.height = bo->height;
70 create.bpp = pixelDepth;
71 drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &create);
72
73 /* bind the dumb-buffer to an FB object */
74 bo->pitch = create.pitch;
75 bo->size = create.size;
76 bo->handle = create.handle;
77
78 handles[0] = bo->handle;
79 pitches[0] = bo->pitch;
80 offsets[0] = 0;
81 ret = drmModeAddFB2(fd, bo->width, bo->height, DRM_FORMAT_ARGB8888, handles, pitches, offsets, &bo->fbId, 0);
82 if (ret) {
83 BATTERY_HILOGD(FEATURE_CHARGING, "[fbtest]failed to add fb %{public}d x %{public}d: errno %{public}s", \
84 bo->width, bo->height, strerror(errno));
85 return -1;
86 }
87
88 /* map the dumb-buffer to userspace */
89 map.handle = create.handle;
90 drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &map);
91 bo->vaddr = static_cast<uint8_t*>(mmap(0, create.size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, map.offset));
92 const uint32_t newColor = 0xff00ff00;
93 uint32_t i = 0;
94 uint32_t color = newColor;
95 while (i < bo->size) {
96 if (memcpy_s(&bo->vaddr[i], bo->size, &color, sizeof(color)) != EOK) {
97 BATTERY_HILOGE(FEATURE_CHARGING, "memcpy_s fail.");
98 return -1;
99 }
100 i += sizeof(color);
101 }
102 return 0;
103 }
104
DrmInit(void)105 int32_t DrmInit(void)
106 {
107 BATTERY_HILOGD(FEATURE_CHARGING, "start init drm");
108 int32_t fd = -1;
109 drmModeConnector* conn;
110 uint32_t connId;
111 uint32_t crtcId;
112 fd = open("/dev/dri/card0", O_RDWR | O_CLOEXEC);
113 if (fd < 0) {
114 BATTERY_HILOGE(FEATURE_CHARGING, "open failed.");
115 return -1;
116 }
117
118 drmModeRes* res = drmModeGetResources(fd);
119 if (res == nullptr) {
120 BATTERY_HILOGE(FEATURE_CHARGING, "res is nullptr");
121 return -1;
122 }
123
124 crtcId = res->crtcs[0];
125 connId = res->connectors[1];
126 conn = drmModeGetConnector(fd, connId);
127 if (conn == nullptr) {
128 BATTERY_HILOGE(FEATURE_CHARGING, "conn is nullptr");
129 return -1;
130 }
131 g_buff.width = conn->modes[0].hdisplay;
132 g_buff.height = conn->modes[0].vdisplay;
133
134 ModesetCreateFb(fd, &g_buff);
135 drmModeSetCrtc(fd, crtcId, g_buff.fbId, 0, 0, &connId, 1, &conn->modes[0]);
136 BATTERY_HILOGD(FEATURE_CHARGING, "drm init success");
137 return 0;
138 }
139
SurfaceDev(SurfaceDev::DevType devType)140 SurfaceDev::SurfaceDev(SurfaceDev::DevType devType)
141 {
142 if (devType == SurfaceDev::DevType::DRM_DEVICE) {
143 DrmInit();
144 } else {
145 BATTERY_HILOGE(FEATURE_CHARGING, "only support drm driver.");
146 }
147 }
148
GetScreenSize(int32_t & w,int32_t & h)149 void SurfaceDev::GetScreenSize(int32_t& w, int32_t& h)
150 {
151 const int32_t screenSizeW = 480;
152 const int32_t screenSizeH = 960;
153 w = screenSizeW;
154 h = screenSizeH;
155 }
156 } // namespace V1_1
157 } // namespace Battery
158 } // namespace HDI
159 } // namespace OHOS
160