1fb299fa2Sopenharmony_ci/*
2fb299fa2Sopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3fb299fa2Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4fb299fa2Sopenharmony_ci * you may not use this file except in compliance with the License.
5fb299fa2Sopenharmony_ci * You may obtain a copy of the License at
6fb299fa2Sopenharmony_ci *
7fb299fa2Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
8fb299fa2Sopenharmony_ci *
9fb299fa2Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10fb299fa2Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11fb299fa2Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12fb299fa2Sopenharmony_ci * See the License for the specific language governing permissions and
13fb299fa2Sopenharmony_ci * limitations under the License.
14fb299fa2Sopenharmony_ci */
15fb299fa2Sopenharmony_ci#include "drm_driver.h"
16fb299fa2Sopenharmony_ci#include <cstdio>
17fb299fa2Sopenharmony_ci#include <unistd.h>
18fb299fa2Sopenharmony_ci#include "log/log.h"
19fb299fa2Sopenharmony_ci#include "securec.h"
20fb299fa2Sopenharmony_ci#include "ui_rotation.h"
21fb299fa2Sopenharmony_ci#include "updater_ui_const.h"
22fb299fa2Sopenharmony_ci
23fb299fa2Sopenharmony_cinamespace Updater {
24fb299fa2Sopenharmony_civoid DrmDriver::Flip(const uint8_t *buf)
25fb299fa2Sopenharmony_ci{
26fb299fa2Sopenharmony_ci    if (buff_.vaddr != MAP_FAILED) {
27fb299fa2Sopenharmony_ci        UiRotation::GetInstance().RotateBuffer(buf, buff_.vaddr, buff_.size);
28fb299fa2Sopenharmony_ci    }
29fb299fa2Sopenharmony_ci}
30fb299fa2Sopenharmony_ci
31fb299fa2Sopenharmony_civoid DrmDriver::Blank(bool blank)
32fb299fa2Sopenharmony_ci{
33fb299fa2Sopenharmony_ci    LOG(INFO) << "drm blank";
34fb299fa2Sopenharmony_ci}
35fb299fa2Sopenharmony_ci
36fb299fa2Sopenharmony_civoid DrmDriver::Exit(void)
37fb299fa2Sopenharmony_ci{
38fb299fa2Sopenharmony_ci    ModesetDestroyFb(&buff_);
39fb299fa2Sopenharmony_ci}
40fb299fa2Sopenharmony_ci
41fb299fa2Sopenharmony_civoid DrmDriver::GetGrSurface(GrSurface &surface)
42fb299fa2Sopenharmony_ci{
43fb299fa2Sopenharmony_ci    surface.width = static_cast<int>(buff_.width);
44fb299fa2Sopenharmony_ci    surface.height = static_cast<int>(buff_.height);
45fb299fa2Sopenharmony_ci    surface.rowBytes = 0;
46fb299fa2Sopenharmony_ci    surface.pixelBytes = 0;
47fb299fa2Sopenharmony_ci}
48fb299fa2Sopenharmony_ci
49fb299fa2Sopenharmony_ciint DrmDriver::ModesetCreateFb(struct BufferObject *bo)
50fb299fa2Sopenharmony_ci{
51fb299fa2Sopenharmony_ci    struct drm_mode_create_dumb create = {};
52fb299fa2Sopenharmony_ci    struct drm_mode_map_dumb map = {};
53fb299fa2Sopenharmony_ci    const int offsetNumber = 4;
54fb299fa2Sopenharmony_ci    uint32_t handles[offsetNumber] = {0};
55fb299fa2Sopenharmony_ci    uint32_t pitches[offsetNumber] = {0};
56fb299fa2Sopenharmony_ci    uint32_t offsets[offsetNumber] = {0};
57fb299fa2Sopenharmony_ci
58fb299fa2Sopenharmony_ci    /* create a dumb-buffer, the pixel format is XRGB888 */
59fb299fa2Sopenharmony_ci    const int pixelDepth = 32;
60fb299fa2Sopenharmony_ci    create.width = bo->width;
61fb299fa2Sopenharmony_ci    create.height = bo->height;
62fb299fa2Sopenharmony_ci    create.bpp = pixelDepth;
63fb299fa2Sopenharmony_ci    drmIoctl(fd_, DRM_IOCTL_MODE_CREATE_DUMB, &create);
64fb299fa2Sopenharmony_ci
65fb299fa2Sopenharmony_ci    /* bind the dumb-buffer to an FB object */
66fb299fa2Sopenharmony_ci    bo->pitch = create.pitch;
67fb299fa2Sopenharmony_ci    bo->size = create.size;
68fb299fa2Sopenharmony_ci    bo->handle = create.handle;
69fb299fa2Sopenharmony_ci
70fb299fa2Sopenharmony_ci    handles[0] = bo->handle;
71fb299fa2Sopenharmony_ci    pitches[0] = bo->pitch;
72fb299fa2Sopenharmony_ci    offsets[0] = 0;
73fb299fa2Sopenharmony_ci    int ret = drmModeAddFB2(fd_, bo->width, bo->height, DRM_FORMAT_ARGB8888, handles, pitches, offsets, &bo->fbId, 0);
74fb299fa2Sopenharmony_ci    if (ret) {
75fb299fa2Sopenharmony_ci        LOG(ERROR) << "[fbtest]failed to add fb (" << bo->width << "x" << bo->height << "): " << strerror(errno);
76fb299fa2Sopenharmony_ci        return -1;
77fb299fa2Sopenharmony_ci    }
78fb299fa2Sopenharmony_ci
79fb299fa2Sopenharmony_ci    /* map the dumb-buffer to userspace */
80fb299fa2Sopenharmony_ci    map.handle = create.handle;
81fb299fa2Sopenharmony_ci    drmIoctl(fd_, DRM_IOCTL_MODE_MAP_DUMB, &map);
82fb299fa2Sopenharmony_ci    bo->vaddr = static_cast<uint8_t *>(mmap(0, create.size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_, map.offset));
83fb299fa2Sopenharmony_ci    if (bo->vaddr == MAP_FAILED) {
84fb299fa2Sopenharmony_ci        LOG(ERROR) << "failed to mmap framebuffer";
85fb299fa2Sopenharmony_ci        return -1;
86fb299fa2Sopenharmony_ci    }
87fb299fa2Sopenharmony_ci    const uint32_t newColor = 0xff000000;
88fb299fa2Sopenharmony_ci    uint32_t i = 0;
89fb299fa2Sopenharmony_ci    uint32_t color = newColor;
90fb299fa2Sopenharmony_ci    while (i < bo->size) {
91fb299fa2Sopenharmony_ci        if (memcpy_s(&bo->vaddr[i], bo->size, &color, sizeof(color)) != EOK) {
92fb299fa2Sopenharmony_ci            return -1;
93fb299fa2Sopenharmony_ci        }
94fb299fa2Sopenharmony_ci        i += sizeof(color);
95fb299fa2Sopenharmony_ci    }
96fb299fa2Sopenharmony_ci    return 0;
97fb299fa2Sopenharmony_ci}
98fb299fa2Sopenharmony_ci
99fb299fa2Sopenharmony_cidrmModeCrtc *DrmDriver::GetCrtc(const drmModeRes &res, const int fd, const drmModeConnector &conn) const
100fb299fa2Sopenharmony_ci{
101fb299fa2Sopenharmony_ci    // if connector has one encoder, use it
102fb299fa2Sopenharmony_ci    drmModeEncoder *encoder = nullptr;
103fb299fa2Sopenharmony_ci    if (conn.encoder_id != 0) {
104fb299fa2Sopenharmony_ci        encoder = drmModeGetEncoder(fd, conn.encoder_id);
105fb299fa2Sopenharmony_ci    }
106fb299fa2Sopenharmony_ci    if (encoder != nullptr && encoder->crtc_id != 0) {
107fb299fa2Sopenharmony_ci        uint32_t crtcId = encoder->crtc_id;
108fb299fa2Sopenharmony_ci        drmModeFreeEncoder(encoder);
109fb299fa2Sopenharmony_ci        return drmModeGetCrtc(fd, crtcId);
110fb299fa2Sopenharmony_ci    }
111fb299fa2Sopenharmony_ci
112fb299fa2Sopenharmony_ci    if (encoder != nullptr) {
113fb299fa2Sopenharmony_ci        drmModeFreeEncoder(encoder);
114fb299fa2Sopenharmony_ci    }
115fb299fa2Sopenharmony_ci
116fb299fa2Sopenharmony_ci    // try get a vaild encoder and crtc
117fb299fa2Sopenharmony_ci    for (int i = 0; i < conn.count_encoders; i++) {
118fb299fa2Sopenharmony_ci        encoder = drmModeGetEncoder(fd, conn.encoders[i]);
119fb299fa2Sopenharmony_ci        if (encoder == nullptr) {
120fb299fa2Sopenharmony_ci            continue;
121fb299fa2Sopenharmony_ci        }
122fb299fa2Sopenharmony_ci
123fb299fa2Sopenharmony_ci        for (int j = 0; j < res.count_crtcs; j++) {
124fb299fa2Sopenharmony_ci            if ((encoder->possible_crtcs & (1u << static_cast<uint32_t>(j))) != 0) {
125fb299fa2Sopenharmony_ci                drmModeFreeEncoder(encoder);
126fb299fa2Sopenharmony_ci                return drmModeGetCrtc(fd, res.crtcs[j]);
127fb299fa2Sopenharmony_ci            }
128fb299fa2Sopenharmony_ci        }
129fb299fa2Sopenharmony_ci        drmModeFreeEncoder(encoder);
130fb299fa2Sopenharmony_ci    }
131fb299fa2Sopenharmony_ci    return nullptr;
132fb299fa2Sopenharmony_ci}
133fb299fa2Sopenharmony_ci
134fb299fa2Sopenharmony_cidrmModeConnector *DrmDriver::GetFirstConnector(const drmModeRes &res, const int fd) const
135fb299fa2Sopenharmony_ci{
136fb299fa2Sopenharmony_ci    // get connected connector
137fb299fa2Sopenharmony_ci    for (int i = 0; i < res.count_connectors; i++) {
138fb299fa2Sopenharmony_ci        drmModeConnector *conn = drmModeGetConnector(fd, res.connectors[i]);
139fb299fa2Sopenharmony_ci        if (conn == nullptr) {
140fb299fa2Sopenharmony_ci            continue;
141fb299fa2Sopenharmony_ci        }
142fb299fa2Sopenharmony_ci        if (conn->count_modes > 0 &&
143fb299fa2Sopenharmony_ci            conn->connection == DRM_MODE_CONNECTED) {
144fb299fa2Sopenharmony_ci            return conn;
145fb299fa2Sopenharmony_ci        }
146fb299fa2Sopenharmony_ci        drmModeFreeConnector(conn);
147fb299fa2Sopenharmony_ci    }
148fb299fa2Sopenharmony_ci    return nullptr;
149fb299fa2Sopenharmony_ci}
150fb299fa2Sopenharmony_ci
151fb299fa2Sopenharmony_cidrmModeConnector *DrmDriver::GetConnectorByType(const drmModeRes &res, const int fd, const uint32_t type) const
152fb299fa2Sopenharmony_ci{
153fb299fa2Sopenharmony_ci    // get connected connector
154fb299fa2Sopenharmony_ci    for (int i = 0; i < res.count_connectors; i++) {
155fb299fa2Sopenharmony_ci        drmModeConnector *conn = drmModeGetConnector(fd, res.connectors[i]);
156fb299fa2Sopenharmony_ci        if (conn == nullptr) {
157fb299fa2Sopenharmony_ci            continue;
158fb299fa2Sopenharmony_ci        }
159fb299fa2Sopenharmony_ci        if (conn->connector_type == type &&
160fb299fa2Sopenharmony_ci            conn->count_modes > 0 &&
161fb299fa2Sopenharmony_ci            conn->connection == DRM_MODE_CONNECTED) {
162fb299fa2Sopenharmony_ci            return conn;
163fb299fa2Sopenharmony_ci        }
164fb299fa2Sopenharmony_ci        drmModeFreeConnector(conn);
165fb299fa2Sopenharmony_ci    }
166fb299fa2Sopenharmony_ci    return nullptr;
167fb299fa2Sopenharmony_ci}
168fb299fa2Sopenharmony_ci
169fb299fa2Sopenharmony_ci
170fb299fa2Sopenharmony_cidrmModeConnector *DrmDriver::GetConnector(const drmModeRes &res, const int fd, uint32_t &modeId) const
171fb299fa2Sopenharmony_ci{
172fb299fa2Sopenharmony_ci    // get main connector : lvds edp and dsi
173fb299fa2Sopenharmony_ci    uint32_t mainConnector[] = {
174fb299fa2Sopenharmony_ci        DRM_MODE_CONNECTOR_LVDS,
175fb299fa2Sopenharmony_ci        DRM_MODE_CONNECTOR_eDP,
176fb299fa2Sopenharmony_ci        DRM_MODE_CONNECTOR_DSI,
177fb299fa2Sopenharmony_ci    };
178fb299fa2Sopenharmony_ci
179fb299fa2Sopenharmony_ci    drmModeConnector *conn = nullptr;
180fb299fa2Sopenharmony_ci    for (uint32_t i = 0; i < sizeof(mainConnector) / sizeof(mainConnector[0]); i++) {
181fb299fa2Sopenharmony_ci        conn = GetConnectorByType(res, fd, mainConnector[i]);
182fb299fa2Sopenharmony_ci        if (conn != nullptr) {
183fb299fa2Sopenharmony_ci            break;
184fb299fa2Sopenharmony_ci        }
185fb299fa2Sopenharmony_ci    }
186fb299fa2Sopenharmony_ci
187fb299fa2Sopenharmony_ci    if (conn == nullptr) {
188fb299fa2Sopenharmony_ci        conn = GetFirstConnector(res, fd);
189fb299fa2Sopenharmony_ci    }
190fb299fa2Sopenharmony_ci
191fb299fa2Sopenharmony_ci    if (conn == nullptr) {
192fb299fa2Sopenharmony_ci        LOG(ERROR) << "DrmDriver cannot get vaild connector";
193fb299fa2Sopenharmony_ci        return nullptr;
194fb299fa2Sopenharmony_ci    }
195fb299fa2Sopenharmony_ci
196fb299fa2Sopenharmony_ci    // get preferred mode index
197fb299fa2Sopenharmony_ci    modeId = 0;
198fb299fa2Sopenharmony_ci    for (int i = 0; i < conn->count_modes; i++) {
199fb299fa2Sopenharmony_ci        if ((conn->modes[i].type & DRM_MODE_TYPE_PREFERRED) != 0) {
200fb299fa2Sopenharmony_ci            modeId = static_cast<uint32_t>(i);
201fb299fa2Sopenharmony_ci            break;
202fb299fa2Sopenharmony_ci        }
203fb299fa2Sopenharmony_ci    }
204fb299fa2Sopenharmony_ci
205fb299fa2Sopenharmony_ci    return conn;
206fb299fa2Sopenharmony_ci}
207fb299fa2Sopenharmony_ci
208fb299fa2Sopenharmony_cidrmModeRes *DrmDriver::GetResources(int &fd) const
209fb299fa2Sopenharmony_ci{
210fb299fa2Sopenharmony_ci    // 1: open drm resource
211fb299fa2Sopenharmony_ci    drmModeRes *res = nullptr;
212fb299fa2Sopenharmony_ci    for (int i = 0; i < DRM_MAX_MINOR; i++) {
213fb299fa2Sopenharmony_ci        res = GetOneResources(i, fd);
214fb299fa2Sopenharmony_ci        if (res != nullptr) {
215fb299fa2Sopenharmony_ci            break;
216fb299fa2Sopenharmony_ci        }
217fb299fa2Sopenharmony_ci    }
218fb299fa2Sopenharmony_ci    return res;
219fb299fa2Sopenharmony_ci}
220fb299fa2Sopenharmony_ci
221fb299fa2Sopenharmony_cidrmModeRes *DrmDriver::GetOneResources(const int devIndex, int &fd) const
222fb299fa2Sopenharmony_ci{
223fb299fa2Sopenharmony_ci    // 1: open drm device
224fb299fa2Sopenharmony_ci    fd = -1;
225fb299fa2Sopenharmony_ci    std::string devName = std::string("/dev/dri/card") + std::to_string(devIndex);
226fb299fa2Sopenharmony_ci    int tmpFd = open(devName.c_str(), O_RDWR | O_CLOEXEC);
227fb299fa2Sopenharmony_ci    if (tmpFd < 0) {
228fb299fa2Sopenharmony_ci        LOG(ERROR) << "open failed " << devName;
229fb299fa2Sopenharmony_ci        return nullptr;
230fb299fa2Sopenharmony_ci    }
231fb299fa2Sopenharmony_ci    // 2: check drm capacity
232fb299fa2Sopenharmony_ci    uint64_t cap = 0;
233fb299fa2Sopenharmony_ci    int ret = drmGetCap(tmpFd, DRM_CAP_DUMB_BUFFER, &cap);
234fb299fa2Sopenharmony_ci    if (ret != 0 || cap == 0) {
235fb299fa2Sopenharmony_ci        LOG(ERROR) << "drmGetCap failed";
236fb299fa2Sopenharmony_ci        close(tmpFd);
237fb299fa2Sopenharmony_ci        return nullptr;
238fb299fa2Sopenharmony_ci    }
239fb299fa2Sopenharmony_ci
240fb299fa2Sopenharmony_ci    // 3: get drm resources
241fb299fa2Sopenharmony_ci    drmModeRes *res = drmModeGetResources(tmpFd);
242fb299fa2Sopenharmony_ci    if (res == nullptr) {
243fb299fa2Sopenharmony_ci        LOG(ERROR) << "drmModeGetResources failed";
244fb299fa2Sopenharmony_ci        close(tmpFd);
245fb299fa2Sopenharmony_ci        return nullptr;
246fb299fa2Sopenharmony_ci    }
247fb299fa2Sopenharmony_ci
248fb299fa2Sopenharmony_ci    // 4: check it has connected connector and crtc
249fb299fa2Sopenharmony_ci    if (res->count_crtcs > 0 && res->count_connectors > 0 && res->count_encoders > 0) {
250fb299fa2Sopenharmony_ci        drmModeConnector *conn = GetFirstConnector(*res, tmpFd);
251fb299fa2Sopenharmony_ci        if (conn != nullptr) {
252fb299fa2Sopenharmony_ci            // don't close fd
253fb299fa2Sopenharmony_ci            LOG(INFO) << "drm dev:" << devName;
254fb299fa2Sopenharmony_ci            drmModeFreeConnector(conn);
255fb299fa2Sopenharmony_ci            fd = tmpFd;
256fb299fa2Sopenharmony_ci            return res;
257fb299fa2Sopenharmony_ci        }
258fb299fa2Sopenharmony_ci    }
259fb299fa2Sopenharmony_ci    close(tmpFd);
260fb299fa2Sopenharmony_ci    drmModeFreeResources(res);
261fb299fa2Sopenharmony_ci    return nullptr;
262fb299fa2Sopenharmony_ci}
263fb299fa2Sopenharmony_ci
264fb299fa2Sopenharmony_ciint DrmDriver::DrmInit(void)
265fb299fa2Sopenharmony_ci{
266fb299fa2Sopenharmony_ci    // 1: open drm resource
267fb299fa2Sopenharmony_ci    res_ = GetResources(fd_);
268fb299fa2Sopenharmony_ci    if (fd_ < 0 || res_ == nullptr) {
269fb299fa2Sopenharmony_ci        LOG(ERROR) << "DrmInit: GetResources failed";
270fb299fa2Sopenharmony_ci        return -1;
271fb299fa2Sopenharmony_ci    }
272fb299fa2Sopenharmony_ci
273fb299fa2Sopenharmony_ci    // 2 : get connected connector
274fb299fa2Sopenharmony_ci    uint32_t modeId;
275fb299fa2Sopenharmony_ci    conn_ = GetConnector(*res_, fd_, modeId);
276fb299fa2Sopenharmony_ci    if (conn_ == nullptr) {
277fb299fa2Sopenharmony_ci        LOG(ERROR) << "DrmInit: GetConnector failed";
278fb299fa2Sopenharmony_ci        return -1;
279fb299fa2Sopenharmony_ci    }
280fb299fa2Sopenharmony_ci
281fb299fa2Sopenharmony_ci    // 3: get vaild encoder and crtc
282fb299fa2Sopenharmony_ci    crtc_ = GetCrtc(*res_, fd_, *conn_);
283fb299fa2Sopenharmony_ci    if (crtc_ == nullptr) {
284fb299fa2Sopenharmony_ci        LOG(ERROR) << "DrmInit: GetCrtc failed";
285fb299fa2Sopenharmony_ci        return -1;
286fb299fa2Sopenharmony_ci    }
287fb299fa2Sopenharmony_ci
288fb299fa2Sopenharmony_ci    // 4: create userspace buffer
289fb299fa2Sopenharmony_ci    buff_.width = conn_->modes[modeId].hdisplay;
290fb299fa2Sopenharmony_ci    buff_.height = conn_->modes[modeId].vdisplay;
291fb299fa2Sopenharmony_ci    ModesetCreateFb(&buff_);
292fb299fa2Sopenharmony_ci
293fb299fa2Sopenharmony_ci    // 5: bind ctrc and connector
294fb299fa2Sopenharmony_ci    drmModeSetCrtc(fd_, crtc_->crtc_id, buff_.fbId, 0, 0, &conn_->connector_id, 1, &conn_->modes[modeId]);
295fb299fa2Sopenharmony_ci    LOG(INFO) << "DrmInit: buff_.width:" << buff_.width << " buff_.height:" << buff_.height;
296fb299fa2Sopenharmony_ci    LOG(INFO) << "DrmInit: crtc_id:" << crtc_->crtc_id << " connector_id:" << conn_->connector_id;
297fb299fa2Sopenharmony_ci    LOG(INFO) << " drm init success.";
298fb299fa2Sopenharmony_ci    return 0;
299fb299fa2Sopenharmony_ci}
300fb299fa2Sopenharmony_ci
301fb299fa2Sopenharmony_cibool DrmDriver::Init()
302fb299fa2Sopenharmony_ci{
303fb299fa2Sopenharmony_ci    // this static variable can guarantee Init be called only once
304fb299fa2Sopenharmony_ci    static bool res = [this] () {
305fb299fa2Sopenharmony_ci        if (DrmInit() == -1) {
306fb299fa2Sopenharmony_ci            LOG(ERROR) << "load drm driver fail";
307fb299fa2Sopenharmony_ci            return false;
308fb299fa2Sopenharmony_ci        }
309fb299fa2Sopenharmony_ci        return true;
310fb299fa2Sopenharmony_ci    } ();
311fb299fa2Sopenharmony_ci    return res;
312fb299fa2Sopenharmony_ci}
313fb299fa2Sopenharmony_ci
314fb299fa2Sopenharmony_civoid DrmDriver::ModesetDestroyFb(struct BufferObject *bo)
315fb299fa2Sopenharmony_ci{
316fb299fa2Sopenharmony_ci    if (fd_ > 0 && bo->fbId != 0) {
317fb299fa2Sopenharmony_ci        drmModeRmFB(fd_, bo->fbId);
318fb299fa2Sopenharmony_ci    }
319fb299fa2Sopenharmony_ci    if (bo->vaddr != MAP_FAILED) {
320fb299fa2Sopenharmony_ci        munmap(bo->vaddr, bo->size);
321fb299fa2Sopenharmony_ci    }
322fb299fa2Sopenharmony_ci    if (fd_ > 0) {
323fb299fa2Sopenharmony_ci        struct drm_mode_destroy_dumb destroy = {};
324fb299fa2Sopenharmony_ci        destroy.handle = bo->handle;
325fb299fa2Sopenharmony_ci        drmIoctl(fd_, DRM_IOCTL_GEM_CLOSE, &destroy);
326fb299fa2Sopenharmony_ci    }
327fb299fa2Sopenharmony_ci    if (crtc_ != nullptr) {
328fb299fa2Sopenharmony_ci        drmModeFreeCrtc(crtc_);
329fb299fa2Sopenharmony_ci    }
330fb299fa2Sopenharmony_ci    if (conn_ != nullptr) {
331fb299fa2Sopenharmony_ci        drmModeFreeConnector(conn_);
332fb299fa2Sopenharmony_ci    }
333fb299fa2Sopenharmony_ci    if (res_ != nullptr) {
334fb299fa2Sopenharmony_ci        drmModeFreeResources(res_);
335fb299fa2Sopenharmony_ci    }
336fb299fa2Sopenharmony_ci    if (fd_ > 0) {
337fb299fa2Sopenharmony_ci        close(fd_);
338fb299fa2Sopenharmony_ci        fd_ = -1;
339fb299fa2Sopenharmony_ci    }
340fb299fa2Sopenharmony_ci}
341fb299fa2Sopenharmony_ci
342fb299fa2Sopenharmony_ciDrmDriver::~DrmDriver()
343fb299fa2Sopenharmony_ci{
344fb299fa2Sopenharmony_ci    ModesetDestroyFb(&buff_);
345fb299fa2Sopenharmony_ci}
346fb299fa2Sopenharmony_ci} // namespace Updater
347