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