summaryrefslogtreecommitdiff
path: root/src/v4l2/v4l2_compat.cpp
blob: fd73381d34e92909c95e26ac56560f96335ae24c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
 * Copyright (C) 2019, Google Inc.
 *
 * v4l2_compat.cpp - V4L2 compatibility layer
 */

#include "v4l2_compat_manager.h"

#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>

#define LIBCAMERA_PUBLIC __attribute__((visibility("default")))

using namespace libcamera;

#define extract_va_arg(type, arg, last)	\
{					\
	va_list ap;			\
	va_start(ap, last);		\
	arg = va_arg(ap, type);		\
	va_end(ap);			\
}

extern "C" {

LIBCAMERA_PUBLIC int open(const char *path, int oflag, ...)
{
	mode_t mode = 0;
	if (oflag & O_CREAT || oflag & O_TMPFILE)
		extract_va_arg(mode_t, mode, oflag);

	return V4L2CompatManager::instance()->openat(AT_FDCWD, path,
						     oflag, mode);
}

/* _FORTIFY_SOURCE redirects open to __open_2 */
LIBCAMERA_PUBLIC int __open_2(const char *path, int oflag)
{
	return open(path, oflag);
}

#ifndef open64
LIBCAMERA_PUBLIC int open64(const char *path, int oflag, ...)
{
	mode_t mode = 0;
	if (oflag & O_CREAT || oflag & O_TMPFILE)
		extract_va_arg(mode_t, mode, oflag);

	return V4L2CompatManager::instance()->openat(AT_FDCWD, path,
						     oflag | O_LARGEFILE, mode);
}

LIBCAMERA_PUBLIC int __open64_2(const char *path, int oflag)
{
	return open(path, oflag);
}
#endif

LIBCAMERA_PUBLIC int openat(int dirfd, const char *path, int oflag, ...)
{
	mode_t mode = 0;
	if (oflag & O_CREAT || oflag & O_TMPFILE)
		extract_va_arg(mode_t, mode, oflag);

	return V4L2CompatManager::instance()->openat(dirfd, path, oflag, mode);
}

LIBCAMERA_PUBLIC int __openat_2(int dirfd, const char *path, int oflag)
{
	return openat(dirfd, path, oflag);
}

#ifndef openat64
LIBCAMERA_PUBLIC int openat64(int dirfd, const char *path, int oflag, ...)
{
	mode_t mode = 0;
	if (oflag & O_CREAT || oflag & O_TMPFILE)
		extract_va_arg(mode_t, mode, oflag);

	return V4L2CompatManager::instance()->openat(dirfd, path,
						     oflag | O_LARGEFILE, mode);
}

LIBCAMERA_PUBLIC int __openat64_2(int dirfd, const char *path, int oflag)
{
	return openat(dirfd, path, oflag);
}
#endif

LIBCAMERA_PUBLIC int dup(int oldfd)
{
	return V4L2CompatManager::instance()->dup(oldfd);
}

LIBCAMERA_PUBLIC int close(int fd)
{
	return V4L2CompatManager::instance()->close(fd);
}

LIBCAMERA_PUBLIC void *mmap(void *addr, size_t length, int prot, int flags,
			    int fd, off_t offset)
{
	return V4L2CompatManager::instance()->mmap(addr, length, prot, flags,
						   fd, offset);
}

#ifndef mmap64
LIBCAMERA_PUBLIC void *mmap64(void *addr, size_t length, int prot, int flags,
			      int fd, off64_t offset)
{
	return V4L2CompatManager::instance()->mmap(addr, length, prot, flags,
						   fd, offset);
}
#endif

LIBCAMERA_PUBLIC int munmap(void *addr, size_t length)
{
	return V4L2CompatManager::instance()->munmap(addr, length);
}

LIBCAMERA_PUBLIC int ioctl(int fd, unsigned long request, ...)
{
	void *arg;
	extract_va_arg(void *, arg, request);

	return V4L2CompatManager::instance()->ioctl(fd, request, arg);
}

}
an class="hl num">14, 15, 9 }; value.set(Span<uint8_t>(bytes)); if (value.isNone() || !value.isArray() || value.type() != ControlTypeByte) { cerr << "Control type mismatch after setting to uint8_t array" << endl; return TestFail; } Span<const uint8_t> int8sResult = value.get<Span<const uint8_t>>(); if (bytes.size() != int8sResult.size() || !std::equal(bytes.begin(), bytes.end(), int8sResult.begin())) { cerr << "Control value mismatch after setting to uint8_t array" << endl; return TestFail; } if (value.toString() != "[ 3, 14, 15, 9 ]") { cerr << "Control string mismatch after setting to uint8_t array" << endl; return TestFail; } /* * Integer32 type. */ value.set(0x42000000); if (value.isNone() || value.isArray() || value.type() != ControlTypeInteger32) { cerr << "Control type mismatch after setting to int32_t" << endl; return TestFail; } if (value.get<int32_t>() != 0x42000000) { cerr << "Control value mismatch after setting to int32_t" << endl; return TestFail; } if (value.toString() != "1107296256") { cerr << "Control string mismatch after setting to int32_t" << endl; return TestFail; } std::array<int32_t, 4> int32s{ 3, 14, 15, 9 }; value.set(Span<int32_t>(int32s)); if (value.isNone() || !value.isArray() || value.type() != ControlTypeInteger32) { cerr << "Control type mismatch after setting to int32_t array" << endl; return TestFail; } Span<const int32_t> int32sResult = value.get<Span<const int32_t>>(); if (int32s.size() != int32sResult.size() || !std::equal(int32s.begin(), int32s.end(), int32sResult.begin())) { cerr << "Control value mismatch after setting to int32_t array" << endl; return TestFail; } if (value.toString() != "[ 3, 14, 15, 9 ]") { cerr << "Control string mismatch after setting to int32_t array" << endl; return TestFail; } /* * Integer64 type. */ value.set(static_cast<int64_t>(-42)); if (value.isNone() || value.isArray() || value.type() != ControlTypeInteger64) { cerr << "Control type mismatch after setting to int64_t" << endl; return TestFail; } if (value.get<int64_t>() != -42) { cerr << "Control value mismatch after setting to int64_t" << endl; return TestFail; } if (value.toString() != "-42") { cerr << "Control string mismatch after setting to int64_t" << endl; return TestFail; } std::array<int64_t, 4> int64s{ 3, 14, 15, 9 }; value.set(Span<int64_t>(int64s)); if (value.isNone() || !value.isArray() || value.type() != ControlTypeInteger64) { cerr << "Control type mismatch after setting to int64_t array" << endl; return TestFail; } Span<const int64_t> int64sResult = value.get<Span<const int64_t>>(); if (int64s.size() != int64sResult.size() || !std::equal(int64s.begin(), int64s.end(), int64sResult.begin())) { cerr << "Control value mismatch after setting to int64_t array" << endl; return TestFail; } if (value.toString() != "[ 3, 14, 15, 9 ]") { cerr << "Control string mismatch after setting to int64_t array" << endl; return TestFail; } /* * Float type. */ value.set(-0.42f); if (value.isNone() || value.isArray() || value.type() != ControlTypeFloat) { cerr << "Control type mismatch after setting to float" << endl; return TestFail; } if (value.get<float>() != -0.42f) { cerr << "Control value mismatch after setting to float" << endl; return TestFail; } if (value.toString() != "-0.420000") { cerr << "Control string mismatch after setting to float" << endl; return TestFail; } std::array<float, 3> floats{ 3.141593, 2.718282, 299792458.0 }; value.set(Span<float>(floats)); if (value.isNone() || !value.isArray() || value.type() != ControlTypeFloat) { cerr << "Control type mismatch after setting to float array" << endl; return TestFail; } Span<const float> floatsResult = value.get<Span<const float>>(); if (floats.size() != floatsResult.size() || !std::equal(floats.begin(), floats.end(), floatsResult.begin())) { cerr << "Control value mismatch after setting to float array" << endl; return TestFail; } /* * The string representation for the third value doesn't match * the value in the floats array above, due to limited precision * of the float type that can't properly represent the speed of * light. */ if (value.toString() != "[ 3.141593, 2.718282, 299792448.000000 ]") { cerr << "Control string mismatch after setting to float array" << endl; return TestFail; } /* * String type. */ std::string string{ "libcamera" }; value.set(string); if (value.isNone() || !value.isArray() || value.type() != ControlTypeString || value.numElements() != string.size()) { cerr << "Control type mismatch after setting to string" << endl; return TestFail; } if (value.get<std::string>() != string) { cerr << "Control value mismatch after setting to string" << endl; return TestFail; } if (value.toString() != string) { cerr << "Control string mismatch after setting to string" << endl; return TestFail; } return TestPass; } }; TEST_REGISTER(ControlValueTest)