blob: 7255161f874a53e5ae3e1582a0e53ad77d9c65da [file] [log] [blame]
/*
V4L2 API compliance test tool.
Copyright (C) 2008, 2010 Hans Verkuil <hverkuil@xs4all.nl>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*/
#ifndef _V4L2_COMPLIANCE_H_
#define _V4L2_COMPLIANCE_H_
#include <map>
#include <set>
#include <string>
#include <linux/videodev2.h>
#include <linux/v4l2-subdev.h>
#include <linux/media.h>
#ifdef ANDROID
#include <android-config.h>
#else
#include <config.h>
#endif
#ifndef NO_LIBV4L2
#include <libv4l2.h>
#endif
#include <cv4l-helpers.h>
#include <v4l2-info.h>
#include <media-info.h>
#if !defined(ENODATA) && (defined(__FreeBSD__) || defined(__FreeBSD_kernel__))
#define ENODATA ENOTSUP
#endif
extern bool show_info;
extern bool show_colors;
extern bool show_warnings;
extern bool no_progress;
extern bool exit_on_fail;
extern bool exit_on_warn;
extern bool is_vivid; // We're testing the vivid driver
extern bool is_uvcvideo; // We're testing the uvc driver
extern int kernel_version;
extern int media_fd;
extern unsigned warnings;
extern bool has_mmu;
enum poll_mode {
POLL_MODE_NONE,
POLL_MODE_SELECT,
POLL_MODE_EPOLL,
};
#define JPEG_ENCODER (1 << 0)
#define JPEG_DECODER (1 << 1)
#define STATEFUL_ENCODER (1 << 2)
#define STATEFUL_DECODER (1 << 3)
#define STATELESS_ENCODER (1 << 4)
#define STATELESS_DECODER (1 << 5)
#define IS_ENCODER(node) ((node)->codec_mask & (JPEG_ENCODER | STATEFUL_ENCODER | STATELESS_ENCODER))
#define IS_DECODER(node) ((node)->codec_mask & (JPEG_DECODER | STATEFUL_DECODER | STATELESS_DECODER))
#define V4L2_CTRL_CLASS_VIVID 0x00f00000
#define VIVID_CID_VIVID_BASE (V4L2_CTRL_CLASS_VIVID | 0xf000)
#define VIVID_CID_DISCONNECT (VIVID_CID_VIVID_BASE + 65)
#define VIVID_CID_DQBUF_ERROR (VIVID_CID_VIVID_BASE + 66)
#define VIVID_CID_QUEUE_SETUP_ERROR (VIVID_CID_VIVID_BASE + 67)
#define VIVID_CID_BUF_PREPARE_ERROR (VIVID_CID_VIVID_BASE + 68)
#define VIVID_CID_START_STR_ERROR (VIVID_CID_VIVID_BASE + 69)
#define VIVID_CID_QUEUE_ERROR (VIVID_CID_VIVID_BASE + 70)
#define VIVID_CID_REQ_VALIDATE_ERROR (VIVID_CID_VIVID_BASE + 72)
#define VIVID_CID_CUSTOM_BASE (V4L2_CID_USER_BASE | 0xf000)
#define VIVID_CID_RO_INTEGER (VIVID_CID_CUSTOM_BASE + 12)
struct test_query_ext_ctrl: v4l2_query_ext_ctrl {
__u64 menu_mask;
};
using qctrl_map = std::map<__u32, test_query_ext_ctrl>;
using pixfmt_map = std::map<__u32, __u32>;
using frmsizes_set = std::set<__u64>;
using frmsizes_count_map = std::map<__u32, unsigned>;
struct base_node;
#define V4L2_BUF_TYPE_LAST V4L2_BUF_TYPE_META_OUTPUT
struct base_node {
bool is_video;
bool is_radio;
bool is_vbi;
bool is_sdr;
bool is_meta;
bool is_touch;
bool is_m2m;
bool is_io_mc;
bool is_planar;
bool is_ro_subdev;
bool can_capture;
bool can_output;
bool can_scale;
const char *device;
struct node *node2; /* second open filehandle */
bool has_outputs;
bool has_inputs;
unsigned tuners;
unsigned modulators;
unsigned inputs;
unsigned audio_inputs;
unsigned outputs;
unsigned audio_outputs;
unsigned cur_io_caps;
unsigned std_controls;
unsigned std_compound_controls;
unsigned priv_controls;
unsigned priv_compound_controls;
unsigned codec_mask;
__u32 media_version;
std::string media_bus_info;
media_entity_desc entity;
__u32 function;
media_pad_desc *pads;
media_link_desc *links;
media_v2_topology *topology;
v4l2_subdev_frame_interval_enum subdev_ival;
bool is_passthrough_subdev;
__u8 has_subdev_enum_code;
__u8 has_subdev_enum_fsize;
__u8 has_subdev_enum_fival;
__u8 has_subdev_fmt;
__u8 has_subdev_selection;
int frame_interval_pad;
int enum_frame_interval_pad;
__u32 fbuf_caps;
__u32 buf_caps;
const char *bus_info;
pixfmt_map buftype_pixfmts[V4L2_BUF_TYPE_LAST + 1];
frmsizes_set frmsizes;
frmsizes_count_map frmsizes_count;
bool has_frmintervals;
bool has_enc_cap_frame_interval;
__u32 valid_buftypes;
__u32 valid_buftype;
__u32 valid_memorytype;
bool supports_orphaned_bufs;
// support for this was introduced in 5.9
bool might_support_cache_hints;
};
struct node : public base_node, public cv4l_fd {
node() : base_node() {}
qctrl_map controls;
pixfmt_map buftype_pixfmts[V4L2_BUF_TYPE_LAST + 1];
bool inject_error(__u32 id)
{
v4l2_control ctrl = {
.id = id,
};
return is_vivid && !s_ctrl(ctrl);
}
};
class filehandles {
public:
filehandles() {}
~filehandles()
{
for (std::set<int>::const_iterator iter = fhs.begin(); iter != fhs.end(); ++iter)
close(*iter);
}
int add(int fd)
{
if (fd >= 0)
fhs.insert(fd);
return fd;
}
void del(int fd)
{
if (fd >= 0) {
fhs.erase(fd);
close(fd);
}
}
private:
std::set<int> fhs;
};
#define COLOR_GREEN(s) "\033[32m" s "\033[0m"
#define COLOR_RED(s) "\033[1;31m" s "\033[0m"
#define COLOR_BOLD(s) "\033[1m" s "\033[0m"
#define info(fmt, args...) \
do { \
if (show_info) \
printf("\t\tinfo: " fmt, ##args); \
} while (0)
#define warn(fmt, args...) \
do { \
warnings++; \
if (show_warnings) \
printf("\t\t%s: %s(%d): " fmt, \
show_colors ? \
COLOR_BOLD("warn") : "warn", \
__FILE__, __LINE__, ##args); \
if (exit_on_warn) \
std::exit(EXIT_FAILURE); \
} while (0)
#define warn_once(fmt, args...) \
do { \
static bool show; \
\
if (!show) { \
show = true; \
warn(fmt, ##args); \
} \
} while (0)
#define warn_on_test(test) \
do { \
if (test) \
warn("%s\n", #test); \
} while (0)
#define warn_once_on_test(test) \
do { \
if (test) \
warn_once("%s\n", #test); \
} while (0)
#define warn_or_info(is_info, fmt, args...) \
do { \
if (is_info) \
info(fmt, ##args); \
else \
warn(fmt, ##args); \
} while (0)
#define fail(fmt, args...) \
({ \
printf("\t\t%s: %s(%d): " fmt, show_colors ? \
COLOR_RED("fail") : "fail", __FILE__, __LINE__, ##args); \
if (exit_on_fail) \
std::exit(EXIT_FAILURE); \
1; \
})
#define fail_on_test(test) \
do { \
if (test) \
return fail("%s\n", #test); \
} while (0)
#define fail_on_test_val(test, v) \
do { \
if (test) \
return fail("%s (got %d)\n", #test, v); \
} while (0)
static inline int check_fract(const struct v4l2_fract *f)
{
if (f->numerator && f->denominator)
return 0;
return 1;
}
static inline double fract2f(const struct v4l2_fract *f)
{
return (double)f->numerator / (double)f->denominator;
}
#define doioctl(n, r, p) v4l_named_ioctl((n)->g_v4l_fd(), #r, r, p)
const char *ok(int res);
int check_string(const char *s, size_t len);
int check_ustring(const __u8 *s, int len);
int check_0(const void *p, int len);
int restoreFormat(struct node *node);
void testNode(struct node &node, struct node &node_m2m_cap, struct node &expbuf_node, media_type type,
unsigned frame_count, unsigned all_fmt_frame_count);
std::string stream_from(const std::string &pixelformat, bool &use_hdr);
// Media Controller ioctl tests
int testMediaDeviceInfo(struct node *node);
int testMediaTopology(struct node *node);
int testMediaEnum(struct node *node);
int testMediaSetupLink(struct node *node);
void walkTopology(struct node &node, struct node &expbuf_node,
unsigned frame_count, unsigned all_fmt_frame_count);
// Debug ioctl tests
int testRegister(struct node *node);
int testLogStatus(struct node *node);
// Input ioctl tests
int testTuner(struct node *node);
int testTunerFreq(struct node *node);
int testTunerHwSeek(struct node *node);
int testEnumInputAudio(struct node *node);
int testInput(struct node *node);
int testInputAudio(struct node *node);
// Output ioctl tests
int testModulator(struct node *node);
int testModulatorFreq(struct node *node);
int testEnumOutputAudio(struct node *node);
int testOutput(struct node *node);
int testOutputAudio(struct node *node);
// Control ioctl tests
int testQueryExtControls(struct node *node);
int testQueryControls(struct node *node);
int testSimpleControls(struct node *node);
int testExtendedControls(struct node *node);
int testEvents(struct node *node);
int testVividDisconnect(struct node *node);
int testJpegComp(struct node *node);
// I/O configuration ioctl tests
int testStd(struct node *node);
int testTimings(struct node *node);
int testTimingsCap(struct node *node);
int testEdid(struct node *node);
// Format ioctl tests
int testEnumFormats(struct node *node);
int testParm(struct node *node);
int testFBuf(struct node *node);
int testGetFormats(struct node *node);
int testTryFormats(struct node *node);
int testSetFormats(struct node *node);
int testSlicedVBICap(struct node *node);
int testCropping(struct node *node);
int testComposing(struct node *node);
int testScaling(struct node *node);
// Codec ioctl tests
int testEncoder(struct node *node);
int testEncIndex(struct node *node);
int testDecoder(struct node *node);
// SubDev ioctl tests
int testSubDevCap(struct node *node);
int testSubDevEnum(struct node *node, unsigned which, unsigned pad);
int testSubDevFormat(struct node *node, unsigned which, unsigned pad);
int testSubDevSelection(struct node *node, unsigned which, unsigned pad);
int testSubDevFrameInterval(struct node *node, unsigned pad);
// Buffer ioctl tests
int testReqBufs(struct node *node);
int testReadWrite(struct node *node);
int testExpBuf(struct node *node);
int testBlockingWait(struct node *node);
// 32-bit architecture, 32/64-bit time_t tests
int testTime32_64(struct node *node);
/*
* struct node node:
* the current media node being tested
*
* struct node node_m2m_cap:
* the capture device to be used when testing loopback or m2m, for
* instance, if the node we are testing is m2m, then node == node_m2m_cap,
* but if we have a topology like output->capture, node will be the output
* and node_m2m_cap will be the capture device that v4l2-compliance will
* use to test the loop
*/
int testMmap(struct node *node, struct node *node_m2m_cap, unsigned frame_count,
enum poll_mode pollmode);
int testUserPtr(struct node *node, struct node *node_m2m_cap,
unsigned frame_count, enum poll_mode pollmode);
int testDmaBuf(struct node *expbuf_node, struct node *node,
struct node *node_m2m_cap, unsigned frame_count,
enum poll_mode pollmode);
int testRequests(struct node *node, bool test_streaming);
void streamAllFormats(struct node *node, unsigned frame_count);
void streamM2MAllFormats(struct node *node, unsigned frame_count);
// Color tests
int testColorsAllFormats(struct node *node, unsigned component,
unsigned skip, unsigned perc);
#endif