xref: /aosp_15_r20/external/igt-gpu-tools/lib/igt_sysfs.c (revision d83cc019efdc2edc6c4b16e9034a3ceb8d35d77c)
1*d83cc019SAndroid Build Coastguard Worker /*
2*d83cc019SAndroid Build Coastguard Worker  * Copyright © 2016 Intel Corporation
3*d83cc019SAndroid Build Coastguard Worker  *
4*d83cc019SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
5*d83cc019SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
6*d83cc019SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
7*d83cc019SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*d83cc019SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
9*d83cc019SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
10*d83cc019SAndroid Build Coastguard Worker  *
11*d83cc019SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the next
12*d83cc019SAndroid Build Coastguard Worker  * paragraph) shall be included in all copies or substantial portions of the
13*d83cc019SAndroid Build Coastguard Worker  * Software.
14*d83cc019SAndroid Build Coastguard Worker  *
15*d83cc019SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*d83cc019SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*d83cc019SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18*d83cc019SAndroid Build Coastguard Worker  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*d83cc019SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*d83cc019SAndroid Build Coastguard Worker  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21*d83cc019SAndroid Build Coastguard Worker  * IN THE SOFTWARE.
22*d83cc019SAndroid Build Coastguard Worker  *
23*d83cc019SAndroid Build Coastguard Worker  */
24*d83cc019SAndroid Build Coastguard Worker 
25*d83cc019SAndroid Build Coastguard Worker #include <inttypes.h>
26*d83cc019SAndroid Build Coastguard Worker #include <sys/stat.h>
27*d83cc019SAndroid Build Coastguard Worker #include <sys/sysmacros.h>
28*d83cc019SAndroid Build Coastguard Worker #include <sys/mount.h>
29*d83cc019SAndroid Build Coastguard Worker #include <errno.h>
30*d83cc019SAndroid Build Coastguard Worker #include <stdarg.h>
31*d83cc019SAndroid Build Coastguard Worker #include <stdio.h>
32*d83cc019SAndroid Build Coastguard Worker #include <stdlib.h>
33*d83cc019SAndroid Build Coastguard Worker #include <limits.h>
34*d83cc019SAndroid Build Coastguard Worker #include <string.h>
35*d83cc019SAndroid Build Coastguard Worker #include <fcntl.h>
36*d83cc019SAndroid Build Coastguard Worker #include <unistd.h>
37*d83cc019SAndroid Build Coastguard Worker #include <i915_drm.h>
38*d83cc019SAndroid Build Coastguard Worker #include <dirent.h>
39*d83cc019SAndroid Build Coastguard Worker #include <unistd.h>
40*d83cc019SAndroid Build Coastguard Worker #include <fcntl.h>
41*d83cc019SAndroid Build Coastguard Worker 
42*d83cc019SAndroid Build Coastguard Worker #include "igt_core.h"
43*d83cc019SAndroid Build Coastguard Worker #include "igt_sysfs.h"
44*d83cc019SAndroid Build Coastguard Worker #include "igt_device.h"
45*d83cc019SAndroid Build Coastguard Worker 
46*d83cc019SAndroid Build Coastguard Worker /**
47*d83cc019SAndroid Build Coastguard Worker  * SECTION:igt_sysfs
48*d83cc019SAndroid Build Coastguard Worker  * @short_description: Support code for sysfs features
49*d83cc019SAndroid Build Coastguard Worker  * @title: sysfs
50*d83cc019SAndroid Build Coastguard Worker  * @include: igt.h
51*d83cc019SAndroid Build Coastguard Worker  *
52*d83cc019SAndroid Build Coastguard Worker  * This library provides helpers to access sysfs features. Right now it only
53*d83cc019SAndroid Build Coastguard Worker  * provides basic support for like igt_sysfs_open().
54*d83cc019SAndroid Build Coastguard Worker  */
55*d83cc019SAndroid Build Coastguard Worker 
readN(int fd,char * buf,int len)56*d83cc019SAndroid Build Coastguard Worker static int readN(int fd, char *buf, int len)
57*d83cc019SAndroid Build Coastguard Worker {
58*d83cc019SAndroid Build Coastguard Worker 	int ret, total = 0;
59*d83cc019SAndroid Build Coastguard Worker 	do {
60*d83cc019SAndroid Build Coastguard Worker 		ret = read(fd, buf + total, len - total);
61*d83cc019SAndroid Build Coastguard Worker 		if (ret < 0)
62*d83cc019SAndroid Build Coastguard Worker 			ret = -errno;
63*d83cc019SAndroid Build Coastguard Worker 		if (ret == -EINTR || ret == -EAGAIN)
64*d83cc019SAndroid Build Coastguard Worker 			continue;
65*d83cc019SAndroid Build Coastguard Worker 		if (ret <= 0)
66*d83cc019SAndroid Build Coastguard Worker 			break;
67*d83cc019SAndroid Build Coastguard Worker 		total += ret;
68*d83cc019SAndroid Build Coastguard Worker 	} while (total != len);
69*d83cc019SAndroid Build Coastguard Worker 	return total ?: ret;
70*d83cc019SAndroid Build Coastguard Worker }
71*d83cc019SAndroid Build Coastguard Worker 
writeN(int fd,const char * buf,int len)72*d83cc019SAndroid Build Coastguard Worker static int writeN(int fd, const char *buf, int len)
73*d83cc019SAndroid Build Coastguard Worker {
74*d83cc019SAndroid Build Coastguard Worker 	int ret, total = 0;
75*d83cc019SAndroid Build Coastguard Worker 	do {
76*d83cc019SAndroid Build Coastguard Worker 		ret = write(fd, buf + total, len - total);
77*d83cc019SAndroid Build Coastguard Worker 		if (ret < 0)
78*d83cc019SAndroid Build Coastguard Worker 			ret = -errno;
79*d83cc019SAndroid Build Coastguard Worker 		if (ret == -EINTR || ret == -EAGAIN)
80*d83cc019SAndroid Build Coastguard Worker 			continue;
81*d83cc019SAndroid Build Coastguard Worker 		if (ret <= 0)
82*d83cc019SAndroid Build Coastguard Worker 			break;
83*d83cc019SAndroid Build Coastguard Worker 		total += ret;
84*d83cc019SAndroid Build Coastguard Worker 	} while (total != len);
85*d83cc019SAndroid Build Coastguard Worker 	return total ?: ret;
86*d83cc019SAndroid Build Coastguard Worker }
87*d83cc019SAndroid Build Coastguard Worker 
88*d83cc019SAndroid Build Coastguard Worker /**
89*d83cc019SAndroid Build Coastguard Worker  * igt_sysfs_path:
90*d83cc019SAndroid Build Coastguard Worker  * @device: fd of the device
91*d83cc019SAndroid Build Coastguard Worker  * @path: buffer to fill with the sysfs path to the device
92*d83cc019SAndroid Build Coastguard Worker  * @pathlen: length of @path buffer
93*d83cc019SAndroid Build Coastguard Worker  *
94*d83cc019SAndroid Build Coastguard Worker  * This finds the sysfs directory corresponding to @device.
95*d83cc019SAndroid Build Coastguard Worker  *
96*d83cc019SAndroid Build Coastguard Worker  * Returns:
97*d83cc019SAndroid Build Coastguard Worker  * The directory path, or NULL on failure.
98*d83cc019SAndroid Build Coastguard Worker  */
igt_sysfs_path(int device,char * path,int pathlen)99*d83cc019SAndroid Build Coastguard Worker char *igt_sysfs_path(int device, char *path, int pathlen)
100*d83cc019SAndroid Build Coastguard Worker {
101*d83cc019SAndroid Build Coastguard Worker 	struct stat st;
102*d83cc019SAndroid Build Coastguard Worker 
103*d83cc019SAndroid Build Coastguard Worker 	if (device < 0)
104*d83cc019SAndroid Build Coastguard Worker 		return NULL;
105*d83cc019SAndroid Build Coastguard Worker 
106*d83cc019SAndroid Build Coastguard Worker 	if (fstat(device, &st) || !S_ISCHR(st.st_mode))
107*d83cc019SAndroid Build Coastguard Worker 		return NULL;
108*d83cc019SAndroid Build Coastguard Worker 
109*d83cc019SAndroid Build Coastguard Worker 	snprintf(path, pathlen, "/sys/dev/char/%d:%d",
110*d83cc019SAndroid Build Coastguard Worker 		 major(st.st_rdev), minor(st.st_rdev));
111*d83cc019SAndroid Build Coastguard Worker 
112*d83cc019SAndroid Build Coastguard Worker 	if (access(path, F_OK))
113*d83cc019SAndroid Build Coastguard Worker 		return NULL;
114*d83cc019SAndroid Build Coastguard Worker 
115*d83cc019SAndroid Build Coastguard Worker 	return path;
116*d83cc019SAndroid Build Coastguard Worker }
117*d83cc019SAndroid Build Coastguard Worker 
118*d83cc019SAndroid Build Coastguard Worker /**
119*d83cc019SAndroid Build Coastguard Worker  * igt_sysfs_open:
120*d83cc019SAndroid Build Coastguard Worker  * @device: fd of the device
121*d83cc019SAndroid Build Coastguard Worker  *
122*d83cc019SAndroid Build Coastguard Worker  * This opens the sysfs directory corresponding to device for use
123*d83cc019SAndroid Build Coastguard Worker  * with igt_sysfs_set() and igt_sysfs_get().
124*d83cc019SAndroid Build Coastguard Worker  *
125*d83cc019SAndroid Build Coastguard Worker  * Returns:
126*d83cc019SAndroid Build Coastguard Worker  * The directory fd, or -1 on failure.
127*d83cc019SAndroid Build Coastguard Worker  */
igt_sysfs_open(int device)128*d83cc019SAndroid Build Coastguard Worker int igt_sysfs_open(int device)
129*d83cc019SAndroid Build Coastguard Worker {
130*d83cc019SAndroid Build Coastguard Worker 	char path[80];
131*d83cc019SAndroid Build Coastguard Worker 
132*d83cc019SAndroid Build Coastguard Worker 	if (!igt_sysfs_path(device, path, sizeof(path)))
133*d83cc019SAndroid Build Coastguard Worker 		return -1;
134*d83cc019SAndroid Build Coastguard Worker 
135*d83cc019SAndroid Build Coastguard Worker 	return open(path, O_RDONLY);
136*d83cc019SAndroid Build Coastguard Worker }
137*d83cc019SAndroid Build Coastguard Worker 
138*d83cc019SAndroid Build Coastguard Worker /**
139*d83cc019SAndroid Build Coastguard Worker  * igt_sysfs_set_parameters:
140*d83cc019SAndroid Build Coastguard Worker  * @device: fd of the device
141*d83cc019SAndroid Build Coastguard Worker  * @parameter: the name of the parameter to set
142*d83cc019SAndroid Build Coastguard Worker  * @fmt: printf-esque format string
143*d83cc019SAndroid Build Coastguard Worker  *
144*d83cc019SAndroid Build Coastguard Worker  * Returns true on success
145*d83cc019SAndroid Build Coastguard Worker  */
igt_sysfs_set_parameter(int device,const char * parameter,const char * fmt,...)146*d83cc019SAndroid Build Coastguard Worker bool igt_sysfs_set_parameter(int device,
147*d83cc019SAndroid Build Coastguard Worker 			     const char *parameter,
148*d83cc019SAndroid Build Coastguard Worker 			     const char *fmt, ...)
149*d83cc019SAndroid Build Coastguard Worker {
150*d83cc019SAndroid Build Coastguard Worker 	va_list ap;
151*d83cc019SAndroid Build Coastguard Worker 	int dir;
152*d83cc019SAndroid Build Coastguard Worker 	int ret;
153*d83cc019SAndroid Build Coastguard Worker 
154*d83cc019SAndroid Build Coastguard Worker 	dir = igt_sysfs_open_parameters(device);
155*d83cc019SAndroid Build Coastguard Worker 	if (dir < 0)
156*d83cc019SAndroid Build Coastguard Worker 		return false;
157*d83cc019SAndroid Build Coastguard Worker 
158*d83cc019SAndroid Build Coastguard Worker 	va_start(ap, fmt);
159*d83cc019SAndroid Build Coastguard Worker 	ret = igt_sysfs_vprintf(dir, parameter, fmt, ap);
160*d83cc019SAndroid Build Coastguard Worker 	va_end(ap);
161*d83cc019SAndroid Build Coastguard Worker 
162*d83cc019SAndroid Build Coastguard Worker 	close(dir);
163*d83cc019SAndroid Build Coastguard Worker 
164*d83cc019SAndroid Build Coastguard Worker 	return ret > 0;
165*d83cc019SAndroid Build Coastguard Worker }
166*d83cc019SAndroid Build Coastguard Worker 
167*d83cc019SAndroid Build Coastguard Worker /**
168*d83cc019SAndroid Build Coastguard Worker  * igt_sysfs_open_parameters:
169*d83cc019SAndroid Build Coastguard Worker  * @device: fd of the device
170*d83cc019SAndroid Build Coastguard Worker  *
171*d83cc019SAndroid Build Coastguard Worker  * This opens the module parameters directory (under sysfs) corresponding
172*d83cc019SAndroid Build Coastguard Worker  * to the device for use with igt_sysfs_set() and igt_sysfs_get().
173*d83cc019SAndroid Build Coastguard Worker  *
174*d83cc019SAndroid Build Coastguard Worker  * Returns:
175*d83cc019SAndroid Build Coastguard Worker  * The directory fd, or -1 on failure.
176*d83cc019SAndroid Build Coastguard Worker  */
igt_sysfs_open_parameters(int device)177*d83cc019SAndroid Build Coastguard Worker int igt_sysfs_open_parameters(int device)
178*d83cc019SAndroid Build Coastguard Worker {
179*d83cc019SAndroid Build Coastguard Worker 	int dir, params = -1;
180*d83cc019SAndroid Build Coastguard Worker 
181*d83cc019SAndroid Build Coastguard Worker 	dir = igt_sysfs_open(device);
182*d83cc019SAndroid Build Coastguard Worker 	if (dir >= 0) {
183*d83cc019SAndroid Build Coastguard Worker 		params = openat(dir,
184*d83cc019SAndroid Build Coastguard Worker 				"device/driver/module/parameters",
185*d83cc019SAndroid Build Coastguard Worker 				O_RDONLY);
186*d83cc019SAndroid Build Coastguard Worker 		close(dir);
187*d83cc019SAndroid Build Coastguard Worker 	}
188*d83cc019SAndroid Build Coastguard Worker 
189*d83cc019SAndroid Build Coastguard Worker 	if (params < 0) { /* builtin? */
190*d83cc019SAndroid Build Coastguard Worker 		drm_version_t version;
191*d83cc019SAndroid Build Coastguard Worker 		char name[32] = "";
192*d83cc019SAndroid Build Coastguard Worker 		char path[PATH_MAX];
193*d83cc019SAndroid Build Coastguard Worker 
194*d83cc019SAndroid Build Coastguard Worker 		memset(&version, 0, sizeof(version));
195*d83cc019SAndroid Build Coastguard Worker 		version.name_len = sizeof(name);
196*d83cc019SAndroid Build Coastguard Worker 		version.name = name;
197*d83cc019SAndroid Build Coastguard Worker 		ioctl(device, DRM_IOCTL_VERSION, &version);
198*d83cc019SAndroid Build Coastguard Worker 
199*d83cc019SAndroid Build Coastguard Worker 		sprintf(path, "/sys/module/%s/parameters", name);
200*d83cc019SAndroid Build Coastguard Worker 		params = open(path, O_RDONLY);
201*d83cc019SAndroid Build Coastguard Worker 	}
202*d83cc019SAndroid Build Coastguard Worker 
203*d83cc019SAndroid Build Coastguard Worker 	return params;
204*d83cc019SAndroid Build Coastguard Worker }
205*d83cc019SAndroid Build Coastguard Worker 
206*d83cc019SAndroid Build Coastguard Worker /**
207*d83cc019SAndroid Build Coastguard Worker  * igt_sysfs_write:
208*d83cc019SAndroid Build Coastguard Worker  * @dir: directory for the device from igt_sysfs_open()
209*d83cc019SAndroid Build Coastguard Worker  * @attr: name of the sysfs node to open
210*d83cc019SAndroid Build Coastguard Worker  * @data: the block to write from
211*d83cc019SAndroid Build Coastguard Worker  * @len: the length to write
212*d83cc019SAndroid Build Coastguard Worker  *
213*d83cc019SAndroid Build Coastguard Worker  * This writes @len bytes from @data to the sysfs file.
214*d83cc019SAndroid Build Coastguard Worker  *
215*d83cc019SAndroid Build Coastguard Worker  * Returns:
216*d83cc019SAndroid Build Coastguard Worker  * The number of bytes written, or -errno on error.
217*d83cc019SAndroid Build Coastguard Worker  */
igt_sysfs_write(int dir,const char * attr,const void * data,int len)218*d83cc019SAndroid Build Coastguard Worker int igt_sysfs_write(int dir, const char *attr, const void *data, int len)
219*d83cc019SAndroid Build Coastguard Worker {
220*d83cc019SAndroid Build Coastguard Worker 	int fd;
221*d83cc019SAndroid Build Coastguard Worker 
222*d83cc019SAndroid Build Coastguard Worker 	fd = openat(dir, attr, O_WRONLY);
223*d83cc019SAndroid Build Coastguard Worker 	if (fd < 0)
224*d83cc019SAndroid Build Coastguard Worker 		return -errno;
225*d83cc019SAndroid Build Coastguard Worker 
226*d83cc019SAndroid Build Coastguard Worker 	len = writeN(fd, data, len);
227*d83cc019SAndroid Build Coastguard Worker 	close(fd);
228*d83cc019SAndroid Build Coastguard Worker 
229*d83cc019SAndroid Build Coastguard Worker 	return len;
230*d83cc019SAndroid Build Coastguard Worker }
231*d83cc019SAndroid Build Coastguard Worker 
232*d83cc019SAndroid Build Coastguard Worker /**
233*d83cc019SAndroid Build Coastguard Worker  * igt_sysfs_read:
234*d83cc019SAndroid Build Coastguard Worker  * @dir: directory for the device from igt_sysfs_open()
235*d83cc019SAndroid Build Coastguard Worker  * @attr: name of the sysfs node to open
236*d83cc019SAndroid Build Coastguard Worker  * @data: the block to read into
237*d83cc019SAndroid Build Coastguard Worker  * @len: the maximum length to read
238*d83cc019SAndroid Build Coastguard Worker  *
239*d83cc019SAndroid Build Coastguard Worker  * This reads @len bytes from the sysfs file to @data
240*d83cc019SAndroid Build Coastguard Worker  *
241*d83cc019SAndroid Build Coastguard Worker  * Returns:
242*d83cc019SAndroid Build Coastguard Worker  * The length read, -errno on failure.
243*d83cc019SAndroid Build Coastguard Worker  */
igt_sysfs_read(int dir,const char * attr,void * data,int len)244*d83cc019SAndroid Build Coastguard Worker int igt_sysfs_read(int dir, const char *attr, void *data, int len)
245*d83cc019SAndroid Build Coastguard Worker {
246*d83cc019SAndroid Build Coastguard Worker 	int fd;
247*d83cc019SAndroid Build Coastguard Worker 
248*d83cc019SAndroid Build Coastguard Worker 	fd = openat(dir, attr, O_RDONLY);
249*d83cc019SAndroid Build Coastguard Worker 	if (fd < 0)
250*d83cc019SAndroid Build Coastguard Worker 		return -errno;
251*d83cc019SAndroid Build Coastguard Worker 
252*d83cc019SAndroid Build Coastguard Worker 	len = readN(fd, data, len);
253*d83cc019SAndroid Build Coastguard Worker 	close(fd);
254*d83cc019SAndroid Build Coastguard Worker 
255*d83cc019SAndroid Build Coastguard Worker 	return len;
256*d83cc019SAndroid Build Coastguard Worker }
257*d83cc019SAndroid Build Coastguard Worker 
258*d83cc019SAndroid Build Coastguard Worker /**
259*d83cc019SAndroid Build Coastguard Worker  * igt_sysfs_set:
260*d83cc019SAndroid Build Coastguard Worker  * @dir: directory for the device from igt_sysfs_open()
261*d83cc019SAndroid Build Coastguard Worker  * @attr: name of the sysfs node to open
262*d83cc019SAndroid Build Coastguard Worker  * @value: the string to write
263*d83cc019SAndroid Build Coastguard Worker  *
264*d83cc019SAndroid Build Coastguard Worker  * This writes the value to the sysfs file.
265*d83cc019SAndroid Build Coastguard Worker  *
266*d83cc019SAndroid Build Coastguard Worker  * Returns:
267*d83cc019SAndroid Build Coastguard Worker  * True on success, false on failure.
268*d83cc019SAndroid Build Coastguard Worker  */
igt_sysfs_set(int dir,const char * attr,const char * value)269*d83cc019SAndroid Build Coastguard Worker bool igt_sysfs_set(int dir, const char *attr, const char *value)
270*d83cc019SAndroid Build Coastguard Worker {
271*d83cc019SAndroid Build Coastguard Worker 	int len = strlen(value);
272*d83cc019SAndroid Build Coastguard Worker 	return igt_sysfs_write(dir, attr, value, len) == len;
273*d83cc019SAndroid Build Coastguard Worker }
274*d83cc019SAndroid Build Coastguard Worker 
275*d83cc019SAndroid Build Coastguard Worker /**
276*d83cc019SAndroid Build Coastguard Worker  * igt_sysfs_get:
277*d83cc019SAndroid Build Coastguard Worker  * @dir: directory for the device from igt_sysfs_open()
278*d83cc019SAndroid Build Coastguard Worker  * @attr: name of the sysfs node to open
279*d83cc019SAndroid Build Coastguard Worker  *
280*d83cc019SAndroid Build Coastguard Worker  * This reads the value from the sysfs file.
281*d83cc019SAndroid Build Coastguard Worker  *
282*d83cc019SAndroid Build Coastguard Worker  * Returns:
283*d83cc019SAndroid Build Coastguard Worker  * A nul-terminated string, must be freed by caller after use, or NULL
284*d83cc019SAndroid Build Coastguard Worker  * on failure.
285*d83cc019SAndroid Build Coastguard Worker  */
igt_sysfs_get(int dir,const char * attr)286*d83cc019SAndroid Build Coastguard Worker char *igt_sysfs_get(int dir, const char *attr)
287*d83cc019SAndroid Build Coastguard Worker {
288*d83cc019SAndroid Build Coastguard Worker 	char *buf;
289*d83cc019SAndroid Build Coastguard Worker 	int len, offset, rem;
290*d83cc019SAndroid Build Coastguard Worker 	int ret, fd;
291*d83cc019SAndroid Build Coastguard Worker 
292*d83cc019SAndroid Build Coastguard Worker 	fd = openat(dir, attr, O_RDONLY);
293*d83cc019SAndroid Build Coastguard Worker 	if (fd < 0)
294*d83cc019SAndroid Build Coastguard Worker 		return NULL;
295*d83cc019SAndroid Build Coastguard Worker 
296*d83cc019SAndroid Build Coastguard Worker 	offset = 0;
297*d83cc019SAndroid Build Coastguard Worker 	len = 64;
298*d83cc019SAndroid Build Coastguard Worker 	rem = len - offset - 1;
299*d83cc019SAndroid Build Coastguard Worker 	buf = malloc(len);
300*d83cc019SAndroid Build Coastguard Worker 	if (!buf)
301*d83cc019SAndroid Build Coastguard Worker 		goto out;
302*d83cc019SAndroid Build Coastguard Worker 
303*d83cc019SAndroid Build Coastguard Worker 	while ((ret = readN(fd, buf + offset, rem)) == rem) {
304*d83cc019SAndroid Build Coastguard Worker 		char *newbuf;
305*d83cc019SAndroid Build Coastguard Worker 
306*d83cc019SAndroid Build Coastguard Worker 		newbuf = realloc(buf, 2*len);
307*d83cc019SAndroid Build Coastguard Worker 		if (!newbuf)
308*d83cc019SAndroid Build Coastguard Worker 			break;
309*d83cc019SAndroid Build Coastguard Worker 
310*d83cc019SAndroid Build Coastguard Worker 		buf = newbuf;
311*d83cc019SAndroid Build Coastguard Worker 		len *= 2;
312*d83cc019SAndroid Build Coastguard Worker 		offset += ret;
313*d83cc019SAndroid Build Coastguard Worker 		rem = len - offset - 1;
314*d83cc019SAndroid Build Coastguard Worker 	}
315*d83cc019SAndroid Build Coastguard Worker 
316*d83cc019SAndroid Build Coastguard Worker 	if (ret > 0)
317*d83cc019SAndroid Build Coastguard Worker 		offset += ret;
318*d83cc019SAndroid Build Coastguard Worker 	buf[offset] = '\0';
319*d83cc019SAndroid Build Coastguard Worker 	while (offset > 0 && buf[offset-1] == '\n')
320*d83cc019SAndroid Build Coastguard Worker 		buf[--offset] = '\0';
321*d83cc019SAndroid Build Coastguard Worker 
322*d83cc019SAndroid Build Coastguard Worker out:
323*d83cc019SAndroid Build Coastguard Worker 	close(fd);
324*d83cc019SAndroid Build Coastguard Worker 	return buf;
325*d83cc019SAndroid Build Coastguard Worker }
326*d83cc019SAndroid Build Coastguard Worker 
327*d83cc019SAndroid Build Coastguard Worker /**
328*d83cc019SAndroid Build Coastguard Worker  * igt_sysfs_scanf:
329*d83cc019SAndroid Build Coastguard Worker  * @dir: directory for the device from igt_sysfs_open()
330*d83cc019SAndroid Build Coastguard Worker  * @attr: name of the sysfs node to open
331*d83cc019SAndroid Build Coastguard Worker  * @fmt: scanf format string
332*d83cc019SAndroid Build Coastguard Worker  * @...: Additional paramaters to store the scaned input values
333*d83cc019SAndroid Build Coastguard Worker  *
334*d83cc019SAndroid Build Coastguard Worker  * scanf() wrapper for sysfs.
335*d83cc019SAndroid Build Coastguard Worker  *
336*d83cc019SAndroid Build Coastguard Worker  * Returns:
337*d83cc019SAndroid Build Coastguard Worker  * Number of values successfully scanned (which can be 0), EOF on errors or
338*d83cc019SAndroid Build Coastguard Worker  * premature end of file.
339*d83cc019SAndroid Build Coastguard Worker  */
igt_sysfs_scanf(int dir,const char * attr,const char * fmt,...)340*d83cc019SAndroid Build Coastguard Worker int igt_sysfs_scanf(int dir, const char *attr, const char *fmt, ...)
341*d83cc019SAndroid Build Coastguard Worker {
342*d83cc019SAndroid Build Coastguard Worker 	FILE *file;
343*d83cc019SAndroid Build Coastguard Worker 	int fd;
344*d83cc019SAndroid Build Coastguard Worker 	int ret = -1;
345*d83cc019SAndroid Build Coastguard Worker 
346*d83cc019SAndroid Build Coastguard Worker 	fd = openat(dir, attr, O_RDONLY);
347*d83cc019SAndroid Build Coastguard Worker 	if (fd < 0)
348*d83cc019SAndroid Build Coastguard Worker 		return -1;
349*d83cc019SAndroid Build Coastguard Worker 
350*d83cc019SAndroid Build Coastguard Worker 	file = fdopen(fd, "r");
351*d83cc019SAndroid Build Coastguard Worker 	if (file) {
352*d83cc019SAndroid Build Coastguard Worker 		va_list ap;
353*d83cc019SAndroid Build Coastguard Worker 
354*d83cc019SAndroid Build Coastguard Worker 		va_start(ap, fmt);
355*d83cc019SAndroid Build Coastguard Worker 		ret = vfscanf(file, fmt, ap);
356*d83cc019SAndroid Build Coastguard Worker 		va_end(ap);
357*d83cc019SAndroid Build Coastguard Worker 
358*d83cc019SAndroid Build Coastguard Worker 		fclose(file);
359*d83cc019SAndroid Build Coastguard Worker 	} else {
360*d83cc019SAndroid Build Coastguard Worker 		close(fd);
361*d83cc019SAndroid Build Coastguard Worker 	}
362*d83cc019SAndroid Build Coastguard Worker 
363*d83cc019SAndroid Build Coastguard Worker 	return ret;
364*d83cc019SAndroid Build Coastguard Worker }
365*d83cc019SAndroid Build Coastguard Worker 
igt_sysfs_vprintf(int dir,const char * attr,const char * fmt,va_list ap)366*d83cc019SAndroid Build Coastguard Worker int igt_sysfs_vprintf(int dir, const char *attr, const char *fmt, va_list ap)
367*d83cc019SAndroid Build Coastguard Worker {
368*d83cc019SAndroid Build Coastguard Worker 	char stack[128], *buf = stack;
369*d83cc019SAndroid Build Coastguard Worker 	va_list tmp;
370*d83cc019SAndroid Build Coastguard Worker 	int ret, fd;
371*d83cc019SAndroid Build Coastguard Worker 
372*d83cc019SAndroid Build Coastguard Worker 	fd = openat(dir, attr, O_WRONLY);
373*d83cc019SAndroid Build Coastguard Worker 	if (fd < 0)
374*d83cc019SAndroid Build Coastguard Worker 		return -errno;
375*d83cc019SAndroid Build Coastguard Worker 
376*d83cc019SAndroid Build Coastguard Worker 	va_copy(tmp, ap);
377*d83cc019SAndroid Build Coastguard Worker 	ret = vsnprintf(buf, sizeof(stack), fmt, tmp);
378*d83cc019SAndroid Build Coastguard Worker 	va_end(tmp);
379*d83cc019SAndroid Build Coastguard Worker 	if (ret < 0)
380*d83cc019SAndroid Build Coastguard Worker 		return -EINVAL;
381*d83cc019SAndroid Build Coastguard Worker 
382*d83cc019SAndroid Build Coastguard Worker 	if (ret > sizeof(stack)) {
383*d83cc019SAndroid Build Coastguard Worker 		unsigned int len = ret + 1;
384*d83cc019SAndroid Build Coastguard Worker 
385*d83cc019SAndroid Build Coastguard Worker 		buf = malloc(len);
386*d83cc019SAndroid Build Coastguard Worker 		if (!buf)
387*d83cc019SAndroid Build Coastguard Worker 			return -ENOMEM;
388*d83cc019SAndroid Build Coastguard Worker 
389*d83cc019SAndroid Build Coastguard Worker 		ret = vsnprintf(buf, ret, fmt, ap);
390*d83cc019SAndroid Build Coastguard Worker 		if (ret > len) {
391*d83cc019SAndroid Build Coastguard Worker 			free(buf);
392*d83cc019SAndroid Build Coastguard Worker 			return -EINVAL;
393*d83cc019SAndroid Build Coastguard Worker 		}
394*d83cc019SAndroid Build Coastguard Worker 	}
395*d83cc019SAndroid Build Coastguard Worker 
396*d83cc019SAndroid Build Coastguard Worker 	ret = writeN(fd, buf, ret);
397*d83cc019SAndroid Build Coastguard Worker 
398*d83cc019SAndroid Build Coastguard Worker 	close(fd);
399*d83cc019SAndroid Build Coastguard Worker 	if (buf != stack)
400*d83cc019SAndroid Build Coastguard Worker 		free(buf);
401*d83cc019SAndroid Build Coastguard Worker 
402*d83cc019SAndroid Build Coastguard Worker 	return ret;
403*d83cc019SAndroid Build Coastguard Worker }
404*d83cc019SAndroid Build Coastguard Worker 
405*d83cc019SAndroid Build Coastguard Worker /**
406*d83cc019SAndroid Build Coastguard Worker  * igt_sysfs_printf:
407*d83cc019SAndroid Build Coastguard Worker  * @dir: directory for the device from igt_sysfs_open()
408*d83cc019SAndroid Build Coastguard Worker  * @attr: name of the sysfs node to open
409*d83cc019SAndroid Build Coastguard Worker  * @fmt: printf format string
410*d83cc019SAndroid Build Coastguard Worker  * @...: Additional paramaters to store the scaned input values
411*d83cc019SAndroid Build Coastguard Worker  *
412*d83cc019SAndroid Build Coastguard Worker  * printf() wrapper for sysfs.
413*d83cc019SAndroid Build Coastguard Worker  *
414*d83cc019SAndroid Build Coastguard Worker  * Returns:
415*d83cc019SAndroid Build Coastguard Worker  * Number of characters written, negative value on error.
416*d83cc019SAndroid Build Coastguard Worker  */
igt_sysfs_printf(int dir,const char * attr,const char * fmt,...)417*d83cc019SAndroid Build Coastguard Worker int igt_sysfs_printf(int dir, const char *attr, const char *fmt, ...)
418*d83cc019SAndroid Build Coastguard Worker {
419*d83cc019SAndroid Build Coastguard Worker 	va_list ap;
420*d83cc019SAndroid Build Coastguard Worker 	int ret;
421*d83cc019SAndroid Build Coastguard Worker 
422*d83cc019SAndroid Build Coastguard Worker 	va_start(ap, fmt);
423*d83cc019SAndroid Build Coastguard Worker 	ret = igt_sysfs_vprintf(dir, attr, fmt, ap);
424*d83cc019SAndroid Build Coastguard Worker 	va_end(ap);
425*d83cc019SAndroid Build Coastguard Worker 
426*d83cc019SAndroid Build Coastguard Worker 	return ret;
427*d83cc019SAndroid Build Coastguard Worker }
428*d83cc019SAndroid Build Coastguard Worker 
429*d83cc019SAndroid Build Coastguard Worker /**
430*d83cc019SAndroid Build Coastguard Worker  * igt_sysfs_get_u32:
431*d83cc019SAndroid Build Coastguard Worker  * @dir: directory for the device from igt_sysfs_open()
432*d83cc019SAndroid Build Coastguard Worker  * @attr: name of the sysfs node to open
433*d83cc019SAndroid Build Coastguard Worker  *
434*d83cc019SAndroid Build Coastguard Worker  * Convenience wrapper to read a unsigned 32bit integer from a sysfs file.
435*d83cc019SAndroid Build Coastguard Worker  *
436*d83cc019SAndroid Build Coastguard Worker  * Returns:
437*d83cc019SAndroid Build Coastguard Worker  * The value read.
438*d83cc019SAndroid Build Coastguard Worker  */
igt_sysfs_get_u32(int dir,const char * attr)439*d83cc019SAndroid Build Coastguard Worker uint32_t igt_sysfs_get_u32(int dir, const char *attr)
440*d83cc019SAndroid Build Coastguard Worker {
441*d83cc019SAndroid Build Coastguard Worker 	uint32_t result;
442*d83cc019SAndroid Build Coastguard Worker 
443*d83cc019SAndroid Build Coastguard Worker 	if (igt_sysfs_scanf(dir, attr, "%u", &result) != 1)
444*d83cc019SAndroid Build Coastguard Worker 		return 0;
445*d83cc019SAndroid Build Coastguard Worker 
446*d83cc019SAndroid Build Coastguard Worker 	return result;
447*d83cc019SAndroid Build Coastguard Worker }
448*d83cc019SAndroid Build Coastguard Worker 
449*d83cc019SAndroid Build Coastguard Worker /**
450*d83cc019SAndroid Build Coastguard Worker  * igt_sysfs_set_u32:
451*d83cc019SAndroid Build Coastguard Worker  * @dir: directory for the device from igt_sysfs_open()
452*d83cc019SAndroid Build Coastguard Worker  * @attr: name of the sysfs node to open
453*d83cc019SAndroid Build Coastguard Worker  * @value: value to set
454*d83cc019SAndroid Build Coastguard Worker  *
455*d83cc019SAndroid Build Coastguard Worker  * Convenience wrapper to write a unsigned 32bit integer to a sysfs file.
456*d83cc019SAndroid Build Coastguard Worker  *
457*d83cc019SAndroid Build Coastguard Worker  * Returns:
458*d83cc019SAndroid Build Coastguard Worker  * True if successfully written
459*d83cc019SAndroid Build Coastguard Worker  */
igt_sysfs_set_u32(int dir,const char * attr,uint32_t value)460*d83cc019SAndroid Build Coastguard Worker bool igt_sysfs_set_u32(int dir, const char *attr, uint32_t value)
461*d83cc019SAndroid Build Coastguard Worker {
462*d83cc019SAndroid Build Coastguard Worker 	return igt_sysfs_printf(dir, attr, "%u", value) > 0;
463*d83cc019SAndroid Build Coastguard Worker }
464*d83cc019SAndroid Build Coastguard Worker 
465*d83cc019SAndroid Build Coastguard Worker /**
466*d83cc019SAndroid Build Coastguard Worker  * igt_sysfs_get_boolean:
467*d83cc019SAndroid Build Coastguard Worker  * @dir: directory for the device from igt_sysfs_open()
468*d83cc019SAndroid Build Coastguard Worker  * @attr: name of the sysfs node to open
469*d83cc019SAndroid Build Coastguard Worker  *
470*d83cc019SAndroid Build Coastguard Worker  * Convenience wrapper to read a boolean sysfs file.
471*d83cc019SAndroid Build Coastguard Worker  *
472*d83cc019SAndroid Build Coastguard Worker  * Returns:
473*d83cc019SAndroid Build Coastguard Worker  * The value read.
474*d83cc019SAndroid Build Coastguard Worker  */
igt_sysfs_get_boolean(int dir,const char * attr)475*d83cc019SAndroid Build Coastguard Worker bool igt_sysfs_get_boolean(int dir, const char *attr)
476*d83cc019SAndroid Build Coastguard Worker {
477*d83cc019SAndroid Build Coastguard Worker 	int result;
478*d83cc019SAndroid Build Coastguard Worker 
479*d83cc019SAndroid Build Coastguard Worker 	if (igt_sysfs_scanf(dir, attr, "%d", &result) != 1)
480*d83cc019SAndroid Build Coastguard Worker 		return false;
481*d83cc019SAndroid Build Coastguard Worker 
482*d83cc019SAndroid Build Coastguard Worker 	return result;
483*d83cc019SAndroid Build Coastguard Worker }
484*d83cc019SAndroid Build Coastguard Worker 
485*d83cc019SAndroid Build Coastguard Worker /**
486*d83cc019SAndroid Build Coastguard Worker  * igt_sysfs_set_boolean:
487*d83cc019SAndroid Build Coastguard Worker  * @dir: directory for the device from igt_sysfs_open()
488*d83cc019SAndroid Build Coastguard Worker  * @attr: name of the sysfs node to open
489*d83cc019SAndroid Build Coastguard Worker  * @value: value to set
490*d83cc019SAndroid Build Coastguard Worker  *
491*d83cc019SAndroid Build Coastguard Worker  * Convenience wrapper to write a boolean sysfs file.
492*d83cc019SAndroid Build Coastguard Worker  *
493*d83cc019SAndroid Build Coastguard Worker  * Returns:
494*d83cc019SAndroid Build Coastguard Worker  * The value read.
495*d83cc019SAndroid Build Coastguard Worker  */
igt_sysfs_set_boolean(int dir,const char * attr,bool value)496*d83cc019SAndroid Build Coastguard Worker bool igt_sysfs_set_boolean(int dir, const char *attr, bool value)
497*d83cc019SAndroid Build Coastguard Worker {
498*d83cc019SAndroid Build Coastguard Worker 	return igt_sysfs_printf(dir, attr, "%d", value) == 1;
499*d83cc019SAndroid Build Coastguard Worker }
500*d83cc019SAndroid Build Coastguard Worker 
bind_con(const char * name,bool enable)501*d83cc019SAndroid Build Coastguard Worker static void bind_con(const char *name, bool enable)
502*d83cc019SAndroid Build Coastguard Worker {
503*d83cc019SAndroid Build Coastguard Worker 	const char *path = "/sys/class/vtconsole";
504*d83cc019SAndroid Build Coastguard Worker 	DIR *dir;
505*d83cc019SAndroid Build Coastguard Worker 	struct dirent *de;
506*d83cc019SAndroid Build Coastguard Worker 
507*d83cc019SAndroid Build Coastguard Worker 	dir = opendir(path);
508*d83cc019SAndroid Build Coastguard Worker 	if (!dir)
509*d83cc019SAndroid Build Coastguard Worker 		return;
510*d83cc019SAndroid Build Coastguard Worker 
511*d83cc019SAndroid Build Coastguard Worker 	while ((de = readdir(dir))) {
512*d83cc019SAndroid Build Coastguard Worker 		char buf[PATH_MAX];
513*d83cc019SAndroid Build Coastguard Worker 		int fd, len;
514*d83cc019SAndroid Build Coastguard Worker 
515*d83cc019SAndroid Build Coastguard Worker 		if (strncmp(de->d_name, "vtcon", 5))
516*d83cc019SAndroid Build Coastguard Worker 			continue;
517*d83cc019SAndroid Build Coastguard Worker 
518*d83cc019SAndroid Build Coastguard Worker 		sprintf(buf, "%s/%s/name", path, de->d_name);
519*d83cc019SAndroid Build Coastguard Worker 		fd = open(buf, O_RDONLY);
520*d83cc019SAndroid Build Coastguard Worker 		if (fd < 0)
521*d83cc019SAndroid Build Coastguard Worker 			continue;
522*d83cc019SAndroid Build Coastguard Worker 
523*d83cc019SAndroid Build Coastguard Worker 		buf[sizeof(buf) - 1] = '\0';
524*d83cc019SAndroid Build Coastguard Worker 		len = read(fd, buf, sizeof(buf) - 1);
525*d83cc019SAndroid Build Coastguard Worker 		close(fd);
526*d83cc019SAndroid Build Coastguard Worker 		if (len >= 0)
527*d83cc019SAndroid Build Coastguard Worker 			buf[len] = '\0';
528*d83cc019SAndroid Build Coastguard Worker 
529*d83cc019SAndroid Build Coastguard Worker 		if (!strstr(buf, name))
530*d83cc019SAndroid Build Coastguard Worker 			continue;
531*d83cc019SAndroid Build Coastguard Worker 
532*d83cc019SAndroid Build Coastguard Worker 		sprintf(buf, "%s/%s/bind", path, de->d_name);
533*d83cc019SAndroid Build Coastguard Worker 		fd = open(buf, O_WRONLY);
534*d83cc019SAndroid Build Coastguard Worker 		if (fd != -1) {
535*d83cc019SAndroid Build Coastguard Worker 			igt_ignore_warn(write(fd, enable ? "1\n" : "0\n", 2));
536*d83cc019SAndroid Build Coastguard Worker 			close(fd);
537*d83cc019SAndroid Build Coastguard Worker 		}
538*d83cc019SAndroid Build Coastguard Worker 		break;
539*d83cc019SAndroid Build Coastguard Worker 	}
540*d83cc019SAndroid Build Coastguard Worker 	closedir(dir);
541*d83cc019SAndroid Build Coastguard Worker }
542*d83cc019SAndroid Build Coastguard Worker 
543*d83cc019SAndroid Build Coastguard Worker /**
544*d83cc019SAndroid Build Coastguard Worker  * bind_fbcon:
545*d83cc019SAndroid Build Coastguard Worker  * @enable: boolean value
546*d83cc019SAndroid Build Coastguard Worker  *
547*d83cc019SAndroid Build Coastguard Worker  * This functions enables/disables the text console running on top of the
548*d83cc019SAndroid Build Coastguard Worker  * framebuffer device.
549*d83cc019SAndroid Build Coastguard Worker  */
bind_fbcon(bool enable)550*d83cc019SAndroid Build Coastguard Worker void bind_fbcon(bool enable)
551*d83cc019SAndroid Build Coastguard Worker {
552*d83cc019SAndroid Build Coastguard Worker 	/*
553*d83cc019SAndroid Build Coastguard Worker 	 * The vtcon bind interface seems somewhat broken. Possibly
554*d83cc019SAndroid Build Coastguard Worker 	 * depending on the order the console drivers have been
555*d83cc019SAndroid Build Coastguard Worker 	 * registered you either have to unbind the old driver,
556*d83cc019SAndroid Build Coastguard Worker 	 * or bind the new driver. Let's do both.
557*d83cc019SAndroid Build Coastguard Worker 	 */
558*d83cc019SAndroid Build Coastguard Worker 	bind_con("dummy device", !enable);
559*d83cc019SAndroid Build Coastguard Worker 	bind_con("frame buffer device", enable);
560*d83cc019SAndroid Build Coastguard Worker }
561*d83cc019SAndroid Build Coastguard Worker 
562*d83cc019SAndroid Build Coastguard Worker /**
563*d83cc019SAndroid Build Coastguard Worker  * kick_snd_hda_intel:
564*d83cc019SAndroid Build Coastguard Worker  *
565*d83cc019SAndroid Build Coastguard Worker  * This functions unbinds the snd_hda_intel driver so the module cand be
566*d83cc019SAndroid Build Coastguard Worker  * unloaded.
567*d83cc019SAndroid Build Coastguard Worker  *
568*d83cc019SAndroid Build Coastguard Worker  */
kick_snd_hda_intel(void)569*d83cc019SAndroid Build Coastguard Worker void kick_snd_hda_intel(void)
570*d83cc019SAndroid Build Coastguard Worker {
571*d83cc019SAndroid Build Coastguard Worker 	DIR *dir;
572*d83cc019SAndroid Build Coastguard Worker 	struct dirent *snd_hda;
573*d83cc019SAndroid Build Coastguard Worker 	int fd; size_t len;
574*d83cc019SAndroid Build Coastguard Worker 
575*d83cc019SAndroid Build Coastguard Worker 	const char *dpath = "/sys/bus/pci/drivers/snd_hda_intel";
576*d83cc019SAndroid Build Coastguard Worker 	const char *path = "/sys/bus/pci/drivers/snd_hda_intel/unbind";
577*d83cc019SAndroid Build Coastguard Worker 	const char *devid = "0000:";
578*d83cc019SAndroid Build Coastguard Worker 
579*d83cc019SAndroid Build Coastguard Worker 	fd = open(path, O_WRONLY);
580*d83cc019SAndroid Build Coastguard Worker 	if (fd < 0) {
581*d83cc019SAndroid Build Coastguard Worker 		return;
582*d83cc019SAndroid Build Coastguard Worker 	}
583*d83cc019SAndroid Build Coastguard Worker 
584*d83cc019SAndroid Build Coastguard Worker 	dir = opendir(dpath);
585*d83cc019SAndroid Build Coastguard Worker 	if (!dir)
586*d83cc019SAndroid Build Coastguard Worker 		goto out;
587*d83cc019SAndroid Build Coastguard Worker 
588*d83cc019SAndroid Build Coastguard Worker 	len = strlen(devid);
589*d83cc019SAndroid Build Coastguard Worker 	while ((snd_hda = readdir(dir))) {
590*d83cc019SAndroid Build Coastguard Worker 		struct stat st;
591*d83cc019SAndroid Build Coastguard Worker 		char fpath[PATH_MAX];
592*d83cc019SAndroid Build Coastguard Worker 
593*d83cc019SAndroid Build Coastguard Worker 		if (*snd_hda->d_name == '.')
594*d83cc019SAndroid Build Coastguard Worker 			continue;
595*d83cc019SAndroid Build Coastguard Worker 
596*d83cc019SAndroid Build Coastguard Worker 		snprintf(fpath, sizeof(fpath), "%s/%s", dpath, snd_hda->d_name);
597*d83cc019SAndroid Build Coastguard Worker 		if (lstat(fpath, &st))
598*d83cc019SAndroid Build Coastguard Worker 			continue;
599*d83cc019SAndroid Build Coastguard Worker 
600*d83cc019SAndroid Build Coastguard Worker 		if (!S_ISLNK(st.st_mode))
601*d83cc019SAndroid Build Coastguard Worker 			continue;
602*d83cc019SAndroid Build Coastguard Worker 
603*d83cc019SAndroid Build Coastguard Worker 		if (!strncmp(devid, snd_hda->d_name, len)) {
604*d83cc019SAndroid Build Coastguard Worker 			igt_ignore_warn(write(fd, snd_hda->d_name,
605*d83cc019SAndroid Build Coastguard Worker 					strlen(snd_hda->d_name)));
606*d83cc019SAndroid Build Coastguard Worker 		}
607*d83cc019SAndroid Build Coastguard Worker 	}
608*d83cc019SAndroid Build Coastguard Worker 
609*d83cc019SAndroid Build Coastguard Worker 	closedir(dir);
610*d83cc019SAndroid Build Coastguard Worker out:
611*d83cc019SAndroid Build Coastguard Worker 	close(fd);
612*d83cc019SAndroid Build Coastguard Worker }
613*d83cc019SAndroid Build Coastguard Worker 
614*d83cc019SAndroid Build Coastguard Worker static int fbcon_cursor_blink_fd = -1;
615*d83cc019SAndroid Build Coastguard Worker static char fbcon_cursor_blink_prev_value[2];
616*d83cc019SAndroid Build Coastguard Worker 
fbcon_cursor_blink_restore(int sig)617*d83cc019SAndroid Build Coastguard Worker static void fbcon_cursor_blink_restore(int sig)
618*d83cc019SAndroid Build Coastguard Worker {
619*d83cc019SAndroid Build Coastguard Worker 	write(fbcon_cursor_blink_fd, fbcon_cursor_blink_prev_value,
620*d83cc019SAndroid Build Coastguard Worker 	      strlen(fbcon_cursor_blink_prev_value) + 1);
621*d83cc019SAndroid Build Coastguard Worker 	close(fbcon_cursor_blink_fd);
622*d83cc019SAndroid Build Coastguard Worker }
623*d83cc019SAndroid Build Coastguard Worker 
624*d83cc019SAndroid Build Coastguard Worker /**
625*d83cc019SAndroid Build Coastguard Worker  * fbcon_blink_enable:
626*d83cc019SAndroid Build Coastguard Worker  * @enable: if true enables the fbcon cursor blinking otherwise disables it
627*d83cc019SAndroid Build Coastguard Worker  *
628*d83cc019SAndroid Build Coastguard Worker  * Enables or disables the cursor blinking in fbcon, it also restores the
629*d83cc019SAndroid Build Coastguard Worker  * previous blinking state when exiting test.
630*d83cc019SAndroid Build Coastguard Worker  *
631*d83cc019SAndroid Build Coastguard Worker  */
fbcon_blink_enable(bool enable)632*d83cc019SAndroid Build Coastguard Worker void fbcon_blink_enable(bool enable)
633*d83cc019SAndroid Build Coastguard Worker {
634*d83cc019SAndroid Build Coastguard Worker 	const char *cur_blink_path = "/sys/class/graphics/fbcon/cursor_blink";
635*d83cc019SAndroid Build Coastguard Worker 	int fd, r;
636*d83cc019SAndroid Build Coastguard Worker 	char buffer[2];
637*d83cc019SAndroid Build Coastguard Worker 
638*d83cc019SAndroid Build Coastguard Worker 	fd = open(cur_blink_path, O_RDWR);
639*d83cc019SAndroid Build Coastguard Worker 	igt_require(fd >= 0);
640*d83cc019SAndroid Build Coastguard Worker 
641*d83cc019SAndroid Build Coastguard Worker 	/* Restore original value on exit */
642*d83cc019SAndroid Build Coastguard Worker 	if (fbcon_cursor_blink_fd == -1) {
643*d83cc019SAndroid Build Coastguard Worker 		r = read(fd, fbcon_cursor_blink_prev_value,
644*d83cc019SAndroid Build Coastguard Worker 			 sizeof(fbcon_cursor_blink_prev_value));
645*d83cc019SAndroid Build Coastguard Worker 		if (r > 0) {
646*d83cc019SAndroid Build Coastguard Worker 			fbcon_cursor_blink_fd = dup(fd);
647*d83cc019SAndroid Build Coastguard Worker 			igt_assert(fbcon_cursor_blink_fd >= 0);
648*d83cc019SAndroid Build Coastguard Worker 			igt_install_exit_handler(fbcon_cursor_blink_restore);
649*d83cc019SAndroid Build Coastguard Worker 		}
650*d83cc019SAndroid Build Coastguard Worker 	}
651*d83cc019SAndroid Build Coastguard Worker 
652*d83cc019SAndroid Build Coastguard Worker 	r = snprintf(buffer, sizeof(buffer), enable ? "1" : "0");
653*d83cc019SAndroid Build Coastguard Worker 	write(fd, buffer, r + 1);
654*d83cc019SAndroid Build Coastguard Worker 	close(fd);
655*d83cc019SAndroid Build Coastguard Worker }
656