1 /*-------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2022 NVIDIA, Inc.
6 * Copyright (c) 2022 The Khronos Group Inc.
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 *
20 *//*!
21 * \file
22 * \brief Drm utilities.
23 *//*--------------------------------------------------------------------*/
24
25 #if DEQP_SUPPORT_DRM && !defined(CTS_USES_VULKANSC)
26
27 #include "tcuLibDrm.hpp"
28
29 #include "tcuDefs.hpp"
30
31 #include "deMemory.h"
32
33 #include <fcntl.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <unistd.h>
37
38 #if !defined(__FreeBSD__)
39 // major() and minor() are defined in sys/types.h on FreeBSD, and in
40 // sys/sysmacros.h on Linux and Solaris.
41 #include <sys/sysmacros.h>
42 #endif // !defined(__FreeBSD__)
43
44 namespace tcu
45 {
46
LibDrm(void)47 LibDrm::LibDrm(void) : DynamicLibrary(libDrmFiles)
48 {
49 pGetDevices2 = (PFNDRMGETDEVICES2PROC)getFunction("drmGetDevices2");
50 pGetDevices = (PFNDRMGETDEVICESPROC)getFunction("drmGetDevices");
51 pFreeDevices = (PFNDRMFREEDEVICESPROC)getFunction("drmFreeDevices");
52 pGetResources = (PFNDRMMODEGETRESOURCESPROC)getFunction("drmModeGetResources");
53 pFreeResources = (PFNDRMMODEFREERESOURCESPROC)getFunction("drmModeFreeResources");
54 pGetConnector = (PFNDRMMODEGETCONNECTORPROC)getFunction("drmModeGetConnector");
55 pFreeConnector = (PFNDRMMODEFREECONNECTORPROC)getFunction("drmModeFreeConnector");
56 pGetEncoder = (PFNDRMMODEGETENCODERPROC)getFunction("drmModeGetEncoder");
57 pFreeEncoder = (PFNDRMMODEFREEENCODERPROC)getFunction("drmModeFreeEncoder");
58 pCreateLease = (PFNDRMMODECREATELEASEPROC)getFunction("drmModeCreateLease");
59 pAuthMagic = (PFNDRMAUTHMAGIC)getFunction("drmAuthMagic");
60
61 /* libdrm did not add this API until 2.4.65, return NotSupported if it's too old. */
62 if (!pGetDevices2 && !pGetDevices)
63 TCU_THROW(NotSupportedError, "Could not load a valid drmGetDevices() variant from libdrm");
64 if (!pFreeDevices)
65 TCU_THROW(NotSupportedError, "Could not load drmFreeDevices() from libdrm");
66 if (!pGetResources)
67 TCU_FAIL("Could not load drmModeGetResources() from libdrm");
68 if (!pFreeResources)
69 TCU_FAIL("Could not load drmModeFreeResources() from libdrm");
70 if (!pGetConnector)
71 TCU_FAIL("Could not load drmModeGetConnector() from libdrm");
72 if (!pFreeConnector)
73 TCU_FAIL("Could not load drmModeFreeConnector() from libdrm");
74 if (!pGetEncoder)
75 TCU_FAIL("Could not load drmModeGetEncoder() from libdrm");
76 if (!pFreeEncoder)
77 TCU_FAIL("Could not load drmModeFreeEncoder() from libdrm");
78 if (!pCreateLease)
79 TCU_FAIL("Could not load drmModeCreateLease() from libdrm");
80 if (!pAuthMagic)
81 TCU_FAIL("Could not load drmAuthMagic() from libdrm");
82 }
83
~LibDrm(void)84 LibDrm::~LibDrm(void)
85 {
86 }
87
getDevices(int * pNumDevices) const88 drmDevicePtr *LibDrm::getDevices(int *pNumDevices) const
89 {
90 *pNumDevices = intGetDevices(DE_NULL, 0);
91
92 if (*pNumDevices < 0)
93 TCU_THROW(NotSupportedError, "Failed to query number of DRM devices in system");
94
95 if (*pNumDevices == 0)
96 return DE_NULL;
97
98 drmDevicePtr *devs = new drmDevicePtr[*pNumDevices];
99
100 *pNumDevices = intGetDevices(devs, *pNumDevices);
101
102 if (*pNumDevices < 0)
103 {
104 delete[] devs;
105 TCU_FAIL("Failed to query list of DRM devices in system");
106 }
107
108 return devs;
109 }
110
findDeviceNode(drmDevicePtr * devices,int count,int64_t major,int64_t minor) const111 const char *LibDrm::findDeviceNode(drmDevicePtr *devices, int count, int64_t major, int64_t minor) const
112 {
113 for (int i = 0; i < count; i++)
114 {
115 for (int j = 0; j < DRM_NODE_MAX; j++)
116 {
117 if (!(devices[i]->available_nodes & (1 << j)))
118 continue;
119
120 struct stat statBuf;
121 deMemset(&statBuf, 0, sizeof(statBuf));
122 int res = stat(devices[i]->nodes[j], &statBuf);
123
124 if (res || !(statBuf.st_mode & S_IFCHR))
125 continue;
126
127 if (major == major(statBuf.st_rdev) && minor == minor(statBuf.st_rdev))
128 {
129 return devices[i]->nodes[j];
130 }
131 }
132 }
133
134 return DE_NULL;
135 }
136
freeDevices(drmDevicePtr * devices,int count) const137 void LibDrm::freeDevices(drmDevicePtr *devices, int count) const
138 {
139 pFreeDevices(devices, count);
140 delete[] devices;
141 }
142
closeAndDeleteFd(int * fd)143 static void closeAndDeleteFd(int *fd)
144 {
145 if (fd)
146 {
147 close(*fd);
148 delete fd;
149 }
150 }
151
openFd(const char * node) const152 LibDrm::FdPtr LibDrm::openFd(const char *node) const
153 {
154 int fd = open(node, O_RDWR);
155 if (fd < 0)
156 return FdPtr(DE_NULL);
157 else
158 return FdPtr(new int{fd}, closeAndDeleteFd);
159 }
160
getResources(int fd) const161 LibDrm::ResPtr LibDrm::getResources(int fd) const
162 {
163 return ResPtr(pGetResources(fd), pFreeResources);
164 }
165
getConnector(int fd,uint32_t connectorId) const166 LibDrm::ConnectorPtr LibDrm::getConnector(int fd, uint32_t connectorId) const
167 {
168 return ConnectorPtr(pGetConnector(fd, connectorId), pFreeConnector);
169 }
170
getEncoder(int fd,uint32_t encoderId) const171 LibDrm::EncoderPtr LibDrm::getEncoder(int fd, uint32_t encoderId) const
172 {
173 return EncoderPtr(pGetEncoder(fd, encoderId), pFreeEncoder);
174 }
175
createLease(int fd,const uint32_t * objects,int numObjects,int flags) const176 LibDrm::FdPtr LibDrm::createLease(int fd, const uint32_t *objects, int numObjects, int flags) const
177 {
178 uint32_t leaseId;
179 int leaseFd = pCreateLease(fd, objects, numObjects, flags, &leaseId);
180 if (leaseFd < 0)
181 return FdPtr(DE_NULL);
182 else
183 return FdPtr(new int{leaseFd}, closeAndDeleteFd);
184 }
185
authMagic(int fd,drm_magic_t magic) const186 int LibDrm::authMagic(int fd, drm_magic_t magic) const
187 {
188 return pAuthMagic(fd, magic);
189 }
190
intGetDevices(drmDevicePtr devices[],int maxDevices) const191 int LibDrm::intGetDevices(drmDevicePtr devices[], int maxDevices) const
192 {
193 if (pGetDevices2)
194 return pGetDevices2(0, devices, maxDevices);
195 else
196 return pGetDevices(devices, maxDevices);
197 }
198
199 const char *LibDrm::libDrmFiles[] = {"libdrm.so.2", "libdrm.so", nullptr};
200
201 } // namespace tcu
202
203 #endif // DEQP_SUPPORT_DRM && !defined (CTS_USES_VULKANSC)
204