1 /* 2 * v4l-test: Test environment for Video For Linux Two API 3 * 4 * 4 Apr 2009 0.3 Test case for NULL parameter reworked 5 * 29 Mar 2009 0.2 Clean up test case for NULL parameter 6 * 22 Mar 2009 0.1 First release 7 * 8 * Written by Mrton Nmeth <nm127 (at) freemail.hu> 9 * Released under GPL 10 */ 11 12 #include <stdio.h> 13 #include <sys/types.h> 14 #include <sys/stat.h> 15 #include <fcntl.h> 16 #include <unistd.h> 17 #include <sys/ioctl.h> 18 #include <errno.h> 19 #include <string.h> 20 21 #include <linux/videodev2.h> 22 #include <linux/errno.h> 23 24 #include <CUnit/CUnit.h> 25 26 #include "v4l2_test.h" 27 #include "dev_video.h" 28 #include "video_limits.h" 29 30 #include "test_VIDIOC_OUTPUT.h" 31 32 int valid_output_index(int f, __u32 index) 33 { 34 __u32 i; 35 struct v4l2_output output; 36 int ret_enum, errno_enum; 37 int valid = 0; 38 39 /* Search for index with VIDIOC_ENUMOUTPUT. Do not just 40 * check the given index with VIDIOC_ENUMOUTPUT because 41 * we could miss the end of the enumeration. After the 42 * end of enumeration no more indexes are allowed. 43 */ 44 i = 0; 45 do { 46 memset(&output, 0xff, sizeof(output)); 47 output.index = i; 48 ret_enum = ioctl(f, VIDIOC_ENUMOUTPUT, &output); 49 errno_enum = errno; 50 if (ret_enum == 0 && index == i) { 51 valid = 1; 52 break; 53 } 54 i++; 55 } while (ret_enum == 0 && i != 0); 56 return valid; 57 } 58 59 void test_VIDIOC_G_OUTPUT() 60 { 61 int ret_get, errno_get; 62 __u32 index; 63 int f; 64 65 f = get_video_fd(); 66 67 memset(&index, 0xff, sizeof(index)); 68 ret_get = ioctl(f, VIDIOC_G_OUTPUT, &index); 69 errno_get = errno; 70 71 dprintf("\tVIDIOC_G_OUTPUT, ret_get=%i, errno_get=%i\n", ret_get, 72 errno_get); 73 74 if (ret_get == 0) { 75 CU_ASSERT_EQUAL(ret_get, 0); 76 CU_ASSERT(valid_output_index(f, index)); 77 78 dprintf("\tindex=0x%X\n", index); 79 80 } else { 81 CU_ASSERT_EQUAL(ret_get, -1); 82 CU_ASSERT_EQUAL(errno_get, EINVAL); 83 } 84 85 } 86 87 void test_VIDIOC_S_OUTPUT_from_enum() 88 { 89 int ret_get, errno_get; 90 int ret_set, errno_set; 91 int ret_enum, errno_enum; 92 __u32 output_index_orig; 93 struct v4l2_output output; 94 __u32 i; 95 int f; 96 97 f = get_video_fd(); 98 99 memset(&output_index_orig, 0xff, sizeof(output_index_orig)); 100 ret_get = ioctl(f, VIDIOC_G_OUTPUT, &output_index_orig); 101 errno_get = errno; 102 if (ret_get == 0) { 103 CU_ASSERT_EQUAL(ret_get, 0); 104 105 i = 0; 106 do { 107 memset(&output, 0xff, sizeof(output)); 108 output.index = i; 109 ret_enum = ioctl(f, VIDIOC_ENUMOUTPUT, &output); 110 errno_enum = errno; 111 112 dprintf 113 ("\tENUMOUTPUT: i=%u, ret_enum=%i, errno_enum=%i\n", 114 i, ret_enum, errno_enum); 115 116 if (ret_enum == 0) { 117 ret_set = 118 ioctl(f, VIDIOC_S_OUTPUT, &output.index); 119 errno_set = errno; 120 CU_ASSERT_EQUAL(ret_set, 0); 121 122 dprintf 123 ("\toutput.index=0x%X, ret_set=%i, errno_set=%i\n", 124 output.index, ret_set, errno_set); 125 126 } 127 i++; 128 } while (ret_enum == 0 && i != 0); 129 130 /* Setting the original output_id should not fail */ 131 ret_set = ioctl(f, VIDIOC_S_OUTPUT, &output_index_orig); 132 errno_set = errno; 133 CU_ASSERT_EQUAL(ret_set, 0); 134 } else { 135 CU_ASSERT_EQUAL(ret_get, -1); 136 CU_ASSERT_EQUAL(errno_get, EINVAL); 137 } 138 } 139 140 static void do_set_output(int f, __u32 first_wrong_output, __u32 index) 141 { 142 struct v4l2_output output; 143 int ret_set, errno_set; 144 145 if (first_wrong_output <= index) { 146 147 dprintf("\tdo_set_output(f, 0x%X, 0x%X)\n", first_wrong_output, 148 index); 149 150 memset(&output, 0xff, sizeof(output)); 151 output.index = index; 152 ret_set = ioctl(f, VIDIOC_S_OUTPUT, &output.index); 153 errno_set = errno; 154 155 CU_ASSERT_EQUAL(ret_set, -1); 156 CU_ASSERT_EQUAL(errno_set, EINVAL); 157 158 dprintf("\toutput.index=0x%X, ret_set=%i, errno_set=%i\n", 159 output.index, ret_set, errno_set); 160 161 } 162 163 } 164 165 void test_VIDIOC_S_OUTPUT_invalid_outputs() 166 { 167 int ret_get, errno_get; 168 int ret_set, errno_set; 169 int ret_enum, errno_enum; 170 __u32 output_index_orig; 171 struct v4l2_output output; 172 __u32 i, first_wrong_output; 173 int f; 174 175 f = get_video_fd(); 176 177 memset(&output_index_orig, 0xff, sizeof(output_index_orig)); 178 ret_get = ioctl(f, VIDIOC_G_OUTPUT, &output_index_orig); 179 errno_get = errno; 180 if (ret_get == 0) { 181 CU_ASSERT_EQUAL(ret_get, 0); 182 i = 0; 183 do { 184 memset(&output, 0xff, sizeof(output)); 185 output.index = i; 186 ret_enum = ioctl(f, VIDIOC_ENUMOUTPUT, &output); 187 errno_enum = errno; 188 189 dprintf 190 ("\tENUMOUTPUT: i=%u, ret_enum=%i, errno_enum=%i\n", 191 i, ret_enum, errno_enum); 192 193 i++; 194 } while (ret_enum == 0 && i != 0); 195 196 if (i != 0) { 197 first_wrong_output = i; 198 199 /* The output index range 0..(i-1) are valid outputs. */ 200 /* Try index values from range i..U32_MAX */ 201 do_set_output(f, first_wrong_output, i); 202 do_set_output(f, first_wrong_output, i + 1); 203 204 /* Check for signed/unsigned mismatch near S32_MAX */ 205 for (i = 0; i <= first_wrong_output + 1; i++) { 206 do_set_output(f, first_wrong_output, 207 ((__u32) S32_MAX) + i); 208 } 209 210 i = (U32_MAX - 1) - first_wrong_output; 211 do { 212 do_set_output(f, first_wrong_output, i); 213 i++; 214 } while (i != 0); 215 } 216 217 /* Setting the original output_id should not fail */ 218 ret_set = ioctl(f, VIDIOC_S_OUTPUT, &output_index_orig); 219 errno_set = errno; 220 CU_ASSERT_EQUAL(ret_set, 0); 221 } else { 222 CU_ASSERT_EQUAL(ret_get, -1); 223 CU_ASSERT_EQUAL(errno_get, EINVAL); 224 } 225 } 226 227 void test_VIDIOC_G_OUTPUT_NULL() 228 { 229 int ret_get, errno_get; 230 int ret_null, errno_null; 231 __u32 index; 232 233 memset(&index, 0xff, sizeof(index)); 234 ret_get = ioctl(get_video_fd(), VIDIOC_G_OUTPUT, &index); 235 errno_get = errno; 236 237 dprintf("\t%s:%u: VIDIOC_G_OUTPUT, ret_get=%i, errno_get=%i\n", 238 __FILE__, __LINE__, ret_get, errno_get); 239 240 ret_null = ioctl(get_video_fd(), VIDIOC_G_OUTPUT, NULL); 241 errno_null = errno; 242 243 dprintf("\t%s:%u: VIDIOC_G_OUTPUT: ret_null=%i, errno_null=%i\n", 244 __FILE__, __LINE__, ret_null, errno_null); 245 246 if (ret_get == 0) { 247 CU_ASSERT_EQUAL(ret_get, 0); 248 CU_ASSERT_EQUAL(ret_null, -1); 249 CU_ASSERT_EQUAL(errno_null, EFAULT); 250 } else { 251 CU_ASSERT_EQUAL(ret_get, -1); 252 CU_ASSERT_EQUAL(errno_get, EINVAL); 253 CU_ASSERT_EQUAL(ret_null, -1); 254 CU_ASSERT_EQUAL(errno_null, EINVAL); 255 } 256 257 } 258 259 void test_VIDIOC_S_OUTPUT_NULL() 260 { 261 int ret_orig, errno_orig; 262 int ret_set, errno_set; 263 int ret_null, errno_null; 264 __u32 index_orig; 265 __u32 index; 266 267 /* save the original output */ 268 memset(&index_orig, 0, sizeof(index_orig)); 269 ret_orig = ioctl(get_video_fd(), VIDIOC_G_OUTPUT, &index_orig); 270 errno_orig = errno; 271 272 dprintf("\t%s:%u: VIDIOC_G_OUTPUT, ret_orig=%i, errno_orig=%i\n", 273 __FILE__, __LINE__, ret_orig, errno_orig); 274 275 memset(&index, 0xff, sizeof(index)); 276 index = index_orig; 277 ret_set = ioctl(get_video_fd(), VIDIOC_S_OUTPUT, &index); 278 errno_set = errno; 279 280 dprintf("\t%s:%u: VIDIOC_S_OUTPUT ret_set=%i, errno_set=%i\n", 281 __FILE__, __LINE__, ret_set, errno_set); 282 283 ret_null = ioctl(get_video_fd(), VIDIOC_S_OUTPUT, NULL); 284 errno_null = errno; 285 286 dprintf("\t%s:%u: VIDIOC_S_OUTPUT: ret_null=%i, errno_null=%i\n", 287 __FILE__, __LINE__, ret_null, errno_null); 288 289 if (ret_set == 0) { 290 CU_ASSERT_EQUAL(ret_null, -1); 291 CU_ASSERT_EQUAL(errno_null, EFAULT); 292 } else { 293 CU_ASSERT_EQUAL(ret_null, -1); 294 CU_ASSERT_EQUAL(errno_null, EINVAL); 295 } 296 297 } 298