xref: /openbmc/linux/tools/testing/selftests/media_tests/video_device_test.c (revision 2612e3bbc0386368a850140a6c9b990cd496a5ec)
1a4f0e38eSShuah Khan // SPDX-License-Identifier: GPL-2.0
2a4f0e38eSShuah Khan 
3d78388dbSShuah Khan /*
4d78388dbSShuah Khan  * video_device_test - Video Device Test
5d78388dbSShuah Khan  *
6d78388dbSShuah Khan  * Copyright (c) 2016 Shuah Khan <shuahkh@osg.samsung.com>
7d78388dbSShuah Khan  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
8d78388dbSShuah Khan  *
9d78388dbSShuah Khan  */
10d78388dbSShuah Khan 
11d78388dbSShuah Khan /*
12d78388dbSShuah Khan  * This file adds a test for Video Device. This test should not be included
13d78388dbSShuah Khan  * in the Kselftest run. This test should be run when hardware and driver
14d78388dbSShuah Khan  * that makes use of V4L2 API is present.
15d78388dbSShuah Khan  *
16d78388dbSShuah Khan  * This test opens user specified Video Device and calls video ioctls in a
17d78388dbSShuah Khan  * loop once every 10 seconds.
18d78388dbSShuah Khan  *
19d78388dbSShuah Khan  * Usage:
20d78388dbSShuah Khan  *	sudo ./video_device_test -d /dev/videoX
21d78388dbSShuah Khan  *
22d78388dbSShuah Khan  *	While test is running, remove the device or unbind the driver and
23d78388dbSShuah Khan  *	ensure there are no use after free errors and other Oops in the
24d78388dbSShuah Khan  *	dmesg.
25d78388dbSShuah Khan  *	When possible, enable KaSan kernel config option for use-after-free
26d78388dbSShuah Khan  *	error detection.
27d78388dbSShuah Khan */
28d78388dbSShuah Khan 
29d78388dbSShuah Khan #include <stdio.h>
30d78388dbSShuah Khan #include <unistd.h>
31d78388dbSShuah Khan #include <stdlib.h>
32d78388dbSShuah Khan #include <errno.h>
33d78388dbSShuah Khan #include <string.h>
34d78388dbSShuah Khan #include <fcntl.h>
35d78388dbSShuah Khan #include <sys/ioctl.h>
36d78388dbSShuah Khan #include <sys/stat.h>
37d78388dbSShuah Khan #include <time.h>
38d78388dbSShuah Khan #include <linux/videodev2.h>
39d78388dbSShuah Khan 
40*e42bf3cfSIvan Orlov #define PRIORITY_MAX 4
41*e42bf3cfSIvan Orlov 
priority_test(int fd)42*e42bf3cfSIvan Orlov int priority_test(int fd)
43d78388dbSShuah Khan {
44*e42bf3cfSIvan Orlov 	/* This test will try to update the priority associated with a file descriptor */
45*e42bf3cfSIvan Orlov 
46*e42bf3cfSIvan Orlov 	enum v4l2_priority old_priority, new_priority, priority_to_compare;
47*e42bf3cfSIvan Orlov 	int ret;
48*e42bf3cfSIvan Orlov 	int result = 0;
49*e42bf3cfSIvan Orlov 
50*e42bf3cfSIvan Orlov 	ret = ioctl(fd, VIDIOC_G_PRIORITY, &old_priority);
51*e42bf3cfSIvan Orlov 	if (ret < 0) {
52*e42bf3cfSIvan Orlov 		printf("Failed to get priority: %s\n", strerror(errno));
53*e42bf3cfSIvan Orlov 		return -1;
54*e42bf3cfSIvan Orlov 	}
55*e42bf3cfSIvan Orlov 	new_priority = (old_priority + 1) % PRIORITY_MAX;
56*e42bf3cfSIvan Orlov 	ret = ioctl(fd, VIDIOC_S_PRIORITY, &new_priority);
57*e42bf3cfSIvan Orlov 	if (ret < 0) {
58*e42bf3cfSIvan Orlov 		printf("Failed to set priority: %s\n", strerror(errno));
59*e42bf3cfSIvan Orlov 		return -1;
60*e42bf3cfSIvan Orlov 	}
61*e42bf3cfSIvan Orlov 	ret = ioctl(fd, VIDIOC_G_PRIORITY, &priority_to_compare);
62*e42bf3cfSIvan Orlov 	if (ret < 0) {
63*e42bf3cfSIvan Orlov 		printf("Failed to get new priority: %s\n", strerror(errno));
64*e42bf3cfSIvan Orlov 		result = -1;
65*e42bf3cfSIvan Orlov 		goto cleanup;
66*e42bf3cfSIvan Orlov 	}
67*e42bf3cfSIvan Orlov 	if (priority_to_compare != new_priority) {
68*e42bf3cfSIvan Orlov 		printf("Priority wasn't set - test failed\n");
69*e42bf3cfSIvan Orlov 		result = -1;
70*e42bf3cfSIvan Orlov 	}
71*e42bf3cfSIvan Orlov 
72*e42bf3cfSIvan Orlov cleanup:
73*e42bf3cfSIvan Orlov 	ret = ioctl(fd, VIDIOC_S_PRIORITY, &old_priority);
74*e42bf3cfSIvan Orlov 	if (ret < 0) {
75*e42bf3cfSIvan Orlov 		printf("Failed to restore priority: %s\n", strerror(errno));
76*e42bf3cfSIvan Orlov 		return -1;
77*e42bf3cfSIvan Orlov 	}
78*e42bf3cfSIvan Orlov 	return result;
79*e42bf3cfSIvan Orlov }
80*e42bf3cfSIvan Orlov 
loop_test(int fd)81*e42bf3cfSIvan Orlov int loop_test(int fd)
82*e42bf3cfSIvan Orlov {
83d78388dbSShuah Khan 	int count;
84d78388dbSShuah Khan 	struct v4l2_tuner vtuner;
85d78388dbSShuah Khan 	struct v4l2_capability vcap;
86d78388dbSShuah Khan 	int ret;
87d78388dbSShuah Khan 
88d78388dbSShuah Khan 	/* Generate random number of interations */
89d78388dbSShuah Khan 	srand((unsigned int) time(NULL));
90d78388dbSShuah Khan 	count = rand();
91d78388dbSShuah Khan 
92d78388dbSShuah Khan 	printf("\nNote:\n"
93d78388dbSShuah Khan 	       "While test is running, remove the device or unbind\n"
94d78388dbSShuah Khan 	       "driver and ensure there are no use after free errors\n"
95d78388dbSShuah Khan 	       "and other Oops in the dmesg. When possible, enable KaSan\n"
96d78388dbSShuah Khan 	       "kernel config option for use-after-free error detection.\n\n");
97d78388dbSShuah Khan 
98d78388dbSShuah Khan 	while (count > 0) {
99d78388dbSShuah Khan 		ret = ioctl(fd, VIDIOC_QUERYCAP, &vcap);
100d78388dbSShuah Khan 		if (ret < 0)
101d78388dbSShuah Khan 			printf("VIDIOC_QUERYCAP errno %s\n", strerror(errno));
102d78388dbSShuah Khan 		else
103d78388dbSShuah Khan 			printf("Video device driver %s\n", vcap.driver);
104d78388dbSShuah Khan 
105d78388dbSShuah Khan 		ret = ioctl(fd, VIDIOC_G_TUNER, &vtuner);
106d78388dbSShuah Khan 		if (ret < 0)
107d78388dbSShuah Khan 			printf("VIDIOC_G_TUNER, errno %s\n", strerror(errno));
108d78388dbSShuah Khan 		else
109d78388dbSShuah Khan 			printf("type %d rangelow %d rangehigh %d\n",
110d78388dbSShuah Khan 				vtuner.type, vtuner.rangelow, vtuner.rangehigh);
111d78388dbSShuah Khan 		sleep(10);
112d78388dbSShuah Khan 		count--;
113d78388dbSShuah Khan 	}
114*e42bf3cfSIvan Orlov 	return 0;
115*e42bf3cfSIvan Orlov }
116*e42bf3cfSIvan Orlov 
main(int argc,char ** argv)117*e42bf3cfSIvan Orlov int main(int argc, char **argv)
118*e42bf3cfSIvan Orlov {
119*e42bf3cfSIvan Orlov 	int opt;
120*e42bf3cfSIvan Orlov 	char video_dev[256];
121*e42bf3cfSIvan Orlov 	int fd;
122*e42bf3cfSIvan Orlov 	int test_result;
123*e42bf3cfSIvan Orlov 
124*e42bf3cfSIvan Orlov 	if (argc < 2) {
125*e42bf3cfSIvan Orlov 		printf("Usage: %s [-d </dev/videoX>]\n", argv[0]);
126*e42bf3cfSIvan Orlov 		exit(-1);
127*e42bf3cfSIvan Orlov 	}
128*e42bf3cfSIvan Orlov 
129*e42bf3cfSIvan Orlov 	/* Process arguments */
130*e42bf3cfSIvan Orlov 	while ((opt = getopt(argc, argv, "d:")) != -1) {
131*e42bf3cfSIvan Orlov 		switch (opt) {
132*e42bf3cfSIvan Orlov 		case 'd':
133*e42bf3cfSIvan Orlov 			strncpy(video_dev, optarg, sizeof(video_dev) - 1);
134*e42bf3cfSIvan Orlov 			video_dev[sizeof(video_dev)-1] = '\0';
135*e42bf3cfSIvan Orlov 			break;
136*e42bf3cfSIvan Orlov 		default:
137*e42bf3cfSIvan Orlov 			printf("Usage: %s [-d </dev/videoX>]\n", argv[0]);
138*e42bf3cfSIvan Orlov 			exit(-1);
139*e42bf3cfSIvan Orlov 		}
140*e42bf3cfSIvan Orlov 	}
141*e42bf3cfSIvan Orlov 
142*e42bf3cfSIvan Orlov 	/* Open Video device and keep it open */
143*e42bf3cfSIvan Orlov 	fd = open(video_dev, O_RDWR);
144*e42bf3cfSIvan Orlov 	if (fd == -1) {
145*e42bf3cfSIvan Orlov 		printf("Video Device open errno %s\n", strerror(errno));
146*e42bf3cfSIvan Orlov 		exit(-1);
147*e42bf3cfSIvan Orlov 	}
148*e42bf3cfSIvan Orlov 
149*e42bf3cfSIvan Orlov 	test_result = priority_test(fd);
150*e42bf3cfSIvan Orlov 	if (!test_result)
151*e42bf3cfSIvan Orlov 		printf("Priority test - PASSED\n");
152*e42bf3cfSIvan Orlov 	else
153*e42bf3cfSIvan Orlov 		printf("Priority test - FAILED\n");
154*e42bf3cfSIvan Orlov 
155*e42bf3cfSIvan Orlov 	loop_test(fd);
156d78388dbSShuah Khan }
157