mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-14 07:00:43 +02:00
460 lines
12 KiB
C++
460 lines
12 KiB
C++
#include "LinuxSyscalls/x32/Ioctl/HelperDefines.h"
|
|
#include "LinuxSyscalls/x32/Types.h"
|
|
|
|
#include <cstdint>
|
|
#include <linux/videodev2.h>
|
|
#include <sys/ioctl.h>
|
|
|
|
#define CPYT(x) val.x = x
|
|
#define CPYF(x) x = val.x
|
|
|
|
extern "C" {
|
|
// Upstream definitions that changed over time.
|
|
struct upstream_v4l2_create_buffers {
|
|
uint32_t index;
|
|
uint32_t count;
|
|
uint32_t memory;
|
|
struct v4l2_format format;
|
|
uint32_t capabilities;
|
|
uint32_t flags;
|
|
uint32_t max_num_buffers;
|
|
uint32_t reserved[5];
|
|
};
|
|
|
|
struct upstream_v4l2_remove_buffers {
|
|
uint32_t index;
|
|
uint32_t count;
|
|
uint32_t type;
|
|
uint32_t reserved[13];
|
|
};
|
|
}
|
|
|
|
namespace FEX::HLE::x32 {
|
|
namespace V4l2 {
|
|
|
|
struct FEX_ANNOTATE("alias-x86_32-v4l2_window") FEX_ANNOTATE("fex-match") fex_v4l2_window {
|
|
struct v4l2_rect w;
|
|
uint32_t field;
|
|
uint32_t chromakey;
|
|
compat_uptr_t clips;
|
|
uint32_t clipcount;
|
|
compat_uptr_t bitmap;
|
|
uint8_t global_alpha;
|
|
|
|
fex_v4l2_window() = default;
|
|
};
|
|
|
|
struct FEX_ANNOTATE("alias-x86_32-v4l2_format") FEX_ANNOTATE("fex-match") fex_v4l2_format {
|
|
uint32_t type;
|
|
union {
|
|
struct v4l2_pix_format pix;
|
|
struct v4l2_pix_format_mplane pix_mp;
|
|
// Just a valid place holder for struct verifier.
|
|
fex_v4l2_window win;
|
|
struct v4l2_vbi_format vbi;
|
|
struct v4l2_sliced_vbi_format sliced;
|
|
struct v4l2_sdr_format sdr;
|
|
struct v4l2_meta_format meta;
|
|
__u8 raw_data[200];
|
|
} fmt;
|
|
|
|
fex_v4l2_format() = delete;
|
|
|
|
operator v4l2_format() const {
|
|
v4l2_format val {};
|
|
CPYT(type);
|
|
|
|
switch (type) {
|
|
case V4L2_BUF_TYPE_VIDEO_CAPTURE: memcpy(&val.fmt, &fmt, sizeof(struct v4l2_pix_format)); break;
|
|
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: memcpy(&val.fmt, &fmt, sizeof(struct v4l2_pix_format_mplane)); break;
|
|
case V4L2_BUF_TYPE_VBI_CAPTURE: memcpy(&val.fmt, &fmt, sizeof(struct v4l2_vbi_format)); break;
|
|
case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: memcpy(&val.fmt, &fmt, sizeof(struct v4l2_sliced_vbi_format)); break;
|
|
case V4L2_BUF_TYPE_SDR_CAPTURE: memcpy(&val.fmt, &fmt, sizeof(struct v4l2_sdr_format)); break;
|
|
case V4L2_BUF_TYPE_META_CAPTURE: memcpy(&val.fmt, &fmt, sizeof(struct v4l2_meta_format)); break;
|
|
case V4L2_BUF_TYPE_VIDEO_OVERLAY: break;
|
|
default: memcpy(&val.fmt, &fmt, 200); break;
|
|
}
|
|
|
|
return val;
|
|
};
|
|
|
|
fex_v4l2_format(v4l2_format val) {
|
|
CPYF(type);
|
|
switch (type) {
|
|
case V4L2_BUF_TYPE_VIDEO_CAPTURE: memcpy(&fmt, &val.fmt, sizeof(struct v4l2_pix_format)); break;
|
|
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: memcpy(&fmt, &val.fmt, sizeof(struct v4l2_pix_format_mplane)); break;
|
|
case V4L2_BUF_TYPE_VBI_CAPTURE: memcpy(&fmt, &val.fmt, sizeof(struct v4l2_vbi_format)); break;
|
|
case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: memcpy(&fmt, &val.fmt, sizeof(struct v4l2_sliced_vbi_format)); break;
|
|
case V4L2_BUF_TYPE_SDR_CAPTURE: memcpy(&fmt, &val.fmt, sizeof(struct v4l2_sdr_format)); break;
|
|
case V4L2_BUF_TYPE_META_CAPTURE: memcpy(&fmt, &val.fmt, sizeof(struct v4l2_meta_format)); break;
|
|
case V4L2_BUF_TYPE_VIDEO_OVERLAY: break;
|
|
default: memcpy(&fmt, &val.fmt, 200); break;
|
|
}
|
|
}
|
|
};
|
|
|
|
struct FEX_ANNOTATE("alias-x86_32-v4l2_buffer") FEX_ANNOTATE("fex-match") fex_v4l2_buffer {
|
|
uint32_t index;
|
|
uint32_t type;
|
|
uint32_t bytesused;
|
|
uint32_t flags;
|
|
uint32_t field;
|
|
struct timeval32 timestamp;
|
|
struct v4l2_timecode timecode;
|
|
uint32_t sequence;
|
|
uint32_t memory;
|
|
|
|
union {
|
|
uint32_t offset;
|
|
compat_ptr<void> userptr;
|
|
compat_ptr<struct v4l2_plane> planes;
|
|
int32_t fd;
|
|
} m;
|
|
uint32_t length;
|
|
uint32_t reserved2;
|
|
union {
|
|
int32_t request_fd;
|
|
uint32_t reserved;
|
|
};
|
|
|
|
fex_v4l2_buffer() = delete;
|
|
|
|
operator v4l2_buffer() const {
|
|
v4l2_buffer val {};
|
|
CPYT(index);
|
|
CPYT(type);
|
|
CPYT(bytesused);
|
|
CPYT(flags);
|
|
CPYT(field);
|
|
CPYT(timestamp);
|
|
CPYT(timecode);
|
|
CPYT(sequence);
|
|
CPYT(memory);
|
|
CPYT(length);
|
|
CPYT(reserved2);
|
|
CPYT(m.offset);
|
|
CPYT(request_fd);
|
|
return val;
|
|
}
|
|
|
|
fex_v4l2_buffer(v4l2_buffer val)
|
|
: timestamp {val.timestamp}
|
|
, m {.offset = val.m.offset} {
|
|
CPYF(index);
|
|
CPYF(type);
|
|
CPYF(bytesused);
|
|
CPYF(flags);
|
|
CPYF(field);
|
|
CPYF(timecode);
|
|
CPYF(sequence);
|
|
CPYF(memory);
|
|
CPYF(length);
|
|
CPYF(reserved2);
|
|
CPYF(request_fd);
|
|
}
|
|
};
|
|
|
|
struct FEX_ANNOTATE("alias-x86_32-v4l2_framebuffer") FEX_ANNOTATE("fex-match") fex_v4l2_framebuffer {
|
|
uint32_t capability;
|
|
uint32_t flags;
|
|
compat_ptr<void> base;
|
|
struct {
|
|
uint32_t width;
|
|
uint32_t height;
|
|
uint32_t pixelformat;
|
|
uint32_t field;
|
|
uint32_t bytesperline;
|
|
uint32_t sizeimage;
|
|
uint32_t colorspace;
|
|
uint32_t priv;
|
|
} fmt;
|
|
|
|
fex_v4l2_framebuffer() = delete;
|
|
|
|
operator v4l2_framebuffer() const {
|
|
v4l2_framebuffer val {};
|
|
CPYT(capability);
|
|
CPYT(flags);
|
|
CPYT(base);
|
|
memcpy(&val.fmt, &fmt, sizeof(fmt));
|
|
return val;
|
|
}
|
|
|
|
fex_v4l2_framebuffer(v4l2_framebuffer val)
|
|
: base {auto_compat_ptr {val.base}} {
|
|
CPYF(capability);
|
|
CPYF(flags);
|
|
memcpy(&fmt, &val.fmt, sizeof(fmt));
|
|
}
|
|
};
|
|
|
|
struct FEX_ANNOTATE("alias-x86_32-v4l2_standard") FEX_ANNOTATE("fex-match") fex_v4l2_standard {
|
|
uint32_t index;
|
|
compat_uint64_t id;
|
|
uint8_t name[24];
|
|
struct v4l2_fract frameperiod;
|
|
uint32_t framelines;
|
|
uint32_t reserved[4];
|
|
|
|
fex_v4l2_standard() = delete;
|
|
|
|
operator v4l2_standard() const {
|
|
v4l2_standard val {};
|
|
CPYT(index);
|
|
CPYT(id);
|
|
memcpy(&val.name, name, sizeof(name));
|
|
CPYT(frameperiod);
|
|
CPYT(framelines);
|
|
memcpy(&val.reserved, reserved, sizeof(uint32_t) * 4);
|
|
return val;
|
|
}
|
|
|
|
fex_v4l2_standard(v4l2_standard val) {
|
|
CPYF(index);
|
|
CPYF(id);
|
|
memcpy(&name, val.name, sizeof(name));
|
|
CPYF(frameperiod);
|
|
CPYF(framelines);
|
|
memcpy(&reserved, val.reserved, sizeof(uint32_t) * 4);
|
|
}
|
|
};
|
|
|
|
struct FEX_ANNOTATE("alias-x86_32-v4l2_input") FEX_ANNOTATE("fex-match") fex_v4l2_input {
|
|
uint32_t index;
|
|
uint8_t name[32];
|
|
uint32_t type;
|
|
uint32_t audioset;
|
|
uint32_t tuner;
|
|
compat_uint64_t std;
|
|
uint32_t status;
|
|
uint32_t capabilities;
|
|
uint32_t reserved[3];
|
|
|
|
fex_v4l2_input() = delete;
|
|
|
|
operator v4l2_input() const {
|
|
v4l2_input val {};
|
|
CPYT(index);
|
|
memcpy(&val.name, &name, sizeof(name));
|
|
CPYT(type);
|
|
CPYT(audioset);
|
|
CPYT(tuner);
|
|
CPYT(std);
|
|
CPYT(status);
|
|
CPYT(capabilities);
|
|
memcpy(&val.reserved, &reserved, sizeof(uint32_t) * 3);
|
|
return val;
|
|
}
|
|
|
|
fex_v4l2_input(v4l2_input val) {
|
|
CPYF(index);
|
|
memcpy(&name, &val.name, sizeof(name));
|
|
CPYF(type);
|
|
CPYF(audioset);
|
|
CPYF(tuner);
|
|
CPYF(std);
|
|
CPYF(status);
|
|
CPYF(capabilities);
|
|
memcpy(&reserved, &val.reserved, sizeof(uint32_t) * 3);
|
|
}
|
|
};
|
|
|
|
struct FEX_ANNOTATE("alias-x86_32-v4l2_edid") FEX_ANNOTATE("fex-match") fex_v4l2_edid {
|
|
uint32_t pad;
|
|
uint32_t start_block;
|
|
uint32_t blocks;
|
|
uint32_t reserved[5];
|
|
compat_ptr<uint8_t> edid;
|
|
|
|
fex_v4l2_edid() = delete;
|
|
|
|
operator v4l2_edid() const {
|
|
v4l2_edid val {};
|
|
CPYT(pad);
|
|
CPYT(start_block);
|
|
CPYT(blocks);
|
|
memcpy(&val.reserved, &reserved, sizeof(uint32_t) * 5);
|
|
CPYT(edid);
|
|
return val;
|
|
}
|
|
|
|
fex_v4l2_edid(v4l2_edid val)
|
|
: edid {auto_compat_ptr {val.edid}} {
|
|
CPYF(pad);
|
|
CPYF(start_block);
|
|
CPYF(blocks);
|
|
memcpy(&reserved, &val.reserved, sizeof(uint32_t) * 5);
|
|
}
|
|
};
|
|
|
|
struct FEX_ANNOTATE("alias-x86_32-v4l2_ext_controls") FEX_ANNOTATE("fex-match") fex_v4l2_ext_controls {
|
|
union {
|
|
uint32_t ctrl_class;
|
|
uint32_t which;
|
|
};
|
|
uint32_t count;
|
|
uint32_t error_idx;
|
|
int32_t request_fd;
|
|
uint32_t reserved[1];
|
|
compat_ptr<struct v4l2_ext_control> controls;
|
|
|
|
fex_v4l2_ext_controls() = delete;
|
|
|
|
operator v4l2_ext_controls() const {
|
|
v4l2_ext_controls val {};
|
|
CPYT(which);
|
|
CPYT(count);
|
|
CPYT(error_idx);
|
|
CPYT(request_fd);
|
|
CPYT(reserved[0]);
|
|
CPYT(controls);
|
|
return val;
|
|
}
|
|
|
|
fex_v4l2_ext_controls(v4l2_ext_controls val)
|
|
: controls {auto_compat_ptr {val.controls}} {
|
|
CPYF(which);
|
|
CPYF(count);
|
|
CPYF(error_idx);
|
|
CPYF(request_fd);
|
|
CPYF(reserved[0]);
|
|
}
|
|
};
|
|
|
|
struct FEX_ANNOTATE("alias-x86_32-v4l2_event_ctrl") FEX_ANNOTATE("fex-match") fex_v4l2_event_ctrl {
|
|
uint32_t changes;
|
|
uint32_t type;
|
|
union {
|
|
int32_t value;
|
|
compat_int64_t value64;
|
|
};
|
|
uint32_t flags;
|
|
int32_t minimum;
|
|
int32_t maximum;
|
|
int32_t step;
|
|
int32_t default_value;
|
|
|
|
fex_v4l2_event_ctrl() = default;
|
|
|
|
operator v4l2_event_ctrl() const {
|
|
v4l2_event_ctrl val {};
|
|
CPYT(changes);
|
|
CPYT(type);
|
|
CPYT(value64);
|
|
CPYT(flags);
|
|
CPYT(minimum);
|
|
CPYT(maximum);
|
|
CPYT(step);
|
|
CPYT(default_value);
|
|
return val;
|
|
}
|
|
|
|
fex_v4l2_event_ctrl(v4l2_event_ctrl val) {
|
|
CPYF(changes);
|
|
CPYF(type);
|
|
CPYF(value64);
|
|
CPYF(flags);
|
|
CPYF(minimum);
|
|
CPYF(maximum);
|
|
CPYF(step);
|
|
CPYF(default_value);
|
|
}
|
|
};
|
|
|
|
struct FEX_ANNOTATE("alias-x86_32-v4l2_event") FEX_ANNOTATE("fex-match") fex_v4l2_event {
|
|
uint32_t type;
|
|
union {
|
|
struct v4l2_event_vsync vsync;
|
|
fex_v4l2_event_ctrl ctrl;
|
|
struct v4l2_event_frame_sync frame_sync;
|
|
struct v4l2_event_src_change src_change;
|
|
struct v4l2_event_motion_det motion_det;
|
|
uint8_t data[64];
|
|
} u;
|
|
uint32_t pending;
|
|
uint32_t sequence;
|
|
timespec32 timestamp;
|
|
uint32_t id;
|
|
uint32_t reserved[8];
|
|
|
|
fex_v4l2_event() = delete;
|
|
|
|
operator v4l2_event() const {
|
|
v4l2_event val {};
|
|
CPYT(type);
|
|
switch (type) {
|
|
case V4L2_EVENT_VSYNC: CPYT(u.vsync); break;
|
|
case V4L2_EVENT_CTRL: CPYT(u.ctrl); break;
|
|
case V4L2_EVENT_FRAME_SYNC: CPYT(u.frame_sync); break;
|
|
case V4L2_EVENT_SOURCE_CHANGE: CPYT(u.src_change); break;
|
|
case V4L2_EVENT_MOTION_DET: CPYT(u.motion_det); break;
|
|
default: memcpy(&val.u.data, &u.data, 64); break;
|
|
}
|
|
CPYT(pending);
|
|
CPYT(sequence);
|
|
CPYT(timestamp);
|
|
CPYT(id);
|
|
memcpy(&val.reserved, &reserved, sizeof(uint32_t) * 8);
|
|
return val;
|
|
}
|
|
|
|
fex_v4l2_event(v4l2_event val) {
|
|
CPYF(type);
|
|
switch (type) {
|
|
case V4L2_EVENT_VSYNC: CPYF(u.vsync); break;
|
|
case V4L2_EVENT_CTRL: CPYF(u.ctrl); break;
|
|
case V4L2_EVENT_FRAME_SYNC: CPYF(u.frame_sync); break;
|
|
case V4L2_EVENT_SOURCE_CHANGE: CPYF(u.src_change); break;
|
|
case V4L2_EVENT_MOTION_DET: CPYF(u.motion_det); break;
|
|
default: memcpy(&u.data, &val.u.data, 64); break;
|
|
}
|
|
CPYF(pending);
|
|
CPYF(sequence);
|
|
CPYF(timestamp);
|
|
CPYF(id);
|
|
memcpy(&reserved, &val.reserved, sizeof(uint32_t) * 8);
|
|
}
|
|
};
|
|
|
|
struct FEX_ANNOTATE("alias-x86_32-upstream_v4l2_create_buffers") FEX_ANNOTATE("fex-match") fex_v4l2_create_buffers {
|
|
uint32_t index;
|
|
uint32_t count;
|
|
uint32_t memory;
|
|
fex_v4l2_format format;
|
|
uint32_t capabilities;
|
|
uint32_t flags;
|
|
uint32_t max_num_buffers;
|
|
uint32_t reserved[5];
|
|
|
|
fex_v4l2_create_buffers() = delete;
|
|
operator upstream_v4l2_create_buffers() const {
|
|
upstream_v4l2_create_buffers val {};
|
|
CPYT(index);
|
|
CPYT(count);
|
|
CPYT(memory);
|
|
CPYT(format);
|
|
CPYT(capabilities);
|
|
CPYT(flags);
|
|
CPYT(max_num_buffers);
|
|
memcpy(&val.reserved, &reserved, sizeof(uint32_t) * 5);
|
|
return val;
|
|
}
|
|
|
|
fex_v4l2_create_buffers(upstream_v4l2_create_buffers val)
|
|
: format {val.format} {
|
|
CPYF(index);
|
|
CPYF(count);
|
|
CPYF(memory);
|
|
CPYF(capabilities);
|
|
CPYF(flags);
|
|
CPYF(max_num_buffers);
|
|
memcpy(&reserved, &val.reserved, sizeof(uint32_t) * 5);
|
|
}
|
|
};
|
|
|
|
#include "LinuxSyscalls/x32/Ioctl/v4l2.inl"
|
|
} // namespace V4l2
|
|
} // namespace FEX::HLE::x32
|
|
#undef CPYT
|
|
#undef CPYF
|