Files
RedBear-OS/local/recipes/libs/libdrm/redox.patch
T
vasilito 19c65be7b1 feat: VirtIO GPU driver, libdrm DRM ioctls, KWin/KF6 build fixes, display stack additions
- Add full VirtIO GPU driver with command submission, resource management,
  VirtQueue implementation, and transport layer; includes diagnostic probes
  for resource_create_2d ERR_INVALID_RESOURCE_ID investigation
- Expand libdrm Redox support with DRM ioctl wrappers (ADDFB, RMFB,
  CREATE_DUMB, MAP_DUMB, DESTROY_DUMB, GET_RESOURCES, GET_CONNECTOR,
  GET_CRTC, SET_CRTC, MODE_OBJ_GET_PROPERTIES, etc.) and xf86drm_redox.h
- Add redox-drm scheme handlers for VirtIO GPU-specific DRM ioctls
  (VIRTGPU_RESOURCE_CREATE, VIRTGPU_MAP, VIRTGPU_WAIT, VIRTGPU_INFO, etc.)
- Add display stack recipes: freetype2, lcms2, libdisplay-info, libepoxy,
  libxcvt
- Fix KWin build (recipe.toml expanded, kf6-ksvg added)
- Fix KF6 CMakeLists for cross-compilation (attica, kcmutils, kcolorscheme,
  kcompletion, kconfigwidgets, kdeclarative, kiconthemes, kitemmodels,
  kitemviews, kjobwidgets, ktextwidgets, kwayland, kxmlgui, kpty, solid)
- Add Qt6 futex support patch
- Add relibc patches: P3 strtold, P3 ld-so search path, P5 DRM ioctl removal
- Add base P4 pcid config scheme patch
- Update driver-manager hotplug/config, PCI config in redox-driver-sys
- Update greeter compositor and KDE session scripts
- Update AGENTS.md with zero-tolerance stubs policy and project knowledge
2026-05-14 10:31:13 +01:00

1543 lines
37 KiB
Diff

diff -ruN source-old/include/drm/drm.h source/include/drm/drm.h
--- source-old/include/drm/drm.h
+++ source/include/drm/drm.h
@@ -44,7 +44,11 @@
#else /* One of the BSDs */
#include <stdint.h>
+#if defined(__redox__)
+#include <sys/ioctl.h>
+#else
#include <sys/ioccom.h>
+#endif
#include <sys/types.h>
typedef int8_t __s8;
typedef uint8_t __u8;
diff -ruN source-old/xf86drm.c source/xf86drm.c
--- source-old/xf86drm.c
+++ source/xf86drm.c
@@ -57,6 +57,19 @@
#ifdef MAJOR_IN_SYSMACROS
#include <sys/sysmacros.h>
#endif
+#if defined(__redox__)
+// From musl sys/sysmacros.h
+#define major(x) \
+ ((unsigned)( (((x)>>31>>1) & 0xfffff000) | (((x)>>8) & 0x00000fff) ))
+#define minor(x) \
+ ((unsigned)( (((x)>>12) & 0xffffff00) | ((x) & 0x000000ff) ))
+
+#define makedev(x,y) ( \
+ (((x)&0xfffff000ULL) << 32) | \
+ (((x)&0x00000fffULL) << 8) | \
+ (((y)&0xffffff00ULL) << 12) | \
+ (((y)&0x000000ffULL)) )
+#endif
#if HAVE_SYS_SYSCTL_H
#include <sys/sysctl.h>
#endif
@@ -75,6 +88,7 @@
#endif
#include "xf86drm.h"
+#include "xf86drm_redox.h"
#include "libdrm_macros.h"
#include "drm_fourcc.h"
@@ -300,13 +314,18 @@
uint64_t type = (modifier >> 52) & 0xf;
FILE *fp;
- size_t size = 0;
char *modifier_name = NULL;
bool result = false;
+#if defined(__redox__)
+ fprintf(stderr, "open_memstream not available on Redox\n");
+ return NULL;
+#else
+ size_t size = 0;
fp = open_memstream(&modifier_name, &size);
if (!fp)
return NULL;
+#endif
switch (type) {
case DRM_FORMAT_MOD_ARM_TYPE_AFBC:
@@ -407,11 +426,16 @@
uint64_t tile_version = AMD_FMT_MOD_GET(TILE_VERSION, modifier);
FILE *fp;
char *mod_amd = NULL;
- size_t size = 0;
+#if defined(__redox__)
+ fprintf(stderr, "open_memstream not available on Redox\n");
+ return NULL;
+#else
+ size_t size = 0;
fp = open_memstream(&mod_amd, &size);
if (!fp)
return NULL;
+#endif
switch (tile_version) {
case AMD_FMT_MOD_TILE_VER_GFX9:
@@ -680,18 +704,259 @@
free(pt);
}
+#if defined(__redox__)
+static int redox_drm_write_all(int fd, const void *buf, size_t len)
+{
+ const uint8_t *bytes = buf;
+ size_t offset = 0;
+
+ while (offset < len) {
+ ssize_t written = write(fd, bytes + offset, len - offset);
+ if (written < 0) {
+ if (errno == EINTR || errno == EAGAIN)
+ continue;
+ return -1;
+ }
+ if (written == 0) {
+ errno = EIO;
+ return -1;
+ }
+ offset += (size_t)written;
+ }
+
+ return 0;
+}
+
+static int redox_drm_read_all(int fd, void *buf, size_t len)
+{
+ uint8_t *bytes = buf;
+ size_t offset = 0;
+
+ while (offset < len) {
+ ssize_t read_count = read(fd, bytes + offset, len - offset);
+ if (read_count < 0) {
+ if (errno == EINTR || errno == EAGAIN)
+ continue;
+ return -1;
+ }
+ if (read_count == 0) {
+ errno = EIO;
+ return -1;
+ }
+ offset += (size_t)read_count;
+ }
+
+ return 0;
+}
+
+static int redox_drm_send_request(int fd, unsigned long request_code,
+ const void *payload, size_t payload_size)
+{
+ const size_t request_word_size = sizeof(uintptr_t);
+ const size_t total_size = request_word_size + payload_size;
+ uint8_t stack_request[sizeof(uintptr_t)];
+ uint8_t *request_bytes = stack_request;
+ uintptr_t request_word = (uintptr_t)request_code;
+ size_t i;
+
+ if (total_size > sizeof(stack_request)) {
+ request_bytes = drmMalloc(total_size);
+ if (!request_bytes) {
+ errno = ENOMEM;
+ return -1;
+ }
+ }
+
+ for (i = 0; i < request_word_size; ++i)
+ request_bytes[i] = (uint8_t)((request_word >> (i * 8)) & 0xffU);
+
+ if (payload_size != 0)
+ memcpy(request_bytes + request_word_size, payload, payload_size);
+
+ if (redox_drm_write_all(fd, request_bytes, total_size) != 0) {
+ if (request_bytes != stack_request)
+ drmFree(request_bytes);
+ return -1;
+ }
+
+ if (request_bytes != stack_request)
+ drmFree(request_bytes);
+
+ return 0;
+}
+
+static int redox_drm_get_response_size(int fd, size_t *response_size)
+{
+ stat_t st;
+
+ if (fstat(fd, &st) != 0)
+ return -1;
+
+ *response_size = (size_t)st.st_size;
+ return 0;
+}
+
+unsigned long redox_translate_request(unsigned long linux_nr)
+{
+ switch (linux_nr) {
+ case 0x0C:
+ return REDOX_DRM_IOCTL_GET_CAP;
+ case 0x0D:
+ return REDOX_DRM_IOCTL_SET_CLIENT_CAP;
+ case 0x09:
+ return REDOX_DRM_IOCTL_GEM_CLOSE;
+ case 0xA6:
+ return REDOX_DRM_IOCTL_MODE_GETENCODER;
+ case 0xB3:
+ return REDOX_DRM_IOCTL_MODE_MAP_DUMB;
+ case 0xB4:
+ return REDOX_DRM_IOCTL_MODE_DESTROY_DUMB;
+ case 0xAF:
+ return REDOX_DRM_IOCTL_MODE_RMFB;
+ default:
+ return 0;
+ }
+}
+
+int redox_drm_exchange(int fd, unsigned long request_code,
+ const void *payload, size_t payload_size,
+ void *response, size_t response_capacity,
+ size_t *response_size)
+{
+ uint8_t stack_buffer[64];
+ uint8_t *response_buffer = stack_buffer;
+ size_t actual_response_size = 0;
+
+ if (redox_drm_send_request(fd, request_code, payload, payload_size) != 0)
+ return -1;
+
+ if (redox_drm_get_response_size(fd, &actual_response_size) != 0)
+ return -1;
+
+ if (response_size)
+ *response_size = actual_response_size;
+
+ if (actual_response_size == 0)
+ return 0;
+
+ if (response && response_capacity >= actual_response_size) {
+ return redox_drm_read_all(fd, response, actual_response_size);
+ }
+
+ if (actual_response_size > sizeof(stack_buffer)) {
+ response_buffer = drmMalloc(actual_response_size);
+ if (!response_buffer) {
+ errno = ENOMEM;
+ return -1;
+ }
+ }
+
+ if (redox_drm_read_all(fd, response_buffer, actual_response_size) != 0) {
+ if (response_buffer != stack_buffer)
+ drmFree(response_buffer);
+ return -1;
+ }
+
+ if (response_buffer != stack_buffer)
+ drmFree(response_buffer);
+
+ if (response && response_capacity < actual_response_size) {
+ errno = EMSGSIZE;
+ return -1;
+ }
+
+ return 0;
+}
+
+int redox_drm_exchange_alloc(int fd, unsigned long request_code,
+ const void *payload, size_t payload_size,
+ void **response, size_t *response_size)
+{
+ size_t actual_response_size = 0;
+ void *allocated_response = NULL;
+
+ if (!response) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (redox_drm_send_request(fd, request_code, payload, payload_size) != 0)
+ return -1;
+
+ if (redox_drm_get_response_size(fd, &actual_response_size) != 0)
+ return -1;
+
+ if (actual_response_size != 0) {
+ allocated_response = drmMalloc(actual_response_size);
+ if (!allocated_response) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ if (redox_drm_read_all(fd, allocated_response, actual_response_size) != 0) {
+ drmFree(allocated_response);
+ return -1;
+ }
+ }
+
+ *response = allocated_response;
+ if (response_size)
+ *response_size = actual_response_size;
+ return 0;
+}
+
+static size_t redox_drm_expected_response_size(unsigned long linux_nr, size_t arg_size)
+{
+ switch (linux_nr) {
+ case 0x0C:
+ case 0xA6:
+ case 0xB3:
+ return arg_size;
+ default:
+ return 0;
+ }
+}
+
+int redox_drm_simple_ioctl(int fd, unsigned long request, void *arg)
+{
+ const unsigned long linux_nr = REDOX_LINUX_IOCTL_NR(request);
+ const unsigned long request_code = redox_translate_request(linux_nr);
+ const size_t arg_size = REDOX_LINUX_IOCTL_SIZE(request);
+ const size_t expected_response_size = redox_drm_expected_response_size(linux_nr, arg_size);
+
+ if (request_code == 0) {
+ errno = ENOTTY;
+ return -1;
+ }
+
+ if (redox_drm_exchange(fd, request_code,
+ arg, arg ? arg_size : 0,
+ expected_response_size ? arg : NULL,
+ expected_response_size,
+ NULL) != 0) {
+ return -1;
+ }
+
+ return 0;
+}
+#endif
+
/**
* Call ioctl, restarting if it is interrupted
*/
drm_public int
drmIoctl(int fd, unsigned long request, void *arg)
{
+ #if defined(__redox__)
+ return redox_drm_simple_ioctl(fd, request, arg);
+ #else
int ret;
do {
ret = ioctl(fd, request, arg);
} while (ret == -1 && (errno == EINTR || errno == EAGAIN));
return ret;
+ #endif
}
static unsigned long drmGetKeyFromFd(int fd)
@@ -823,6 +1088,21 @@
return NULL;
}
+static int drmGetNodePath(char *buf, size_t buf_len, int type, int minor)
+{
+ const char *dev_name = drmGetDeviceName(type);
+
+#if defined(__redox__)
+ if (type == DRM_NODE_RENDER)
+ return snprintf(buf, buf_len, "%s/" DRM_RENDER_MINOR_NAME, DRM_DIR_NAME);
+#endif
+
+ if (!dev_name)
+ return -1;
+
+ return snprintf(buf, buf_len, dev_name, DRM_DIR_NAME, minor);
+}
+
/**
* Open the DRM device, creating it if necessary.
*
@@ -839,7 +1119,6 @@
static int drmOpenDevice(dev_t dev, int minor, int type)
{
stat_t st;
- const char *dev_name = drmGetDeviceName(type);
char buf[DRM_NODE_NAME_MAX];
int fd;
mode_t devmode = DRM_DEV_MODE, serv_mode;
@@ -850,10 +1129,8 @@
gid_t group = DRM_DEV_GID;
#endif
- if (!dev_name)
+ if (drmGetNodePath(buf, sizeof(buf), type, minor) < 0)
return -EINVAL;
-
- sprintf(buf, dev_name, DRM_DIR_NAME, minor);
drmMsg("drmOpenDevice: node name is %s\n", buf);
if (drm_server_info && drm_server_info->get_perms) {
@@ -958,15 +1235,13 @@
{
int fd;
char buf[DRM_NODE_NAME_MAX];
- const char *dev_name = drmGetDeviceName(type);
if (create)
return drmOpenDevice(makedev(DRM_MAJOR, minor), minor, type);
- if (!dev_name)
+ if (drmGetNodePath(buf, sizeof(buf), type, minor) < 0)
return -EINVAL;
- sprintf(buf, dev_name, DRM_DIR_NAME, minor);
if ((fd = open(buf, O_RDWR | O_CLOEXEC)) >= 0)
return fd;
return -errno;
@@ -1060,6 +1335,7 @@
return -1;
}
+#if !defined(__redox__)
static const char *drmGetMinorName(int type)
{
switch (type) {
@@ -1071,6 +1347,7 @@
return NULL;
}
}
+#endif
/**
* Open the device by bus ID.
@@ -1168,7 +1445,11 @@
for (i = base; i < base + DRM_MAX_MINOR; i++) {
if ((fd = drmOpenMinor(i, 1, type)) >= 0) {
if ((version = drmGetVersion(fd))) {
+ #if defined(__redox__)
+ if (!version->name || !strcmp(version->name, name)) {
+ #else
if (!strcmp(version->name, name)) {
+ #endif
drmFreeVersion(version);
id = drmGetBusid(fd);
drmMsg("drmGetBusid returned '%s'\n", id ? id : "NULL");
@@ -1321,6 +1602,7 @@
* Used by drmGetVersion() to free the memory pointed by \p %v as well as all
* the non-null strings pointers in it.
*/
+#if !defined(__redox__)
static void drmFreeKernelVersion(drm_version_t *v)
{
if (!v)
@@ -1330,6 +1612,7 @@
drmFree(v->desc);
drmFree(v);
}
+#endif
/**
@@ -1342,6 +1625,7 @@
* Used by drmGetVersion() to translate the information returned by the ioctl
* interface in a private structure into the public structure counterpart.
*/
+#if !defined(__redox__)
static void drmCopyVersion(drmVersionPtr d, const drm_version_t *s)
{
d->version_major = s->version_major;
@@ -1354,6 +1638,7 @@
d->desc_len = s->desc_len;
d->desc = s->desc ? strdup(s->desc) : NULL;
}
+#endif
/**
@@ -1373,6 +1658,27 @@
*/
drm_public drmVersionPtr drmGetVersion(int fd)
{
+ #if defined(__redox__)
+ drmVersionPtr retval = drmMalloc(sizeof(*retval));
+ struct redox_drm_version_wire version;
+
+ if (!retval)
+ return NULL;
+
+ if (redox_drm_exchange(fd, REDOX_DRM_IOCTL_VERSION,
+ NULL, 0,
+ &version, sizeof(version),
+ NULL) != 0) {
+ drmFree(retval);
+ return NULL;
+ }
+
+ memclear(*retval);
+ retval->version_major = version.major;
+ retval->version_minor = version.minor;
+ retval->version_patchlevel = version.patch;
+ return retval;
+ #else
drmVersionPtr retval;
drm_version_t *version = drmMalloc(sizeof(*version));
@@ -1403,6 +1709,7 @@
drmCopyVersion(retval, version);
drmFreeKernelVersion(version);
return retval;
+ #endif
}
@@ -3306,7 +3613,8 @@
d = sbuf.st_rdev;
for (i = 0; i < DRM_MAX_MINOR; i++) {
- snprintf(name, sizeof name, DRM_DEV_NAME, DRM_DIR_NAME, i);
+ if (drmGetNodePath(name, sizeof(name), DRM_NODE_PRIMARY, i) < 0)
+ return NULL;
if (stat(name, &sbuf) == 0 && sbuf.st_rdev == d)
break;
}
@@ -3366,6 +3674,23 @@
drm_public int drmPrimeHandleToFD(int fd, uint32_t handle, uint32_t flags,
int *prime_fd)
{
+ #if defined(__redox__)
+ struct redox_drm_prime_handle_to_fd_wire request;
+ struct redox_drm_prime_handle_to_fd_response_wire response;
+
+ memclear(request);
+ request.handle = handle;
+ request.flags = flags;
+ if (redox_drm_exchange(fd, REDOX_DRM_IOCTL_PRIME_HANDLE_TO_FD,
+ &request, sizeof(request),
+ &response, sizeof(response),
+ NULL) != 0) {
+ return -errno;
+ }
+
+ *prime_fd = response.fd;
+ return 0;
+ #else
struct drm_prime_handle args;
int ret;
@@ -3379,10 +3704,27 @@
*prime_fd = args.fd;
return 0;
+ #endif
}
drm_public int drmPrimeFDToHandle(int fd, int prime_fd, uint32_t *handle)
{
+ #if defined(__redox__)
+ struct redox_drm_prime_fd_to_handle_wire request;
+ struct redox_drm_prime_fd_to_handle_response_wire response;
+
+ memclear(request);
+ request.fd = prime_fd;
+ if (redox_drm_exchange(fd, REDOX_DRM_IOCTL_PRIME_FD_TO_HANDLE,
+ &request, sizeof(request),
+ &response, sizeof(response),
+ NULL) != 0) {
+ return -errno;
+ }
+
+ *handle = response.handle;
+ return 0;
+ #else
struct drm_prime_handle args;
int ret;
@@ -3394,6 +3736,7 @@
*handle = args.handle;
return 0;
+ #endif
}
drm_public int drmCloseBufferHandle(int fd, uint32_t handle)
@@ -3495,7 +3838,6 @@
#else
struct stat sbuf;
char buf[PATH_MAX + 1];
- const char *dev_name = drmGetDeviceName(type);
unsigned int maj, min;
int n;
@@ -3508,11 +3850,10 @@
if (!drmNodeIsDRM(maj, min) || !S_ISCHR(sbuf.st_mode))
return NULL;
- if (!dev_name)
+ n = drmGetNodePath(buf, sizeof(buf), type, min);
+ if (n < 0)
return NULL;
-
- n = snprintf(buf, sizeof(buf), dev_name, DRM_DIR_NAME, min);
- if (n == -1 || n >= sizeof(buf))
+ if ((size_t)n >= sizeof(buf))
return NULL;
return strdup(buf);
@@ -4877,7 +5218,6 @@
#else
struct stat sbuf;
char node[PATH_MAX + 1];
- const char *dev_name;
int node_type;
int maj, min, n;
@@ -4894,12 +5234,8 @@
if (node_type == -1)
return NULL;
- dev_name = drmGetDeviceName(node_type);
- if (!dev_name)
- return NULL;
-
- n = snprintf(node, PATH_MAX, dev_name, DRM_DIR_NAME, min);
- if (n == -1 || n >= PATH_MAX)
+ n = drmGetNodePath(node, sizeof(node), node_type, min);
+ if (n < 0 || n >= PATH_MAX)
return NULL;
return strdup(node);
diff -ruN source-old/xf86drm.h source/xf86drm.h
--- source-old/xf86drm.h
+++ source/xf86drm.h
@@ -47,7 +47,7 @@
#define DRM_MAX_MINOR 64 /* deprecated */
#endif
-#if defined(__linux__)
+#if defined(__linux__) || defined(__redox__)
#define DRM_IOCTL_NR(n) _IOC_NR(n)
#define DRM_IOC_VOID _IOC_NONE
@@ -81,6 +81,12 @@
#define DRM_PRIMARY_MINOR_NAME "drm"
#define DRM_CONTROL_MINOR_NAME "drmC" /* deprecated */
#define DRM_RENDER_MINOR_NAME "drmR"
+#elif defined(__redox__)
+#define DRM_DIR_NAME "/scheme/drm"
+#define DRM_PRIMARY_MINOR_NAME "card"
+#define DRM_CONTROL_MINOR_NAME "controlD" /* deprecated */
+#define DRM_RENDER_MINOR_NAME "renderD"
+#define DRM_PROC_NAME "/proc/dri/" /* For backward Linux compatibility */
#else
#define DRM_DIR_NAME "/dev/dri"
#define DRM_PRIMARY_MINOR_NAME "card"
diff -ruN source-old/xf86drmMode.c source/xf86drmMode.c
--- source-old/xf86drmMode.c
+++ source/xf86drmMode.c
@@ -50,6 +50,7 @@
#include "libdrm_macros.h"
#include "xf86drmMode.h"
#include "xf86drm.h"
+#include "xf86drm_redox.h"
#include <drm.h>
#include <drm_fourcc.h>
#include <string.h>
@@ -68,6 +69,212 @@
return ret < 0 ? -errno : ret;
}
+static void* drmAllocCpy(char *array, int count, int entry_size);
+
+#if defined(__redox__)
+static void redox_drm_mode_from_wire(drmModeModeInfoPtr mode,
+ const struct redox_drm_mode_wire *wire,
+ const char *name)
+{
+ memclear(*mode);
+ mode->clock = wire->clock;
+ mode->hdisplay = wire->hdisplay;
+ mode->hsync_start = wire->hsync_start;
+ mode->hsync_end = wire->hsync_end;
+ mode->htotal = wire->htotal;
+ mode->hskew = wire->hskew;
+ mode->vdisplay = wire->vdisplay;
+ mode->vsync_start = wire->vsync_start;
+ mode->vsync_end = wire->vsync_end;
+ mode->vtotal = wire->vtotal;
+ mode->vscan = wire->vscan;
+ mode->vrefresh = wire->vrefresh;
+ mode->flags = wire->flags;
+ mode->type = wire->type;
+ if (name) {
+ size_t name_len = strlen(name);
+ if (name_len >= DRM_DISPLAY_MODE_LEN)
+ name_len = DRM_DISPLAY_MODE_LEN - 1;
+ memcpy(mode->name, name, name_len);
+ }
+}
+
+static void redox_drm_mode_to_wire(struct redox_drm_mode_wire *wire,
+ const drmModeModeInfo *mode)
+{
+ memclear(*wire);
+ wire->clock = mode->clock;
+ wire->hdisplay = mode->hdisplay;
+ wire->hsync_start = mode->hsync_start;
+ wire->hsync_end = mode->hsync_end;
+ wire->htotal = mode->htotal;
+ wire->hskew = mode->hskew;
+ wire->vdisplay = mode->vdisplay;
+ wire->vsync_start = mode->vsync_start;
+ wire->vsync_end = mode->vsync_end;
+ wire->vtotal = mode->vtotal;
+ wire->vscan = mode->vscan;
+ wire->vrefresh = mode->vrefresh;
+ wire->flags = mode->flags;
+ wire->type = mode->type;
+}
+
+static int redox_drm_fetch_resources(int fd,
+ struct redox_drm_resources_wire *header,
+ uint32_t **connector_ids)
+{
+ void *response = NULL;
+ size_t response_size = 0;
+ size_t expected_size;
+
+ if (redox_drm_exchange_alloc(fd, REDOX_DRM_IOCTL_MODE_GETRESOURCES,
+ NULL, 0,
+ &response, &response_size) != 0) {
+ return -1;
+ }
+
+ if (response_size < sizeof(*header)) {
+ drmFree(response);
+ errno = EPROTO;
+ return -1;
+ }
+
+ memcpy(header, response, sizeof(*header));
+ expected_size = sizeof(*header) +
+ ((size_t)header->connector_count * sizeof(uint32_t));
+ if (response_size < expected_size) {
+ drmFree(response);
+ errno = EPROTO;
+ return -1;
+ }
+
+ *connector_ids = NULL;
+ if (header->connector_count != 0) {
+ *connector_ids = drmAllocCpy((char *)response + sizeof(*header),
+ header->connector_count, sizeof(uint32_t));
+ if (!*connector_ids) {
+ drmFree(response);
+ errno = ENOMEM;
+ return -1;
+ }
+ }
+
+ drmFree(response);
+ return 0;
+}
+
+static int redox_drm_parse_connector_response(const void *blob, size_t blob_size,
+ struct redox_drm_connector_wire *header,
+ drmModeModeInfoPtr *modes_out)
+{
+ const uint8_t *bytes = blob;
+ drmModeModeInfoPtr modes = NULL;
+ size_t offset = sizeof(*header);
+ uint32_t i;
+
+ if (blob_size < sizeof(*header)) {
+ errno = EPROTO;
+ return -1;
+ }
+
+ memcpy(header, bytes, sizeof(*header));
+ if (header->mode_count != 0) {
+ modes = drmMalloc(header->mode_count * sizeof(*modes));
+ if (!modes) {
+ errno = ENOMEM;
+ return -1;
+ }
+ }
+
+ for (i = 0; i < header->mode_count; ++i) {
+ struct redox_drm_mode_wire mode_wire;
+ const char *name;
+ size_t name_len;
+
+ if (blob_size - offset < sizeof(mode_wire)) {
+ drmFree(modes);
+ errno = EPROTO;
+ return -1;
+ }
+
+ memcpy(&mode_wire, bytes + offset, sizeof(mode_wire));
+ offset += sizeof(mode_wire);
+ name = (const char *)bytes + offset;
+ name_len = strnlen(name, blob_size - offset);
+ if (offset + name_len >= blob_size) {
+ drmFree(modes);
+ errno = EPROTO;
+ return -1;
+ }
+
+ redox_drm_mode_from_wire(&modes[i], &mode_wire, name);
+ offset += name_len + 1;
+ }
+
+ *modes_out = modes;
+ return 0;
+}
+
+static int redox_drm_fetch_connector(int fd, uint32_t connector_id,
+ struct redox_drm_connector_wire *header,
+ drmModeModeInfoPtr *modes_out)
+{
+ void *response = NULL;
+ size_t response_size = 0;
+ int ret;
+
+ if (redox_drm_exchange_alloc(fd, REDOX_DRM_IOCTL_MODE_GETCONNECTOR,
+ &connector_id, sizeof(connector_id),
+ &response, &response_size) != 0) {
+ return -1;
+ }
+
+ ret = redox_drm_parse_connector_response(response, response_size,
+ header, modes_out);
+ drmFree(response);
+ return ret;
+}
+
+static uint32_t redox_drm_connector_type_id(int fd, uint32_t connector_id,
+ uint32_t connector_type)
+{
+ struct redox_drm_resources_wire resources;
+ uint32_t *connector_ids = NULL;
+ uint32_t ordinal = 0;
+ uint32_t i;
+
+ if (redox_drm_fetch_resources(fd, &resources, &connector_ids) != 0)
+ return 0;
+
+ for (i = 0; i < resources.connector_count; ++i) {
+ struct redox_drm_connector_wire header;
+ drmModeModeInfoPtr modes = NULL;
+
+ if (redox_drm_fetch_connector(fd, connector_ids[i], &header, &modes) != 0)
+ break;
+ drmFree(modes);
+
+ if (header.connector_type == connector_type)
+ ++ordinal;
+ if (header.connector_id == connector_id)
+ break;
+ }
+
+ drmFree(connector_ids);
+ return ordinal;
+}
+
+static int redox_drm_page_flip_unsupported(uint32_t flags)
+{
+ if (flags & (DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_PAGE_FLIP_TARGET)) {
+ errno = EOPNOTSUPP;
+ return -1;
+ }
+
+ return 0;
+}
+#endif
+
/*
* Util functions
*/
@@ -153,16 +360,104 @@
drm_public int drmIsKMS(int fd)
{
+ #if defined(__redox__)
+ struct redox_drm_resources_wire resources;
+ uint32_t *connector_ids = NULL;
+ int is_kms;
+
+ if (redox_drm_fetch_resources(fd, &resources, &connector_ids) != 0)
+ return 0;
+
+ is_kms = resources.crtc_count > 0 &&
+ resources.connector_count > 0 &&
+ resources.encoder_count > 0;
+ drmFree(connector_ids);
+ return is_kms;
+ #else
struct drm_mode_card_res res = {0};
if (drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res) != 0)
return 0;
return res.count_crtcs > 0 && res.count_connectors > 0 && res.count_encoders > 0;
+ #endif
}
drm_public drmModeResPtr drmModeGetResources(int fd)
{
+ #if defined(__redox__)
+ struct redox_drm_resources_wire resources;
+ uint32_t *connector_ids = NULL;
+ drmModeResPtr r = NULL;
+ uint32_t i;
+
+ if (redox_drm_fetch_resources(fd, &resources, &connector_ids) != 0)
+ return NULL;
+
+ r = drmMalloc(sizeof(*r));
+ if (!r) {
+ drmFree(connector_ids);
+ return NULL;
+ }
+ memclear(*r);
+
+ r->count_connectors = resources.connector_count;
+ r->count_crtcs = resources.crtc_count;
+ r->count_encoders = resources.encoder_count;
+ r->connectors = connector_ids;
+
+ if (resources.crtc_count != 0) {
+ r->crtcs = drmMalloc(resources.crtc_count * sizeof(*r->crtcs));
+ if (!r->crtcs)
+ goto err_allocs;
+ for (i = 0; i < resources.crtc_count; ++i)
+ r->crtcs[i] = i + 1;
+ }
+
+ if (resources.encoder_count != 0) {
+ r->encoders = drmMalloc(resources.encoder_count * sizeof(*r->encoders));
+ if (!r->encoders)
+ goto err_allocs;
+ memset(r->encoders, 0, resources.encoder_count * sizeof(*r->encoders));
+ }
+
+ for (i = 0; i < resources.connector_count; ++i) {
+ struct redox_drm_connector_wire connector;
+ drmModeModeInfoPtr modes = NULL;
+ uint32_t j;
+
+ if (redox_drm_fetch_connector(fd, connector_ids[i], &connector, &modes) != 0)
+ goto err_allocs;
+
+ if (i < resources.encoder_count)
+ r->encoders[i] = connector.encoder_id;
+
+ for (j = 0; j < connector.mode_count; ++j) {
+ uint32_t width = modes[j].hdisplay;
+ uint32_t height = modes[j].vdisplay;
+ if (r->min_width == 0 || width < r->min_width)
+ r->min_width = width;
+ if (width > r->max_width)
+ r->max_width = width;
+ if (r->min_height == 0 || height < r->min_height)
+ r->min_height = height;
+ if (height > r->max_height)
+ r->max_height = height;
+ }
+ drmFree(modes);
+ }
+
+ if (resources.encoder_count > resources.connector_count) {
+ for (i = resources.connector_count; i < resources.encoder_count; ++i)
+ r->encoders[i] = 0;
+ }
+
+ return r;
+
+err_allocs:
+ drmModeFreeResources(r);
+ return NULL;
+ #else
struct drm_mode_card_res res, counts;
drmModeResPtr r = 0;
@@ -253,6 +548,7 @@
drmFree(U642VOID(res.encoder_id_ptr));
return r;
+ #endif
}
@@ -260,6 +556,26 @@
uint8_t bpp, uint32_t pitch, uint32_t bo_handle,
uint32_t *buf_id)
{
+ #if defined(__redox__)
+ struct redox_drm_add_fb_wire wire;
+
+ memclear(wire);
+ wire.width = width;
+ wire.height = height;
+ wire.pitch = pitch;
+ wire.bpp = bpp;
+ wire.depth = depth;
+ wire.handle = bo_handle;
+ if (redox_drm_exchange(fd, REDOX_DRM_IOCTL_MODE_ADDFB,
+ &wire, sizeof(wire),
+ &wire, sizeof(wire),
+ NULL) != 0) {
+ return -errno;
+ }
+
+ *buf_id = wire.fb_id;
+ return 0;
+ #else
struct drm_mode_fb_cmd f;
int ret;
@@ -276,6 +592,7 @@
*buf_id = f.fb_id;
return 0;
+ #endif
}
drm_public int drmModeAddFB2WithModifiers(int fd, uint32_t width,
@@ -317,7 +634,22 @@
drm_public int drmModeRmFB(int fd, uint32_t bufferId)
{
+ #if defined(__redox__)
+ struct redox_drm_rm_fb_wire wire;
+
+ memclear(wire);
+ wire.fb_id = bufferId;
+ if (redox_drm_exchange(fd, REDOX_DRM_IOCTL_MODE_RMFB,
+ &wire, sizeof(wire),
+ NULL, 0,
+ NULL) != 0) {
+ return -errno;
+ }
+
+ return 0;
+ #else
return DRM_IOCTL(fd, DRM_IOCTL_MODE_RMFB, &bufferId);
+ #endif
}
drm_public int drmModeCloseFB(int fd, uint32_t buffer_id)
@@ -374,6 +706,40 @@
drm_public drmModeCrtcPtr drmModeGetCrtc(int fd, uint32_t crtcId)
{
+ #if defined(__redox__)
+ struct redox_drm_get_crtc_wire wire;
+ drmModeCrtcPtr r;
+
+ memclear(wire);
+ wire.crtc_id = crtcId;
+ if (redox_drm_exchange(fd, REDOX_DRM_IOCTL_MODE_GETCRTC,
+ &wire, sizeof(wire),
+ &wire, sizeof(wire),
+ NULL) != 0) {
+ return NULL;
+ }
+
+ r = drmMalloc(sizeof(*r));
+ if (!r)
+ return NULL;
+
+ memclear(*r);
+ r->crtc_id = wire.crtc_id;
+ r->x = wire.x;
+ r->y = wire.y;
+ r->mode_valid = wire.mode_valid;
+ if (r->mode_valid) {
+ char mode_name[DRM_DISPLAY_MODE_LEN];
+ snprintf(mode_name, sizeof(mode_name), "%ux%u@%u",
+ wire.mode.hdisplay, wire.mode.vdisplay, wire.mode.vrefresh);
+ redox_drm_mode_from_wire(&r->mode, &wire.mode, mode_name);
+ r->width = wire.mode.hdisplay;
+ r->height = wire.mode.vdisplay;
+ }
+ r->buffer_id = wire.fb_id;
+ r->gamma_size = 0;
+ return r;
+ #else
struct drm_mode_crtc crtc;
drmModeCrtcPtr r;
@@ -402,12 +768,47 @@
r->buffer_id = crtc.fb_id;
r->gamma_size = crtc.gamma_size;
return r;
+ #endif
}
drm_public int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId,
uint32_t x, uint32_t y, uint32_t *connectors, int count,
drmModeModeInfoPtr mode)
{
+ #if defined(__redox__)
+ struct redox_drm_set_crtc_wire wire;
+
+ if ((x != 0 || y != 0) && bufferId != 0) {
+ errno = EOPNOTSUPP;
+ return -errno;
+ }
+ if (count < 0 || count > 8) {
+ errno = EINVAL;
+ return -errno;
+ }
+ if (bufferId != 0 && !mode) {
+ errno = EINVAL;
+ return -errno;
+ }
+
+ memclear(wire);
+ wire.crtc_id = crtcId;
+ wire.fb_handle = bufferId;
+ wire.connector_count = count;
+ if (count > 0)
+ memcpy(wire.connectors, connectors, count * sizeof(*connectors));
+ if (mode)
+ redox_drm_mode_to_wire(&wire.mode, mode);
+
+ if (redox_drm_exchange(fd, REDOX_DRM_IOCTL_MODE_SETCRTC,
+ &wire, sizeof(wire),
+ NULL, 0,
+ NULL) != 0) {
+ return -errno;
+ }
+
+ return 0;
+ #else
struct drm_mode_crtc crtc;
memclear(crtc);
@@ -423,6 +824,7 @@
}
return DRM_IOCTL(fd, DRM_IOCTL_MODE_SETCRTC, &crtc);
+ #endif
}
/*
@@ -480,6 +882,30 @@
*/
drm_public drmModeEncoderPtr drmModeGetEncoder(int fd, uint32_t encoder_id)
{
+ #if defined(__redox__)
+ struct drm_mode_get_encoder enc;
+ drmModeEncoderPtr r = NULL;
+
+ memclear(enc);
+ enc.encoder_id = encoder_id;
+ if (redox_drm_exchange(fd, REDOX_DRM_IOCTL_MODE_GETENCODER,
+ &enc, sizeof(enc),
+ &enc, sizeof(enc),
+ NULL) != 0) {
+ return NULL;
+ }
+
+ r = drmMalloc(sizeof(*r));
+ if (!r)
+ return NULL;
+
+ r->encoder_id = enc.encoder_id;
+ r->crtc_id = enc.crtc_id;
+ r->encoder_type = enc.encoder_type;
+ r->possible_crtcs = enc.possible_crtcs;
+ r->possible_clones = enc.possible_clones;
+ return r;
+ #else
struct drm_mode_get_encoder enc;
drmModeEncoderPtr r = NULL;
@@ -499,6 +925,7 @@
r->possible_clones = enc.possible_clones;
return r;
+ #endif
}
/*
@@ -507,6 +934,50 @@
static drmModeConnectorPtr
_drmModeGetConnector(int fd, uint32_t connector_id, int probe)
{
+ #if defined(__redox__)
+ struct redox_drm_connector_wire conn;
+ drmModeConnectorPtr r = NULL;
+ drmModeModeInfoPtr modes = NULL;
+
+ (void)probe;
+ if (redox_drm_fetch_connector(fd, connector_id, &conn, &modes) != 0)
+ return NULL;
+
+ r = drmMalloc(sizeof(*r));
+ if (!r)
+ goto err_allocs;
+ memclear(*r);
+
+ r->connector_id = conn.connector_id;
+ r->encoder_id = conn.encoder_id;
+ r->connection = conn.connection;
+ r->mmWidth = conn.mm_width;
+ r->mmHeight = conn.mm_height;
+ r->subpixel = DRM_MODE_SUBPIXEL_UNKNOWN;
+ r->count_modes = conn.mode_count;
+ r->modes = modes;
+ r->count_props = 0;
+ r->props = NULL;
+ r->prop_values = NULL;
+ r->count_encoders = conn.encoder_id ? 1 : 0;
+ if (r->count_encoders != 0) {
+ r->encoders = drmMalloc(sizeof(*r->encoders));
+ if (!r->encoders)
+ goto err_allocs;
+ r->encoders[0] = conn.encoder_id;
+ }
+ r->connector_type = conn.connector_type;
+ r->connector_type_id = redox_drm_connector_type_id(fd,
+ conn.connector_id,
+ conn.connector_type);
+ return r;
+
+err_allocs:
+ drmFree(modes);
+ drmFree(r ? r->encoders : NULL);
+ drmFree(r);
+ return NULL;
+ #else
struct drm_mode_get_connector conn, counts;
drmModeConnectorPtr r = NULL;
struct drm_mode_modeinfo stack_mode;
@@ -608,6 +1079,7 @@
drmFree(U642VOID(conn.encoders_ptr));
return r;
+ #endif
}
drm_public drmModeConnectorPtr drmModeGetConnector(int fd, uint32_t connector_id)
@@ -1100,6 +1572,27 @@
drm_public int drmModePageFlip(int fd, uint32_t crtc_id, uint32_t fb_id,
uint32_t flags, void *user_data)
{
+ #if defined(__redox__)
+ struct redox_drm_page_flip_wire flip;
+ uint64_t sequence;
+
+ (void)user_data;
+ if (redox_drm_page_flip_unsupported(flags) != 0)
+ return -errno;
+
+ memclear(flip);
+ flip.fb_handle = fb_id;
+ flip.crtc_id = crtc_id;
+ flip.flags = flags;
+ if (redox_drm_exchange(fd, REDOX_DRM_IOCTL_MODE_PAGE_FLIP,
+ &flip, sizeof(flip),
+ &sequence, sizeof(sequence),
+ NULL) != 0) {
+ return -errno;
+ }
+
+ return 0;
+ #else
struct drm_mode_crtc_page_flip flip;
memclear(flip);
@@ -1109,12 +1602,23 @@
flip.flags = flags;
return DRM_IOCTL(fd, DRM_IOCTL_MODE_PAGE_FLIP, &flip);
+ #endif
}
drm_public int drmModePageFlipTarget(int fd, uint32_t crtc_id, uint32_t fb_id,
uint32_t flags, void *user_data,
uint32_t target_vblank)
{
+ #if defined(__redox__)
+ (void)fd;
+ (void)crtc_id;
+ (void)fb_id;
+ (void)flags;
+ (void)user_data;
+ (void)target_vblank;
+ errno = EOPNOTSUPP;
+ return -errno;
+ #else
struct drm_mode_crtc_page_flip_target flip_target;
memclear(flip_target);
@@ -1125,6 +1629,7 @@
flip_target.sequence = target_vblank;
return DRM_IOCTL(fd, DRM_IOCTL_MODE_PAGE_FLIP, &flip_target);
+ #endif
}
drm_public int drmModeSetPlane(int fd, uint32_t plane_id, uint32_t crtc_id,
@@ -1839,6 +2344,26 @@
uint32_t flags, uint32_t *handle, uint32_t *pitch,
uint64_t *size)
{
+ #if defined(__redox__)
+ struct redox_drm_create_dumb_wire create;
+
+ memclear(create);
+ create.width = width;
+ create.height = height;
+ create.bpp = bpp;
+ create.flags = flags;
+ if (redox_drm_exchange(fd, REDOX_DRM_IOCTL_MODE_CREATE_DUMB,
+ &create, sizeof(create),
+ &create, sizeof(create),
+ NULL) != 0) {
+ return -errno;
+ }
+
+ *handle = create.handle;
+ *pitch = create.pitch;
+ *size = create.size;
+ return 0;
+ #else
int ret;
struct drm_mode_create_dumb create = {
.width = width,
@@ -1855,21 +2380,52 @@
*pitch = create.pitch;
*size = create.size;
return 0;
+ #endif
}
drm_public int
drmModeDestroyDumbBuffer(int fd, uint32_t handle)
{
+ #if defined(__redox__)
+ struct redox_drm_destroy_dumb_wire destroy;
+
+ memclear(destroy);
+ destroy.handle = handle;
+ if (redox_drm_exchange(fd, REDOX_DRM_IOCTL_MODE_DESTROY_DUMB,
+ &destroy, sizeof(destroy),
+ NULL, 0,
+ NULL) != 0) {
+ return -errno;
+ }
+
+ return 0;
+ #else
struct drm_mode_destroy_dumb destroy = {
.handle = handle,
};
return DRM_IOCTL(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy);
+ #endif
}
drm_public int
drmModeMapDumbBuffer(int fd, uint32_t handle, uint64_t *offset)
{
+ #if defined(__redox__)
+ struct redox_drm_map_dumb_wire map;
+
+ memclear(map);
+ map.handle = handle;
+ if (redox_drm_exchange(fd, REDOX_DRM_IOCTL_MODE_MAP_DUMB,
+ &map, sizeof(map),
+ &map, sizeof(map),
+ NULL) != 0) {
+ return -errno;
+ }
+
+ *offset = map.offset;
+ return 0;
+ #else
int ret;
struct drm_mode_map_dumb map = {
.handle = handle,
@@ -1881,4 +2437,5 @@
*offset = map.offset;
return 0;
+ #endif
}
diff -ruN source-old/xf86drm_redox.h source/xf86drm_redox.h
--- source-old/xf86drm_redox.h
+++ source/xf86drm_redox.h
@@ -0,0 +1,162 @@
+#ifndef _XF86DRM_REDOX_H_
+#define _XF86DRM_REDOX_H_
+
+#if defined(__redox__)
+
+#include <stddef.h>
+#include <stdint.h>
+
+#define REDOX_DRM_IOCTL_BASE 0x00A0UL
+
+#define REDOX_LINUX_IOCTL_NR(request) ((unsigned long)((request) & 0xffUL))
+#define REDOX_LINUX_IOCTL_SIZE(request) (((unsigned long)(request) >> 16) & 0x3fffUL)
+
+#define REDOX_DRM_IOCTL_MODE_GETRESOURCES (REDOX_DRM_IOCTL_BASE + 0)
+#define REDOX_DRM_IOCTL_MODE_SETCRTC (REDOX_DRM_IOCTL_BASE + 2)
+#define REDOX_DRM_IOCTL_MODE_GETCRTC (REDOX_DRM_IOCTL_BASE + 3)
+#define REDOX_DRM_IOCTL_MODE_GETENCODER (REDOX_DRM_IOCTL_BASE + 6)
+#define REDOX_DRM_IOCTL_MODE_GETCONNECTOR (REDOX_DRM_IOCTL_BASE + 7)
+#define REDOX_DRM_IOCTL_MODE_PAGE_FLIP (REDOX_DRM_IOCTL_BASE + 16)
+#define REDOX_DRM_IOCTL_MODE_CREATE_DUMB (REDOX_DRM_IOCTL_BASE + 18)
+#define REDOX_DRM_IOCTL_MODE_MAP_DUMB (REDOX_DRM_IOCTL_BASE + 19)
+#define REDOX_DRM_IOCTL_MODE_DESTROY_DUMB (REDOX_DRM_IOCTL_BASE + 20)
+#define REDOX_DRM_IOCTL_MODE_ADDFB (REDOX_DRM_IOCTL_BASE + 21)
+#define REDOX_DRM_IOCTL_MODE_RMFB (REDOX_DRM_IOCTL_BASE + 22)
+#define REDOX_DRM_IOCTL_GET_CAP (REDOX_DRM_IOCTL_BASE + 23)
+#define REDOX_DRM_IOCTL_SET_CLIENT_CAP (REDOX_DRM_IOCTL_BASE + 24)
+#define REDOX_DRM_IOCTL_VERSION (REDOX_DRM_IOCTL_BASE + 25)
+#define REDOX_DRM_IOCTL_GEM_CLOSE (REDOX_DRM_IOCTL_BASE + 27)
+#define REDOX_DRM_IOCTL_PRIME_HANDLE_TO_FD (REDOX_DRM_IOCTL_BASE + 29)
+#define REDOX_DRM_IOCTL_PRIME_FD_TO_HANDLE (REDOX_DRM_IOCTL_BASE + 30)
+
+struct redox_drm_resources_wire {
+ uint32_t connector_count;
+ uint32_t crtc_count;
+ uint32_t encoder_count;
+};
+
+struct redox_drm_connector_wire {
+ uint32_t connector_id;
+ uint32_t connection;
+ uint32_t connector_type;
+ uint32_t mm_width;
+ uint32_t mm_height;
+ uint32_t encoder_id;
+ uint32_t mode_count;
+};
+
+struct redox_drm_mode_wire {
+ uint32_t clock;
+ uint16_t hdisplay;
+ uint16_t hsync_start;
+ uint16_t hsync_end;
+ uint16_t htotal;
+ uint16_t hskew;
+ uint16_t vdisplay;
+ uint16_t vsync_start;
+ uint16_t vsync_end;
+ uint16_t vtotal;
+ uint16_t vscan;
+ uint32_t vrefresh;
+ uint32_t flags;
+ uint32_t type;
+};
+
+struct redox_drm_set_crtc_wire {
+ uint32_t crtc_id;
+ uint32_t fb_handle;
+ uint32_t connector_count;
+ uint32_t connectors[8];
+ struct redox_drm_mode_wire mode;
+};
+
+struct redox_drm_page_flip_wire {
+ uint32_t crtc_id;
+ uint32_t fb_handle;
+ uint32_t flags;
+};
+
+struct redox_drm_create_dumb_wire {
+ uint32_t width;
+ uint32_t height;
+ uint32_t bpp;
+ uint32_t flags;
+ uint32_t pitch;
+ uint32_t reserved0;
+ uint64_t size;
+ uint32_t handle;
+ uint32_t reserved1;
+};
+
+struct redox_drm_map_dumb_wire {
+ uint32_t handle;
+ uint32_t pad;
+ uint64_t offset;
+};
+
+struct redox_drm_destroy_dumb_wire {
+ uint32_t handle;
+};
+
+struct redox_drm_add_fb_wire {
+ uint32_t width;
+ uint32_t height;
+ uint32_t pitch;
+ uint32_t bpp;
+ uint32_t depth;
+ uint32_t handle;
+ uint32_t fb_id;
+};
+
+struct redox_drm_rm_fb_wire {
+ uint32_t fb_id;
+};
+
+struct redox_drm_get_crtc_wire {
+ uint32_t crtc_id;
+ uint32_t fb_id;
+ uint32_t x;
+ uint32_t y;
+ uint32_t mode_valid;
+ struct redox_drm_mode_wire mode;
+};
+
+struct redox_drm_version_wire {
+ int32_t major;
+ int32_t minor;
+ int32_t patch;
+};
+
+struct redox_drm_prime_handle_to_fd_wire {
+ uint32_t handle;
+ uint32_t flags;
+};
+
+struct redox_drm_prime_handle_to_fd_response_wire {
+ int32_t fd;
+ uint32_t pad;
+};
+
+struct redox_drm_prime_fd_to_handle_wire {
+ int32_t fd;
+ uint32_t pad;
+};
+
+struct redox_drm_prime_fd_to_handle_response_wire {
+ uint32_t handle;
+ uint32_t pad;
+};
+
+unsigned long redox_translate_request(unsigned long linux_nr);
+int redox_drm_simple_ioctl(int fd, unsigned long request, void *arg);
+int redox_drm_exchange(int fd, unsigned long request_code,
+ const void *payload, size_t payload_size,
+ void *response, size_t response_capacity,
+ size_t *response_size);
+int redox_drm_exchange_alloc(int fd, unsigned long request_code,
+ const void *payload, size_t payload_size,
+ void **response, size_t *response_size);
+
+#endif
+
+#endif