diff options
author | Alistair Strachan <astrachan@google.com> | 2018-05-10 12:23:31 -0700 |
---|---|---|
committer | Alistair Strachan <astrachan@google.com> | 2018-05-16 10:55:08 -0700 |
commit | 4186e8bbdec00546f0af20ee2da557e7fcfe127a (patch) | |
tree | f59cd59f0f19660e04979e982e129720d9edcf85 | |
parent | 7868877020bf21ba99a7428b88f6318631462753 (diff) |
Add xf86drm.h wrapper with pending features.
Fork of a libdrm change so we can move forward with a mesa3d merge
without needing to update libdrm again.
From: Robert Foss <robert.foss@collabora.com>
drmHandleMatch is intended to allow for userspace to filter out
devices that it does not want to open.
Opening specific devices using paths alone is not a reliable due to
probing order. This function intends to provide a mechanism
for filtering out devices that don't fit what you need using an
extensible set of filters.
drm_match_key_t is intended to be extended with whatever
filter that would come in handy down the line.
As a catch-all filter, the DRM_MATCH_FUNCTION was included
which allows the caller to filter based on an arbitrary function.
An function pointer filter could of course filter based on
anything. But for the sake of convenience a few other simple
filters have been included.
If the function pointer filter ends up being called with a
boilerplate fp by mutliple libdrm users, perhaps that funtion
could be moved into libdrm at a future date.
Signed-off-by: Robert Foss <robert.foss@collabora.com>
[astrachan: cherry picked pending upstream change to resolve merge issue]
Bug: 79165890
List: https://patchwork.kernel.org/patch/10368203/
Change-Id: I2d3e6e0e85e5ac0d3039051078d7df9abb36e126
Signed-off-by: Alistair Strachan <astrachan@google.com>
-rw-r--r-- | include/xf86drm.h | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/include/xf86drm.h b/include/xf86drm.h new file mode 100644 index 0000000000..dd6e2b92ea --- /dev/null +++ b/include/xf86drm.h @@ -0,0 +1,130 @@ +/* + * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas. + * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#pragma once + +#include_next <xf86drm.h> + +#include <string.h> +#include <errno.h> + +/* + * FIXME: Below code comes from https://patchwork.kernel.org/patch/10368203/ + * FIXME: Remove or rework once that has been merged + */ + +typedef enum drm_match_key { + /* Match against DRM_NODE_{PRIMARY,RENDER,...} type */ + DRM_MATCH_NODE_TYPE = 1, + DRM_MATCH_DRIVER_NAME = 2, + DRM_MATCH_BUS_PCI_VENDOR = 3, + DRM_MATCH_FUNCTION = 4, +} drm_match_key_t; + +typedef struct drm_match_func { + void *data; + int (*fp)(int, void*); /* Intended arguments are fp(fd, data) */ +} drm_match_func_t; + +typedef struct drm_match { + drm_match_key_t type; + union { + int s; + uint16_t u16; + char *str; + drm_match_func_t func; + }; +} drm_match_t; + +static inline int drmHandleMatch(int fd, drm_match_t *filters, int nbr_filters) +{ + if (fd < 0) + goto error; + + if (nbr_filters > 0 && filters == NULL) + goto error; + + drmVersionPtr ver = drmGetVersion(fd); + if (!ver) + goto fail; + + drmDevicePtr dev = NULL; + if (drmGetDevice2(fd, 0, &dev) != 0) { + goto fail; + } + + for (int i = 0; i < nbr_filters; i++) { + drm_match_t *f = &filters[i]; + switch (f->type) { + case DRM_MATCH_NODE_TYPE: + if (!(dev->available_nodes & (1 << f->s))) + goto fail; + break; + case DRM_MATCH_DRIVER_NAME: + if (!f->str) + goto error; + + /* This bypass is used by when the driver name is used + by the Android property_get() func, when it hasn't found + the property and the string is empty as a result. */ + if (strlen(f->str) == 0) + continue; + + if (strncmp(ver->name, f->str, strlen(ver->name))) + goto fail; + break; + case DRM_MATCH_BUS_PCI_VENDOR: + if (dev->bustype != DRM_BUS_PCI) + goto fail; + if (dev->deviceinfo.pci->vendor_id != f->u16) + goto fail; + break; + case DRM_MATCH_FUNCTION: + if (!f->func.fp) + goto error; + int (*fp)(int, void*) = f->func.fp; + void *data = f->func.data; + if (!fp(fd, data)) + goto fail; + break; + default: + goto error; + } + } + +success: + drmFreeVersion(ver); + drmFreeDevice(&dev); + return 0; +error: + drmFreeVersion(ver); + drmFreeDevice(&dev); + return -EINVAL; +fail: + drmFreeVersion(ver); + drmFreeDevice(&dev); + return 1; +} + |